tutorial online how español descarga c++ cmake

c++ - online - descarga cmake



cmake: incluye las dependencias de la biblioteca en lib estático (2)

Estoy creando una biblioteca estática en cmake, que depende de muchas otras bibliotecas estáticas. Me gustaría que todos se incluyeran en el archivo de salida .lib / .a, para poder enviar un gran archivo lib a los clientes. En VS2010 hay una opción "Vincular dependencias de biblioteca" que hace exactamente esto.

Pero no puedo encontrar cómo hacerlo en cmake. ¿Puedes establecer esta bandera a través de cmake, u obtener el mismo resultado de otra manera? He intentado target_link_libraries (...) y también add_dependencies (...) pero cmake parece simplemente ignorar esta línea para las librerías estáticas


Me gustaría mejorar las otras soluciones al proporcionar mi archivo CMakeLists.txt que también funciona en términos de dependencias de construcción.

Solución mal uso de CMake

cmake_minimum_required(VERSION 2.8) add_library(lib1 test1.cpp) add_library(lib2 test2.cpp) include_directories(${CMAKE_CURRENT_DIR}) add_executable(mainexec main.cpp) target_link_libraries(mainexec combinedLib) # Important to place before add_custom_target set(LIBNAME "combinedLib.lib") add_custom_command( OUTPUT ${LIBNAME} COMMAND lib.exe /OUT:${LIBNAME} $<TARGET_FILE:lib1> $<TARGET_FILE:lib2> DEPENDS lib1 lib2 COMMENT "Combining libs..." ) add_custom_target(combinedLib DEPENDS ${LIBNAME} )

Tenga en cuenta que esta solución funciona hasta ahora con Visual Studio, pero creo que puede ser compatible con múltiples plataformas. Puedo imaginar que la siguiente versión podría funcionar para plataformas basadas en Unix:

set(LIBNAME "libCombinedLib.a") add_custom_command( OUTPUT ${LIBNAME} COMMAND ar -rcT ${LIBNAME} $<TARGET_FILE:lib1> $<TARGET_FILE:lib2> DEPENDS lib1 lib2 COMMENT "Combining libs..." )

Tenga en cuenta que estas soluciones de alguna manera hacen un mal uso de CMake, ya que se quejaría de un objetivo de tipo UTILITY (en lugar de STATIC o SHARED) si coloca la llamada target_link_libraries después de la declaración add_custom_target .

Solución compatible con la declaración de objetivos de CMake

Para hacerlo compatible, puede reemplazar la llamada `target_link_libraries ''por

target_link_libraries(mainexec ${LIBNAME}) add_dependencies(mainexec combinedLib)

En mi caso, no es del todo satisfactorio porque mainexec tiene que saber sobre combinedLib aunque espera que todas las dependencias sean manejadas por la llamada target_link_libraries .

Solución alternativa con menos acoplamiento.

Mirando un poco más hacia objetivos importados, encontré una solución que resuelve mi último problema:

cmake_minimum_required(VERSION 2.8) add_library(lib1 test1.cpp) add_library(lib2 test2.cpp) include_directories(${CMAKE_CURRENT_DIR}) add_executable(mainexec main.cpp) set(LIBNAME "combinedLib.lib") add_custom_command( OUTPUT ${LIBNAME} COMMAND lib.exe /OUT:${LIBNAME} $<TARGET_FILE:lib1> $<TARGET_FILE:lib2> DEPENDS lib1 lib2 COMMENT "Combining libs..." ) add_custom_target(combinedLibGenerator DEPENDS ${LIBNAME} ) add_library(combinedLib STATIC IMPORTED) set_property(TARGET combinedLib PROPERTY IMPORTED_LOCATION ${LIBNAME}) add_dependencies(combinedLib combinedLibGenerator) target_link_libraries(mainexec combinedLib)

Si tiene la intención de modularizar todo, añada GLOBAL después de STATIC IMPORTED para que el destino importado sea visible globalmente.

Solución CMake portátil

Con las versiones actuales de CMake, CMake proporciona soporte completo para dependencias transitivas y bibliotecas de interfaz. Una biblioteca de interfaz puede entonces "vincularse" con otras bibliotecas y esta biblioteca de interfaz puede, a su vez, "vincularse" con. ¿Por qué comillas? Si bien esto funciona bien, en realidad no crea una biblioteca física combinada, sino que crea una especie de alias para el conjunto de "sub-libs". Aún así, esta era la solución que eventualmente necesitábamos, por lo que quería agregarla aquí.

add_library(combinedLib INTERFACE) target_link_libraries(combinedLib INTERFACE lib1 lib2) target_link_libraries(mainexec combinedLib)

¡Eso es!


Está bien, así que tengo una solución. Primero, es importante reconocer que las bibliotecas estáticas no vinculan otras bibliotecas estáticas en el código. Se debe crear una biblioteca combinada, que en linux se puede hacer con ar . Consulte Vincular bibliotecas estáticas a otras bibliotecas estáticas para obtener más información allí.

Considere dos archivos de origen:

test1.c:

int hi() { return 0; }

test2.c:

int bye() { return 1; }

El CMakeLists.txt para crear dos bibliotecas y luego crear una biblioteca combinada se ve así:

proyecto (test)

add_library(lib1 STATIC test1.c) add_library(lib2 STATIC test2.c) add_custom_target(combined ALL COMMAND ${CMAKE_AR} rc libcombined.a $<TARGET_FILE:lib1> $<TARGET_FILE:lib2>)

Las opciones para el comando ar dependen de la plataforma en este caso, aunque la variable CMAKE_AR es independiente de la plataforma. Hojearé para ver si hay una forma más general de hacer esto, pero este enfoque funcionará en sistemas que usan ar .

Editar:

Basado en Cómo configurar las opciones para CMAKE_AR , parece que la mejor manera de hacerlo sería:

add_custom_target(combined ALL COMMAND ${CMAKE_CXX_ARCHIVE_CREATE} libcombined.a $<TARGET_FILE:lib1> $<TARGET_FILE:lib2>)

Esto debería ser independiente de la plataforma porque esta es la estructura de comando utilizada para crear archivos internamente por CMake. Por supuesto, las únicas opciones que desea pasar a su comando de archivo son rc ya que están incorporadas en CMake para el comando ar .