Makefile multiple dependency lines for a single target? - c++

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.

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.

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.

POSIX 7 also says that multiple lines for a given target work http://pubs.opengroup.org/onlinepubs/9699919799/
A target that has prerequisites, but does not have any commands, can be used to add to the prerequisite list for that target. Only one target rule for any given target can contain commands.
so long as only one has the commands.

Related

Makefile to get source files in multiple subdirectories

I am creating a custom Makefile to to build a C++ Linux application. I have my cpp source files in a folder called src on the same level as the Makefile. So far I have been able to build my object files with the following :
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp | $(OBJ_DIR)
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $#
Now my project is starting to get a bit more complicated and I want subdirectories within src , such as src/common , and also, not every file is a cpp file now but also a c file.
I guess having a separate Makefile for each subdirectory is the best way but I am trying to keep this simple for now with just one Makefile.
I tried the following but doesn't work
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp $(SRC_DIR)/common/%.cpp $(SRC_DIR)/common/%.c | $(OBJ_DIR)
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $#
I could have the Makefile do a shell find to find all cpp and c files but also trying to avoid this.
I'd appreciate any recommendations.
This:
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp $(SRC_DIR)/common/%.cpp $(SRC_DIR)/common/%.c | $(OBJ_DIR)
cannot work; what it says that if make wants to build some file $(OBJ_DIR)/XXX.o and there is no explicit rule, then if and only if ALL the prerequisites $(SRC_DIR)/XXX.cpp, $(SRC_DIR)/common/XXX.cpp, and $(SRC_DIR)/common/XXX.c exist or can be created by make, then the rule will match.
If the same target could be built from multiple different prerequisites you must create multiple rules, one per prerequisite.
Also, it doesn't make sense to compile both C files (.c) and C++ files (.cpp) using the same recipe. C++ compilers use the variables CXX and CXXFLAGS and C compilers use the variables CC and CFLAGS.
As for avoiding find, you can't avoid informing make what files you want to be compiled, in some manner. You either have to list them in your makefile explicitly, or else use some method to generate them dynamically. There's no way around this. You don't have to use find if you don't want to; for example if you know that all the files will be either one or two directories down you could use wildcard, like:
SRCS := $(wildcard $(SRC_DIR)/*.cpp $(SRC_DIR)/*.c $(SRC_DIR)/*/*.cpp $(SRC_DIR)/*/*.c)

Example makefile for building simple c project recompiling when headers change

Does anyone have a complete makefile that can do the following:
Rebuilds the project if a HEADER file changes
The cpp files are listed in the makefile
The header files are NOT listed in the makefile
The header files are allowed to have different names than the cpp files
Some of the cpp files do not have header files
I have seen instructions for figuring out how to make the make tool figure out header dependencies, but none of these instructions provide anything remotely resembling a working example. A simple example would be as follows: main.cpp C1.cpp C1.h C2.cpp C2.h
CXX = g++
OBJECTS := main.o C1.o C2.o
all: $(OBJECTS)
%.o : %.cpp
$(CXX) $(CPPFLAGS) -Wall -MMD -c $< -o $#
-include *.d
EDIT: As TobySpeight points out, this won't work if you build an object file, rename or delete one of the prerequisite source or header files, then try to rebuild the object file; the .d file will still require the missing file, and the build will fail. I neglected to include lines to deal with that case:
%.h: ;
%.cpp: ;
(This is effective, but crude. The more precise approach is to put some sed commands in the %.o rule, so as to add specific null rules to the .d file, one for each prerequisite, but the sed commands are ugly, and the approach above is good enough for almost all cases.)
You can also use CMake for this. Everything you need to write is:
add_executable (exec main.cpp C1.cpp C2.cpp)

Pattern Matching mingw make

I'm extremely new to Makefiles, and I'm currently trying to build my first one on a project I'm starting.
The problem I'm having is having it automatically know how to handle all my .cpp files without defining rules for each one.
I also want my object files to all be put in one folder which is $(PLATFORM)/obj/ where PLATFORM=win32 in this case.
The follwing is what I'm using for a Makefile, executing it with mingw32-make.exe
CXX=g++
CXXFLAGS=-c -Wall -DALLEGRO_STATICLINK
LDFLAGS=
PLATFORM=win32
SOURCES=main.cpp
EXECUTABLE=app.exe
OBJDIR=$(PLATFORM)/obj/
OBJECTS= $(SOURCES:%.cpp=$(OBJDIR)%.o)
all: $(EXECUTABLE)
%.o: %.c
$(CXX) $(CXXFLAGS) $< -o $#
$(EXECUTABLE): $(OBJECTS)
$(CXX) $(OBJECTS) $(LDFLAGS) -o $(EXECUTABLE)
I'm getting the error:
mingw32-make: * No rule to make target win32/obj/main.o', needed by
app.exe' . Stop.
I'm not sure what I'm doing wrong, I've been looking around at other examples of makefiles and they seem to have a similar structure, so I'm not sure whats wrong with mine. I'm looking for an explanation of why this is happening, and advice on how to fix it.
Also, any comments on my style, suggestions for making it more clean/standardized would be great as well. While learning to make makefiles, I want to make sure I'm learning properly.
Thanks
make sees that it needs to create win32/obj/main.o, but can't see any rule to tell it how to do that.
You have three rules, one for all, one for %.o and one for $(EXECUTABLE). The first one and the last one will not tell make how to create win32/obj/main.o.
The second rule probably should, but it says this: if you want to create <something>.o, then first make sure that there's a file called <something>.c (if it doesn't exist, try to find a rule to make it). Then run the following command: $(CXX) ...
But the file <something>.c doesn't exist, because your files end with .cpp. So this rule fails. make can't find any other rule to build win32/obj/main.o, so it gives up.
In summary, you need to change the rule so that %.o depends on %.cpp, and then make will be able to run the command to create the object file. So the rule should be:
%.o: %.cpp
$(CXX) $(CXXFLAGS) $< -o $#
By the way, make also has predefined implicit rules. Because you give an explicit rule for %.o you're actually overriding the predefined rule. I suggest you try at some point not to give this rule at all (but still define CXX and CXXFLAGS) and see what happens. See this for details.
I don't want to dissuade you from using manual makefiles, but if you want to eliminate the problem altogether, there are autotools available that will generate the makefiles for you. Since you're using Windows, I suspect you're using cygwin (or perhaps MingGW). For cygwin, just download the autotools binary package. If you're using eclipse for your IDE (which I strongly promote), you can configure your environment to pick up on the autotools. This way, you just focus on writing the code. All configurability options still exist, but you don't have to know make.

Managing Dependency Complexity in Make Files

I am working on my first open source C++ project: https://github.com/jehugaleahsa/spider-cpp.
I am managing my own Makefile and I have "best practices" question regarding how to manage dependencies. Right now, I make each .o file dependent on each of the included header files in the .cpp file. So:
code.o: code.cpp code.hpp dep1.hpp de2.hpp
g++ -c code.cpp
First of all, I am pretty sure Make supports a shorthand for creating object files. If someone would show an example of this, I'd appreciate it.
Next, is there a way to avoid listing every included header as a dependency? I want to make sure if I change a dependency, that the changes are still compatible. Listing the included headers is tedious and easy to mess up.
OP:
First of all, I am pretty sure Make supports a shorthand for creating object files. If someone would show an example of this, I'd appreciate it.
From here:
OBJS := foo.o bar.o
#Your program should have the objects as dependencies, and link them
proggie: $(OBJS)
gcc $(OBJS) -o proggie
# compile
%.o: %.c
gcc -c $(CFLAGS) $*.c -o $*.o
OP:
Next, is there a way to avoid listing every included header as a dependency
Lower down on the same page, see these lines:
# pull in dependency info for *existing* .o files
-include $(OBJS:.o=.d)
# compile and generate dependency info
%.o: %.c
gcc -c $(CFLAGS) $*.c -o $*.o
gcc -MM $(CFLAGS) $*.c > $*.d
Basically what this does is use gcc's -MM option to obtain a list of header files, and now we can depend on them. Thus we output a file with a list of such header files to a .d file, and then next time, we add the list of files as a dependency, which is what the -include command does. The "-" avoids error if the dependency .d files don't exist yet.
Note, you should modify the above to account for .cpp files
Yes, make supports shorthand for creating object files. This is called rules. And yes, there is a way to avoid listing every included header as a dependency. g++/gcc has -MM option which will generate the full list of dependencies.
Unfortunately, there is no simple explanation on how to do it which I could put here.. You have to read docs and play with make utility. I found this book very helpful: "Managing Projects with GNU Make". There is a doc on GNU site but I found it a bit harder to read. www.gnu.org/software/make/manual/make.html

Using GCC dependency files causes Make to rebuild project completely every time

I've followed the instructions online to set up gcc (actually g++) to generate .d files for dependencies, and now my makefile looks something like this:
CPPFLAGS := ... -MMD -MP
...
OBJECTS := $(shell find *.cpp *.s | sed -e 's/\.cpp/\.o/' -e 's/\.s/\.o/')
all: setupdir $(OBJECTS) link image
And then at the end of the file:
-include $(pathsubst %.d,obj/%.d,$(OBJECTS:.o=.d))
The .d files are being correctly generated, and all show up in the obj directory. The problem is, now, even with the assembly files that don't have .d files generated for them the entire source tree is being rebuilt every time I run make. The project doesn't take long to compile, but still, how would one go about fixing it so that make runs correctly?
It's important to note that -M is not magic bullet for dependencies, in many cases you'll need to specify certain headers so things are re-built appropriately if they change. In fact, the most common problem with letting gcc handle dependencies is things not being re-built that should be (broadly depending on the version of GCC being used by whoever runs make).
That being said, I don't see anything blatantly wrong with what you're doing.
What I recommend doing is eliminating the shell tricks, since it's quite easy to specify exactly what you want. E.g.
foo_SOURCES = \
src/foo.cpp \
src/bar.cpp
foo_OBJECTS = $(foo_SOURCES:.cpp=.o)
foo_DEPS = $(foo_OBJECTS:.o=.d)
%.o : %.cpp
$(CC) $(CFLAGS) ... $< -o $#
$(CC) -M $< > $(#.o=.d)
# lots more rules and targets here
# and finally, at the bottom:
-include $(foo_DEPS)
This is off the top of my head in meta form, so check it to be sure. I believe your problem is actually the dependencies not being included, but I don't see anything obviously wrong with the way you are using pathsubst.
As people have noted in comments, running make with debug on may be helpful, but a good first step would be to specify your objects and dependencies without talking to the shell.
If you get that working, try just storing the results of your shell calls and echoing them to the screen. That's a lot less noisy than make's debug output.