From e134e53b47fc9f0337529ce2b6851cec6319a8af Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 16 Sep 2015 10:24:16 -0400 Subject: Add support for *.manifest source files with MSVC tools Classify .manifest sources separately, add dependencies on them, and pass them to the MS manifest tool to merge with linker-generated manifest files. Inspired-by: Gilles Khouzam --- Help/release/dev/ms-manifest-files.rst | 7 ++++++ Modules/Platform/Windows-MSVC.cmake | 4 +-- Source/cmCommonTargetGenerator.cxx | 17 +++++++++++++ Source/cmCommonTargetGenerator.h | 1 + Source/cmGeneratorTarget.cxx | 14 +++++++++++ Source/cmGeneratorTarget.h | 2 ++ Source/cmLocalGenerator.cxx | 7 ++++++ Source/cmLocalGenerator.h | 1 + Source/cmLocalVisualStudio7Generator.cxx | 14 +++++++++++ Source/cmMakefileExecutableTargetGenerator.cxx | 4 +++ Source/cmMakefileLibraryTargetGenerator.cxx | 4 +++ Source/cmMakefileTargetGenerator.cxx | 9 +++++++ Source/cmNinjaNormalTargetGenerator.cxx | 3 +++ Source/cmNinjaTargetGenerator.cxx | 9 +++++++ Source/cmVisualStudio10TargetGenerator.cxx | 29 ++++++++++++++++++++++ Source/cmVisualStudio10TargetGenerator.h | 1 + Source/cmcmd.cxx | 21 ++++++++++++---- Tests/CMakeLists.txt | 1 + Tests/MSManifest/CMakeLists.txt | 5 ++++ Tests/MSManifest/Subdir/CMakeLists.txt | 9 +++++++ Tests/MSManifest/Subdir/check.cmake | 6 +++++ Tests/MSManifest/Subdir/main.c | 1 + Tests/MSManifest/Subdir/test.manifest.in | 4 +++ Tests/RunCMake/BuildDepends/C-Exe-Manifest.cmake | 19 ++++++++++++++ .../BuildDepends/C-Exe-Manifest.step1.cmake | 6 +++++ .../BuildDepends/C-Exe-Manifest.step2.cmake | 6 +++++ Tests/RunCMake/BuildDepends/RunCMakeTest.cmake | 11 ++++++++ Tests/RunCMake/BuildDepends/check.cmake | 3 +++ Tests/RunCMake/BuildDepends/main.c | 1 + 29 files changed, 212 insertions(+), 7 deletions(-) create mode 100644 Help/release/dev/ms-manifest-files.rst create mode 100644 Tests/MSManifest/CMakeLists.txt create mode 100644 Tests/MSManifest/Subdir/CMakeLists.txt create mode 100644 Tests/MSManifest/Subdir/check.cmake create mode 100644 Tests/MSManifest/Subdir/main.c create mode 100644 Tests/MSManifest/Subdir/test.manifest.in create mode 100644 Tests/RunCMake/BuildDepends/C-Exe-Manifest.cmake create mode 100644 Tests/RunCMake/BuildDepends/C-Exe-Manifest.step1.cmake create mode 100644 Tests/RunCMake/BuildDepends/C-Exe-Manifest.step2.cmake create mode 100644 Tests/RunCMake/BuildDepends/main.c diff --git a/Help/release/dev/ms-manifest-files.rst b/Help/release/dev/ms-manifest-files.rst new file mode 100644 index 0000000..94fbe83 --- /dev/null +++ b/Help/release/dev/ms-manifest-files.rst @@ -0,0 +1,7 @@ +ms-manifest-files +----------------- + +* CMake learned to honor ``*.manifest`` source files with MSVC tools. + Manifest files named as sources of ``.exe`` and ``.dll`` targets + will be merged with linker-generated manifests and embedded in the + binary. diff --git a/Modules/Platform/Windows-MSVC.cmake b/Modules/Platform/Windows-MSVC.cmake index d4b1cd8..8594596 100644 --- a/Modules/Platform/Windows-MSVC.cmake +++ b/Modules/Platform/Windows-MSVC.cmake @@ -274,8 +274,8 @@ set (CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL_INIT ${CMAKE_EXE_LINKER_FLAGS_MINSIZER macro(__windows_compiler_msvc lang) if(NOT MSVC_VERSION LESS 1400) # for 2005 make sure the manifest is put in the dll with mt - set(_CMAKE_VS_LINK_DLL " -E vs_link_dll --intdir= ") - set(_CMAKE_VS_LINK_EXE " -E vs_link_exe --intdir= ") + set(_CMAKE_VS_LINK_DLL " -E vs_link_dll --intdir= --manifests -- ") + set(_CMAKE_VS_LINK_EXE " -E vs_link_exe --intdir= --manifests -- ") endif() set(CMAKE_${lang}_CREATE_SHARED_LIBRARY "${_CMAKE_VS_LINK_DLL} ${CMAKE_CL_NOLOGO} ${CMAKE_START_TEMP_FILE} /out: /implib: /pdb: /dll /version:.${_PLATFORM_LINK_FLAGS} ${CMAKE_END_TEMP_FILE}") diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx index 4840e89..252e231 100644 --- a/Source/cmCommonTargetGenerator.cxx +++ b/Source/cmCommonTargetGenerator.cxx @@ -412,3 +412,20 @@ cmCommonTargetGenerator::GetLinkedTargetDirectories() const } return dirs; } + +std::string cmCommonTargetGenerator::GetManifests() +{ + std::vector manifest_srcs; + this->GeneratorTarget->GetManifests(manifest_srcs, this->ConfigName); + + std::vector manifests; + for (std::vector::iterator mi = manifest_srcs.begin(); + mi != manifest_srcs.end(); ++mi) + { + manifests.push_back(this->Convert((*mi)->GetFullPath(), + this->WorkingDirectory, + cmOutputConverter::SHELL)); + } + + return cmJoin(manifests, " "); +} diff --git a/Source/cmCommonTargetGenerator.h b/Source/cmCommonTargetGenerator.h index 0a49e12..a4b2c10 100644 --- a/Source/cmCommonTargetGenerator.h +++ b/Source/cmCommonTargetGenerator.h @@ -88,6 +88,7 @@ protected: ByLanguageMap DefinesByLanguage; std::string GetIncludes(std::string const& l); ByLanguageMap IncludesByLanguage; + std::string GetManifests(); std::vector GetLinkedTargetDirectories() const; }; diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 09387b7..fb5805b 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -75,6 +75,7 @@ struct IDLSourcesTag {}; struct ResxTag {}; struct ModuleDefinitionFileTag {}; struct AppManifestTag{}; +struct ManifestsTag{}; struct CertificatesTag{}; struct XamlTag{}; @@ -216,6 +217,10 @@ struct TagVisitor { DoAccept::Result>::Do(this->Data, sf); } + else if (ext == "manifest") + { + DoAccept::Result>::Do(this->Data, sf); + } else if (ext == "pfx") { DoAccept::Result>::Do(this->Data, sf); @@ -626,6 +631,15 @@ cmGeneratorTarget //---------------------------------------------------------------------------- void cmGeneratorTarget +::GetManifests(std::vector& data, + const std::string& config) const +{ + IMPLEMENT_VISIT(Manifests); +} + +//---------------------------------------------------------------------------- +void +cmGeneratorTarget ::GetCertificates(std::vector& data, const std::string& config) const { diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 06d9a1f..916f281 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -71,6 +71,8 @@ public: const std::string& config) const; void GetAppManifest(std::vector&, const std::string& config) const; + void GetManifests(std::vector&, + const std::string& config) const; void GetCertificates(std::vector&, const std::string& config) const; void GetXamlSources(std::vector&, diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 46d5cd8..97a9f1e 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -525,6 +525,13 @@ cmLocalGenerator::ExpandRuleVariable(std::string const& variable, return replaceValues.LinkFlags; } } + if(replaceValues.Manifests) + { + if(variable == "MANIFESTS") + { + return replaceValues.Manifests; + } + } if(replaceValues.Flags) { if(variable == "FLAGS") diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index b051e5d..771131f 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -219,6 +219,7 @@ public: const char* TargetSOName; const char* TargetInstallNameDir; const char* LinkFlags; + const char* Manifests; const char* LanguageCompileFlags; const char* Defines; const char* Includes; diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 191f739..a4bce8a 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -984,6 +984,20 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout, "\t\t\t manifest_srcs; + gt->GetManifests(manifest_srcs, configName); + if (!manifest_srcs.empty()) + { + fout << "\n\t\t\t\tAdditionalManifestFiles=\""; + for (std::vector::const_iterator + mi = manifest_srcs.begin(); mi != manifest_srcs.end(); ++mi) + { + std::string m = (*mi)->GetFullPath(); + fout << this->ConvertToXMLOutputPath(m.c_str()) << ";"; + } + fout << "\""; + } + // Check if we need the FAT32 workaround. // Check the filesystem type where the target will be written. if (cmLVS6G_IsFAT(target.GetDirectory(configName).c_str())) diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index ccb0974..90f679e 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -353,6 +353,8 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) useResponseFileForObjects, buildObjs, depends, useWatcomQuote); + std::string manifests = this->GetManifests(); + cmLocalGenerator::RuleVariables vars; vars.RuleLauncher = "RULE_LAUNCH_LINK"; vars.CMTarget = this->Target; @@ -391,6 +393,8 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) vars.LinkLibraries = linkLibs.c_str(); vars.Flags = flags.c_str(); vars.LinkFlags = linkFlags.c_str(); + vars.Manifests = manifests.c_str(); + // Expand placeholders in the commands. this->LocalGenerator->TargetImplib = targetOutPathImport; for(std::vector::iterator i = real_link_commands.begin(); diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index 2f995e8..cd387a0 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -616,6 +616,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules } } + std::string manifests = this->GetManifests(); + cmLocalGenerator::RuleVariables vars; vars.TargetPDB = targetOutPathPDB.c_str(); @@ -660,6 +662,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules } vars.LinkFlags = linkFlags.c_str(); + vars.Manifests = manifests.c_str(); + // Compute the directory portion of the install_name setting. std::string install_name_dir; if(this->Target->GetType() == cmTarget::SHARED_LIBRARY) diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index cf88a74..b278087 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -1493,6 +1493,15 @@ void cmMakefileTargetGenerator depends.push_back(this->ModuleDefinitionFile); } + // Add a dependency on user-specified manifest files, if any. + std::vector manifest_srcs; + this->GeneratorTarget->GetManifests(manifest_srcs, this->ConfigName); + for (std::vector::iterator mi = manifest_srcs.begin(); + mi != manifest_srcs.end(); ++mi) + { + depends.push_back((*mi)->GetFullPath()); + } + // Add user-specified dependencies. if(const char* linkDepends = this->Target->GetProperty("LINK_DEPENDS")) diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index f62f8ad..7e7e600 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -237,6 +237,7 @@ cmNinjaNormalTargetGenerator vars.Flags = "$FLAGS"; vars.LinkFlags = "$LINK_FLAGS"; + vars.Manifests = "$MANIFESTS"; std::string langFlags; if (targetType != cmTarget::EXECUTABLE) @@ -509,6 +510,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() vars["LINK_FLAGS"] = cmGlobalNinjaGenerator ::EncodeLiteral(vars["LINK_FLAGS"]); + vars["MANIFESTS"] = this->GetManifests(); + vars["LINK_PATH"] = frameworkPath + linkPath; // Compute architecture specific link flags. Yes, these go into a different diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 81fdde2..752c8a7 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -209,6 +209,15 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps() const result.push_back(this->ConvertToNinjaPath(this->ModuleDefinitionFile)); } + // Add a dependency on user-specified manifest files, if any. + std::vector manifest_srcs; + this->GeneratorTarget->GetManifests(manifest_srcs, this->ConfigName); + for (std::vector::iterator mi = manifest_srcs.begin(); + mi != manifest_srcs.end(); ++mi) + { + result.push_back(this->ConvertToNinjaPath((*mi)->GetFullPath())); + } + // Add user-specified dependencies. if (const char* linkDepends = this->Target->GetProperty("LINK_DEPENDS")) { diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 4c380f7..cb5048d 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -2203,6 +2203,33 @@ cmVisualStudio10TargetGenerator::WriteLibOptions(std::string const& config) } } +void cmVisualStudio10TargetGenerator::WriteManifestOptions( + std::string const& config) +{ + if (this->Target->GetType() != cmTarget::EXECUTABLE && + this->Target->GetType() != cmTarget::SHARED_LIBRARY && + this->Target->GetType() != cmTarget::MODULE_LIBRARY) + { + return; + } + + std::vector manifest_srcs; + this->GeneratorTarget->GetManifests(manifest_srcs, config); + if (!manifest_srcs.empty()) + { + this->WriteString("\n", 2); + this->WriteString("", 3); + for (std::vector::const_iterator + mi = manifest_srcs.begin(); mi != manifest_srcs.end(); ++mi) + { + std::string m = this->ConvertPath((*mi)->GetFullPath(), false); + this->ConvertToWindowsSlash(m); + (*this->BuildFileStream) << m << ";"; + } + (*this->BuildFileStream) << "\n"; + this->WriteString("\n", 2); + } +} //---------------------------------------------------------------------------- void cmVisualStudio10TargetGenerator::WriteAntBuildOptions( @@ -2740,6 +2767,8 @@ void cmVisualStudio10TargetGenerator::WriteItemDefinitionGroups() this->WriteLinkOptions(*i); // output lib flags this->WriteLibOptions(*i); + // output manifest flags + this->WriteManifestOptions(*i); if(this->NsightTegra && this->Target->GetType() == cmTarget::EXECUTABLE && this->Target->GetPropertyAsBool("ANDROID_GUI")) diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h index 451f8b2..5fadb60 100644 --- a/Source/cmVisualStudio10TargetGenerator.h +++ b/Source/cmVisualStudio10TargetGenerator.h @@ -111,6 +111,7 @@ private: void AddLibraries(cmComputeLinkInformation& cli, std::vector& libVec); void WriteLibOptions(std::string const& config); + void WriteManifestOptions(std::string const& config); void WriteEvents(std::string const& configName); void WriteEvent(const char* name, std::vector const& commands, diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index 307e78b..f44c77d 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -1362,6 +1362,7 @@ class cmVSLink bool Incremental; bool LinkGeneratesManifest; std::vector LinkCommand; + std::vector UserManifests; std::string LinkerManifestFile; std::string ManifestFile; std::string ManifestFileRC; @@ -1480,6 +1481,13 @@ bool cmVSLink::Parse(std::vector::const_iterator argBeg, ++arg; break; } + else if (*arg == "--manifests") + { + for (++arg; arg != argEnd && !cmHasLiteralPrefix(*arg, "-"); ++arg) + { + this->UserManifests.push_back(*arg); + } + } else if (cmHasLiteralPrefix(*arg, "--intdir=")) { intDir = arg->substr(9); @@ -1544,10 +1552,11 @@ bool cmVSLink::Parse(std::vector::const_iterator argBeg, this->ManifestFileRes = intDir + "/manifest.res"; this->LinkCommand.push_back(this->ManifestFileRes); } - else + else if (this->UserManifests.empty()) { - // CMake places the linker-generated manifest next to the binary (as if it - // were not to be embedded) when not linking incrementally. + // Prior to support for user-specified manifests CMake placed the + // linker-generated manifest next to the binary (as if it were not to be + // embedded) when not linking incrementally. Preserve this behavior. this->ManifestFile = this->TargetFile + ".manifest"; this->LinkerManifestFile = this->ManifestFile; } @@ -1564,7 +1573,7 @@ bool cmVSLink::Parse(std::vector::const_iterator argBeg, int cmVSLink::Link() { if (this->Incremental && - this->LinkGeneratesManifest) + (this->LinkGeneratesManifest || !this->UserManifests.empty())) { if (this->Verbose) { @@ -1688,7 +1697,7 @@ int cmVSLink::LinkNonIncremental() } // If we have no manifest files we are done. - if (!this->LinkGeneratesManifest) + if (!this->LinkGeneratesManifest && this->UserManifests.empty()) { return 0; } @@ -1709,6 +1718,8 @@ int cmVSLink::RunMT(std::string const& out, bool notify) { mtCommand.push_back(this->LinkerManifestFile); } + mtCommand.insert(mtCommand.end(), + this->UserManifests.begin(), this->UserManifests.end()); mtCommand.push_back(out); if (notify) { diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 2c6a42c..fff04ce 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -276,6 +276,7 @@ if(BUILD_TESTING) if(TEST_RESOURCES) ADD_TEST_MACRO(VSResource VSResource) endif() + ADD_TEST_MACRO(MSManifest MSManifest) ADD_TEST_MACRO(Simple Simple) ADD_TEST_MACRO(PreOrder PreOrder) ADD_TEST_MACRO(MissingSourceFile MissingSourceFile) diff --git a/Tests/MSManifest/CMakeLists.txt b/Tests/MSManifest/CMakeLists.txt new file mode 100644 index 0000000..300cfa6 --- /dev/null +++ b/Tests/MSManifest/CMakeLists.txt @@ -0,0 +1,5 @@ +cmake_minimum_required(VERSION 3.3) +project(MSManifest C) + +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) +add_subdirectory(Subdir) diff --git a/Tests/MSManifest/Subdir/CMakeLists.txt b/Tests/MSManifest/Subdir/CMakeLists.txt new file mode 100644 index 0000000..a47cf00 --- /dev/null +++ b/Tests/MSManifest/Subdir/CMakeLists.txt @@ -0,0 +1,9 @@ +configure_file(test.manifest.in test.manifest) +add_executable(MSManifest main.c ${CMAKE_CURRENT_BINARY_DIR}/test.manifest) + +if(MSVC AND NOT MSVC_VERSION LESS 1400) + add_custom_command(TARGET MSManifest POST_BUILD VERBATIM + COMMAND ${CMAKE_COMMAND} -Dexe=$ + -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake + ) +endif() diff --git a/Tests/MSManifest/Subdir/check.cmake b/Tests/MSManifest/Subdir/check.cmake new file mode 100644 index 0000000..b7b6841 --- /dev/null +++ b/Tests/MSManifest/Subdir/check.cmake @@ -0,0 +1,6 @@ +file(STRINGS "${exe}" content REGEX "name=\"Kitware.CMake.MSManifestTest\"") +if(content) + message(STATUS "Expected manifest content found:\n ${content}") +else() + message(FATAL_ERROR "Expected manifest content not found in\n ${exe}") +endif() diff --git a/Tests/MSManifest/Subdir/main.c b/Tests/MSManifest/Subdir/main.c new file mode 100644 index 0000000..78f2de1 --- /dev/null +++ b/Tests/MSManifest/Subdir/main.c @@ -0,0 +1 @@ +int main(void) { return 0; } diff --git a/Tests/MSManifest/Subdir/test.manifest.in b/Tests/MSManifest/Subdir/test.manifest.in new file mode 100644 index 0000000..540961a --- /dev/null +++ b/Tests/MSManifest/Subdir/test.manifest.in @@ -0,0 +1,4 @@ + + + diff --git a/Tests/RunCMake/BuildDepends/C-Exe-Manifest.cmake b/Tests/RunCMake/BuildDepends/C-Exe-Manifest.cmake new file mode 100644 index 0000000..ef33012 --- /dev/null +++ b/Tests/RunCMake/BuildDepends/C-Exe-Manifest.cmake @@ -0,0 +1,19 @@ +enable_language(C) + +add_executable(main main.c ${CMAKE_CURRENT_BINARY_DIR}/test.manifest) + +if(MSVC AND NOT MSVC_VERSION LESS 1400) + set(EXTRA_CHECK [[ +file(STRINGS "$" content REGEX "name=\"Kitware.CMake.C-Exe-Manifest-step[0-9]\"") +if(NOT "${content}" MATCHES "name=\"Kitware.CMake.C-Exe-Manifest-step${check_step}\"") + set(RunCMake_TEST_FAILED "Binary has no manifest with name=\"Kitware.CMake.C-Exe-Manifest-step${check_step}\":\n ${content}") +endif() +]]) +endif() + +file(GENERATE OUTPUT check-$>.cmake CONTENT " +set(check_pairs + \"$|${CMAKE_CURRENT_BINARY_DIR}/test.manifest\" + ) +${EXTRA_CHECK} +") diff --git a/Tests/RunCMake/BuildDepends/C-Exe-Manifest.step1.cmake b/Tests/RunCMake/BuildDepends/C-Exe-Manifest.step1.cmake new file mode 100644 index 0000000..c0b939d --- /dev/null +++ b/Tests/RunCMake/BuildDepends/C-Exe-Manifest.step1.cmake @@ -0,0 +1,6 @@ +file(WRITE "${RunCMake_TEST_BINARY_DIR}/test.manifest" [[ + + + +]]) diff --git a/Tests/RunCMake/BuildDepends/C-Exe-Manifest.step2.cmake b/Tests/RunCMake/BuildDepends/C-Exe-Manifest.step2.cmake new file mode 100644 index 0000000..a75bf21 --- /dev/null +++ b/Tests/RunCMake/BuildDepends/C-Exe-Manifest.step2.cmake @@ -0,0 +1,6 @@ +file(WRITE "${RunCMake_TEST_BINARY_DIR}/test.manifest" [[ + + + +]]) diff --git a/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake b/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake index 98132cc..8782ba9 100644 --- a/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake +++ b/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake @@ -14,6 +14,9 @@ function(run_BuildDepends CASE) set(RunCMake-check-file check.cmake) set(check_step 1) run_cmake_command(${CASE}-build1 ${CMAKE_COMMAND} --build . --config Debug) + if(run_BuildDepends_skip_step_2) + return() + endif() execute_process(COMMAND ${CMAKE_COMMAND} -E sleep 1.125) # handle 1s resolution include(${RunCMake_SOURCE_DIR}/${CASE}.step2.cmake OPTIONAL) set(check_step 2) @@ -21,3 +24,11 @@ function(run_BuildDepends CASE) endfunction() run_BuildDepends(C-Exe) +if(NOT RunCMake_GENERATOR MATCHES "Visual Studio [67]|Xcode") + if(RunCMake_GENERATOR MATCHES "Visual Studio 10") + # VS 10 forgets to re-link when a manifest changes + set(run_BuildDepends_skip_step_2 1) + endif() + run_BuildDepends(C-Exe-Manifest) + unset(run_BuildDepends_skip_step_2) +endif() diff --git a/Tests/RunCMake/BuildDepends/check.cmake b/Tests/RunCMake/BuildDepends/check.cmake index be6debc..26a9eb6 100644 --- a/Tests/RunCMake/BuildDepends/check.cmake +++ b/Tests/RunCMake/BuildDepends/check.cmake @@ -1,5 +1,8 @@ if(EXISTS ${RunCMake_TEST_BINARY_DIR}/check-debug.cmake) include(${RunCMake_TEST_BINARY_DIR}/check-debug.cmake) + if(RunCMake_TEST_FAILED) + return() + endif() foreach(exe IN LISTS check_exes) execute_process(COMMAND ${exe} RESULT_VARIABLE res) if(NOT res EQUAL ${check_step}) diff --git a/Tests/RunCMake/BuildDepends/main.c b/Tests/RunCMake/BuildDepends/main.c new file mode 100644 index 0000000..78f2de1 --- /dev/null +++ b/Tests/RunCMake/BuildDepends/main.c @@ -0,0 +1 @@ +int main(void) { return 0; } -- cgit v0.12