我怎样才能embedded一个具有CMake构build的Windows DLL中的特定清单文件?

所以我有一个正在使用CMake构build的DLL,需要embedded一个特定的清单文件。 在Visual Studio设置中,我可以在Manifest Tool / Input和Ouput / Additional Manifest Files下添加清单文件名,并且它可以正常工作。 看起来这是CMake应该可以做到的事情,但我一直无法弄清楚。

任何想法,我怎么可以用CMake完成这个?

Solutions Collecting From Web of "我怎样才能embedded一个具有CMake构build的Windows DLL中的特定清单文件?"

cmake-3.4现在已经学会了如何处理被列为源文件的* .manifest文件。

https://cmake.org/cmake/help/v3.4/release/3.4.html#other

在CMake中生成Additional Manifest Files字段是不可能的(我检查了源代码)。 所以我们必须偷偷摸摸

Visual生成一个自己的清单(yourapp.exe.manifest.intermediate)并将其与您的文件混合。 所以我们必须生成一次该清单,禁用生成,然后使用生成的清单。

生成清单:

如果您知道如何自行编写完整的清单,则此步骤是可选的。 如果你像世界其他地方一样:

  • 像往常一样创建自己的清单
  • 将其添加到界面( Additional Manifest Files
  • 重新编译,重新链接
  • 找到yourapp.exe.manifest(在.exe旁边)。 将其复制到您的源代码目录并进行版本化。 不要犹豫,重新命名,如yourapp.final.manifest,如果它更清晰

禁用代:

 IF( WIN32 ) SET ( CMAKE_SHARED_LINKER_FLAGS /MANIFEST:NO ) ENDIF( WIN32 ) 

之后使用生成的清单:

这是通过手动调用mt.exe(通常在链接器之后调用的清单工具,除非它被禁用)在后构建步骤中完成:

 add_custom_command( TARGET YourApp POST_BUILD COMMAND "mt.exe" -manifest \"$(TargetDir)\\yourapp.final.manifest\" -outputresource:"$(TargetDir)$(TargetFileName)"\;\#1 COMMENT "Adding manifest..." ) 

(您可能需要将$(TargetDir)更改为$(OutDir),具体取决于您如何编写CMake;使用Visual的Macros按钮来查看它们的值,请记住:#1为可执行文件,#2为dll)

我发现你可以使用mt.exe将多个清单文件(或可执行文件中的嵌入式清单)合并到一个现有清单文件(或可执行文件)中。 这样,您不必禁用视觉工作室的自动清单生成。 您可以添加新的清单数据与mt.exe作为后构建步骤。 例:

program.exe嵌入了清单:

 <?xml version="1.0"?> <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <dependency> <dependentAssembly> <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="amd64" publicKeyToken="6595b64144ccf1df" language="*"/> </dependentAssembly> </dependency> <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"> <security> <requestedPrivileges> <requestedExecutionLevel level="asInvoker" uiAccess="false"/> </requestedPrivileges> </security> </trustInfo> </assembly> 

dpiaware.manifest包含:

 <?xml version="1.0"?> <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <application xmlns="urn:schemas-microsoft-com:asm.v3"> <windowsSettings> <ms_windowsSettings:dpiAware xmlns:ms_windowsSettings="http://schemas.microsoft.com/SMI/2005/WindowsSettings" xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</ms_windowsSettings:dpiAware> </windowsSettings> </application> </assembly> 

运行命令:

 mt.exe -manifest dpiaware.manifest "-inputresource:program.exe;#1" -outputresource:program.exe;#1 

现在program.exe包含嵌入式清单:

 <?xml version="1.0"?> <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <dependency> <dependentAssembly> <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="amd64" publicKeyToken="6595b64144ccf1df" language="*"/> </dependentAssembly> </dependency> <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"> <security> <requestedPrivileges> <requestedExecutionLevel level="asInvoker" uiAccess="false"/> </requestedPrivileges> </security> </trustInfo> <application xmlns="urn:schemas-microsoft-com:asm.v3"> <windowsSettings> <ms_windowsSettings:dpiAware xmlns:ms_windowsSettings="http://schemas.microsoft.com/SMI/2005/WindowsSettings" xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</ms_windowsSettings:dpiAware> </windowsSettings> </application> </assembly> 

只是自己做了这个练习,这就是把我带到这个页面的原因。 Calvin1602的回答很好的解决了这个问题,但是为了使它适合于我,我不得不简单地修改语法。 下面是最终工作的确切命令:

 if (WIN32) set(CMAKE_SHARED_LINKER_FLAGS /MANIFEST:NO) endif() add_custom_command(TARGET odrmanager POST_BUILD COMMAND "mt.exe" -manifest \"${CMAKE_CURRENT_SOURCE_DIR}\\odrmanager.dll.manifest\" -outputresource:\"${CMAKE_CURRENT_BINARY_DIR}\\odrmanager\\odrmanager.dll\"\;\#2 COMMENT "Adding custom manifest containing MSVCRT80 dependency..." ) 

注意,当目标是一个应用程序时,你应该在mt.exe命令中使用#1 ;当它是一个DLL时,应该使用#1 (至少据我了解 – 它不适用于我,除非我改变12 )。

另外,如果需要,可以使用mt.exe从DLL中提取原始清单。 该命令如下所示:

 mt -inputresource:odrmanager.dll;#2 -out:odrmanager.manifest 

如果你有一个你要合并的依赖关系的清单文件,手动编辑输出并不难。但是我喜欢Calvin1602的技巧,让Visual Studio为你做,如果你使用的是Visual Studio解决方案文件,而不是NMAKE。

这非常有帮助。 以下是我最终要做的一个需要MSVCR90清单的DLL,你的里程可能会有所不同:

 add_custom_command( TARGET foo POST_BUILD COMMAND mt.exe -manifest \"${MYDEPDIR}/msvcr90/Microsoft.VC90.CRT.manifest\" "-inputresource:\"${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/foo.dll\";#2" -outputresource:\"${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/foo.dll\";#2 COMMENT "Appending manifest for MSVCRT90 dependency." )