diff --git a/Modules/Platform/Windows-MSVC.cmake b/Modules/Platform/Windows-MSVC.cmake index 189d1fd5a2..0530441d9d 100644 --- a/Modules/Platform/Windows-MSVC.cmake +++ b/Modules/Platform/Windows-MSVC.cmake @@ -357,8 +357,8 @@ unset(__WINDOWS_MSVC_CMP0141) 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= --rc= --mt= --manifests -- ") - set(_CMAKE_VS_LINK_EXE " -E vs_link_exe --intdir= --rc= --mt= --manifests -- ") + set(_CMAKE_VS_LINK_DLL " -E vs_link_dll --msvc-ver=${MSVC_VERSION} --intdir= --rc= --mt= --manifests -- ") + set(_CMAKE_VS_LINK_EXE " -E vs_link_exe --msvc-ver=${MSVC_VERSION} --intdir= --rc= --mt= --manifests -- ") endif() if(CMAKE_SYSTEM_NAME STREQUAL "WindowsKernelModeDriver") set(_DLL_DRIVER "-driver") diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index eaff8efc34..c6d89bdeec 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -2130,6 +2130,7 @@ class cmVSLink int Type; bool Verbose; bool Incremental = false; + bool LinkEmbedsManifest = true; bool LinkGeneratesManifest = true; std::vector LinkCommand; std::vector UserManifests; @@ -2284,6 +2285,12 @@ bool cmVSLink::Parse(std::vector::const_iterator argBeg, } else if (cmHasLiteralPrefix(*arg, "--mt=")) { this->MtPath = arg->substr(5); ++arg; + } else if (cmHasLiteralPrefix(*arg, "--msvc-ver=")) { + unsigned long msvc_ver = 0; + if (cmStrToULong(arg->c_str() + 11, &msvc_ver)) { + this->LinkEmbedsManifest = msvc_ver > 1600; + } + ++arg; } else { std::cerr << "unknown argument '" << *arg << "'\n"; return false; @@ -2333,11 +2340,13 @@ bool cmVSLink::Parse(std::vector::const_iterator argBeg, // pass it to the link command. this->ManifestFileRC = intDir + "/manifest.rc"; this->ManifestFileRes = intDir + "/manifest.res"; + } - if (this->LinkGeneratesManifest) { - this->LinkCommand.emplace_back("/MANIFEST"); - this->LinkCommand.push_back("/MANIFESTFILE:" + this->LinkerManifestFile); - } + if (this->LinkGeneratesManifest && + (this->Incremental || !this->LinkEmbedsManifest)) { + this->LinkCommand.emplace_back("/MANIFEST"); + this->LinkCommand.emplace_back("/MANIFESTFILE:" + + this->LinkerManifestFile); } return true; @@ -2471,6 +2480,24 @@ int cmVSLink::LinkIncremental() int cmVSLink::LinkNonIncremental() { + if (!this->LinkEmbedsManifest) { + // Run the link command (possibly generates intermediate manifest). + if (!RunCommand("LINK", this->LinkCommand, this->Verbose, + FORMAT_DECIMAL)) { + return -1; + } + + // If we have no manifest files we are done. + if (!this->LinkGeneratesManifest && this->UserManifests.empty()) { + return 0; + } + + // Run the manifest tool to embed the final manifest in the binary. + std::string mtOut = "/outputresource:" + this->TargetFile + + (this->Type == 1 ? ";#1" : ";#2"); + return this->RunMT(mtOut, false); + } + // The MSVC link tool expects 'rc' to be in the PATH if it needs to embed // manifests, but the user might explicitly set 'CMAKE_RC_COMPILER' instead. // Add its location as a fallback at the end of PATH. diff --git a/Tests/MSManifest/Subdir2/check.cmake b/Tests/MSManifest/Subdir2/check.cmake index 4a1705bef5..385190b8dc 100644 --- a/Tests/MSManifest/Subdir2/check.cmake +++ b/Tests/MSManifest/Subdir2/check.cmake @@ -14,7 +14,7 @@ else() endif() # Verify Third Manifest Content is inside Executable. -file(STRINGS "${exe}" manifest_content3 REGEX "true") +file(STRINGS "${exe}" manifest_content3 REGEX "PerMonitorV2") if(manifest_content3) message(STATUS "Expected manifest content found:\n ${manifest_content3}") else()