I have a simple makefile which finds the CPP files relative to it and builds the target from there. How could I modify this to also precompile the header files relative to it when building the target?
TARGET ?= application
CXXFLAGS += -Os -I. -MMD -MP -std=c++11
SOURCES := $(shell find -L . -name '*.cpp')
OBJECTS := $(SOURCES:.cpp=.o)
DEPENDS := $(SOURCES:.cpp=.d)
$(TARGET): $(OBJECTS)
$(CXX) $(OBJECTS) -o $# $(LDLIBS)
.PHONY: clean
clean :
$(RM) $(TARGET) $(OBJECTS) $(DEPENDS)
-include $(DEPENDS)
Looks like I'm not able to do what I had in mind. The solution here is to follow #Rup's advice and include the major dependencies in a single compiled header.
GCC - 3.21 Using Precompiled Headers
A precompiled header file can be used only when these conditions apply:
Only one precompiled header can be used in a particular compilation.
Related
I have the following makefile that I use to build a program (a kernel, actually) that I'm working on. Its from scratch and I'm learning about the process, so its not perfect, but I think its powerful enough at this point for my level of experience writing makefiles.
AS = nasm
CC = gcc
LD = ld
TARGET = core
BUILD = build
SOURCES = source
INCLUDE = include
ASM = assembly
VPATH = $(SOURCES)
CFLAGS = -Wall -O -fstrength-reduce -fomit-frame-pointer -finline-functions \
-nostdinc -fno-builtin -I $(INCLUDE)
ASFLAGS = -f elf
#CFILES = core.c consoleio.c system.c
CFILES = $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
SFILES = assembly/start.asm
SOBJS = $(SFILES:.asm=.o)
COBJS = $(CFILES:.c=.o)
OBJS = $(SOBJS) $(COBJS)
build : $(TARGET).img
$(TARGET).img : $(TARGET).elf
c:/python26/python.exe concat.py stage1 stage2 pad.bin core.elf floppy.img
$(TARGET).elf : $(OBJS)
$(LD) -T link.ld -o $# $^
$(SOBJS) : $(SFILES)
$(AS) $(ASFLAGS) $< -o $#
%.o: %.c
#echo Compiling $<...
$(CC) $(CFLAGS) -c -o $# $<
#Clean Script - Should clear out all .o files everywhere and all that.
clean:
-del *.img
-del *.o
-del assembly\*.o
-del core.elf
My main issue with this makefile is that when I modify a header file that one or more C files include, the C files aren't rebuilt. I can fix this quite easily by having all of my header files be dependencies for all of my C files, but that would effectively cause a complete rebuild of the project any time I changed/added a header file, which would not be very graceful.
What I want is for only the C files that include the header file I change to be rebuilt, and for the entire project to be linked again. I can do the linking by causing all header files to be dependencies of the target, but I cannot figure out how to make the C files be invalidated when their included header files are newer.
I've heard that GCC has some commands to make this possible (so the makefile can somehow figure out which files need to be rebuilt) but I can't for the life of me find an actual implementation example to look at. Can someone post a solution that will enable this behavior in a makefile?
EDIT: I should clarify, I'm familiar with the concept of putting the individual targets in and having each target.o require the header files. That requires me to be editing the makefile every time I include a header file somewhere, which is a bit of a pain. I'm looking for a solution that can derive the header file dependencies on its own, which I'm fairly certain I've seen in other projects.
As already pointed out elsewhere on this site, see this page:
Auto-Dependency Generation
In short, gcc can automatically create .d dependency files for you, which are mini makefile fragments containing the dependencies of the .c file you compiled.
Every time you change the .c file and compile it, the .d file will be updated.
Besides adding the -M flag to gcc, you'll need to include the .d files in the makefile (like Chris wrote above).
There are some more complicated issues in the page which are solved using sed, but you can ignore them and do a "make clean" to clear away the .d files whenever make complains about not being able to build a header file that no longer exists.
You could add a 'make depend' command as others have stated but why not get gcc to create dependencies and compile at the same time:
DEPS := $(COBJS:.o=.d)
-include $(DEPS)
%.o: %.c
$(CC) -c $(CFLAGS) -MM -MF $(patsubst %.o,%.d,$#) -o $# $<
The '-MF' parameter specifies a file to store the dependencies in.
The dash at the start of '-include' tells Make to continue when the .d file doesn't exist (e.g. on first compilation).
Note there seems to be a bug in gcc regarding the -o option. If you set the object filename to say obj/_file__c.o then the generated _file_.d will still contain _file_.o, not obj/_file_c.o.
This is equivalent to Chris Dodd's answer, but uses a different naming convention (and coincidentally doesn't require the sed magic. Copied from a later duplicate.
If you are using a GNU compiler, the compiler can assemble a list of dependencies for you. Makefile fragment:
depend: .depend
.depend: $(SOURCES)
rm -f ./.depend
$(CC) $(CFLAGS) -MM $^>>./.depend;
include .depend
There is also the tool makedepend, but I never liked it as much as gcc -MM
You'll have to make individual targets for each C file, and then list the header file as a dependency. You can still use your generic targets, and just place the .h dependencies afterwards, like so:
%.o: %.c
#echo Compiling $<...
$(CC) $(CFLAGS) -c -o $# $<
foo.c: bar.h
# And so on...
Basically, you need to dynamically create the makefile rules to rebuild the object files when the header files change. If you use gcc and gnumake, this is fairly easy; just put something like:
$(OBJDIR)/%.d: %.c
$(CC) -MM -MG $(CPPFLAGS) $< | sed -e 's,^\([^:]*\)\.o[ ]*:,$(#D)/\1.o $(#D)/\1.d:,' >$#
ifneq ($(MAKECMDGOALS),clean)
include $(SRCS:%.c=$(OBJDIR)/%.d)
endif
in your makefile.
Over and above what #mipadi said, you can also explore the use of the '-M' option to generate a record of the dependencies. You might even generate those into a separate file (perhaps 'depend.mk') which you then include in the makefile. Or you can find a 'make depend' rule which edits the makefile with the correct dependencies (Google terms: "do not remove this line" and depend).
Simpler solution: Just use the Makefile to have the .c to .o compilation rule be dependent on the header file(s) and whatever else is relevant in your project as a dependency.
E.g., in the Makefile somewhere:
DEPENDENCIES=mydefs.h yourdefs.h Makefile GameOfThrones.S07E01.mkv
::: (your other Makefile statements like rules
::: for constructing executables or libraries)
# Compile any .c to the corresponding .o file:
%.o: %.c $(DEPENDENCIES)
$(CC) $(CFLAGS) -c -o $# $<
None of the answers worked for me. E.g. Martin Fido's answer suggests gcc can create dependency file, but when I tried that it was generating empty (zero bytes) object files for me without any warnings or errors. It might be a gcc bug. I am on
$ gcc --version gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-16)
So here's my complete Makefile that works for me; it's a combination of solutions + something that wasn't mentioned by anyone else (e.g. "suffix replacement rule" specified as .cc.o:):
CC = g++
CFLAGS = -Wall -g -std=c++0x
INCLUDES = -I./includes/
# LFLAGS = -L../lib
# LIBS = -lmylib -lm
# List of all source files
SRCS = main.cc cache.cc
# Object files defined from source files
OBJS = $(SRCS:.cc=.o)
# # define the executable file
MAIN = cache_test
#List of non-file based targets:
.PHONY: depend clean all
## .DEFAULT_GOAL := all
# List of dependencies defined from list of object files
DEPS := $(OBJS:.o=.d)
all: $(MAIN)
-include $(DEPS)
$(MAIN): $(OBJS)
$(CC) $(CFLAGS) $(INCLUDES) -o $(MAIN) $(OBJS) $(LFLAGS) $(LIBS)
#suffix replacement rule for building .o's from .cc's
#build dependency files first, second line actually compiles into .o
.cc.o:
$(CC) $(CFLAGS) $(INCLUDES) -c -MM -MF $(patsubst %.o,%.d,$#) $<
$(CC) $(CFLAGS) $(INCLUDES) -c -o $# $<
clean:
$(RM) *.o *~ $(MAIN) *.d
Notice I used .cc .. The above Makefile is easy to adjust for .c files.
Also notice importance of these two lines :
$(CC) $(CFLAGS) $(INCLUDES) -c -MM -MF $(patsubst %.o,%.d,$#) $<
$(CC) $(CFLAGS) $(INCLUDES) -c -o $# $<
so gcc is called once to build a dependency file first, and then actually compiles a .cc file. And so on for each source file.
I believe the mkdep command is what you want. It actually scans .c files for #include lines and creates a dependency tree for them. I believe Automake/Autoconf projects use this by default.
here is my .c and .o files hierarchy:
---/src/IRBuild/main.c
func1.c
func2.c
---/inclue/main.h
func1.h
func2.h
---/build/IRBuild/main.o
func1.o
func2.o
irbuild
Below is my Makefile under ~/src/IRBuild/, I had build compile dependency with .c and .h files, which means whenever .c or .h files are changed. "make" will rebuild the object files. BUT because I output .o files to ~/build/IRBuild/, instead of current directory, "make" will rebuild all the .o files everytime I do make.
How should I build dependencies with .o files in other directories? Only re-compile the particular file when it's .c, .h, or .o file changed?
Stuck here for two days, thanks a lot!
EXE=irbuild
# G++ as default compiler
CC=g++
# Compile time flags
CXXFLAGS = -g -Wall
# Library paths in addition to /usr/lib
LFLAGS=-std=c++0x
# Libraries to link into executable:
#LIBS = -lmylib -lm
# Include files directory other than /usr/include
INCLUDES=-I../../include/
SRC=$(wildcard *.cpp)
OBJ=$(SRC:.cpp=.o)
DEP=$(OBJ:.o=.d)
BUILD=../../build/IRBuild
TESTS=../../tests/
OBJS :=$(foreach obj, $(OBJ), $(BUILD)/$(obj))
.PHONY: depend clean
all: $(EXE)
cp $(EXE) $(TESTS)
$(EXE): $(OBJ)
$(CC) $(CXXFLAGS) $(LFLAGS) $(INCLUDES) -o $(EXE) $(OBJS)
.cpp.o:
$(CC) $(CXXFLAGS) $(LFLAGS) $(INCLUDES) -c $< -o $(BUILD)/$#
clean:
rm -f $(OBJS) $(DEP) $(EXE)
depend: .depend
.depend: $(SRC)
rm -f ./.depend
$(CC) $(CXXFLAGS) $(LFLAGS) $(INCLUDES) -MM $^ -MF ./.depend;
include .depend
You are violating rule 2 from http://make.mad-scientist.net/rules.html which is why it rebuilds them all the time it thinks they don't exist. (Listing $(OBJ) in the prereqs and $(OBJS) in the recipe linking line is also a bit of a makefile "smell".)
You need to use a rule that correctly maps from your target files to their prerequisites.
Either manually or using vpath.
There are a number of ways to make the manual method work depending on how much effort you want to put in to setting things up. The vpath method is likely to be a fair bit easier.
Using vpath should just require using $(OBJS) as the $(EXE) prereqs and then adding vpath %.cpp . and vpath %.h ../../include or something like that.
I have looked, and found a few answers that look like they're related to this question, but none seem to help.
It is the usual story - I have a folder of .hpp and .cpp files which I'd like to compile to .o files, and then only have files recompiled when files they depend on have been changed.
My current makefile is:
SRCS = $(shell find ../Includes/ -name "*.cpp")
DEPS = $(SRCS:.cpp=.d)
OBJS = $(SRCS:.cpp=.o)
all: $(DEPS) $(OBJS)
# Create the dependency files
%.d : %.cpp
clang++ -MM $< -o $# -c -std=c++11
# Include the dependency files
include $(DEPS)
# Compile the source files
%.o : %.cpp
clang++ -c -Wall -std=c++11 $< -o $#
I've run this a few times (so the dependency files exist before I run make, and should definitely exist when I include them). I've also tried adding %.d to the dependancies of %.o.
Basically all that happens at the moment is that 'touch'ing a .cpp causes the .o and .d files to be regenerated, and touching a .hpp file (that is listed in the .d files for other files) does nothing.
Example Dependency File:
SomeFile.o : ../Includes/SomeFile.cpp \
../Includes/SomeFile.hpp ../Includes/SomeOtherFile.hpp
Apart from the path issue, I find it more natural to create the dependencies along the way, i.e. with the -MD or -MMD flags. That way you don't need a rule to update the dependency file.
CPPFLAGS += -MMD
TARGET := hello
.DEFAULT: all
all: $(TARGET)
SRCS := $(shell find . -type f -name "*.cpp")
OBJS := $(SRCS:.cpp=.o)
DEPS := $(SRCS:.cpp=.d)
hello: $(OBJS)
$(LINK.cc) -o $# $^
-include $(DEPS)
It turns out that I was creating rules for:
SomeFile.o : ...
Whereas I needed a rule for:
../Includes/SomeFile.o : ...
Thanks to NovaDenizen who set me on the right path.
Sometimes I need my project to use plain makefile, although it's a dated building technology not recommended for any use, but since make is available almost everywhere it sometimes makes sense.
However I want my Makefile to look something like
Include "../buildexec.mk"
TARG = my_exec
CPPFILES = file1.cpp \
file2.cpp \
and have all the generic (and horrible) dependency tracking code being in buildexec.mk.
Is there such a "Make library"?
In Go, there's a standard Makefile you can include, and your Makefile looks as beautiful like this:
include $(GOROOT)/src/Make.inc
TARG=irc
GOFILES=irc.go irc_struct.go irc_callback.go
include $(GOROOT)/src/Make.pkg
Anything similar for C++?
clarification: I know of tup, cmake and scons/ I know of waf and bjam and so on/ but I want my deps to so small/ so that compilation is no trouble at all. I specifically asked for Make support, not for Make alternative.
I would suggest generating the makefile with automake instead. Cmake also generates makefiles, while also being able to generate project files for several IDEs.
The problem is there is no one make. The very basic syntax is always the same, but anything slightly more complex (which you need for such includes) is not compatible even between GNU make and BSD make (not trying to mention nmake). Automake can however deal with several versions of make and provide automatic dependency rules where available (only some compilers support them).
You probably want to look at CMake or Premake.
With large C/C++ projects you tend to have additional requirements such as platform specific APIs or libraries that need customization.
This will do what you're asking for (at least in GNUMake).
makelib.mk:
$(TARG): $(CPPFILES:.cc=.o)
$(CC) $^ -o $#
%.o : %.cc
$(CC) -MD -o $# $<
#cp $*.d $*.P; \
sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
-e '/^$$/ d' -e 's/$$/ :/' < $*.d >> $*.P; \
rm -f $*.d
-include $(CPPFILES:.cc=.P)
Makefile:
CPPFILES = foo.cc bar.cc
TARG = someTarget
include makelib.mk # Note lower-case "i"
CPPFILES = baz.cc quartz.cc quince.cc
TARG = anotherTarget
include makelib.mk
...
But a word of advice: don't curse your tools so much. It's energy you could be using to either learn how to use them or switch to ones you like better.
There's a googlecode project doing exactly what I wanted:
http://code.google.com/p/nonrec-make/
There is none of my knowledge. There are really a lot of problems with make, but it is still the most available tool around, and once you get it running properly you should just focus on your development.
Until there, you will have to write makefiles. But instead of looking for a 'make library', a really simple solution (if you're actually initiated in Make language), often overlooked for being too obvious, is to implement your own. Create a make script containing a set of default pattern rules and variables for communication with the project makefile, and just include this script in every project's makefile. It's not hard, maybe a little time-consuming, but it often pays off really well, specially if you have lots of small projects to manage.
I work with such a design. I have a couple of GNU make scripts carefully designed to offer an almost trivial mechanism to create rather complex build systems: automatic dependency generation, handling of different languages, generation of language parsers, different build configurations (debug or release), build log generation, and so on. And the script is not cumbersome: the current version contains just about 250 lines of makefile code, excluding comments.
I will leave you with a sample of an older version of such system, handling C source code only, which contained a few features. It should handle the compilation of binaries and libraries (both static and dynamic). It also should help you track inter-project dependencies through the DEPS variable.
Call this $(ROOT)/project.mk:
# Remove the default suffix rules.
.SUFFIXES:
# Turn on the delete-on-error feature.
.DELETE_ON_ERROR:
# Set up additional command variables.
STRIP ?= strip
# Set up a global search path to locate prerequisites.
VPATH := $(VPATH) $(shell find -type d)
# Locate all source files from the default locations in the project tree.
SRC := $(SRC) $(shell find src -name '*.c')
# Set up the default dependency files.
DEP := $(DEP) $(addprefix dep/,$(addsuffix .d,$(basename $(notdir $(filter %.c,$(SRC))))))
# Set up the default object files.
OBJ := $(OBJ) $(addprefix obj/,$(addsuffix .o,$(basename $(notdir $(filter %.c,$(SRC))))))
# Set up a set of default flags for all commands used.
STRIPFLAGS ?= -p
CPPFLAGS ?= -DNDEBUG
CFLAGS ?= -Wall -Wextra -Werror -pedantic -O3 -march=native -fomit-frame-pointer -ffast-math
LDFLAGS ?= --as-needed -O1
ARFLAGS ?= -scr
# Set up the default include and library search paths.
override INCLUDES := \
$(addprefix $(ROOT)/,$(addsuffix /include,$(DEPS))) \
$(INCLUDES)
override LIBRARIES := \
$(addprefix $(ROOT)/,$(addsuffix /lib,$(DEPS))) \
$(LIBRARIES) lib
# The default rule to build every target in the project.
.PHONY: all
all: deps $(DEP) $(OBJ) $(BIN) $(LIB)
# Phony rule to recursively build the library dependencies.
.PHONY: deps
deps:
#for dep in $(DEPS); do cd $(ROOT)/lib/$$dep && $(MAKE); done
# Secondary expansion is used to properly locate prerequisites.
.SECONDEXPANSION:
# Rule for dependency file generation.
%.d: $$(notdir $$*).c
$(CC) -M $(CPPFLAGS) $(CFLAGS) -iquote include $(addprefix -I ,$(INCLUDES)) $< -MM -MG -MP -MT '$# $(filter %/$(notdir $*).o,$(OBJ))' > $#
# Rule for compiling object files.
%.o: $$(notdir $$*).c
$(CC) -c $(CPPFLAGS) $(CFLAGS) -iquote include $(addprefix -I ,$(INCLUDES)) $< -o $#
# Rule for linking binaries.
%: $$(notdir $$*).c
$(CC) $(CPPFLAGS) $(CFLAGS) $(addprefix -Xlinker ,$(LDFLAGS)) -iquote include $(addprefix -I ,$(INCLUDES)) $(addprefix -L ,$(LIBRARIES)) $(filter-out $<,$^) -o $# $(addprefix -l,$(LDLIBS))
$(STRIP) $(STRIPFLAGS) $#
# Rule for linking shared libraries.
%.so: $$(notdir $$*).c
$(CC) $(CPPFLAGS) $(CFLAGS) $(addprefix -Xlinker ,$(LDFLAGS)) -iquote include $(addprefix -I ,$(INCLUDES)) $(addprefix -L ,$(LIBRARIES)) $(filter-out $<,$^) -o $# -fpic -shared -Wl,-h,$(notdir $#) $(addprefix -l,$(LDLIBS))
$(STRIP) $(STRIPFLAGS) $#
# Rule for generating static libraries.
%.a:
$(AR) $(ARFLAGS) $# $?
# Include all dependency files and remake them if necessary.
ifneq ($(MAKECMDGOALS),clean)
include $(DEP)
endif
# Phony rule to clean the entire build tree.
.PHONY: clean
clean:
#for dep in $(DEPS); do cd $(ROOT)/lib/$$dep && $(MAKE) clean; done
$(RM) $(DEP) $(OBJ) $(BIN) $(LIB) $(CLEAN)
ROOT contains the path for your projects' directory (working copy of repository, for example), typically exported as an environment variable. You will also need a couple of directories (bin, dep, obj and src) in your projects.
An example Makefile using this system could be:
DEPS := mylib
BIN := bin/test
LIB := lib/libtest.a
include $(ROOT)/project.mk
bin/test: $(OBJ)
lib/libtest.a: obj/test1.o obj/test2.o
That is, you just write the minimum necessary about your project, and let the build system do the rest. You can always explicitly specify the value for a given variable (SRC, for example, or CFLAGS), but if you don't, then it gets a reasonable default.
The above was tailored to my needs, but it should be simple to adapt to yours, while keep things as easy as the examples you've mentioned.
I want a build rule to be triggered by an include directive if the target of the include is out of date or doesn't exist.
Currently the makefile 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 it seems like the include directive is executing before the rule to build make.deps which effectively means that make is either getting no dependency list if make.deps doesn't exist or always getting the make.deps from the previous build and not the current one.
For example:
$ 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 sounds like if the include target doesn't exist it will continue processing the parent makefile try and build the target, but it's not completely clear to me how this works:
If an included makefile cannot be
found in any of these directories, a
warning message is generated, but it
is not an immediately fatal error;
processing of the makefile containing
the include continues. Once it has
finished reading makefiles, make will
try to remake any that are out of date
or don't exist. See section How
Makefiles Are Remade. Only after it
has tried to find a way to remake a
makefile and failed, will make
diagnose the missing makefile as a
fatal error.
ANSWER
This is a modification of the answer I accepted. The one thing missing was that the dependency files also depend on the sources, and won't get regenerated unless they are added to the deps files which are being included:
%.d: $(program_CXX_SRCS)
# $(CXX) $(CPPFLAGS) -MM $*.cpp | sed -e 's#^\(.*\)\.o:#\1.d \1.o:#' > $#
sed adds the name of the .d file to the beginning of each dependency line like so:
foo.d foo.o: foo.cpp foo.h bar.h baz.h
I got the idea from this amazing paper on the dangers of recursive make:
Recursive Make Considered Harmful
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
You are relying on an implicit rule to compile your .cpp files. You have to redefine it to use the -MM and -MF flags that will create the dependency file.
%.o: %.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $# -MM -MF $#.d
Then, you have to include these dependencies files in the Makefile, using -include that will not error when the dependencies files do not exist yet (on the first time, or after a clean).
program_DEPS := $(program_OBJS:.o=.o.d)
-include $(program_DEPS)
And remember to add the rm command for the dependencies files in the clean rule.
An important point that it took me a while to grasp is that the make.deps from the previous build are good enough. Think about it: for a given object file, the only way the list of dependency files can change is if... one of the old dependency files has been altered. And if that's the case, then the old make.deps will cause that object file to be rebuilt, and if rebuilding the object file also rebuilds make.deps, then everything will be up to date. You don't have to rebuild make.deps before checking to see which objects must be rebuilt.
The include directives work like they do in C and C++ - they are processed before anything else happens, to build the "real" makefile that make then processes. Specifically, they are processed before any rules are fired.