Linker errors from makefile - c++

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)

Related

How do I create object files into a different directory than Makefile's one?

I'm new on using Makefiles because I've been programming with VS2019 on Windows, solving all my compilation and linking problems.
This is the result:
BUILD_DIR:= ./build
SRC_DIRS := ./src
INCL_DIR := ./includes
CC := /usr/bin/g++ #Compiler used
LVERSION := -std=c++17 #Language Version
CXXFLAGS := -g #Cpp flags
CFLAGS := -Wall #Compiler Flags
LFLAGS := -lstdc++fs #Linker Flags
SRCS := Audio.cpp Song.cpp Visual.cpp VisualSong.cpp
LIBS :=
INCLUDES := $(SRCS:%.cpp=$(INCL_DIR)/%.h)
OBJS := $(SRCS:%.cpp=$(BUILD_DIR)/%.o)
PROG := progName.exe
progName: $(OBJS)
$(CC) $(CFLAGS) $(CXXFLAGS) -o $(INCLUDES) $(PROG) $(OBJS)
$(BUILD_DIR)/%.o: $(INCL_DIR)/%.h $(SRC_DIRS)/%.cpp
$(CC) ${CFLAGS} $(CXXFLAGS) $(LVERSION) ${LFLAGS} -c $^
.PHONY: progName
clean:
/bin/rm -rf build/*.o $(PROG) includes/*.gch
This makefile works until is trying to look on objects file, supposedly created on build directory but, in the end, they're created in Makefile's directory, which is an inconvenient since all what i want is to have separated files for organization purposes.
I know that somehow using implicit rules that are using the dst's directory should do the trick, but i think that I'm missing something on the way...
I'm on a Windows 10 machine with WSL for Ubuntu, but this shouldn't be a problem at all for this problem.
Could anyone explain to me what am I missing?
Look at this rule:
$(BUILD_DIR)/%.o: $(INCL_DIR)/%.h $(SRC_DIRS)/%.cpp
$(CC) ${CFLAGS} $(CXXFLAGS) $(LVERSION) ${LFLAGS} -c $^
Ostensibly it is the rule to build build/foo.o, but the recipe ($(CC)...) actually builds foo.o. There is an easy fix:
$(BUILD_DIR)/%.o: $(INCL_DIR)/%.h $(SRC_DIRS)/%.cpp
$(CC) ${CFLAGS} $(CXXFLAGS) $(LVERSION) ${LFLAGS} -c $^ -o $#
Once that works I suggest you make one further change:
$(BUILD_DIR)/%.o: $(SRC_DIRS)/%.cpp $(INCL_DIR)/%.h
$(CC) ${CFLAGS} $(CXXFLAGS) $(LVERSION) ${LFLAGS} -c $< -o $#

C++ Makefile on "complex" tree structure

I have found a lot of related questions, but I was still not able to make my own Makefile.
This makefile is using Mingw64 on Windows, and I want it to run on *nix, currently Debian, but I would like to be able to make it run on Alpine too, as it's used in a Docker container.
The project tree structure is something like :
./
src/
main.cpp
Server.cpp <- use asio and Utils/Split.h
Server.h <- use asio
Utils/
Split.h
lib/
asio/include/ <- asio library (without boost, header only)
Makefile <- That is what I am trying to do right now
Dockerfile
I tried multiple things, here is my latest Makefile (that obviously, does not work) :
NAME := GameServer
CXX := g++
CXXFLAGS := -std=c++2a -DASIO_STANDALONE
SRC_DIR := ./src
LIBS := -I lib/asio-1.18.1/include \
-I lib/rapidjson-1.1.0/include \
-I src
rwildcard = $(wildcard $1$2) $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2))
SRCS := $(call rwildcard,$(SRC_DIR),*.cpp)
OBJS := $(SRCS:%.cpp=%.o)
.PHONY: all
all: $(NAME)
$(NAME): $(OBJS)
$(CXX) -o $# $^
$(OBJS): $(SRCS)
$(CXX) $(CXXFLAGS) -c -o $# $< $(LIBS)
Note: the code (.cpp, .h) is valid, it's coming from an already-running project, but built on Visual Studio (compiled with MSVC).
Here are the two functions done my mingw32-make :
g++ -c -o src/Server.o src/main.cpp -I lib/asio/include -I src
g++ -o Server src/main.o src/Server.o
First line : It should builds the .o from the .cpp and adds the include to asio. I added -I src to add src/Utils, but I guess that's not the way of doing it ?
Second line : It should (link ?) the two .o in a single file : the executable.
The errors I am getting with this makefile are :
src/Server.o:main.cpp:(.text+0x36): multiple definition of 'main', src/main.o:main.cpp:(.text+0x36): first defined here (and this, for every .o)
src/main.o:main.cpp:(.text+0x4b): undefined reference to 'Server::Server()' (and this, for every Server methods main calls, even some from asio)
They appears when the second g++ line starts (g++ -o Server src/main.o src/Server.o)
So here are my questions :
What am I doing wrong ?
Is there a better way of trying to make a development environment on Windows and still be able to copy the project in a Docker container (and then compile it with the gcc image) to build it with the same Makefile ?
Sorry if I forgot to mention some details, I am new with Mingw and its environment.
Thank you
Edit : Corrected version :
NAME := GameServer
CXX := g++
CXXFLAGS := -std=c++1z
SRC_DIR := ./src
LIBS := -lwsock32 -lws2_32 \
-I lib/asio-1.18.1/include \
-I lib/rapidjson-1.1.0/include \
-I src
rwildcard = $(wildcard $1$2) $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2))
SRCS := $(call rwildcard,$(SRC_DIR),*.cpp)
OBJS := $(SRCS:%.cpp=%.o)
.PHONY: all
all: $(NAME)
$(NAME): $(OBJS)
$(CXX) -o $# $^ $(LIBS)
$(OBJS): $(SRC_DIR)/%.o: $(SRC_DIR)/%.cpp
$(CXX) $(CXXFLAGS) -c -o $# $< $(LIBS)
Consider the rule...
$(OBJS): $(SRCS)
$(CXX) $(CXXFLAGS) -c -o $# $< $(LIBS)
This tells make that all items in $(OBJS) depend on all items in $(SRCS). But the command...
$(CXX) $(CXXFLAGS) -c -o $# $< $(LIBS)
...always compiles the first dependency as identified by $<. It just so happens that in your case $< is src/main.cpp.
Instead you should probably use a pattern rule such as...
$(SRC_DIR)/%.o: $(SRC_DIR)/%.cpp
$(CXX) $(CXXFLAGS) -c -o $# $< $(LIBS)
You can also limit the scope of that rule to only those targets specified by $(OBJS) with a full static pattern rule...
$(OBJS): $(SRC_DIR)/%.o: $(SRC_DIR)/%.cpp
$(CXX) $(CXXFLAGS) -c -o $# $< $(LIBS)

Compiling both C and CPP source in a single makefile target

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.

Makefile compiling the good files without the dependencies

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 $# $<

C++ Makefile missing separator in .dep

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.