Как я могу встроить определенный файл манифеста в Windows DLL с помощью сборки CMake? - PullRequest
9 голосов
/ 13 июня 2011

Итак, у меня есть библиотека DLL, которая создается с помощью CMake, для которой требуется встроенный файл манифеста.В настройках Visual Studio я могу просто добавить имя файла манифеста в «Инструмент манифеста» и «Ввод» и «Дополнительные файлы манифеста», и оно работает правильно.Похоже, что это то, что должно быть выполнимо с CMake, но я не смог понять это.

Есть какие-нибудь идеи о том, как я могу сделать это с CMake?

Ответы [ 5 ]

13 голосов
/ 29 декабря 2015

cmake-3.4 теперь научился обрабатывать файлы * .manifest, перечисленные как исходные файлы.

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

8 голосов
/ 02 декабря 2011

Невозможно создать поле Additional Manifest Files в CMake (я проверил исходный код). Поэтому мы должны быть хитрее.

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 для DLLs)

4 голосов
/ 13 января 2014

Я только что обнаружил, что вы можете объединить несколько файлов манифеста (или встроенных манифестов внутри исполняемых файлов) в существующий файл манифеста (или исполняемый файл) с 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>
2 голосов
/ 08 марта 2012

Я просто сам прошел это упражнение, что и привело меня на эту страницу.Ответ 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..." 
                  )

Обратите внимание, что вы должны использовать #1 в команде mt.exe, когда целью является приложение, и #2, когда это DLL (по крайней мере,Насколько я понимаю, у меня не получалось, пока я не изменил 1 на 2).

Также вы можете использовать mt.exe для извлечения исходного манифеста изDLL, если вы хотите / нужно.Команда выглядит следующим образом:

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

Нетрудно вручную отредактировать вывод, если у вас есть файл манифеста для зависимости, в которую вы хотите объединить. Но мне нравится трюк Calvin1602 с Visual Studioсделайте это за вас, если вы используете файлы решений Visual Studio, а не nmake.

0 голосов
/ 20 июня 2014

Это было очень полезно. Вот что я в итоге сделал для DLL, которая требовала манифеста MSVCR90, ваш пробег может отличаться:

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."
)
...