问题描述
|
因此,我有一个使用CMake构建的DLL,该DLL需要嵌入特定的清单文件。在Visual Studio设置中,我只需在清单工具/输入和Ouput /附加清单文件下添加清单文件名,即可正常工作。看起来这是应该使用CMake可以实现的功能,但是我一直无法弄清楚。
关于如何使用CMake完成此操作的任何想法?
解决方法
cmake-3.4现在已经学习了如何处理* .manifest文件作为源文件列出。
https://cmake.org/cmake/help/v3.4/release/3.4.html#other
, 无法在CMake中生成“ 0”字段(我检查了源代码)。因此,我们必须更加狡猾。
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...\"
)
(根据编写CMake的方式,您可能需要将$(TargetDir)更改为$(OutDir);使用Visual \的Macros
按钮查看其值。请记住:#1用于可执行文件,#2用于dll。 )
, 我刚刚发现,您可以使用mt.exe将多个清单文件(或可执行文件中嵌入的清单)合并到现有清单文件(或可执行文件)中。这样,您不必禁用Visual Studio的自动清单生成。您可以使用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时应在#2
中使用(至少,据我所知,它对我不起作用,直到我更改了1
到2
)。
另外,如果需要,可以使用ѭ11来从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.\"
)