On OS X Mavericks i am trying to build a project using the following Makefile:
CC=g++
EXECUTABLE=minigi
SRC_DIR=src
INTERM_DIR=obj
INCLUDES=-I $(SRC_DIR) -I /usr/local/Cg/examples/OpenGL/glew/include/
LIBS=-L/usr/local/lang/NVIDIA_GPU_Computing_SDK/sdk/C/common/lib/linux/ -lpng -stdc++ -lGL -lGLU -lGLEW -lSDLmain -lSDL -lgomp
CFLAGS_COMMON=$(INCLUDES)
CFLAGS=$(CFLAGS_COMMON) -O3 -DNDEBUG -fopenmp
#CFLAGS=$(CFLAGS_COMMON) -g -O0 -D_DEBUG
SOURCE_FILES=$(shell find $(SRC_DIR) -iname '*.cpp')
DEP_FILES=$(SOURCE_FILES:$(SRC_DIR)/%.cpp=./$(INTERM_DIR)/%.dep)
OBJ_FILES=$(SOURCE_FILES:$(SRC_DIR)/%.cpp=./$(INTERM_DIR)/%.o)
all: $(EXECUTABLE)
clean:
rm -rf obj $(EXECUTABLE)
.PHONY: clean all
.SUFFIXES:
.SUFFIXES:.o .dep .cpp .h
$(INTERM_DIR)/%.dep: $(SRC_DIR)/%.cpp
mkdir -p `dirname $#`
printf `dirname $#`/ > $#
$(CC) $(CFLAGS_COMMON) $< -MM | sed -r -e 's,^(.*)\.o\s*\:,\1.o $# :,g' >> $#
ifneq ($(MAKECMDGOALS),clean)
-include $(DEP_FILES)
endif
$(INTERM_DIR)/%.o: $(SRC_DIR)/%.cpp
mkdir -p $(INTERM_DIR)
$(CC) $(CFLAGS) -c $< -o $#
$(EXECUTABLE): $(OBJ_FILES)
$(CC) $^ $(LIBS) -o $#
However, when I type make I get the following error:
obj/app/sdl_gl_appliacation.dep:1: *** missing separator. Stop.
The file obj/app/sdl_gl_application.dep looks as follows:
-n obj/app/
As I know very little about makefiles (and did not write the posted one) every help would be appreciated.
P.S.
I modified the line printf dirname $#/ > $# . In the original file there was an echo -n but that is not working on OS X.
Well, let's clean this up a little bit.
The way the dependencies are handled really is ugly, GCC can do it for you automatically.
EXECUTABLE := minigi
SRC_DIR := src
OBJ_DIR := obj
SRC_FILES := $(wildcard $(SRC_DIR)/*.cpp)
OBJ_FILES := $(SRC_FILES:$(SRC_DIR)/%.cpp=$(OBJ_DIR)/%.o)
DEP_FILES := $(OBJ_FILES:.o=.d)
LDLIBS := -lpng -lstdc++ -lGL -lGLU -lGLEW -lSDLmain -lSDL -lgomp
LDFLAGS := -L/usr/local/lang/NVIDIA_GPU_Computing_SDK/sdk/C/common/lib/linux/
CPPFLAGS := -MMD -MP -DNDEBUG -fopenmp -I $(SRC_DIR) -I /usr/local/Cg/examples/OpenGL/glew/include/
CXXFLAGS := -O3
.PHONY: all clean
all: $(EXECUTABLE)
clean:
$(RM) -r $(OBJ_DIR) $(EXECUTABLE)
$(EXECUTABLE): $(OBJ_FILES)
$(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $#
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp | $(OBJ_DIR)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $# -c $<
$(OBJ_DIR):
mkdir $#
ifeq "$(MAKECMDGOALS)" ""
-include $(DEP_FILES)
endif
Some quick notes :
You're using C++, so you should use $(CXX) instead of $(CC) which is used for C code.
Along with this, you should use $(CXXFLAGS) instead of $(CFLAGS).
$(CPPFLAGS) is meant for preprocessor flags (-I, -D, or -fopenmp which is a compile-time flag).
-MMD -MP preprocessor flags will auto-generate dependency files when compiling. Learn more.
$(LDFLAGS) is meant for linker flags such as -L flags.
$(LDLIBS) is meant for linker libs such as -l flags
Avoid using the $(shell ) function since it will be executed every time the variable is expanded when assigned with the = operator instead of the := operator. $(wildcard ) is more suited for the job of listing files.
Related
I'm having a little trouble adapting a makefile I found here. What I have is below. When I run it, I get hundreds of "undefined reference to" errors, mostly complaining about the inability to find things in UnitTest. For example, the first is
/home/t/pf/test/main.cpp:63: undefined reference to `UnitTest::RunAllTests()'
Why is this happening? Does this have something to do with how the dependencies are being automatically generated?
Here's the makefile:
# output binary
BIN := main
# source files
SRCS := \
main.cpp test_resamplers.cpp test_rv_eval.cpp test_rv_samp.cpp
# intermediate directory for generated object files
OBJDIR := .o
# intermediate directory for generated dependency files
DEPDIR := .d
# object files, auto generated from source files
OBJS := $(patsubst %,$(OBJDIR)/%.o,$(basename $(SRCS)))
# compilers (at least gcc and clang) don't create the subdirectories automatically
$(shell mkdir -p $(DEPDIR))
$(shell mkdir -p $(dir $(OBJS)) >/dev/null)
# C++ compiler
CXX := g++
# linker
LD := g++
# C++ flags
CXXFLAGS := -std=c++11
# C/C++ flags
CPPFLAGS := -g -Wall -Wextra -pedantic -I/usr/local/include/UnitTest++ -I/usr/include/eigen3 -I../include
# linker flags
LDFLAGS := "-L../bin" "-L/usr/local/lib"
# flags required for dependency generation; passed to compilers
DEPFLAGS = -MT $# -MD -MP -MF $(DEPDIR)/$*.Td
# libraries
LDLIBS := -lpf -lUnitTest++
# compile C++ source files
COMPILE.cc = $(CXX) $(DEPFLAGS) $(CXXFLAGS) $(CPPFLAGS) -c -o $#
# link object files to binary
LINK.o = $(LD) $(LDFLAGS) $(LDLIBS) -o $#
# precompile step
PRECOMPILE =
# postcompile step
POSTCOMPILE = mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d
all: $(BIN)
.PHONY: clean
clean:
$(RM) -r $(OBJDIR) $(DEPDIR)
.PHONY: help
help:
#echo available targets: all clean
$(BIN): $(OBJS)
$(LINK.o) $^
$(OBJDIR)/%.o: %.cpp
$(OBJDIR)/%.o: %.cpp $(DEPDIR)/%.d
$(PRECOMPILE)
$(COMPILE.cc) $<
$(POSTCOMPILE)
.PRECIOUS = $(DEPDIR)/%.d
$(DEPDIR)/%.d: ;
-include $(DEPS)
All your undefined references must appear when line $(LINK.o) $^ is reached, this message is a link problem.
with g++ the link order matters see link order. I would try replacing
# link object files to binary
LINK.o = $(LD) $(LDFLAGS) $(LDLIBS) -o $#
by
# link object files to binary
LINK.o = $(LD) $(LDFLAGS) -o $#
and
$(BIN): $(OBJS)
$(LINK.o) $^
by
$(BIN): $(OBJS)
$(LINK.o) $^ $(LDLIBS)
I have a makefile where I am working with both C source and CPP source. Below is a snippet of code from the makefile. Is there a way to combine the following two targets to compile both filetypes?
#definitions
OBJ_DIR := obj
DEP_DIR := dep
CXX := g++
DEBUG := -g -O0
OPT := -std=c++11 -Wextra -Wall -pthread
LFLAGS = $(DEBUG) $(OPT) $(INC)
CFLAGS = $(LFLAGS) -c
#auto-dependency generation (part 1)
DEP_FLAGS = -MT $# -MMD -MP -MF $(DEP_DIR)/$*.Td
POSTCOMPILE = #mv -f $(DEP_DIR)/$*.Td $(DEP_DIR)/$*.d && touch $#
#compile object files from CPP source
$(OBJ_DIR)/%.o: %.cpp $(DEP_DIR)/%.d
$(CXX) $(CFLAGS) $(DEP_FLAGS) $< -o $#
$(POSTCOMPILE)
#compile object files from C source
$(OBJ_DIR)/%.o: %.c $(DEP_DIR)/%.d
$(CXX) $(CFLAGS) $(DEP_FLAGS) $< -o $#
$(POSTCOMPILE)
#auto-dependency generation (part 2)
$(DEP_DIR)/%.d: ;
.PRECIOUS: $(DEP_DIR)/%.d
include $(wildcard $(DEP_DIR)/*.d)
I have tried to use the wildcard function with a variety of different formatting using second expansion but to no avail.
I am using Make 4.2. The auto-dependency generation code was taken from http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/.
Thanks in advance
Using the right variables as well as the define, call and eval features, the following is possible:
EXT := c cpp
define rule =
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.$(1)
$$(COMPILE.$(1)) $$< -o $$#
endef
$(foreach ext, $(EXT), $(eval $(call rule,$(ext)))) # NO SPACE before $(ext)!!!
make has implicit variables and rules, especially many COMPILE.* rules (you can see them all by issuing the shell command make -p | grep 'COMPILE.* ='):
COMPILE.c = $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
COMPILE.cpp = $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
CPPFLAGS is used for preprocessor flags (cpp is the preprocessor executable in the GNU GCC toolchain). TARGET_ARCH is empty on most platforms by default.
Here is a full yet minimalist working Makefile with better auto-dependency generation (note that putting the .d files in a folder separate from the .o pointlessly complicates the makefile):
TARGET := executable
EXT := c cpp
SRC_DIR := .
OBJ_DIR := obj
DEP_DIR := dep
CPPFLAGS = -MMD -MP -MF $(#:$(OBJ_DIR)/%.o=$(DEP_DIR)/%.d)
CFLAGS := -Wall -Wextra -pthread
CXXFLAGS := -std=c++11 $(CFLAGS)
LDFLAGS := -pthread
SOURCE := $(foreach ext, $(EXT), $(wildcard $(SRC_DIR)/*.$(ext)))
OBJECT := $(SOURCE:$(SRC_DIR)/%=$(OBJ_DIR)/%.o)
DEPEND := $(OBJECT:$(OBJ_DIR)/%.o=$(DEP_DIR)/%.d)
define rule =
$(OBJ_DIR)/%.$(1).o: $(SRC_DIR)/%.$(1) | $(OBJ_DIR) $(DEP_DIR)
$$(COMPILE.$(1)) $$< -o $$#
endef
.PHONY: all clean
all: $(TARGET)
$(TARGET): $(OBJECT)
$(CXX) $(LDFLAGS) $^ -o $#
$(foreach ext, $(EXT), $(eval $(call rule,$(ext))))
$(OBJ_DIR) $(DEP_DIR):
mkdir -p $#
-include $(DEPEND)
clean:
$(RM) -r $(TARGET) $(OBJ_DIR) $(DEP_DIR)
Also note that I chose to add the original source file extension (c or cpp) to the object file name (.c.o or .cpp.o) to tackle the case where we could encounter source files with different extension but with the same name.
I have a problem with the dependencies in my Makefile.
There is no problem with the compilation, it compiles perfectly the good *.cc and *.hh but unfortunately, it does not re-compile the dependencies, thus there is no update in the executable.
Here is my makefile:
EXEC ?= program
SRCS = $(shell find -name *.cc)
DEP = $(SRCS:.cc=.d)
OBJDIR = objs
OBJS = $(SRCS:./%.cc=$(OBJDIR)/%.o)
CXX = g++
CFLAGS = -std=c++14 $(addprefix "-I", $(shell find -type d))
## Clean rule
.PHONY: clean
clean:
rm -rf $(OBJDIR)
rm -f $(EXEC)
$(EXEC) : $(OBJS)
#echo "Linking: $#"
$(CXX) $(OBJS) -o $#
-include $(DEP)
$(OBJDIR)/%.o : ./%.cc ./%.hh
#mkdir -p $(#D)
#echo "Compiling: $<"
#$(CXX) -c $(CFLAGS) -MT $# -MMD -MP -o $# $<
It is probably something related to the flag used by g++ but I do not manage to find the solution;
Thanks in advance for the help that you can provide on this issue,
If you do not specify the filename for the generated dependency files, it is going to be ${#:%.o=%.d} (compiler logic). I.e. your dependency files are in $(OBJDIR) and not in ./ where your makefile expects them to be.
Two alternative solutions:
DEP := $(OBJS:%.o=%.d).
#$(CXX) -c $(CFLAGS) -MT $# -MMD -MP -MF $(<:%.cc=%.d) -o $# $<
I have some problems trying to put .o files into a separate directory (/build).
Actually, my sources (in /src) contain some subdirectories, and my Makefile only create the .o of the .cpp contained at the first "level". The other .o are just ignored, so, the target cannot be created.
In my /src directory, I have "three levels" (src/first/second/).
Here's the code of the Makefile :
CC=g++
CFLAGS=-W -Wall -ansi -pedantic -s -O3 -Os -std=c++11 -fpermissive
LDFLAGS= -lboost_system -lboost_regex
SRCDIR=src
HEADDIR=include
LIBDIR=build
BINDIR=bin
BIN=LTN
SRC = $(wildcard src/*.cpp src/*/*.cpp src/*/*/*.cpp)
OBJ = $(patsubst %.cpp,$(LIBDIR)/%.o,$(SRC))
all: $(BIN)
LTN: $(OBJ)
$(CC) -o $(BINDIR)/$# $^ $(LDFLAGS)
$(LIBDIR)/$(SRCDIR)/%.o: $(SRCDIR)/%.cpp $(HEADDIR)/%.h
$(CC) -o $# -c $< $(CFLAGS)
.PHONY = clean
You can try this:
CC=g++
CFLAGS=-W -Wall -ansi -pedantic -s -O3 -Os -std=c++11 -fpermissive
LDFLAGS= -lboost_system -lboost_regex
SRCDIR=src
HEADDIR=include
LIBDIR=build
BINDIR=bin
BIN=LTN
SRC=$(shell find . -name '*.cpp')
TMP=$(subst $(SRCDIR),$(LIBDIR), $(SRC))
OBJ=$(patsubst %.cpp,%.o,$(TMP))
all: $(BIN)
LTN: $(OBJ)
#[ ! -d $(BINDIR) ] & mkdir -p $(BINDIR)
$(CC) -o $(BINDIR)/$# $^ $(LDFLAGS)
$(LIBDIR)/%.o: $(SRCDIR)/%.cpp
#[ ! -d $(dir $#) ] & mkdir -p $(dir $#)
$(CC) -o $# -c $< $(CFLAGS)
.PHONY = clean
Currently, whenever I do make my makefile tells me
make: `some/obj/file.o' is up to date.
regardless of whether I've edited any of the files involved in generating that object file. How do I make it detect changes? Here is a simple makefile that reproduces the problem:
SHELL := /bin/bash
src := src
sources := $(shell find $(srcDir) -name "*.cpp")
objects := $(sources:%.cpp=%.o)
-include $(sources:%.cpp=%.d)
all: prog
prog: $(objects)
g++ $(objects) -o /a.out
%.o: %.cpp
$(CXX) $(CXXFLAGS) -MMD -MP -c $< -I $(srcDir) -o $#
clean:
find $(srcDir) -type f -iname "*.o" -delete
find $(srcDir) -type f -iname "*.d" -delete
currently I have to run make clean everytime to get it to recompile, which obviously isn't ideal!
EDIT: Here is my attempt based on Chnossos's answer:
EXE := a.out
SRCDIR := src
SRC := $(shell find $(srcDir) -name "*.cpp")
DIR := .obj
OBJ := $(SRC:%.cpp=$(DIR)/%.o)
DEP := $(OBJ:.o=.d)
CXXFLAGS += -std=c++11
CXXFLAGS += -I /home/arman/lib/eigen-eigen-6b38706d90a9
CXXFLAGS += -I /home/arman/lib/boost_1_55_0
CXXFLAGS += -I /home/arman/lib/lodepng/
CXXFLAGS += -L /home/arman/lib/boost_1_55_0/stage/lib
CPPFLAGS += -MMD -MP
.PHONY: all clean
-include $(DEP)
all: $(EXE)
$(EXE): $(OBJ)
$(CXX) $(OBJ) -o $#
$(DIR)/%.o: %.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $# -c $< -I $(SRCDIR)
clean:
$(RM) -f $(DIR)
I am now getting the following error:
src/core/file1.cpp:839:1: fatal error: opening dependency file .obj/./src/core/file1.d: No such file or directory
Note that I have the following directory structure:
/prog/makefile -> The makefile
/prog/dir1/ -> some cpp/hpp files
/prog/dir2/ -> more cpp/hpp files
/prog/ ->there are some cpp/hpp files here too
I have many folders (more than just dir1 and dir2) so I'd like to not have to specify them each time.
EXE := a.out
SRC := $(wildcard *.cpp)
OBJ := $(SRC:.cpp=.o)
DEP := $(OBJ:.o=.d)
CPPFLAGS := -MMD -MP -I.
.PHONY: all clean
all: $(EXE)
$(EXE): $(OBJ)
$(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $#
clean:
$(RM) $(OBJ) $(DEP)
-include $(DEP)
You can also with a little efforts compile your .o and .d files into a hidden folder like this :
EXE := a.out
SRC := $(wildcard *.cpp)
DIR := .obj
OBJ := $(SRC:%.cpp=$(DIR)/%.o)
DEP := $(OBJ:.o=.d)
CPPFLAGS := -MMD -MP -I.
.PHONY: all clean
all: $(EXE)
$(EXE): $(OBJ)
$(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $#
$(DIR)/%.o: %.cpp | $(DIR)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $# -c $<
$(DIR):
#mkdir $#
clean:
$(RM) -r $(DIR)
-include $(DEP)
EDIT: Here is my attempt for your edit :
Some quick note, the $(LDLIBS) is here for your -l flags, whereas $(LDFLAGS) is meant for -L flags.
SRCDIR := src
OBJDIR := .obj
EXE := a.out
SRC := $(shell find $(SRCDIR) -name "*.cpp")
OBJ := $(SRC:$(SRCDIR)/%.cpp=$(OBJDIR)/%.o)
DEP := $(OBJ:.o=.d)
CPPFLAGS := -MMD -MP
CPPFLAGS += -I$(SRCDIR)
CPPFLAGS += -I$(HOME)/lib/eigen-eigen-6b38706d90a9
CPPFLAGS += -I$(HOME)/lib/boost_1_55_0
CPPFLAGS += -I$(HOME)/lib/lodepng/
CXXFLAGS := -std=c++11
LDFLAGS += -L$(HOME)/lib/boost_1_55_0/stage/lib
LDLIBS :=
.PHONY: all clean
all: $(EXE)
$(EXE): $(OBJ)
$(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $#
.SECONDEXPANSION:
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp | $$(#D)/
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $# -c $<
%/:
mkdir -p $#
clean:
$(RM) -r $(OBJDIR)
-include $(DEP)
Tell me if something is missing.
-M family of gcc options (-MM, -MMT) generate the makefile fragments you need. A standard technique is
DEPS := $(SOURCES:.c=.d)
.c.d:
$(CC) -o $< -MM $(CFLAGS)
-include $(DEPS)