Make enable directive and dependency creation using -MM

I want the build rule to be triggered by the include directive if the include target is obsolete or does not exist.

Currently, the make file looks like this:

program_NAME := wget++ program_H_SRCS := $(wildcard *.h) program_CXX_SRCS := $(wildcard *.cpp) program_CXX_OBJS := ${program_CXX_SRCS:.cpp=.o} program_OBJS := $(program_CXX_OBJS) DEPS = make.deps .PHONY: all clean distclean all: $(program_NAME) $(DEPS) $(program_NAME): $(program_OBJS) $(LINK.cc) $(program_OBJS) -o $(program_NAME) clean: @- $(RM) $(program_NAME) @- $(RM) $(program_OBJS) @- $(RM) make.deps distclean: clean make.deps: $(program_CXX_SRCS) $(program_H_SRCS) $(CXX) $(CPPFLAGS) -MM $(program_CXX_SRCS) > make.deps include $(DEPS) 

The problem is that the include directive appears to make make.deps before the rule, which actually means that make either does not get a list of dependencies if make.deps does not exist or always gets make.deps from the previous assembly rather than current.

For instance:

 $ make clean $ make makefile:32: make.deps: No such file or directory g++ -MM addrCache.cpp connCache.cpp httpClient.cpp wget++.cpp > make.deps g++ -c -o addrCache.o addrCache.cpp g++ -c -o connCache.o connCache.cpp g++ -c -o httpClient.o httpClient.cpp g++ -c -o wget++.o wget++.cpp g++ addrCache.o connCache.o httpClient.o wget++.o -o wget++ 

Edit

I read the docs for the include directive , and it looks like if the inclusion target does not exist, it will continue processing the parent makefile trying to build the target, but I don’t quite understand how it works:

If the included makefile cannot be found in any of these, a warning message appears, but it is not an immediate fatal error; processing of the makefile containing the inclusion continues. Once it has finished profiles, make try to redo everything that is outdated or does not exist. See How Makefiles Redesigned. Only after that I tried to find a way to redo the makefile and failed to diagnose the missing makefile as a fatal error.

ANSWER

This is a modification of the answer I accepted. The only thing that wasn't there was that the dependency files are also source dependent and will not be restored unless they are added to the deps files that are included:

 %.d: $(program_CXX_SRCS) @ $(CXX) $(CPPFLAGS) -MM $*.cpp | sed -e ' s@ ^\(.*\)\.o:@\1.d \1.o:@' > $@ 

sed adds the .d file .d at the beginning of each dependency line as follows:

 foo.d foo.o: foo.cpp foo.h bar.h baz.h 

I got an idea from this amazing article about the dangers of recursive make:

Recursive analysis is considered malicious

I also add the following to the makefile:

 clean_list += ${program_SRCS:.c=.d} # At the end of the makefile # Include the list of dependancies generated for each object file # unless make was called with target clean ifneq "$(MAKECMDGOALS)" "clean" -include ${program_SRCS:.c=.d} endif 
+4
source share
3 answers

You rely on an implicit rule to compile your .cpp files. You must override it to use the -MM and -MF flags, which will create the dependency file.

 %.o: %.cpp $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@ -MM -MF $@.d 

Then you must include these dependency files in the Makefile using -include , which will not be erroneous if the dependency files do not exist (for the first time or after cleaning).

 program_DEPS := $(program_OBJS:.o=.od) -include $(program_DEPS) 

And don't forget to add the rm command for dependency files in the cleanup rule.

+2
source

The important point that it took me some time is that the make.deps from the previous build are pretty good . Think about it: for a given object file, the only way to change the list of dependency files is if ... one of the old dependency files has been changed. And if this is so, then the old make.dep will cause this object file to be rebuilt, and if rebuilding the object file will also lead to the restoration of make.deps, then everything will be relevant. You do not need to rebuild make.dep before checking which objects need to be rebuilt.

+2
source

Include directives work the same way as in C and C ++ - they are processed before anything else happens to create a β€œreal” makefile, which then processes it. In particular, they are processed before any rules are run.

0
source

Source: https://habr.com/ru/post/1309302/


All Articles