Our project was quite large and actually used several scons ‘variant_dirs’ for different components. Gcc/Clang put the paths to the corresponding sources into the generated coverage files and other tools like gcov/lcov use those paths when generating coverage reports.
Normally this doesn’t matter, but it caused me problems when I was trying to collect code coverage metrics for a project. It’s actually _really hard_ to control the directory where scons runs the compiler from: I had a case where I needed to have the compiler run from a different directory than where scons was running it. One example where I got bit by scons specifically: They _are_ often _easier_ to get a project up running quickly, but have _a lot_ more hidden internal complexity. I think the “simplicity” in tools like cmake and scons are illusionary. Hope those techniques are helpful for you. INC_FLAGS := $(addprefix -I,$(INC_DIRS)).INC_DIRS := $(shell find $(SRC_DIRS) -type d).Find all the directories under the given source directories: I used a similar technique to generate include directory flags. o to every source file path:Īnd then you can make your target depend on the objects files:Īutomatic Generation of Include Directory Flags I basically just prepend a $(BUILD_DIR)/ and append a. SRCS := $(shell find $(SRC_DIRS) -name *.cpp -or -name *.c -or -name *.s)īut because Make works backward from the object files to the source, we need to compute all the object files we want from our source files.
The simplest and fastest way I found to do this was to just shell out and use find. d files, you just need to find them all:Īutomatic Determination of List of Object/Source Filesįirst, find all of the source files in the given source directories. To generate the dependency files, all you have to do is add some flags to the compile command (supported by both Clang and GCC): If you generate the dependency files as part of the compilation step, things get much simpler. However, the docs seem to assume that the dependency files are generated in a separate step from the compile step, which complicates things. o files having different ideas about what types or prototypes look like. Especially since, if you mess it up, you don’t get any explicit errors–things just don’t get re-compiled when they ought to be. Handling the header dependencies is perhaps the most tedious thing about using the classic Make technique. o files in the same directory, you can use $(BUILD_DIR)%.o: %.c. For example, instead of a pattern like: %.o: %.c, which would map your. To do this in Make, you mostly just need to prepend your output directory to the beginning of your pattern rules. It also makes a lot of other things, such as grep’ing the source, a lot nicer. build) even if other artifacts besides the ones generated via Make end up there. This makes is easy to do a clean (just rm -rf. I want all the artifacts from a build to end up in some directory (I usually name it “./build”) that’s separate from the source. Here’s an overview of how it works: Out-of-Source Builds If you run into issues, running make -d can be helpful.
Then make sure you have CC and CFLAGS set to what you need for your project or just use the Make defaults. src (you can change this directory by changing SRC_DIRS). To use one of them, put the Make code in a file call Makefile (make sure the TAB characters get copied! Make is very picky about those) and all of your source and headers in the directory or a subdirectory of.
$(CC) $(LDFLAGS) $(OBJS) -o $(LOADLIBES) $(LDLIBS) $(MKDIR_P) $(dir $(CPPFLAGS) $(CXXFLAGS) -c $< -o cleanĪlso, if you don’t care about out-of-source builds, you can use this even simpler Makefile, which takes advantage of the built-in implicit rules: $(MKDIR_P) $(dir $(CPPFLAGS) $(CFLAGS) -c $< -o c++ source $(MKDIR_P) $(dir $(ASFLAGS) -c $< -o c source INC_DIRS := $(shell find $(SRC_DIRS) -type d) SRCS := $(shell find $(SRC_DIRS) -name *.cpp -or -name *.c -or -name *.s) Here is a simple Makefile that will do all these things and works with C, C++, and assembly:
Automatic generation of include directory flags.Automatic determination of list of object/source files.Automatic (and accurate!) header dependencies.Out-of-source builds (object files get dumped in a separate directory from the source).
Until recently, there were four things I wanted my build system to do for me that I hadn’t figured out how to do in Make: I’ve used Make for a lot for small projects, but for larger ones, it was just too tedious.