2011-06-13 16 views
9

Tengo una DLL que se está creando con CMake que requiere que se incruste un archivo de manifiesto específico. En la configuración de Visual Studio, puedo agregar el nombre del archivo de manifiesto en Manifest Tool/Input y Ouput/Additional Manifest Files, y funciona correctamente. Parece que esto es algo que debería ser factible con CMake, pero no he podido descifrarlo.¿Cómo puedo incrustar un archivo de manifiesto específico en una DLL de Windows con una compilación CMake?

¿Alguna idea sobre cómo puedo lograr esto con CMake?

Respuesta

7

No es posible generar el campo Additional Manifest Files en CMake (Comprobé el código fuente). Entonces tenemos que ser más astutos.

Visual genera un manifiesto propio (yourapp.exe.manifest.intermediate) y lo mezcla con el suyo. Entonces, tenemos que generar este manifiesto una vez, inhabilitar la generación y usar el manifiesto generado después.

Generando el manifiesto:

Este paso es opcional si usted sabe cómo escribir un manifiesto completo por sí mismo. Si usted es como el resto del mundo:

  • Crear su propio manifiesto, como de costumbre
  • Añádelo en la interfaz (Additional Manifest Files)
  • recompilación, volver a vincular
  • Localizar YourApp.exe.manifest (al lado de tu .exe). Cópielo en su directorio de fuentes y vuélvalo a versionar. No dude en cambiar el nombre de ella, como yourapp.final.manifest, si es más claro para usted

Desactivación de la generación:

IF(WIN32) 
    SET (CMAKE_SHARED_LINKER_FLAGS /MANIFEST:NO) 
ENDIF(WIN32) 

Usando el manifiesto generado después:

Esto se hace mediante una llamada manual a mt.exe (la herramienta de manifiesto que normalmente se llama después del vinculador ... a menos que esté deshabilitada) en un paso posterior a la compilación:

add_custom_command(
    TARGET YourApp 
    POST_BUILD 
    COMMAND "mt.exe" -manifest \"$(TargetDir)\\yourapp.final.manifest\" -outputresource:"$(TargetDir)$(TargetFileName)"\;\#1 
    COMMENT "Adding manifest..." 
) 

(Probablemente necesite cambiar $ (TargetDir) a $ (OutDir) dependiendo de cómo haya escrito su CMake; Use el botón Visual Macros para ver sus valores. Y recuerde: # 1 para ejecutables, # 2 para dlls)

2

I solo realicé este ejercicio yo mismo, que es lo que me trajo a esta página. La respuesta de Calvin1602 establece la solución, pero tuve que arreglar un poco la sintaxis para que funcione. Estos son los comandos exactos que finalmente funcionó:

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

Tenga en cuenta que debe usar #1 en el comando mt.exe cuando el objetivo es una aplicación y #2 cuando es una DLL (al menos, en lo que a entender IT- -No funcionó para mí hasta que cambié el 1 a un 2.

Además, puede usar mt.exe para extraer el manifiesto original de la DLL si lo desea/necesita.El comando es el siguiente:

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

No es demasiado difícil de editar a mano la salida si usted tiene un archivo de manifiesto de la dependencia que desea combinar en Pero sorta como truco de tener Visual Studio de Calvin1602 hacerlo. para ti si estás usando archivos de solución de Visual Studio en lugar de nmake.

3

Acabo de descubrir que puede unir varios archivos de manifiesto (o manifiestos incrustados dentro de ejecutables) en un archivo manifiesto existente (o ejecutable) con mt.exe. De esta forma, no tiene que deshabilitar la generación automática de manifiestos de visual studio. Puede simplemente agregar nuevos datos de manifiesto con mt.exe como un paso posterior a la compilación. Ejemplo:

program.exe manifiesta ha incrustado:

<?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 contiene: comando

<?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> 

Run:

mt.exe -manifest dpiaware.manifest "-inputresource:program.exe;#1" -outputresource:program.exe;#1 

manifiesta Ahora program.exe contiene incrustado:

<?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

Esto fue muy útil. Esto es lo que terminé haciendo un DLL que necesita un manifiesto msvcr90, su experiencia puede variar:

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