I have written a Makefile to compile an openCV program on OSX (more general in Unix systems).
The code has a header named constants.hpp
where some constants are defined.
I would like to make the Makefile recompile the program when this header file changes because the values of the constants in it change the program behavior.
My Makefile is the following
CPP = g++
CPPFLAGS = -std=c++11
all: main.o
main.o: main.cpp
$(CPP) $^ $(CPPFLAGS) -o $@
Searching around I tried to define after CPPFLAGS
the value:
DEPS = constants.hpp
and then since main.o
depends on it
adding the dependency as follows:
main.o: main.cpp $(DEPS)
$(CPP) $^ $(CPPFLAGS) -o $@
but the error I get is clang: error: cannot specify -o when generating multiple output files
.
I tried also this answer and tried to use th e M
MM
flags but I am missing something.
How to make Makefile recompile when a header file is changed?
EDIT: Following the comments to DevSolar I had to modify completely the question and he asked also the source code. Since I found useless to copy all the source code here I simplified it with a simple hello world program.
The following is the main.cpp
:
#include<iostream>
#include"constants.hpp"
int main()
{
std::cout<<"Hello world, the value is: " << myValue <<"\n";
return 0;
}
and the following the constants.hpp
:
static const int myValue = 10;
Preface
You are using
$(CPP)
and$(CPPFLAGS)
... that's for the preprocessor. What you want to use is$(CXX)
and$(CXXFLAGS)
, for the C++ compiler.The following assumes GNU make and a GCC-compatible compiler (clang will do).
Step One
Use generic rules, not one per source file -- the latter will very quickly become unwieldly, and is very error-prone.
Either list your source files manually...
...or have all source files listed automatically:
You also need a list of the object files (one .o per .cpp):
Now provide a rule for the executable, depending on all the object files...
...and a generic rule on how to turn the individual source file into an object file:
Making this rule depend on the Makefile as well ensures that e.g. changes in
$(CXXFLAGS)
trigger a recompile as well.$<
resolves to the first dependency (the source file).We will extend this rule later.
Step Two
We will have a dependency file for each source file. (Bear with me here.) We can generate a list of those files...
...and include them into the Makefile:
The
-
there means thatmake
will not complain if those files do not exist -- because they do not, at this point.Step Three (Core of the answer to your question)
Have the compiler generate those dependency files for us -- because it knows best. For that, we extend our build rule:
The
-MMD
flag generates the dependency file (%.d
), which will hold (in Makefile syntax) rules making the generated file (%.o
in this case) depend on the source file and any non-system headers it includes. That means the object file gets recreated automatically whenever relevant sources are touched. If you want to also depend on system headers (i.e., checking them for updates on each compile), use-MD
instead.The
-MP
option adds empty dummy rules, which avoid errors should header files be removed from the filesystem.At the first compile run, there is no dependency information -- but since the object files don't exist either, the compiler must run anyway. For every subsequent run,
make
will include the auto-generated dependency files, and "do the right thing".All-In-One (with some more syntactic sugar added):
If you only have one source code file entering the compilation which the object file depends on try
This will only work as long as you don't use multiple
.cpp
files entering the compilation.$^
is an automatic variable which holds all the prerequisites of the current recipe separated by whitespaces whereas$<
just holds the first prerequisite. This is why you can't use this solution for multiple.cpp
files in the same compilation.