2008-10-15 15 views
11

Estoy obligado a escribir documentación para mi proyecto actual que enumera todos los archivos .c y para cada uno enumera cada archivo .h que está incluido directa o indirectamente por ese archivo.Detección automática de dependencias C

Este es un proyecto grande, y aunque tenemos Makefiles que teóricamente tienen esta información, esos Makefiles a veces son incorrectos (hemos heredado este proyecto de otra compañía). A menudo hemos tenido que hacer un make clean ; make para que nuestros cambios realmente se vean reflejados en la compilación, por lo que no quiero confiar en estos Makefiles.

Entonces, ¿hay alguna herramienta que nos permita darle el nombre de un archivo .c y una ruta de inclusión y que nos diga todos los archivos .h que están incluidos directa o indirectamente por el archivo .c? No tenemos nada raro como

#define my_include "some_file.h" 
#include my_include 

por lo que la herramienta no tiene que ser perfecta. Cualquier cosa que busque archivos .c y .h en una ruta include para los includes regulares sería suficiente.

Respuesta

14

Lo que hago en mi Makefile es

SRCS=$(wildcard *.c) 

depend: $(SRCS) 
    gcc -M $(CFLAGS) $(SRCS) >depend 

include depend 

Esto significa que si alguno de los archivos de origen se actualizan, la regla dependerá funcionará, y utilizar -M gcc para actualizar el archivo llamado dependen. Esto se incluye en el archivo MAKE para proporcionar las reglas de dependencia para todos los archivos fuente.

Make comprobará que un archivo esté actualizado antes de incluirlo, por lo que esta regla dependerá si es necesario siempre que ejecute make sin que necesite hacer un "make dependen".

Esto se ejecutará en cualquier momento que cualquier archivo haya cambiado. Nunca encontré esto como un problema, pero si tenía una gran cantidad de archivos en el directorio, podría tardar demasiado, en cuyo caso podría intentar tener un archivo de dependencia por archivo fuente, como este:

SRCS=$(wildcard *.c) 
DEPS=$(SRCS:.c=.dep) 

%.dep : %.c 
    gcc -M $(CFLAGS) $< >[email protected] 

include $(DEPS) 

Tenga en cuenta que puede usar -MM en lugar de -M para no incluir los encabezados del sistema.

+0

podría cambiar un encabezado para incluir una cabecera adicional, cambiando con ello las dependencias de todos los archivos de origen, pero su lista de dependencias no conseguiría actualizada. Hacerlo completamente bien puede ser un IIRC bastante complicado, pero un buen comienzo es incluir todos tus propios encabezados en las dependencias de depend. –

+2

Ah, y para el rendimiento, tenga en cuenta que esto vuelve a procesar todos los archivos si algún archivo cambia. Por lo tanto, es posible que desee tener varios archivos dependientes (tal vez incluso uno por archivo fuente).Finalmente, tenga en cuenta que generalmente puede usar -MM, que omite las dependencias de los encabezados del sistema, ya que no los cambiará. –

+0

En realidad mentí - Siempre uso -MM yo mismo :) –

5

"gcc -M file.c" hace lo que necesita.

1

En MSVC (2005 y 2008 al menos, posiblemente otras versiones también pero no VC6) puede hacer que el compilador le diga todos los archivos que se incluyeron durante la compilación. El resultado es bastante detallado, pero completo y bastante fácil de analizar con ojos humanos.

En Configuración del proyecto, vaya a la pestaña C/C++> Avanzado, y seleccione "Mostrar incluye", luego reconstruya su proyecto desde cero.

+0

O desde la línea de comando/makefile: -showIncludes –

4

Una alternativa a gcc -M es fastdep. El autor de Fastdep informa que fastdep es diez veces más rápido que gcc's -M. Si el proyecto tarda un tiempo en compilarse, vale la pena echar un vistazo al fastdep.

2

Use SCons

$ scons --tree=all 
scons: Reading SConscript files ... 

scons: done reading SConscript files. 
scons: Building targets ... 
scons: `.' is up to date. 
+-. 
    +-SConstruct 
    +-app 
    | +-test.o 
    | | +-test.c 
    | | +-/include/PCI_1149_1.h 
    | | +-/include/Pci.h 
    | | +-/usr/bin/gcc 
    | +-/usr/bin/gcc 
    | +-/lib/libpci1149_64.a 
    ... 
+0

¡Agradable! De hecho, miré a través de la API SCons ya que pensé que tendría que rebuscar con sus elementos internos para lograrlo. Mantendré este interruptor de línea de comando en mente en el futuro. –

Cuestiones relacionadas