Browse Source

Merge topic 'enhance-include_external_msproject'

b803410 VS: Fix line-too-long style errors
8787f94 Merge branch 'list-empty-error' into enhance-include_external_msproject
4a30258 include_external_msproject: Test TYPE, GUID, PLATFORM options (#13120)
f3191f5 Merge branch 'test-RunCMake-check' into enhance-include_external_msproject
5913903 include_external_msproject: Add TYPE, GUID, PLATFORM options (#13120)
David Cole 13 years ago
parent
commit
91f83347d3

+ 10 - 4
Source/cmGlobalVisualStudio71Generator.cxx

@@ -241,9 +241,12 @@ void cmGlobalVisualStudio71Generator
 ::WriteExternalProject(std::ostream& fout, 
 ::WriteExternalProject(std::ostream& fout, 
                        const char* name,
                        const char* name,
                        const char* location,
                        const char* location,
+                       const char* typeGuid,
                        const std::set<cmStdString>& depends)
                        const std::set<cmStdString>& depends)
 { 
 { 
-  fout << "Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"" 
+  fout << "Project(\"{"
+       << (typeGuid ? typeGuid : "8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942")
+       << "}\") = \""
        << name << "\", \""
        << name << "\", \""
        << this->ConvertToSolutionPath(location) << "\", \"{"
        << this->ConvertToSolutionPath(location) << "\", \"{"
        << this->GetGUID(name)
        << this->GetGUID(name)
@@ -279,18 +282,21 @@ void cmGlobalVisualStudio71Generator
 // executables to the libraries it uses are also done here
 // executables to the libraries it uses are also done here
 void cmGlobalVisualStudio71Generator
 void cmGlobalVisualStudio71Generator
 ::WriteProjectConfigurations(std::ostream& fout, const char* name,
 ::WriteProjectConfigurations(std::ostream& fout, const char* name,
-                             bool partOfDefaultBuild)
+                             bool partOfDefaultBuild,
+                             const char* platformMapping)
 {
 {
   std::string guid = this->GetGUID(name);
   std::string guid = this->GetGUID(name);
   for(std::vector<std::string>::iterator i = this->Configurations.begin();
   for(std::vector<std::string>::iterator i = this->Configurations.begin();
       i != this->Configurations.end(); ++i)
       i != this->Configurations.end(); ++i)
     {
     {
     fout << "\t\t{" << guid << "}." << *i 
     fout << "\t\t{" << guid << "}." << *i 
-         << ".ActiveCfg = " << *i << "|Win32\n";
+         << ".ActiveCfg = " << *i << "|"
+         << (platformMapping ? platformMapping : "Win32") << std::endl;
     if(partOfDefaultBuild)
     if(partOfDefaultBuild)
       {
       {
       fout << "\t\t{" << guid << "}." << *i
       fout << "\t\t{" << guid << "}." << *i
-           << ".Build.0 = " << *i << "|Win32\n";
+           << ".Build.0 = " << *i << "|"
+           << (platformMapping ? platformMapping : "Win32") << std::endl;
       }
       }
     }
     }
 }
 }

+ 3 - 1
Source/cmGlobalVisualStudio71Generator.h

@@ -64,10 +64,12 @@ protected:
                            const char* name, const char* path, cmTarget &t);
                            const char* name, const char* path, cmTarget &t);
   virtual void WriteProjectConfigurations(std::ostream& fout,
   virtual void WriteProjectConfigurations(std::ostream& fout,
                                           const char* name,
                                           const char* name,
-                                          bool partOfDefaultBuild);
+                                          bool partOfDefaultBuild,
+                                          const char* platformMapping = NULL);
   virtual void WriteExternalProject(std::ostream& fout,
   virtual void WriteExternalProject(std::ostream& fout,
                                     const char* name,
                                     const char* name,
                                     const char* path,
                                     const char* path,
+                                    const char* typeGuid,
                                     const std::set<cmStdString>& depends);
                                     const std::set<cmStdString>& depends);
   virtual void WriteSLNFooter(std::ostream& fout);
   virtual void WriteSLNFooter(std::ostream& fout);
   virtual void WriteSLNHeader(std::ostream& fout);
   virtual void WriteSLNHeader(std::ostream& fout);

+ 20 - 8
Source/cmGlobalVisualStudio7Generator.cxx

@@ -250,8 +250,9 @@ void cmGlobalVisualStudio7Generator::WriteTargetConfigurations(
     const char* expath = target->GetProperty("EXTERNAL_MSPROJECT");
     const char* expath = target->GetProperty("EXTERNAL_MSPROJECT");
     if(expath)
     if(expath)
       {
       {
-      this->WriteProjectConfigurations(fout, target->GetName(),
-                                       true);
+      this->WriteProjectConfigurations(
+        fout, target->GetName(),
+        true, target->GetProperty("VS_PLATFORM_MAPPING"));
       }
       }
     else
     else
       {
       {
@@ -286,8 +287,12 @@ void cmGlobalVisualStudio7Generator::WriteTargetsToSolution(
       {
       {
       std::string project = target->GetName();
       std::string project = target->GetName();
       std::string location = expath;
       std::string location = expath;
-      this->WriteExternalProject(fout, project.c_str(), 
-                                 location.c_str(), target->GetUtilities());
+
+      this->WriteExternalProject(fout,
+                                 project.c_str(),
+                                 location.c_str(),
+                                 target->GetProperty("VS_PROJECT_TYPE"),
+                                 target->GetUtilities());
       written = true;
       written = true;
       }
       }
     else
     else
@@ -580,18 +585,21 @@ cmGlobalVisualStudio7Generator
 // executables to the libraries it uses are also done here
 // executables to the libraries it uses are also done here
 void cmGlobalVisualStudio7Generator
 void cmGlobalVisualStudio7Generator
 ::WriteProjectConfigurations(std::ostream& fout, const char* name,
 ::WriteProjectConfigurations(std::ostream& fout, const char* name,
-                             bool partOfDefaultBuild)
+                             bool partOfDefaultBuild,
+                             const char* platformMapping)
 {
 {
   std::string guid = this->GetGUID(name);
   std::string guid = this->GetGUID(name);
   for(std::vector<std::string>::iterator i = this->Configurations.begin();
   for(std::vector<std::string>::iterator i = this->Configurations.begin();
       i != this->Configurations.end(); ++i)
       i != this->Configurations.end(); ++i)
     {
     {
     fout << "\t\t{" << guid << "}." << *i
     fout << "\t\t{" << guid << "}." << *i
-         << ".ActiveCfg = " << *i << "|Win32\n";
+         << ".ActiveCfg = " << *i << "|"
+         << (platformMapping ? platformMapping : "Win32") << "\n";
     if(partOfDefaultBuild)
     if(partOfDefaultBuild)
       {
       {
       fout << "\t\t{" << guid << "}." << *i
       fout << "\t\t{" << guid << "}." << *i
-           << ".Build.0 = " << *i << "|Win32\n";
+           << ".Build.0 = " << *i << "|"
+           << (platformMapping ? platformMapping : "Win32") << "\n";
       }
       }
     }
     }
 }
 }
@@ -604,10 +612,14 @@ void cmGlobalVisualStudio7Generator
 void cmGlobalVisualStudio7Generator::WriteExternalProject(std::ostream& fout, 
 void cmGlobalVisualStudio7Generator::WriteExternalProject(std::ostream& fout, 
                                const char* name,
                                const char* name,
                                const char* location,
                                const char* location,
+                               const char* typeGuid,
                                const std::set<cmStdString>&)
                                const std::set<cmStdString>&)
 { 
 { 
   std::string d = cmSystemTools::ConvertToOutputPath(location);
   std::string d = cmSystemTools::ConvertToOutputPath(location);
-  fout << "Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"" 
+  fout << "Project("
+       << "\"{"
+       << (typeGuid ? typeGuid : "8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942")
+       << "}\") = \""
        << name << "\", \""
        << name << "\", \""
        << this->ConvertToSolutionPath(location) << "\", \"{"
        << this->ConvertToSolutionPath(location) << "\", \"{"
        << this->GetGUID(name)
        << this->GetGUID(name)

+ 3 - 1
Source/cmGlobalVisualStudio7Generator.h

@@ -107,7 +107,8 @@ protected:
                            const char* name, const char* path, cmTarget &t);
                            const char* name, const char* path, cmTarget &t);
   virtual void WriteProjectConfigurations(std::ostream& fout,
   virtual void WriteProjectConfigurations(std::ostream& fout,
                                           const char* name,
                                           const char* name,
-                                          bool partOfDefaultBuild);
+                                          bool partOfDefaultBuild,
+                                          const char* platformMapping = NULL);
   virtual void WriteSLNFooter(std::ostream& fout);
   virtual void WriteSLNFooter(std::ostream& fout);
   virtual void WriteSLNHeader(std::ostream& fout);
   virtual void WriteSLNHeader(std::ostream& fout);
   virtual std::string WriteUtilityDepend(cmTarget* target);
   virtual std::string WriteUtilityDepend(cmTarget* target);
@@ -130,6 +131,7 @@ protected:
   virtual void WriteExternalProject(std::ostream& fout,
   virtual void WriteExternalProject(std::ostream& fout,
                                     const char* name,
                                     const char* name,
                                     const char* path,
                                     const char* path,
+                                    const char* typeGuid,
                                     const std::set<cmStdString>&
                                     const std::set<cmStdString>&
                                     dependencies);
                                     dependencies);
 
 

+ 8 - 5
Source/cmGlobalVisualStudio8Generator.cxx

@@ -268,20 +268,23 @@ cmGlobalVisualStudio8Generator
 void
 void
 cmGlobalVisualStudio8Generator
 cmGlobalVisualStudio8Generator
 ::WriteProjectConfigurations(std::ostream& fout, const char* name,
 ::WriteProjectConfigurations(std::ostream& fout, const char* name,
-                             bool partOfDefaultBuild)
+                             bool partOfDefaultBuild,
+                             const char* platformMapping)
 {
 {
   std::string guid = this->GetGUID(name);
   std::string guid = this->GetGUID(name);
   for(std::vector<std::string>::iterator i = this->Configurations.begin();
   for(std::vector<std::string>::iterator i = this->Configurations.begin();
       i != this->Configurations.end(); ++i)
       i != this->Configurations.end(); ++i)
     {
     {
     fout << "\t\t{" << guid << "}." << *i
     fout << "\t\t{" << guid << "}." << *i
-         << "|" << this->GetPlatformName() << ".ActiveCfg = "
-         << *i << "|" << this->GetPlatformName() << "\n";
+         << "|" << this->GetPlatformName() << ".ActiveCfg = " << *i << "|"
+         << (platformMapping ? platformMapping : this->GetPlatformName())
+         << "\n";
     if(partOfDefaultBuild)
     if(partOfDefaultBuild)
       {
       {
       fout << "\t\t{" << guid << "}." << *i
       fout << "\t\t{" << guid << "}." << *i
-           << "|" << this->GetPlatformName() << ".Build.0 = "
-           << *i << "|" << this->GetPlatformName() << "\n";
+           << "|" << this->GetPlatformName() << ".Build.0 = " << *i << "|"
+           << (platformMapping ? platformMapping : this->GetPlatformName())
+           << "\n";
       }
       }
     }
     }
 }
 }

+ 2 - 1
Source/cmGlobalVisualStudio8Generator.h

@@ -77,7 +77,8 @@ protected:
   virtual void WriteSolutionConfigurations(std::ostream& fout);
   virtual void WriteSolutionConfigurations(std::ostream& fout);
   virtual void WriteProjectConfigurations(std::ostream& fout,
   virtual void WriteProjectConfigurations(std::ostream& fout,
                                           const char* name,
                                           const char* name,
-                                          bool partOfDefaultBuild);
+                                          bool partOfDefaultBuild,
+                                          const char* platformMapping = NULL);
   virtual bool ComputeTargetDepends();
   virtual bool ComputeTargetDepends();
   virtual void WriteProjectDepends(std::ostream& fout, const char* name,
   virtual void WriteProjectDepends(std::ostream& fout, const char* name,
                                    const char* path, cmTarget &t);
                                    const char* path, cmTarget &t);

+ 62 - 5
Source/cmIncludeExternalMSProjectCommand.cxx

@@ -25,18 +25,75 @@ bool cmIncludeExternalMSProjectCommand
 #ifdef _WIN32
 #ifdef _WIN32
   if(this->Makefile->GetDefinition("WIN32"))
   if(this->Makefile->GetDefinition("WIN32"))
     {
     {
+    enum Doing { DoingNone, DoingType, DoingGuid, DoingPlatform };
+
+    Doing doing = DoingNone;
+
+    std::string customType;
+    std::string customGuid;
+    std::string platformMapping;
+
+    std::vector<std::string> depends;
+    for (unsigned int i=2; i<args.size(); ++i)
+      {
+      if (args[i] == "TYPE")
+        {
+        doing = DoingType;
+        }
+      else if (args[i] == "GUID")
+        {
+        doing = DoingGuid;
+        }
+      else if (args[i] == "PLATFORM")
+        {
+        doing = DoingPlatform;
+        }
+      else
+        {
+        switch (doing)
+          {
+          case DoingNone: depends.push_back(args[i]);    break;
+          case DoingType: customType = args[i];          break;
+          case DoingGuid: customGuid = args[i];          break;
+          case DoingPlatform: platformMapping = args[i]; break;
+          }
+        doing = DoingNone;
+        }
+      }
+
+    // Hack together a utility target storing enough information
+    // to reproduce the target inclusion.
+    std::string utility_name = args[0];
+
     std::string path = args[1];
     std::string path = args[1];
     cmSystemTools::ConvertToUnixSlashes(path);
     cmSystemTools::ConvertToUnixSlashes(path);
 
 
+    if (!customGuid.empty())
+      {
+      std::string guidVariable = utility_name + "_GUID_CMAKE";
+      this->Makefile->GetCMakeInstance()->AddCacheEntry(
+        guidVariable.c_str(), customGuid.c_str(),
+        "Stored GUID", cmCacheManager::INTERNAL);
+      }
+
     // Create a target instance for this utility.
     // Create a target instance for this utility.
     cmTarget* target=this->Makefile->AddNewTarget(cmTarget::UTILITY, 
     cmTarget* target=this->Makefile->AddNewTarget(cmTarget::UTILITY, 
-                                                  args[0].c_str());
+                                                  utility_name.c_str());
+
+    target->SetProperty("GENERATOR_FILE_NAME", utility_name.c_str());
     target->SetProperty("EXTERNAL_MSPROJECT", path.c_str());
     target->SetProperty("EXTERNAL_MSPROJECT", path.c_str());
-    target->SetProperty("EXCLUDE_FROM_ALL","FALSE"); 
-    target->SetProperty("GENERATOR_FILE_NAME", args[0].c_str());
-    for (unsigned int i=2; i<args.size(); ++i) 
+    target->SetProperty("EXCLUDE_FROM_ALL", "FALSE");
+
+    if (!customType.empty())
+      target->SetProperty("VS_PROJECT_TYPE",customType.c_str());
+    if (!platformMapping.empty())
+      target->SetProperty("VS_PLATFORM_MAPPING",platformMapping.c_str());
+
+    for (std::vector<std::string>::const_iterator it = depends.begin();
+         it != depends.end();
+         ++it)
       {
       {
-      target->AddUtility(args[i].c_str());
+      target->AddUtility(it->c_str());
       }
       }
     }
     }
 #endif
 #endif

+ 11 - 1
Source/cmIncludeExternalMSProjectCommand.h

@@ -59,11 +59,21 @@ public:
     {
     {
     return
     return
       "  include_external_msproject(projectname location\n"
       "  include_external_msproject(projectname location\n"
+      "                             [TYPE projectTypeGUID]\n"
+      "                             [GUID projectGUID]\n"
+      "                             [PLATFORM platformName]\n"
       "                             dep1 dep2 ...)\n"
       "                             dep1 dep2 ...)\n"
       "Includes an external Microsoft project in the generated workspace "
       "Includes an external Microsoft project in the generated workspace "
       "file.  Currently does nothing on UNIX. This will create a "
       "file.  Currently does nothing on UNIX. This will create a "
       "target named [projectname].  This can be used in the add_dependencies "
       "target named [projectname].  This can be used in the add_dependencies "
-      "command to make things depend on the external project.";
+      "command to make things depend on the external project."
+      "\n"
+      "TYPE, GUID and PLATFORM are optional parameters that allow one "
+      "to specify the type of project, id (GUID) of the project and "
+      "the name of the target platform.  "
+      "This is useful for projects requiring values other than the default "
+      "(e.g. WIX projects). "
+      "These options are not supported by the Visual Studio 6 generator.";
     }
     }
   
   
   cmTypeMacro(cmIncludeExternalMSProjectCommand, cmCommand);
   cmTypeMacro(cmIncludeExternalMSProjectCommand, cmCommand);

+ 8 - 0
Source/cmLocalVisualStudio10Generator.cxx

@@ -99,6 +99,14 @@ void cmLocalVisualStudio10Generator
 {
 {
   cmVS10XMLParser parser;
   cmVS10XMLParser parser;
   parser.ParseFile(path); 
   parser.ParseFile(path); 
+
+  // if we can not find a GUID then create one
+  if(parser.GUID.empty())
+    {
+    this->GlobalGenerator->CreateGUID(name);
+    return;
+    }
+
   std::string guidStoreName = name;
   std::string guidStoreName = name;
   guidStoreName += "_GUID_CMAKE";
   guidStoreName += "_GUID_CMAKE";
   // save the GUID in the cache
   // save the GUID in the cache

+ 4 - 0
Tests/RunCMake/CMakeLists.txt

@@ -50,3 +50,7 @@ add_RunCMake_test(ObjectLibrary)
 add_RunCMake_test(build_command)
 add_RunCMake_test(build_command)
 add_RunCMake_test(find_package)
 add_RunCMake_test(find_package)
 add_RunCMake_test(list)
 add_RunCMake_test(list)
+
+if("${CMAKE_TEST_GENERATOR}" MATCHES "Visual Studio [^6]")
+  add_RunCMake_test(include_external_msproject)
+endif()

+ 3 - 0
Tests/RunCMake/include_external_msproject/CMakeLists.txt

@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)

+ 1 - 0
Tests/RunCMake/include_external_msproject/CustomGuid-check.cmake

@@ -0,0 +1 @@
+check_project(CustomGuid external "aaa-bbb-ccc-000" "" "")

+ 2 - 0
Tests/RunCMake/include_external_msproject/CustomGuid.cmake

@@ -0,0 +1,2 @@
+include_external_msproject(external external.project
+                           GUID aaa-bbb-ccc-000)

+ 1 - 0
Tests/RunCMake/include_external_msproject/CustomGuidTypePlatform-check.cmake

@@ -0,0 +1 @@
+check_project(CustomGuidTypePlatform external "aaa-bbb-ccc-111" "aaa-bbb-ccc-ddd-eee" "Custom Platform")

+ 5 - 0
Tests/RunCMake/include_external_msproject/CustomGuidTypePlatform.cmake

@@ -0,0 +1,5 @@
+# Test all optional parameters are set.
+include_external_msproject(external external.project
+                           GUID aaa-bbb-ccc-111
+                           TYPE aaa-bbb-ccc-ddd-eee
+                           PLATFORM "Custom Platform")

+ 1 - 0
Tests/RunCMake/include_external_msproject/CustomTypePlatform-check.cmake

@@ -0,0 +1 @@
+check_project(CustomTypePlatform external "" "aaa-bbb-ccc-ddd-eee" "Custom Platform")

+ 3 - 0
Tests/RunCMake/include_external_msproject/CustomTypePlatform.cmake

@@ -0,0 +1,3 @@
+include_external_msproject(external external.project
+                           TYPE aaa-bbb-ccc-ddd-eee
+                           PLATFORM "Custom Platform")

+ 6 - 0
Tests/RunCMake/include_external_msproject/RunCMakeTest.cmake

@@ -0,0 +1,6 @@
+include(RunCMake)
+include(${CMAKE_CURRENT_LIST_DIR}/check_utils.cmake)
+
+run_cmake(CustomGuid)
+run_cmake(CustomTypePlatform)
+run_cmake(CustomGuidTypePlatform)

+ 109 - 0
Tests/RunCMake/include_external_msproject/check_utils.cmake

@@ -0,0 +1,109 @@
+# Check that file contains line that matches regular expression.
+# Sets IS_FOUND variable to TRUE if found and to FALSE otherwise.
+macro(check_line_exists TARGET_FILE REG_EXP_REF)
+  set(IS_FOUND "FALSE")
+
+  file(STRINGS ${TARGET_FILE} FOUND_LINE LIMIT_COUNT 1 REGEX "${${REG_EXP_REF}}")
+  list(LENGTH FOUND_LINE _VAR_LEN)
+
+  if(_VAR_LEN GREATER 0)
+    set(IS_FOUND "TRUE")
+  endif(_VAR_LEN GREATER 0)
+endmacro(check_line_exists TARGET_FILE REG_EXP_REF)
+
+# Search and parse project section line by project name.
+# If search was successful stores found type and guid into FOUND_TYPE and FOUND_GUID variables respectively.
+# Sets IS_FOUND variable to TRUE if found and to FALSE otherwise.
+macro(parse_project_section TARGET_FILE PROJECT_NAME)
+  set(REG_EXP "^Project\\(\\\"{(.+)}\\\"\\) = \\\"${PROJECT_NAME}\\\", \\\".+\\..+\\\", \\\"{(.+)}\\\"$")
+
+  check_line_exists(${TARGET_FILE} REG_EXP)
+  if(NOT IS_FOUND)
+    return()
+  endif(NOT IS_FOUND)
+
+  string(REGEX REPLACE "${REG_EXP}" "\\1;\\2" _GUIDS "${FOUND_LINE}")
+
+  list(GET _GUIDS 0 FOUND_TYPE)
+  list(GET _GUIDS 1 FOUND_GUID)
+endmacro(parse_project_section TARGET_FILE PROJECT_NAME)
+
+# Search project section line by project name and type.
+# Returns TRUE if found and FALSE otherwise
+function(check_project_type TARGET_FILE PROJECT_NAME PROJECT_TYPE RESULT)
+  set(${RESULT} "FALSE" PARENT_SCOPE)
+
+  parse_project_section(${TARGET_FILE} ${PROJECT_NAME})
+  if(IS_FOUND AND FOUND_TYPE STREQUAL PROJECT_TYPE)
+    set(${RESULT} "TRUE" PARENT_SCOPE)
+  endif(IS_FOUND AND FOUND_TYPE STREQUAL PROJECT_TYPE)
+endfunction(check_project_type TARGET_FILE PROJECT_NAME PROJECT_TYPE RESULT)
+
+
+# Search project section line by project name and id.
+# Returns TRUE if found and FALSE otherwise
+function(check_project_guid TARGET_FILE PROJECT_NAME PROJECT_GUID RESULT)
+  set(${RESULT} "FALSE" PARENT_SCOPE)
+
+  parse_project_section(${TARGET_FILE} ${PROJECT_NAME})
+  if(IS_FOUND AND FOUND_GUID STREQUAL PROJECT_GUID)
+    set(${RESULT} "TRUE" PARENT_SCOPE)
+  endif(IS_FOUND AND FOUND_GUID STREQUAL PROJECT_GUID)
+endfunction(check_project_guid TARGET_FILE PROJECT_NAME PROJECT_GUID RESULT)
+
+
+# Search project's build configuration line by project name and target platform name.
+# Returns TRUE if found and FALSE otherwise
+function(check_custom_platform TARGET_FILE PROJECT_NAME PLATFORM_NAME RESULT)
+  set(${RESULT} "FALSE" PARENT_SCOPE)
+
+  # extract project guid
+  parse_project_section(${TARGET_FILE} ${PROJECT_NAME})
+  if(NOT IS_FOUND)
+    return()
+  endif(NOT IS_FOUND)
+
+  # probably whould be better to use configuration name
+  # extracted from CMAKE_CONFIGURATION_TYPES than just hardcoded "Debug" instead
+  set(REG_EXP "^(\t)*\\{${FOUND_GUID}\\}\\.Debug[^ ]*\\.ActiveCfg = Debug\\|${PLATFORM_NAME}$")
+  check_line_exists(${TARGET_FILE} REG_EXP)
+
+  set(${RESULT} ${IS_FOUND} PARENT_SCOPE)
+endfunction(check_custom_platform TARGET_FILE PLATFORM_NAME RESULT)
+
+# RunCMake test check helper
+function(check_project test name guid type platform)
+  set(sln "${RunCMake_TEST_BINARY_DIR}/${test}.sln")
+  set(sep "")
+  set(failed "")
+  if(NOT type)
+    set(type 8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942)
+  endif()
+  if(NOT platform)
+    if("${RunCMake_GENERATOR}" MATCHES "Win64")
+      set(platform "x64")
+    else()
+      set(platform "Win32")
+    endif()
+  endif()
+  if(guid)
+    check_project_guid("${sln}" "${name}" "${guid}" passed_guid)
+    if(NOT passed_guid)
+      set(failed "${failed}${sep}${name} solution has no project with expected GUID=${guid}")
+      set(sep "\n")
+    endif()
+  else()
+    set(passed_guid 1)
+  endif()
+  check_project_type("${sln}" "${name}" "${type}" passed_type)
+  if(NOT passed_type)
+    set(failed "${failed}${sep}${name} solution has no project with expected TYPE=${type}")
+    set(sep "\n")
+  endif()
+  check_custom_platform("${sln}" "${name}" "${platform}" passed_platform)
+  if(NOT passed_platform)
+    set(failed "${failed}${sep}${name} solution has no project with expected PLATFORM=${platform}")
+    set(sep "\n")
+  endif()
+  set(RunCMake_TEST_FAILED "${failed}" PARENT_SCOPE)
+endfunction()

+ 3 - 0
Tests/RunCMake/include_external_msproject/main.cpp

@@ -0,0 +1,3 @@
+void main()
+{
+}