Consideremos la distribución Debian o Ubuntu donde uno puede instalar algún paquete de biblioteca, digamos libfoobar
y un correspondiente libfoobar-dev
. El primero contiene un objeto de biblioteca compartida. El último generalmente contiene encabezados, variante de biblioteca estática y objetivos exportados cmake (por ejemplo, FoobarTargets.cmake
) que permiten cosas de CMake como find_package
para trabajar sin problemas. para hacerlo FoobarTargets.cmake
tiene que contener ambos objetivos: para la variante estática y para la compartida.
Por otro lado, he leído muchos artículos que afirman que yo (como autor de libfoobar) debería abstenerme de declarar add_library(foobar SHARED ....)
y add_library(foobar_static STATIC ...)
en CMakeLists.txt
a favor de construir e instalar una biblioteca utilizando BUILD_SHARED_LIBS=ON
y BUILD_SHARED_LIBS=OFF
. Pero este enfoque exportará solo una variante de la biblioteca a FoobarTargets.cmake
porque la compilación posterior sobrescribirá la primera.
Entonces, la pregunta es: ¿cómo hacerlo de la manera correcta? Para que el mantenedor del paquete no necesite parchear la biblioteca CMakeLists.txt
para exportar correctamente ambas variantes desde un lado. ¿Y para adherirse al sentido de CMake de una manera verdadera, eliminando objetivos duplicados que difieren solo por estático/compartido del otro lado?
Alex Reinking
escribí una publicación de blog completa sobre esto. Un ejemplo de trabajo es disponible en GitHub.
La idea básica es que necesitas escribir tu FoobarConfig.cmake
archivo de tal manera que cargue uno de FoobarSharedTargets.cmake
o FoobarStaticTargets.cmake
de una manera controlada por el usuario basada en principios, que también es tolerante con la presencia de uno u otro. Abogo por la siguiente estrategia:
- Si el
find_package
listas de llamadas exactamente uno destatic
oshared
entre los componentes requeridos, luego cargue el conjunto correspondiente de objetivos. - Si la variable
Foobar_SHARED_LIBS
está definido, luego cargue el conjunto correspondiente de objetivos. - De lo contrario, respete el ajuste de
BUILD_SHARED_LIBS
para mantener la coherencia con los usuarios de FetchContent.
En todos los casos, sus usuarios enlazarán a Foobar::Foobar
.
En última instancia, no puede tener tanto el estático como el compartido importados en el mismo subdirectorio y al mismo tiempo proporcionar una interfaz consistente de árbol de compilación (FetchContent) y árbol de instalación (buscar paquete). Pero esto no es gran cosa ya que normalmente los consumidores solo quieren uno o el otro, y es totalmente ilegal vincular ambos a un solo objetivo.
-
Dios mío, hace solo una hora que escribí la pregunta y la has encontrado con una respuesta tan completa. Empecé a leer tu publicación y siento de antemano que has hecho un gran trabajo. Voy y leo su artículo hasta el final y le escribiré una vez que complete la lectura. Muchas gracias de antemano.
– Max Dmitrichenko
12 de febrero a las 16:39
-
Vale, he leído tu publicación. 10/10!
– Max Dmitrichenko
13 de febrero a las 9:55