Enlazar libstdc++ estáticamente: ¿algún gotchas?

Necesito implementar una aplicación C ++ basada en Ubuntu 12.10 con libstdc ++ de GCC 4.7 en sistemas que ejecutan Ubuntu 10.04, que viene con una versión considerablemente anterior de libstdc ++.

Actualmente, estoy compilando con , como lo sugiere esta publicación de blog: Vincular libstdc ++ estáticamente. El autor advierte contra el uso de cualquier código C++ cargado dinámicamente al compilar libstdc++ estáticamente, que es algo que aún no he comprobado. Aún así, todo parece ir bien hasta ahora: puedo hacer uso de las características de C ++ 11 en Ubuntu 10.04, que es lo que buscaba.-static-libstdc++ -static-libgcc

Observo que este artículo es de 2005, y tal vez mucho ha cambiado desde entonces. ¿Sus consejos siguen vigentes? ¿Hay algún problema al acecho que deba tener en cuenta?

Respuestas:5 Respuestas 5
Tiempo:hace 9 años, 9 meses
Última modificación:hace 2 años

Solución

Esa publicación de blog es bastante inexacta.

Hasta donde yo sé, se han introducido cambios en C++ ABI con cada versión importante de GCC (es decir, aquellos con diferentes componentes de número de primera o segunda versión).

No es verdad. Los únicos cambios de ABI de C++ introducidos desde GCC 3.4 han sido compatibles con versiones anteriores, lo que significa que el ABI de C++ ha sido estable durante casi nueve años.

Para empeorar las cosas, la mayoría de las principales distribuciones de Linux utilizan instantáneas de GCC y / o parchean sus versiones de GCC, lo que hace que sea prácticamente imposible saber exactamente con qué versiones de GCC podría estar tratando cuando distribuye binarios.

Las diferencias entre las versiones parcheadas de GCC de las distribuciones son menores, y no cambian ABI, por ejemplo, el 20120306 4.6.3 de Fedora (Red Hat 4.6.3-2) es compatible con ABI con las versiones FSF 4.6.x ascendentes y casi con seguridad con cualquier 4.6.x de cualquier otra distribución.

En GNU/Linux, las bibliotecas de tiempo de ejecución de GCC usan el control de versiones de símbolos ELF, por lo que es fácil verificar las versiones de símbolos que necesitan los objetos y las bibliotecas, y si tiene un que proporciona esos símbolos, funcionará, no importa si es una versión parcheada ligeramente diferente de otra versión de su distribución.libstdc++.so

pero ningún código de C++ (o cualquier código que use el soporte de tiempo de ejecución de C++) puede vincularse dinámicamente si esto va a funcionar.

Esto tampoco es cierto.

Dicho esto, vincular estáticamente a es una opción para usted.libstdc++.a

La razón por la que podría no funcionar si carga dinámicamente una biblioteca (usando ) es que los símbolos libstdc++ de los que depende podrían no haber sido necesarios para su aplicación cuando la vinculó (estáticamente), por lo que esos símbolos no estarán presentes en su ejecutable. Eso se puede resolver vinculando dinámicamente la biblioteca compartida a (que es lo correcto de todos modos si depende de ello). La interposición de símbolos ELF significa que los símbolos que están presentes en su ejecutable serán utilizados por la biblioteca compartida, pero otros que no están presentes en su ejecutable se encontrarán en cualquiera que se vincule. Si su aplicación no lo usa, no necesita preocuparse por eso.dlopenlibstdc++.solibstdc++.sodlopen

Otra opción (y la que prefiero) es implementar el más nuevo junto con su aplicación y asegurarse de que se encuentre antes del sistema predeterminado, lo que se puede hacer forzando al vinculador dinámico a buscar en el lugar correcto, ya sea usando la variable de entorno en tiempo de ejecución o estableciendo un en el ejecutable en tiempo de enlace. Prefiero usarlo ya que no depende de que el entorno se configure correctamente para que la aplicación funcione. Si vincula su aplicación con (tenga en cuenta las comillas simples para evitar que el shell intente expandirse), entonces el ejecutable tendrá uno de los cuales le dice al vinculador dinámico que busque bibliotecas compartidas en el mismo directorio que el propio ejecutable. Si coloca el más reciente en el mismo directorio que el ejecutable, se encontrará en tiempo de ejecución, problema resuelto. (Otra opción es colocar el ejecutable en y el libstdc++.so más reciente y vincular con o cualquier otra ubicación fija en relación con el ejecutable, y establecer el RPATH en relación con libstdc++.solibstdc++.so$LD_LIBRARY_PATHRPATHRPATH'-Wl,-rpath,$ORIGIN'$ORIGINRPATH$ORIGINlibstdc++.so/some/path/bin//some/path/lib/'-Wl,-rpath,$ORIGIN/../lib'$ORIGIN)

Otras respuestas

También es posible que deba asegurarse de no depender del glibc dinámico. Ejecute en el ejecutable resultante y observe cualquier dependencia dinámica (libc / libm / libpthread son sospechosos de uso).ldd

Un ejercicio adicional sería construir un montón de ejemplos de C++11 involucrados utilizando esta metodología y probando los binarios resultantes en un sistema real 10.04. En la mayoría de los casos, a menos que haga algo extraño con la carga dinámica, sabrá de inmediato si el programa funciona o se bloquea.

Deja un comentario