serie serial rs232 recibir puerto por leer get_string float enviar datos compiler ccs caracteres cadena c++ gcc linker ld binutils

c++ - serial - ¿Por qué GNU ld resuelve los símbolos de manera diferente cuando se vincula ejecutables vs objetos compartidos?



pic c compiler string (2)

Tengo una pieza trivial de código C ++ que se ve así:

#include <boost/timer/timer.hpp> int main(void) { boost::timer::auto_cpu_timer t; return 0; }

Intenté compilar y vincularlo (con gcc 4.8.1 y GNU ld 2.23.52.20130828) de la siguiente manera:

$ g++ -o test test.cc -lboost_timer /usr/bin/ld: /tmp/cc2jP1jv.o: undefined reference to symbol ''_ZN5boost6system15system_categoryEv'' /usr/lib/libboost_system.so.1.54.0: error adding symbols: DSO missing from command line collect2: error: ld returned 1 exit status

Una solución es mencionar explícitamente -lboost_system en la línea de comandos, y eso funciona. Sin embargo, también puedo hacer:

$ g++ -Wl,--copy-dt-needed-entries -o test test.cc -lboost_timer

De acuerdo con la documentación ld "con --copy-dt-needed-entries" las bibliotecas dinámicas mencionadas en la línea de comando serán buscadas recursivamente, siguiendo sus etiquetas DT_NEEDED a otras bibliotecas, para resolver los símbolos requeridos por el binario de salida ", entonces esto todo tiene sentido: ld está averiguando desde boost_timer que también necesita vincularse contra el sistema boost para resolver todos los símbolos.

Sin embargo, me di cuenta de que esto también funciona:

$ g++ -fPIC -shared -o test test.cc -lboost_timer

Obviamente, ahora he generado un objeto compartido en lugar de un ejecutable. Aparentemente, sin embargo, pude deducir que necesitaba vincular el objeto compartido con el sistema boost:

$ ldd test | grep boost_system libboost_system.so.1.54.0 => /usr/lib/libboost_system.so.1.54.0 (0x00007f385246e000)

Entonces mi pregunta es esta: ¿por qué la resolución de símbolos es diferente cuando se construye un objeto compartido en comparación con un ejecutable? ¿Cómo puedo deducir que mi objeto compartido debería estar enlazado contra boost_system sin especificar --copy-dt-needed-entries ?


Existen diferencias en el comando collect2 que pueden ser relevantes. Los diferentes comandos se comparan en http://imgur.com/eMr2tY2 . El lado derecho crea la biblioteca compartida (-fPic -shared), la izquierda es la compilación normal.


La respuesta directa a mi pregunta está en la opción --[no-]allow-shlib-undefined a ld, creo. Desde la página man:

El comportamiento predeterminado es informar los errores de los símbolos no definidos a los que se hace referencia en las bibliotecas compartidas si el vinculador se usa para crear un archivo ejecutable, pero permitirlos si el vinculador se usa para crear una biblioteca compartida.

Por lo tanto, cuando construyo con -shared , los símbolos en boost_system no están definidos, pero el comportamiento predeterminado de ld es no importarle. Se le puede decir que se preocupe:

$ g++ -fPIC -shared -Wl,--no-allow-shlib-undefined -o test test.cc -lboost_timer /usr/bin/ld: /tmp/cc6j1de3.o: undefined reference to symbol ''_ZN5boost6system15system_categoryEv'' /usr/lib/libboost_system.so.1.54.0: error adding symbols: DSO missing from command line collect2: error: ld returned 1 exit status

Del mismo modo, podemos decir que no se preocupe al construir un ejecutable:

$ g++ -Wl,--allow-shlib-undefined -o test test.cc -lboost_timer /tmp/ccUHoCIU.o: In function `__static_initialization_and_destruction_0(int, int)'': test.cc:(.text+0x7a): undefined reference to `boost::system::generic_category()'' test.cc:(.text+0x86): undefined reference to `boost::system::generic_category()'' test.cc:(.text+0x92): undefined reference to `boost::system::system_category()'' collect2: error: ld returned 1 exit status

Pero la creación del binario falla sin poder definir esos símbolos.

¡Gracias @CharlesBailey por señalarme en la dirección correcta!