2011-06-13 159 views
9

所以我有一個正在使用CMake構建的DLL,需要嵌入特定的清單文件。在Visual Studio設置中,我可以在Manifest Tool/Input和Ouput/Additional Manifest Files下添加清單文件名,並且它可以正常工作。看起來這是CMake應該可以實現的,但我一直無法弄清楚。如何使用CMake構建將特定清單文件嵌入到Windows DLL中?

有關我如何用CMake完成此任務的任何想法?

回答

7

不可能在CMake中生成Additional Manifest Files字段(我檢查了源代碼)。所以我們必須偷偷摸摸。

Visual會生成自己的清單(yourapp.exe.manifest.intermediate)並將其與您的文件混合。 所以我們必須生成一次該清單,禁用生成,然後使用生成的清單。

生成清單:

這一步是可選的,如果你知道如何去寫一個完整的清單。如果你像世界其他地區:

  • 創建自己的表現和往常一樣
  • 它添加在接口(Additional Manifest Files
  • 重新編譯,連接
  • 找到yourapp.exe.manifest(在你的.exe旁邊)。將其複製到您的sources目錄並進行版本化。不要猶豫,將其重命名,像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)

2

只是我自己經歷了這個練習,這是將我帶到這個頁面的原因。 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。

3

我剛剛發現你可以用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> 
0

這非常有幫助。下面是我落得這樣做對於需要一個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." 
) 
相關問題