This is the mail archive of the
mailing list for the GCC project.
- From: martin dot schaffner at epfl dot ch
- To: gcc at gcc dot gnu dot org
- Date: Fri, 15 Aug 2003 03:36:42 +0200
- Subject: link dependencies
Currently a developer has to keep track of every source file addition/renaming/removal in the makefile (or in makefile.am). This is because there is no way for a tool to automatically find out the link dependencies of a given source file, i.e. which other files have to be linked with it for all symbols to be defined.
I developed an idea which removes the need to keep such a list of source files: Every header file declares which source file implements its interface, e.g. foo.h contains a line
#pragma linkdep "foo.c"
This practice allows a tool to automatically generate the list of source files to compile and link, given the file containing the main() function as input, by following all "#include" and "#pragma linkdep" directives.
If there is more than one source file which implements a header file's interface, the one to be compiled can be chosen using preprocessor macros, like this:
#pragma linkdep "foo_x.c"
#pragma linkdep "foo_console.c"
This would remove the need to use makefile variables for conditional compilation, and in many current cases, preprocessor macros are already defined in parallel to makefile variables.
If a source file uses functions from a library, it would contain:
#pragma linkdep <-lfoo>
The angle brackets indicate that we need to link with the file itself, instead of with the compiled version of the file, and the "-l" prefix tells "make" it's a library which can be found by searching the path stored in the .LIBPATTERNS variable. For unusual locations of libraries, the installer would have to tweak the .LIBPATTERNS variable instead of adding -Lpath switches.
If gcc accepts the "-ML" flag, telling it to output link dependencies, a project can be compiled with a makefile which doesn't contain a list of files to compile. Here is an example of such a makefile:
EXE = foo
MAIN_SOURCE = foo.c
all : $(EXE)
include $(wildcard *.d) /dev/null
$(EXE) : $(MAIN_C:.c=.o)
if test -e dirty; then rm dirty; make; else \
gcc $^ $(LDFLAGS) -o $(EXE); fi
%.o : %.c
if test -e $*.d; then cp $*.d $*.d~; else touch $*.d~; fi; if \
gcc -c $(CFLAGS) -MD -ML$(EXE) $< -o $@; \
then if ! diff $*.d $*.d~ >/dev/null; then touch dirty; fi; rm -f $*.d~; \
else ((0)); fi
rm -f $(EXE) core dirty *.o *.d *~
I tested the above code with a patched gcc, and it worked as expected.
Any source file added to the project will be automatically compiled as soon as it's used by another source file. The above makefile requires a "make clean" for an addition or renaming of a source file, but it wouldn't be too hard to change that.
Please comment and critisize.
PS: Please tell me if there is a more appropriate mailing list to discuss this idea. My mails to this list tend to be ignored...