Managing Dependency Complexity in Make Files - c++

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

Related

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)

how to write makefile to take care of changes in the header file

Actually i have a library 'cryptopp' and what i want is that when i make any change to a file and issue the make command it should take care of the changes made in any file in the source directory. well, the GNUMakefile of cryptoopp takes care of the changes 'if' made in the '.cpp' files but not for the changes made in a '.h' file.
So what changes can i make in the 'GNUMakefile' of cryptopp so that it looks at all the modified header files and recompiles all the files dependent on the 'modified' header file.
If you are building with g++ you can let g++ generate dependancy makefiles.
You can include these in your main makefile.
Use the -M and -M* arguments to use this feature. (see http://gcc.gnu.org/onlinedocs/gcc-4.6.1/gcc/Preprocessor-Options.html#Preprocessor-Options)
You have to add all the dependencies to your Makefile:
mycode.o: mycode.cpp mycode.h somelib.h resources.h
$(CXX) -c -o $# $< $(CXXFLAGS) $(INCLUDES)
If you already have a generic pattern matching command line, you don't have to say the command again, you can just list the dependencies:
%o: %.cpp
$(CXX) -c -o $# $< $(CXXFLAGS) $(INCLUDES)
mycode.o: mycode.cpp mycode.h somelib.h resources.h
yourcode.o: yourcode.cpp yourcode.h mycode.h somethingelse.h
# ...
In general, this is a terrible and unscalable mess. You'll almost definitely want a higher-level build system to generate the Makefile for you. Even for very small projects keeping the header dependencies up to date in the Makefile is such a pain that it is simply not worth it.
There are several popular portable build environments. I personally like cmake a lot, which includes discovery if you changed the build settings (say from Debug to Release) and will always build all the necessary files (for example, if you change the cmake master file and type "make" it'll automatically run cmake again for you first).
For a Unix-only solution you could try makedepend, or the infamous autotools, though that's a whole other headache...
You might try 'makedepend' if it's installed on your system. The easiest way is to add a target to your makefile. Something like:
depend:
makedepend *.cc
You might have to replace the '*.cc' with a list of your source files. Then you can regenerate all the dependencies with 'make depend' command. You might want to redirect error messages to /dev/null since it always seems to generate a lot of noise.

Makefile multiple dependency lines for a single target?

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.

any building tool can automatically understand file dependencies in C++ project?

I have a project with 50+ .h files and 50+ .cpp files. I'm using make to build a project, which looks something like this (it's just a piece of an entire file):
HEADERS := $(shell find $(INCLUDE) -name "*.h")
%.obj: %.cpp $(HEADERS)
$(CPP) $(CPPFLAGS) -fPIC -o $# -g -c $<
When I'm making changes to one .h file, the whole project has to be re-compiled. It's annoying and time-consuming. But I don't want to hard-code file dependencies inside Makefile, since it's even more time-consuming. I would like to have some make-like tool, which will find dependencies right inside my .cpp/.h files, automatically. Any suggestions? Thanks in advance!
There are many options, but nothing that works exactly like make. Many build systems will generate the Makefiles with dependencies for you though. CMake and Automake are two commonly used systems that work like that. You define your project file in a meta-language and it will generate the Makefiles.
Scons is good in finding the right sources that need to be recompiled.
It scans the files and the headers and builds up an internal dependency tree.
www.scons.org
If you are using gcc then you can use the -M option. It is designed to do exactly what you want i.e. generate a Makefile rule describing the dependencies.
Simplest way:
depend:
g++ -M *.cpp >.depends
-include .depends
Better way:
SRC=foo.cpp bar.cpp ...
OBJ=$(patsubst %.cpp,%.o,$(SRC))
DEPS=$(patsubst %.o,.deps/%.o.dep,$(OBJ))
all: .deps
.deps:
mkdir -p .deps
.cpp.o:
$(CXX) $(CXXFLAGS) -MD -MF .deps/$#.dep -c -o $# $<
-include $(DEPS)
So compiler will generate all dependencies for each file during build automatically.
Or even better: use Autotools, CMake or other build system that does this job for you.
Jam.
Boost.Build.
The latter is based on a (massively) enhanced version of the former.

In a makefile, how do I execute a command on each file name in variable?

I know I am doing it wrong, but I can't figure out how to organize this makefile. I define my util source files, and use some functions to define the .o files from them here:
UTIL_SRC = utils/src/foo.cpp utils/src/bar.cpp utils/src/baz.cpp
UTIL_OBJS = $(patsubst utils/src/%.cpp,utils/obj/%.o,$(UTIL_SRC))
This is the target that I use these files for:
lib : lib/libutils.a
lib/libutils.a : $(UTIL_OBJS)
rm -f lib/libutils.a
ar -c -q lib/libutils.a $(UTIL_OBJS)
Then, when I get to the rule to compile these babies, I would love to just have one command that would iterate through each UTIL_OBJS file and each UTIL_SRC file. Instead I have resorted to this monstrosity, which defeats the purpose of storing them in variables.
$(UTIL_OBJS) : $(UTIL_SRC)
g++ $(UTIL_FLAGS) utils/src/foo.cpp -o utils/obj/foo.o
g++ $(UTIL_FLAGS) utils/src/bar.cpp -o utils/obj/bar.o
g++ $(UTIL_FLAGS) utils/src/baz.cpp -o utils/obj/baz.o
Can I condense this down to one line? How? Thanks, great ones!
It's usually easier to work with implicit rules. There are a lot of predefined ones, where you'll only need to specify variables.
CXX=g++
CXXFLAGS=$(UTIL_FLAGS)
Then you need to define an executable, like this
myutil: $(UTIL_OBJS)
Since you're not storing your objects in the same directory, you'll need to specify a new implicit rule as well though (otherwise, we'd be done now).
utils/obj/%.o: utils/obj/%.cpp
% is a pattern-match, it'll match the same text on both left and right side, so this rule will make foo.o out of foo.cpp.
Try if that'll work without the command (it might have grabbed that from another rule, I'm not sure), otherwise let it say:
utils/obj/%.o: utils/obj/%.cpp
$(CXX) $(CXXFLAGS) -o $# $^
$# is the target of the rule (e.g. foo.o), and $^ is all files on the right hand side.
I'm writing this off the top of my head, without the possibility to test it, so please let me know how it turned out.. :)
To make it even more elegant, you can include a dependency file
include .depend
If you're running GNU make, it'll try to make the .depend file if it can't find it (with old school make, you need to create it yourself first, it can be just a dummy though, if you'd like to manage it through the makefile)
.depend: $(UTIL_SRC)
$(CXX) -MM -o $# $^
The dependency file will contain lines for each .cpp file, telling make what header files it needs, which will allow make to recompile the necessary files when you change something. This doesn't help with your original question though, just thought it might come in handy.
EDIT:
As a response to your edit. You could probably drop the commands for creating the .a-file as well, that too is already available as an implicit rule. Not sure exactly how it works though, haven't used it much. I do know that there are a bunch of quirks in make for dealing with .a(rchive?)-files.
I think you could use this:
$(UTIL_OBJS) : $(UTIL_SRC)
g++ $(UTIL_FLAGS) $(# : .o = .cpp) -o $#
again, I'm not quite sure... especialy about the $(# : .cpp = .o) part