CMake y Enlaces estáticos


Estoy usando CMake en un proyecto, y estoy tratando de vincular estáticamente algunas bibliotecas. He establecido:

set(BUILD_SHARED_LIBS OFF)
set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++ -static")
set_target_properties(icarus PROPERTIES LINK_SEARCH_END_STATIC 1)

Y me he asegurado al buscar las bibliotecas reales que tengo el *.una versión de ellos.

Actualmente el proyecto importa:

libPocoNet.a 
libPocoUtil.a 
libPocoXML.a 
libPocoFoundation.a 
libmysqlclient.a 
libmysqlpp.a 
libcrypto++.a 
CUDA

Se encuentran todas las bibliotecas, y cuando se hace un enlace dinámico/compartido, funcionan bien. También he intentado establecer banderas de compilación:

set(GCC_CXX_FLAGS ${GCC_CXX_FLAGS} "-static-libgcc -static-libstdc++ -static")

Pero en vano. Si bien no tengo problemas mientras compilo, linkage está lanzando un montón de undefined reference errores para las llamadas encontradas en las bibliotecas anteriores, es decir:

undefined reference to `mysql_thread_init'
undefined reference to `mysql_real_query'
undefined reference to `pthread_mutex_unlock'
undefined reference to `Poco::ErrorHandler::handle()'

No en ese orden en particular, y numerosos errores para cada biblioteca.

Mirando la última línea del CCG veo:

/usr/bin/c++   -g -g  -static-libgcc -static-libstdc++ -static [list of *.cpp files]
-o icarus -rdynamic /usr/local/lib/libPocoFoundation.a /usr/local/lib/libPocoNet.a
/usr/local/lib/libPocoUtil.a /usr/local/lib/libPocoXML.a 
-Wl,-Bstatic -lmysqlclient -lmysqlpp -lcrypto++

Lo que me hace preguntarme:

  1. ¿Por qué las bibliotecas Poco están enlazadas como-rdynamic, y no hay una bandera-Wl-Bstatic? Como si se omitieran / excluyeran del enlace estático.
  2. mysqlclient, mysqlpp y crypto++ parecen estar configurados para vinculación estática, sin embargo, todavía obtener errores

Entonces, podría alguien explicarme:

  1. ¿Cómo configuro el enlace estático parcial usando CMake
  2. ¿Es CMAKE_EXE_LINKER_FLAGS el único que necesito establecer?
  3. ¿Debería forzar el enlace estático para las bibliotecas mencionadas pero no para todo el proyecto?

Por favor, discúlpeme si esas son demasiadas preguntas o demasiado localizadas, no he probado esto antes, y parece que no puedo encontrar mucha información en la red.

Author: Ælex, 2013-06-07

2 answers

He logrado resolver mi problema usando lo siguiente:

#Dynamic/Shared Libs
...
#Static start
set_target_properties(icarus PROPERTIES LINK_SEARCH_START_STATIC 1)
set_target_properties(icarus PROPERTIES LINK_SEARCH_END_STATIC 1)
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
#Static Libs
...
#Set Linker flags
set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++")

Esto funciona sin pasar un -static que crea otros grandes problemas, y esencialmente puede mezclar bibliotecas estáticas y dinámicas.

Siempre que el orden de las bibliotecas estáticas sea correcto, y siempre que las dependencias de las bibliotecas estáticas estén satisfechas, obtengo un ELF que carga lo que son dinámicos (es decir, en mi caso mysqlclient, libmysql++) y estáticos todo el resto (crypto++, PocoNet, PocoUtil, PocoXML, PocoFoundation).

Tenga en cuenta que las bibliotecas enlazadas estáticas tienen sus propias dependencias. Examinando mi aplicación de depuración usando la aplicación readelf - d, veo:

Dynamic section at offset 0x508f88 contains 28 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libmysqlpp.so.3]
 0x0000000000000001 (NEEDED)             Shared library: [libmysqlclient.so.18]
 0x0000000000000001 (NEEDED)             Shared library: [libm.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [ld-linux-x86-64.so.2]
 0x0000000000000001 (NEEDED)             Shared library: [libpthread.so.0]

Sé que pthread es importado por Poco:: Runnable, libm es para operaciones matemáticas, etc. Todavía no sé si esta es la forma correcta de usar CMake para enlaces estáticos parciales.

En el caso de las bibliotecas empaquetadas de Debian, como crypto++, mysql++, mysqlclient, simplemente encontrar el *.una biblioteca funcionó, pero en el caso de Poco Las bibliotecas, que solo me dieron la ruta completa y el nombre de la biblioteca, pero no una bandera, -Bdynamic solo se podían desactivar usando las líneas anteriores.

Nota: Poco no se puede vincular estáticamente, sin -static-libstdc++

Espero que esto ayude a alguien atrapado en algo similar.

 26
Author: Ælex,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-10 21:04:35

Cómo configuro la vinculación estática usando CMake

Bueno... no:) Así no es como funciona CMake: en CMake, primero encuentras la ruta absoluta de una biblioteca, luego enlazas a ella con target_link_libraries.

Por lo tanto, si desea vincular a una biblioteca estática, debe buscar esa biblioteca estática:

find_library(SOMELIB libsomelib.a)

En lugar de:

find_library(SOMELIB somelib)
 12
Author: Guillaume,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-07 21:27:46