Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generate all project dependencies in a single file using gcc -MM flag

I want to generate a single dependency file which consists of all the dependencies of source files using gcc -M flags through Makefile. I googled for this solution but, all the solutions mentioned are for generating multiple deps files for multiple objects.

DEPS = make.dep

$(OBJS): $(SOURCES)
    @$(CC) -MM $(SOURCEs) > $(DEPS)
    @mv -f $(DEPS) $(DEPS).tmp
    @sed -e 's|.$@:|$@:|' < $(DEPS).tmp > $(DEPS)
    @sed -e 's/.*://' -e 's/\\$$//' < $(DEPS).tmp | fmt -1 | \
      sed -e 's/^ *//' -e 's/$$/:/' >> $(DEPS)
    @rm -f $(DEPS).tmp

But it is not working properly. Please tell me where i'm making the mistake.

like image 979
Jabez Avatar asked Dec 30 '09 18:12

Jabez


2 Answers

Something along these lines is what I use to get all my dependencies in a single file:

program_H_SRCS := $(wildcard *.h)
program_C_SRCS := $(wildcard *.c)
DEPS = make.deps

make.deps: $(program_C_SRCS) $(program_H_SRCS)
    $(CC) $(CPPFLAGS) -MM $(program_C_SRCS) > make.deps

include $(DEPS)

This basically causes all the user ( as opposed to system ) dependencies to be rebuilt into a single file whenever any C or H file in the project is modified.

+++++++++ EDIT +++++++++++

I've since found a better way of doing things. I generate a separate dep file for each source file. Here is the basic makefile:

program_NAME := myprogram
program_SRCS := $(wildcard *.c)
program_OBJS := ${program_SRCS:.c=.o}
clean_list += $(program_OBJS) $(program_NAME)

# C Preprocessor Flags
CPPFLAGS += 
# compiler flags
CFLAGS += -ansi -Wall -Wextra -pedantic-errors

.PHONY: all clean distclean

all: $(program_NAME)

clean:
    @- $(RM) $(clean_list)

distclean: clean

# Generate dependencies for all files in project
%.d: $(program_SRCS)
    @ $(CC) $(CPPFLAGS) -MM $*.c | sed -e 's@^\(.*\)\.o:@\1.d \1.o:@' > $@

clean_list += ${program_SRCS:.c=.d}

$(program_NAME): $(program_OBJS)
    indent -linux -brf $(program_SRCS)
    splint $(program_SRCS)
    $(LINK.c) $(program_OBJS) -o $(program_NAME)

ifneq "$(MAKECMDGOALS)" "clean"
# Include the list of dependancies generated for each object file
-include ${program_SRCS:.c=.d}
endif

This does two things:

  1. If any of the files that foo.c depend on change then foo.o is rebuilt without having to rebuild other files in the project.
  2. The dep file itself has the same dependencies as the object file, so that if any of the deps are modified the dep file itself is also regenerated, before the object file deps are checked.
like image 126
Robert S. Barnes Avatar answered Nov 09 '22 09:11

Robert S. Barnes


I think is is expected behaviour for gcc -M, where typically you'd do something like this:

FOO_SOURCES= \
    src/foo.c \
    src/bar.c

FOO_OBJECTS = $(FOO_SOURCES:.c=.o)
FOO_DEPS = $(FOO_OBJECTS:.o=.d)

(... lots of targets ...)

-include $(FOO_DEPS)

Note, -include not include as the dependencies will obviously not exist until at least one build has been run. Regardless, dependencies are generated on a per module basis.

Also note that gcc -M does not always work as you would expect it to work, broadly depending on what version of gcc you happen to be using.

I think what you want is something called makedep, which does what you want without sed hackery in the makefile.

like image 45
Tim Post Avatar answered Nov 09 '22 08:11

Tim Post