Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Makefile multiple dependency lines for a single target?

Tags:

c++

makefile

To generate dependency files I can use something like this to generate dependency files:

-include $(patsubst %.cpp,build/%.d,$(SRC))
build/%.o: %.cpp
    $(CC) $(CXXFLAGS) -c -o $@ $<
    $(CC) $(CXXFLAGS) -MM -MT $@ -MF $(patsubst %.o,%.d,%@) $<

This generates everything and puts both the object and dependency files into the build dir where I want them. But this makes two dependency lines for the <file>.o targets, one from the -include rule and with all the header dependencies, and one which is from the pattern rule. Will this get interpreted correctly, i.e. when a header is modified, the object will be recompiled via the command specified for the pattern rule?

Edit: So this approach does in fact work quite well. I guess I'd like somebody to provide an answer which gives me some insight into what it is exactly that make does in these situations. For instance, what if a different command was given for both rules for the same target? My guess would be that it gives an error since it wouldn't be obvious which command to execute.

like image 301
Steven Lu Avatar asked Jun 02 '11 13:06

Steven Lu


People also ask

Can a makefile have multiple targets?

Usually there is only one target per rule, but occasionally there is a reason to have more (see section Multiple Targets in a Rule). The command lines start with a tab character. The first command may appear on the line after the dependencies, with a tab character, or may appear on the same line, with a semicolon.

What is $@ in makefile?

The file name of the target of the rule. If the target is an archive member, then ' $@ ' is the name of the archive file. In a pattern rule that has multiple targets (see Introduction to Pattern Rules), ' $@ ' is the name of whichever target caused the rule's recipe to be run.

Can you have multiple makefile?

If you use more than one ' -f ' or ' --file ' option, you can specify several makefiles. All the makefiles are effectively concatenated in the order specified.

Is makefile executed sequentially?

Usually, there's just one action line, but there can be as many as you want; each line is executed sequentially, and if any one of them fails, the remainder are not executed. The rule ends at the first line which is not indented.


2 Answers

You should add one more pattern rule to express the dependency between the .cpp and .d files and use that rule to create the .d files (second line in the pattern rule of your question) instead of creating the .d files unconditionally. It might make sense to introduce another dependency between all .h and .cpp files and all .d files to force re-creating the .d files if a header or source file changes.

Here's the separate rule for .d files (hope I got it right):

-include $(patsubst %.cpp,build/%.d,$(SRC))
build/%.o: %.cpp
    $(CC) $(CXXFLAGS) -c -o $@ $<

build/%.d: %.cpp
    $(CC) $(CXXFLAGS) -MM -MT $@ -MF $<

Edit: So this approach does in fact work quite well. I guess I'd like somebody to provide an answer which gives me some insight into what it is exactly that make does in these situations.

I'm afraid currently it would only work by chance (or you have not given all relevant pieces from the make file). See, you have not expressed any dependency between .d files and .cpp files. This, however, is needed so that your .d files get updated before inclusion as make file fragment.

For instance, what if a different command was given for both rules for the same target? My guess would be that it gives an error since it wouldn't be obvious which command to execute.

With that syntax it wouldn't make a difference. But there are some special cases where splitting the rules into two (though otherwise identical rules) has merit. I strongly recommend you get the book "Managing Projects with GNU Make" to get a grip on the various ways of working with GNU Make. The only other recommendation in connection with GNU Make is to read to read the paper here.

like image 98
0xC0000022L Avatar answered Sep 25 '22 12:09

0xC0000022L


Yes, you can specify several rules for one file, and they get merged into one. See the GNU Make documentation.

[...] There can only be one recipe to be executed for a file. [...] An extra rule with just prerequisites can be used to give a few extra prerequisites to many files at once.

And I second that there should be separate rule for .d files. It's names in many projects are deps or depend.

like image 36
Rajish Avatar answered Sep 24 '22 12:09

Rajish