I am working my way through a make tutorial. Very simple test projects I am trying to build has only 3 files: ./src/main.cpp ./src/implementation.cpp and
According to the make manual, you can use the implicit linking rule with multiple objects if one of these matches the executable name, eg:
VPATH = src include
CPPFLAGS = -I include
main: implementation.o
main.o: header.hpp
implementation.o: header.hpp
This will build an executable named main from both main.o and implementation.o.
Note however that the builtin implicit rule uses the C compiler for linking, which will not link against the C++ std library by default, you will need to add the flag -lstdc++
to LDLIBS explicitly
How about this for a minimal Makefile:
SOURCES = src/main.cpp src/implementation.cpp
CXX = g++
CXXFLAGS = -g -W -Wall -Werror
LDFLAGS = -g
OBJECTS = $(SOURCES:.cpp=.o)
prog: $(OBJECTS)
$(CXX) $(LDFLAGS) -o $@ $^
clean::
$(RM) prog
.cpp.o:
$(CXX) -MD -MP $(CXXFLAGS) -o $@ -c $<
clean::
$(RM) src/*.o
DEPENDS = $(SOURCES:.cpp=.d)
-include $(DEPENDS)
%.d:
@touch $@
clean::
$(RM) src/*.d
This assumes GNU make and gcc, but it adds proper dependency tracking, so there is no need to explicitly list the header file dependencies.
There supposed to be an implicit rule for prog or I am missing something?
There is no implicit rule. make
cannot know how to build prog
because it doesn’t know that prog
is supposed to be an executable. make
only uses the file name as a pattern to deduce the build rule. prog
is a generic file name without extension so make
doesn’t know how to treat it.
Hmm...
CXX = g++ # Just an example
CXXFLAGS = -Wall -O2 # Just an example
prog: main.o implementation.o
$(CXX) $(CXXFLAGS) $^ -o $@
main.o: header.hpp
implementation.o: header.hpp
should do the job. Why your variant isn't working is explained in Konrad Rudolph answer
If you want to link c++ object files you can specify LINK.o
to be LINK.cc
at the top
LINK.o := $(LINK.cc)
You should then see c++
instead of cc
in your make
output
The implicit rule for linking object files is:
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
But $(LINK.o)
uses $(CC)
, which is not quite correct for compiling C++ programs, so the easiest fix is:
CC = $(CXX)