estatica - ¿Es posible hacer que CMake cree una versión estática y compartida de la misma biblioteca?
biblioteca estatica (4)
De hecho es posible. Como dijo @Christopher Bruns en su respuesta, debe agregar dos versiones de la biblioteca:
set(libsrc source1.c source2.c source3.c)
add_library(mylib-static STATIC ${libsrc})
add_library(mylib-shared SHARED ${libsrc})
Luego, como se describe here , debe especificar que ambos objetivos deben usar el mismo nombre de salida y no sobrescribir los archivos de los demás:
SET_TARGET_PROPERTIES(mylib-static PROPERTIES OUTPUT_NAME mylib CLEAN_DIRECT_OUTPUT 1)
SET_TARGET_PROPERTIES(mylib-shared PROPERTIES OUTPUT_NAME mylib CLEAN_DIRECT_OUTPUT 1)
De esta forma, obtendrá libmylib.a y libmylib.so (en Linux) o mylib.lib y mylib.dll (en Windows).
La misma fuente, todo eso, solo quiere una versión estática y compartida ambas. ¿Fácil de hacer?
Desde CMake versión 2.8.8, puede usar "bibliotecas de objetos" para evitar la compilación duplicada de los archivos objeto . Usando el ejemplo de Christopher Bruns de una biblioteca con dos archivos fuente:
# list of source files
set(libsrc source1.c source2.c)
# this is the "object library" target: compiles the sources only once
add_library(objlib OBJECT ${libsrc})
# shared libraries need PIC
set_property(TARGET objlib PROPERTY POSITION_INDEPENDENT_CODE 1)
# shared and static libraries built from the same object files
add_library(MyLib_shared SHARED $<TARGET_OBJECTS:objlib>)
add_library(MyLib_static STATIC $<TARGET_OBJECTS:objlib>)
De los documentos CMake :
Una biblioteca de objetos compila los archivos fuente, pero no archiva ni vincula sus archivos de objeto en una biblioteca. En cambio, otros objetivos creados por add_library () o add_executable () pueden hacer referencia a los objetos utilizando una expresión del formulario $ como fuente, donde objlib es el nombre de la biblioteca de objetos.
En pocas palabras, el add_library(objlib OBJECT ${libsrc})
instruye a CMake para que compile los archivos fuente en archivos de objetos *.o
. Esta colección de archivos *.o
se conoce como $<TARGET_OBJECT:objlib>
en los dos add_library(...)
que invocan los comandos de creación de biblioteca apropiados que crean las bibliotecas estáticas y compartidas del mismo conjunto de archivos de objeto. Si tiene muchos archivos fuente, entonces la compilación de los archivos *.o
puede llevar bastante tiempo; con bibliotecas de objetos las compila solo una vez.
El precio que paga es que los archivos de objeto se deben compilar como código independiente de posición porque las bibliotecas compartidas lo necesitan (a las bibliotecas estáticas no les importa). Tenga en cuenta que el código independiente de la posición puede ser menos eficiente, por lo que si busca un rendimiento máximo, entonces optará por las bibliotecas estáticas. Además, es más fácil distribuir ejecutables vinculados estáticamente.
En general, no es necesario duplicar las llamadas ADD_LIBRARY para su propósito. Solo haz uso de
$> man cmake | grep -A6 ''^ *BUILD_SHARED_LIBS$''
BUILD_SHARED_LIBS
Global flag to cause add_library to create shared libraries if on.
If present and true, this will cause all libraries to be built shared unless the library was
explicitly added as a static library. This variable is often added to projects as an OPTION
so that each user of a project can decide if they want to build the project using shared or
static libraries.
mientras construyes primero (en un directorio fuera de la fuente) con -DBUILD_SHARED_LIBS: BOOL = ON y con OFF en el otro
Sí, es moderadamente fácil. Simplemente use dos comandos "add_library":
add_library(MyLib SHARED source1.c source2.c)
add_library(MyLibStatic STATIC source1.c source2.c)
Incluso si tiene muchos archivos fuente, colocaría la lista de fuentes en una variable cmake, por lo que aún es fácil de hacer.
En Windows, probablemente debas darle a cada biblioteca un nombre diferente, ya que hay un archivo ".lib" para compartir y estático. Pero en Linux y Mac puede incluso darles el mismo nombre a ambas bibliotecas (por ejemplo, libMyLib.a y libMyLib.so):
set_target_properties(MyLibStatic PROPERTIES OUTPUT_NAME MyLib)
Pero no recomiendo otorgar el mismo nombre a las versiones estática y dinámica de la biblioteca. Prefiero usar nombres diferentes porque eso hace que sea más fácil elegir enlaces estáticos o dinámicos en la línea de compilación para herramientas que se vinculan a la biblioteca. Por lo general, elijo nombres como libMyLib.so (compartido) y libMyLib_static.a (estático). (Esos serían los nombres en Linux.)