所以我有一個正在使用CMake構建的DLL,需要嵌入特定的清單文件。在Visual Studio設置中,我可以在Manifest Tool/Input和Ouput/Additional Manifest Files下添加清單文件名,並且它可以正常工作。看起來這是CMake應該可以實現的,但我一直無法弄清楚。如何使用CMake構建將特定清單文件嵌入到Windows DLL中?
有關我如何用CMake完成此任務的任何想法?
所以我有一個正在使用CMake構建的DLL,需要嵌入特定的清單文件。在Visual Studio設置中,我可以在Manifest Tool/Input和Ouput/Additional Manifest Files下添加清單文件名,並且它可以正常工作。看起來這是CMake應該可以實現的,但我一直無法弄清楚。如何使用CMake構建將特定清單文件嵌入到Windows DLL中?
有關我如何用CMake完成此任務的任何想法?
不可能在CMake中生成Additional Manifest Files
字段(我檢查了源代碼)。所以我們必須偷偷摸摸。
Visual會生成自己的清單(yourapp.exe.manifest.intermediate)並將其與您的文件混合。 所以我們必須生成一次該清單,禁用生成,然後使用生成的清單。
生成清單:
這一步是可選的,如果你知道如何去寫一個完整的清單。如果你像世界其他地區:
Additional Manifest Files
)禁用代:
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)
我只是我自己經歷了這個練習,這是將我帶到這個頁面的原因。 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
,並#2
當它是一個DLL(至少,據我瞭解它 - - 直到我將1
更改爲2
),它才適用於我。
此外,如果您需要,您可以使用mt.exe
從DLL中提取原始清單。命令如下:
mt -inputresource:odrmanager.dll;#2 -out:odrmanager.manifest
這不是太難,如果你有你想在合併的依賴清單文件手工編輯的輸出,但我有點兒像有Visual Studio中的Calvin1602的把戲做到這一點。如果你使用的是Visual Studio解決方案文件而不是nmake。
我剛剛發現你可以用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>
這非常有幫助。下面是我落得這樣做對於需要一個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."
)
的cmake-3.4現在已經學會了如何處理*列爲源文件.manifest文件。