Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Makefile, header dependencies

Let's say I have a makefile with the rule

%.o: %.c  gcc -Wall -Iinclude ... 

I want *.o to be rebuilt whenever a header file changes. Rather than work out a list of dependencies, whenever any header file in /include changes, then all objects in the dir must be rebuilt.

I can't think of a nice way to change the rule to accomodate this, I'm open to suggestions. Bonus points if the list of headers doesn't have to be hard-coded

like image 760
Mike Avatar asked Mar 07 '10 00:03

Mike


People also ask

Should header files be included in makefile?

The only way to include the header file is to treat the filename in the same way you treat a string. Makefiles are a UNIX thing, not a programming language thing Makefiles contain UNIX commands and will run them in a specified sequence.

What are makefile dependencies?

A dependency is a file that is used as input to create the target. A target often depends on several files. A command is an action that make carries out. A rule may have more than one command, each on its own line.

How do I link my makefile to .a files?

$(CC) $(CFLAGS) -I$(LIB_PATH) -L$(LIB_PATH) -o $(PROGRAM) main. c -l$(LIB) `pkg-config ...` Basically, you need set the include path to the . h file with -I, then -L for the lib path and -l to set the lib name.

What does ?= Mean in makefile?

?= indicates to set the KDIR variable only if it's not set/doesn't have a value. For example: KDIR ?= "foo" KDIR ?= "bar" test: echo $(KDIR)


2 Answers

If you are using a GNU compiler, the compiler can assemble a list of dependencies for you. Makefile fragment:

depend: .depend  .depend: $(SRCS)         rm -f "$@"         $(CC) $(CFLAGS) -MM $^ -MF "$@"  include .depend 

or

depend: .depend  .depend: $(SRCS)         rm -f "$@"         $(CC) $(CFLAGS) -MM $^ > "$@"  include .depend 

where SRCS is a variable pointing to your entire list of source files.

There is also the tool makedepend, but I never liked it as much as gcc -MM

like image 76
5 revs, 4 users 53% Avatar answered Oct 06 '22 21:10

5 revs, 4 users 53%


Most answers are surprisingly complicated or erroneous. However simple and robust examples have been posted elsewhere [codereview]. Admittedly the options provided by the gnu preprocessor are a bit confusing. However, the removal of all directories from the build target with -MM is documented and not a bug [gpp]:

By default CPP takes the name of the main input file, deletes any directory components and any file suffix such as ‘.c’, and appends the platform's usual object suffix.

The (somewhat newer) -MMD option is probably what you want. For completeness an example of a makefile that supports multiple src dirs and build dirs with some comments. For a simple version without build dirs see [codereview].

CXX = clang++ CXX_FLAGS = -Wfatal-errors -Wall -Wextra -Wpedantic -Wconversion -Wshadow  # Final binary BIN = mybin # Put all auto generated stuff to this build dir. BUILD_DIR = ./build  # List of all .cpp source files. CPP = main.cpp $(wildcard dir1/*.cpp) $(wildcard dir2/*.cpp)  # All .o files go to build dir. OBJ = $(CPP:%.cpp=$(BUILD_DIR)/%.o) # Gcc/Clang will create these .d files containing dependencies. DEP = $(OBJ:%.o=%.d)  # Default target named after the binary. $(BIN) : $(BUILD_DIR)/$(BIN)  # Actual target of the binary - depends on all .o files. $(BUILD_DIR)/$(BIN) : $(OBJ)     # Create build directories - same structure as sources.     mkdir -p $(@D)     # Just link all the object files.     $(CXX) $(CXX_FLAGS) $^ -o $@  # Include all .d files -include $(DEP)  # Build target for every single object file. # The potential dependency on header files is covered # by calling `-include $(DEP)`. $(BUILD_DIR)/%.o : %.cpp     mkdir -p $(@D)     # The -MMD flags additionaly creates a .d file with     # the same name as the .o file.     $(CXX) $(CXX_FLAGS) -MMD -c $< -o $@  .PHONY : clean clean :     # This should remove all generated files.     -rm $(BUILD_DIR)/$(BIN) $(OBJ) $(DEP) 

This method works because if there are multiple dependency lines for a single target, the dependencies are simply joined, e.g.:

a.o: a.h a.o: a.c     ./cmd 

is equivalent to:

a.o: a.c a.h     ./cmd 

as mentioned at: Makefile multiple dependency lines for a single target?

like image 30
Sophie Avatar answered Oct 06 '22 21:10

Sophie