¿Es posible hacer que CMake cree una versión estática y compartida de la misma biblioteca?

La misma fuente, todo eso, solo quiere una versión estática y compartida ambas. ¿Fácil de hacer?

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 fonts 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 dynamics en la línea de comstackció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.)

Desde CMake versión 2.8.8, puede usar “bibliotecas de objetos” para evitar la comstackció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 $) add_library(MyLib_static STATIC $) 

De los documentos CMake :

Una biblioteca de objetos comstack los archivos fuente, pero no archiva ni vincula sus archivos de objeto en una biblioteca. En cambio, otros objectives 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 $ 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 comstackción de los archivos *.o puede llevar bastante tiempo; con bibliotecas de objetos las comstack solo una vez.

El precio que paga es que los archivos de objeto se deben comstackr 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

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 aquí , debe especificar que ambos objectives 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).