【问题标题】:How can I embed a specific manifest file in a Windows DLL with a CMake build?如何使用 CMake 构建将特定清单文件嵌入到 Windows DLL 中?
【发布时间】:2023-04-02 20:33:01
【问题描述】:

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

关于如何使用 CMake 完成此任务的任何想法?

【问题讨论】:

    标签: windows cmake manifest


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

      在 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)

      【讨论】:

        【解决方案3】:

        我刚刚发现您可以使用 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>
        

        【讨论】:

          【解决方案4】:

          刚刚自己完成了这个练习,这就是我来到这个页面的原因。 Calvin1602's answer几乎列出了解决方案,但我不得不稍微修改语法以使其适合我。以下是最终起作用的确切命令:

          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)。

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

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

          如果您有要合并的依赖项的清单文件,手动编辑输出并不难。但是如果您使用 Visual Studio 解决方案,我有点喜欢 Calvin1602 让 Visual Studio 为您完成的技巧文件而不是 nmake。

          【讨论】:

            【解决方案5】:

            这很有帮助。这是我最终为需要 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."
            )
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-07-30
              相关资源
              最近更新 更多