Konstantin Shemyak
Konstantin Shemyak

Reputation: 2537

How to collect all dependencies of a large Makefile project?

In a large C project, I have a top Makefile and many sub-Makefiles in different subdirectories. I need to collect all dependencies of the compilation. For that, I add -MMD to CFLAGS and get a bunch of .d dependency files.

These .d files are scattered in the subdirectories. Also, the dependencies are written sometimes as absolute paths, sometimes as paths relevant to the compilation directory, and sometimes containing symbolic links. I have written a script which finds all .d files, traverses their directories, and resolves all found paths. This works, but with tens of thousands of dependency files this dependency collection lasts about the same time as the compilation! (which is too long to wait :) )

Is there a faster way to get all dependencies in a single file? This is ANSI C, GCC and Linux if that matters. Thanks in advance.

Upvotes: 4

Views: 1440

Answers (2)

Simon Richter
Simon Richter

Reputation: 29618

You can create the dependency files along with the first compile run.

During the first run, the objects do not exist yet, so the compiler will be invoked anyway. Create empty dependency files first, then update them while compiling.

It should be possible to extend the minimal Makefile for a single-directory C++ project to work with subdirectories.

Upvotes: 0

Olaf Dietsche
Olaf Dietsche

Reputation: 74078

Instead of -MMD, you can use -MM, which sends the dependencies to standard output.

You can then collect all the output to some dependency file in the top level directory with

gcc -MM ... file.c >>$(top)/all.d

If post processing is the only reason for collecting the output in one file, you can filter the output with a pipe

gcc -MM ... file.c | sh filter.sh >file.d

and keep the dependency files separate.

If the path to some local include file (defs.h) or the main source is important, you can force gcc to include a path by giving the appropriate -I option, e.g.

gcc -MM -I$(top)/path/to ... $(top)/path/to/file.c >>$(top)/all.d

or

gcc -MM -I$(top)/path/to ... $(top)/path/to/file.c | sh filter.sh >file.d

Instead of

file.o: file.c defs.h

gcc will emit

file.o: /absolute/path/to/file.c /absolute/path/to/defs.h

This works with relative paths as well, of course.

Upvotes: 1

Related Questions