DVK
Tengo una aplicación C++ que heredé, que consta de:
- mi aplicación principal
- Varias bibliotecas específicas de la aplicación (libapp1, libapp2, etc…)
- Varias bibliotecas de “terceros” (la mayoría de los “terceros son solo otros equipos de la empresa”) vinculados desde la aplicación principal, desde las bibliotecas libappX específicas de la aplicación y desde otras bibliotecas de terceros, por ejemplo, libext1, libext2, etc. .
En otras palabras, mi código se ve así:
// main.C
#include <app1/a1l1.H>
#include <app2/a2l1.H>
#include <ext1/e1l1.H>
// app1/a1l1.H
#include <app1/a1l2.H>
#include <ext2/e2l1.H>
// app2/a2l1.H
#include <ext2/e2l2.H>
// ext1/e1l1.H
#include <ext3/e3l1.H>
// ext3/e3l1.H
#include <ext4/e4l1.H>
Preguntas:
1) ¿Cómo puedo saber qué bibliotecas se han vinculado al ejecutable final? Esto debe incluir los vinculados estáticamente
En otras palabras, quiero una respuesta de “app1, app2, ext1, ext2, ext3, ext4”
Idealmente, la respuesta estaría disponible desde el propio ejecutable (tengo una versión de depuración construida en caso de que sea más posible). Si eso es imposible, me gustaría saber si hay una herramienta de análisis de código simple (es decir, algo dentro de gcc) para proporcionar ese análisis.
Tenga en cuenta que los archivos de objeto para las bibliotecas externas ya están creados, por lo que al mirar los registros de compilación para ver qué se vinculó, me preocupa que “ext4” no aparezca en el registro ya que no construiremos “ext3 ” biblioteca que ya está preconstruida.
NOTA: ejecutar “nmake” con DEPS establecido en sí para reconstruir todo NO es una opción. Pero SÍ tengo acceso al código fuente completo para bibliotecas externas.
2) Una pregunta un poco separada y menos importante, ¿cómo puedo saber una lista de todos los incluir archivos utilizado en todo el árbol de fuentes que estoy construyendo. Nuevamente, idealmente desde un ejecutable ya construido, del cual tengo una versión de depuración.
=================
ACTUALIZACIÓN: solo para aclarar, nuestras bibliotecas están vinculadas estáticamente, por lo que ldd
(List Synamic Dependencies) no funciona.
Además, la respuesta puede ser para Solaris o Linux, no importa.
Traté de usar nm
pero eso no enumera las bibliotecas
Daniel Frużyński
Tuve un problema similar y encontré una solución: agregar -Wl, –opción detallada al vincular. Cambiará el enlazador al modo detallado:
gcc -o test main.o -ltest -L. -Wl,--verbose
Aquí hay un ejemplo de salida:
GNU ld (GNU Binutils) 2.23.52.20130604
Supported emulations:
i386pep
i386pe
using internal linker script:
==================================================
/* Default linker script, for normal executables */
[many lines here]
==================================================
attempt to open /usr/lib/gcc/x86_64-pc-cygwin/4.8.2/../../../../lib/crt0.o succeeded
/usr/lib/gcc/x86_64-pc-cygwin/4.8.2/../../../../lib/crt0.o
attempt to open /usr/lib/gcc/x86_64-pc-cygwin/4.8.2/crtbegin.o succeeded
/usr/lib/gcc/x86_64-pc-cygwin/4.8.2/crtbegin.o
attempt to open main.o succeeded
main.o
attempt to open ./libtest.dll.a failed
attempt to open ./test.dll.a failed
attempt to open ./libtest.a succeeded
(./libtest.a)test.o
[more lines here]
attempt to open /usr/lib/gcc/x86_64-pc-cygwin/4.8.2/crtend.o succeeded
/usr/lib/gcc/x86_64-pc-cygwin/4.8.2/crtend.o
Actualizar: También puede usar la opción -Wl,–trace en lugar de -Wl,–verbose. También le dará una lista de bibliotecas, pero es menos detallado.
Actualización 2: -Wl,–trace no muestra bibliotecas incluidas indirectamente. Ejemplo: se vincula con libA y libA se vinculó con libB. Si quiere ver que también se necesita libB, debe usar -Wl,–verbose.
-
Como nota para los seguidores, los archivos “.o”
ld
listas para una biblioteca (es decir, las enumeradas después de que diceattempt to open libXX succeeded
) no serán “todos” los archivos .o en una biblioteca, solo los que requiere para satisfacer las dependencias en ese punto. El resto, en esencia, se descarta, aunque esté presente en el archivo .a. referencia: stackoverflow.com/q/14091669/32453– rogerdpack
8 de enero de 2016 a las 1:21
-
¿Hay una manera fácil de hacer esto en Visual Studio 2017?
– Yuriy F.
1 de diciembre de 2018 a las 22:17
-
@YuriyF: Traté de buscar esto en Google y descubrí que MSVC tiene la opción /VERBOSE: learn.microsoft.com/en-us/cpp/build/reference/… . Compruebe si funcionará para usted, no tengo MSVC para probarlo.
– Daniel Frużyński
3 de diciembre de 2018 a las 9:14
-
Visual Studio es una pieza rota de pitido.
– Martín
29 de marzo de 2019 a las 6:59
Para dependencias directas;
ldd <app>
Indirecto/Todas las dependencias;
ldd -r <app>
-
Perdón por no aclarar esto antes, las bibliotecas están enlazadas estáticamente.
ldd
no los enumera.– DVK
7 de febrero de 2011 a las 18:49
-
Encontré la respuesta que estaba buscando por su respuesta, ¡gracias!
– jredd
16/09/2015 a las 18:39
Hasta donde yo sé, no se conserva mucha información sobre las bibliotecas estáticas al vincular (ya que el vinculador solo ve esa biblioteca como una colección de objetos * .o de todos modos).
Si encuentra el comando make que vincula el ejecutable final y agrega un -v
bandera, g++
le mostrará exactamente cómo llama al ld
dominio. Esto debería incluir todas las bibliotecas estáticas necesarias, incluidas las bibliotecas utilizadas por otras bibliotecas; de lo contrario, el paso del vínculo fallaría. Pero también podría incluir bibliotecas adicionales que en realidad no se utilizan.
Otra cosa posiblemente útil es que, al menos en Linux, los objetos y ejecutables generalmente almacenan los nombres de los archivos de código fuente a partir de los cuales fueron creados. (Solo nombre de archivo, sin ruta). Intente
objdump -t executable | grep '*ABS*'
-
objdump parece producir una salida muy similar a
nm
y en realidad no producen listas de bibliotecas. ¿Puedo pasar “-v” a través de un interruptor de línea de comando a nmake? Gracias– DVK
7 febrero 2011 a las 19:10
-
@DVK: ¿Nmake de AT&T? ¿Microsoft nmake? En cualquier caso, probablemente no. Quieres encontrar el último
g++
comando que el proceso de creación hizo o llamaría, luego agregue -v a eso.– Aschepler
7 febrero 2011 a las 19:20
-
entendido. Creo que ya lo hace de forma predeterminada, ya que creo que veo una lista de todos los archivos .a en la línea de comandos de g ++
– DVK
7 febrero 2011 a las 19:21
Tratar de usar ldd
+ su nombre de archivo, esto enumerará las bibliotecas.
Responderé primero a tu segunda pregunta. Simplemente puede utilizar el -H
o -M
flag para ver todos los encabezados (incluido el sistema) procesados en la compilación. gcc -H main.c
debería hacer el truco. Ver qué encabezados están incluidos realmente lo pondrá en el camino correcto para encontrar qué bibliotecas estáticas estaban vinculadas.
podrías usar objdump
en su objeto final (o readelf
en su binario final) para obtener los nombres de todas las funciones allí. Luego tendría que ir a buscar las bibliotecas de las que se extrajeron las funciones, pero eso es un poco engorroso. Definitivamente tendrías que hacer un guión para minimizar el dolor.
Alguien más mencionó usar gcc <stuff> -Wl,-verbose
que simplemente pasa el -verbose
marca al enlazador. Esa es una manera perfecta de obtener una lista de bibliotecas compartidas (archivos .so), pero usted dijo que las suyas son estáticas, por lo que ese no es el camino a seguir en este caso.
¡Buena suerte!
hombre esponja
Esto es lo que uso para generar dependencias de tiempo de enlace:
-include .deps/TARGET.d
$(TARGET): $(OBJECTS)
@echo " LINK $(TARGET)"
@echo '$$(TARGET): \' > .deps/TARGET.d
@$(CXX) -o $(TARGET) $(OBJECTS) $(LDLIBS) -Wl,--trace | sed -r -e "s#.*\(($(MY_LIB_DIR)).*)\).*#\t\\1 \\\\#p;d" | sort | uniq >> .deps/TARGET.d
genera un .deps/TARGET.d
archivo que se ve así:
$(TARGET): \
/home/user/project/lib/lib1.a \
/home/user/project/lib/lib2.a \
/home/user/project2/bin/lib3.so \
@Tom, ya sea Solaris o Linux. No me importa si la respuesta es genérica para ambos o solo funciona en uno.
– DVK
7 febrero 2011 a las 18:40
Sugeriría ldd entonces para su primera pregunta
– Tomás
7 febrero 2011 a las 18:42