Linker command fail with a bunch of undefined reference - c++

I try to compile a project using clang and libc++. Here is my makefile :
EXEC = ModularMadness
SRCDIR = src/
INC =-I$(SRCDIR)
SOURCES := $(wildcard $(SRCDIR)*.cpp) $(wildcard $(SRCDIR)*/*.cpp)
OBJECTS = $(SOURCES:.cpp=.o)
CXX = clang++
CXX_FLAGS = -std=c++1y -stdlib=libc++ $(INC)
all: $(EXEC)
$(EXEC): $(OBJECTS)
$(CXX) $(OBJECTS) -o $(EXEC)
%.o: %.cpp
$(CXX) -c $(CXX_FLAGS) $< -o $#
.PHONY: all clean
clean:
#echo Cleaning...
#rm -f $(EXEC) $(OBJECTS)
#echo done
The .o files creation works fine, but I ran in multiple error like
In function 'std::__1::weak_ptr<module::Module>::lock() const': undefined reference to 'std::__1::__shared_weak_count::lock()' during linker command.
Could someone help me understanding what's the problem here ?
Note
This makefile run perfectly on OS X.

I missed the linker flag -lc++... Thank you perencia.
Here is the working makefile :
EXEC = ModularMadness
SRCDIR = src/
INC =-I$(SRCDIR)
SOURCES := $(wildcard $(SRCDIR)*.cpp) $(wildcard $(SRCDIR)*/*.cpp)
OBJECTS = $(SOURCES:.cpp=.o)
CXX = clang++
CXX_FLAGS = -std=c++1y -stdlib=libc++ $(INC)
all: $(EXEC)
$(EXEC): $(OBJECTS)
$(CXX) $(OBJECTS) -o $(EXEC) -lc++ # Here
%.o: %.cpp
$(CXX) -c $(CXX_FLAGS) $< -o $#
.PHONY: all clean
clean:
#echo Cleaning...
#rm -f $(EXEC) $(OBJECTS)
#echo done

Related

Using Makefile compile multiple .cpp in diferent folders to a single build/ directory [duplicate]

GNU Make 3.82
gcc 4.7.2
c89
I have the following make file:
INC_PATH=-I/home/dev_tools/apr/include/apr-1
LIB_PATH=-L/home/dev_tools/apr/lib
LIBS=-lapr-1 -laprutil-1
RUNTIME_PATH=-Wl,-rpath,/home/dev_tools/apr/lib
CC=gcc
CFLAGS=-Wall -Wextra -g -m32 -O2 -D_DEBUG -D_THREAD_SAFE -D_REENTRANT -D_LARGEFILE64_SOURCE $(INC_PATH)
SOURCES=$(wildcard src/*.c)
OBJECTS=$(patsubst %.c, %.o, $(SOURCES))
EXECUTABLE=bin/to
all: build $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(CFLAGS) -o $# $(RUNTIME_PATH) $(OBJECTS) $(LIB_PATH) $(LIBS)
$(OBJECTS): $(SOURCES)
$(CC) $(CFLAGS) -c $(SOURCES) $(LIB_PATH) $(LIBS)
build:
#mkdir -p bin
clean:
rm -rf $(EXECUTABLE) $(OBJECTS) bin
find . -name "*~" -exec rm {} \;
find . -name "*.o" -exec rm {} \;
My directory structure is like this project/src project/bin. My Makefile is in the project (root) folder, and all my *.h and *.c are in the src directory. Currently I have only one source file called timeout.c
I get this error:
gcc: error: src/timeout.o: No such file or directory
I have used this to get all the source files:
SOURCES=$(wildcard src/*.c)
And the object files:
OBJECTS=$(patsubst %.c, %.o, $(SOURCES))
However, the make seems to create the object file in the project root folder where the Makefile is. Should it not put it in the src directory?
You have two problems in this rule (well, three):
$(OBJECTS): $(SOURCES)
$(CC) $(CFLAGS) -c $(SOURCES) $(LIB_PATH) $(LIBS)
You haven't noticed yet, but the rule makes each object dependent on all sources, and tries to build that way. Not a problem as long as you have only one source. Easy to fix with a static pattern rule and an automatic variable:
$(OBJECTS): src/%.o : src/%.c
$(CC) $(CFLAGS) -c $< $(LIB_PATH) $(LIBS)
Also, the command ("$(CC)...") doesn't specify an output file name, so gcc will infer it from the source file name; if you give it src/timeout.c, it will produce timeout.o (in the working directory, project/). So you should specify the desired path to the output file. Easy to do with another automatic variable:
$(OBJECTS): src/%.o : src/%.c
$(CC) $(CFLAGS) -c $< $(LIB_PATH) $(LIBS) -o $#
Use gcc's -o option to write the output file to a particular location. For instance, you could say:
$(CC) $(CFLAGS) -c $(SOURCES) $(LIB_PATH) $(LIBS) -o $(OBJECTS)
Unfortunately, there's a problem with this line: if there is more than one source file in $(SOURCES), it won't work, since $(OBJECTS) will also contain multiple file names, and the -o option only binds to the first argument.
A way to compile each file in a list of source code files is to use implicit rules. In gmake, you would write:
$(EXECUTABLE): $(OBJECTS)
$(CC) $(CFLAGS) -o $# $(RUNTIME_PATH) $(OBJECTS) $(LIB_PATH) $(LIBS)
%.o : %.c
$(CC) $(CFLAGS) -c $< -o $#
where $< is replaced with name of the input file and $# is replaced with the name out the output file.
I solved this request and here is my Makefile and directory tree.
PROJECT := main.exe
DIR_SRC += .
DIR_SRC += ./src
DIR_INC += -lpthread
DIR_INC += -I./inc
DIR_INC += $(addprefix -I, $(DIR_SRC))
SRC_C += $(wildcard $(addsuffix /*.c, $(DIR_SRC)))
#OBJ := $(filter %.o, $(SRC_C:.c=.o))
OBJ := $(patsubst %.c, %.o, $(SRC_C))
EXE := $(PROJECT)
CC_PREFIX :=
CC := $(CC_PREFIX)gcc
CFLAG =
CLIB = -L .
.PHONY:all
all:$(OBJ) $(EXE)
%.o: %.c
$(CC) $(CFLAG) $(DIR_INC) -c $< -o $#
$(EXE): $(OBJ)
$(CC) $(CFLAG) $(CLIB) $(OBJ) -o $#
clean:
rm -r $(EXE) $(OBJ)
See my directory tree:

Makefile for building C++ Google Protocol Buffers Project

I Just started fooling around using Google Protocol Buffers and I am trying to incorporate the C++ output files from the protocol buffer compiler into my project. I have Been using a simple makefile for my projects so far and it does the trick for building source files all sharing the same extension. I use ".cpp" for my source files but Google Protocol Buffers outputs its source as ".pb.cc" files. I need to be able to compile and link both types of source files into one executable.
I have been searching and fiddling around with my makefile for a few hours now and have had no success.
My Current Makefile:
PROGRAM_NAME=aserv
CC=gcc
CXX=g++
RM=rm -f
CPPFLAGS=-g --std=c++14 -O3 -I/usr/local/include/
LDFLAGS=-g -L/usr/local/lib -L/usr/local/lib/boost
LDLIBS= -lrtaudio -pthread -lboost_system -lprotobuf
INSTALL_DIR = /usr/local/bin/
SRCS=$(wildcard *.cpp)
OBJS=$(subst .cpp,.o,$(SRCS))
all: $(PROGRAM_NAME)
$(PROGRAM_NAME): $(OBJS)
$(CXX) $(LDFLAGS) -o $(PROGRAM_NAME) $(OBJS) $(LDLIBS)
depend: .depend
.depend: $(SRCS)
rm -f ./.depend
$(CXX) $(CPPFLAGS) -MM $^>>./.depend;
clean:
$(RM) $(OBJS) $(PROGRAM_NAME) .depend
install:
cp $(PROGRAM_NAME) $(INSTALL_DIR)$(PROGRAM_NAME)
uninstall:
$(RM) $(INSTALL_DIR)$(PROGRAM_NAME)
dist-clean: clean
$(RM) *~ .depend
include .depend
I am not too well versed in writing makefiles yet, so I just don't quite know what to do to make this work.
If it helps i have GNU make 4.1 and gcc 5.3.1 on Ubuntu 16.04 beta
I couldnt get your original Makefile to work so I changed a few things but I think the tricky part with this is the implicit rules that make generates to build your .o files. I think for the .pb.cc files you need to generate .pb.o objects so that the implicit rules can match them.
Try this:
PROGRAM_NAME = aserv
CC = gcc
CXX = g++
RM = rm -f
CXXFLAGS = --std=c++14 -pthread -g -O3 -MMD -MP
CPPFLAGS = -I/usr/local/include/
LDFLAGS = -L/usr/local/lib -L/usr/local/lib/boost
LDLIBS = -lrtaudio -lboost_system -lprotobuf
INSTALL_DIR = /usr/local/bin
SRCS = $(wildcard *.cpp) $(wildcard *.pb.cc)
OBJS = $(subst .pb.cc,.pb.o,$(subst .cpp,.o,$(SRCS)))
DEPS = $(subst .pb.cc,.pb.d,$(subst .cpp,.d,$(SRCS)))
all: $(PROGRAM_NAME)
$(PROGRAM_NAME): $(OBJS)
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -o $# $^ $(LDFLAGS) $(LDLIBS)
-include $(DEPS)
clean:
$(RM) $(OBJS) $(PROGRAM_NAME)
install:
cp $(PROGRAM_NAME) $(INSTALL_DIR)
uninstall:
$(RM) $(INSTALL_DIR)/$(PROGRAM_NAME)
dist-clean: clean
$(RM) *~ $(DEPS)
If you wanto to only strictly rely on Make, and not the surrounding shell you can add another set of SRC and OBJ variables, which will serve as a second set of dependencies.
Add these right below the first set:
SRC1=$(wildcard *.pb.cc)
OBJ1=$(subst .pb.cc,.o,$(SRC1))
And change the .depend and $(PROGRAM_NAME) rule:
.depend: $(SRCS) $(SRC1)
$(PROGRAM_NAME): $(OBJS) $(OBJ1)
$(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $#
%.o: %.c
$(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) -c -o $# $<

How to compile/link a unittest in a Linux Makefile correctly?

On a Linux system I want to compile and link an unittest using the gtest framework. I am using the following Makefile:
CC := g++ # This is the main compiler
SRCDIR := src
BUILDDIR := build
TARGET := bin/myapp
TEST := tester
SRCEXT := cpp
SOURCES := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT))
OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.o))
CFLAGS := -g
LIB := -pthread -L lib -L /usr/local/lib -lsqlite3 -lboost_thread -lcrypto
INC := -I include
$(TARGET): $(OBJECTS)
#echo " Linking..."
#echo " $(CC) $^ -g -o $(TARGET) $(LIB)"; $(CC) $^ -o $(TARGET) $(LIB)
$(BUILDDIR)/%.o: $(SRCDIR)/%.$(SRCEXT)
#mkdir -p $(BUILDDIR)
#echo " $(CC) $(CFLAGS) $(INC) -c -o $# $<"; $(CC) $(CFLAGS) $(INC) -c -o $# $<
clean:
#echo " Cleaning...";
#echo " $(RM) -r $(BUILDDIR) $(TARGET)"; $(RM) -r $(BUILDDIR) $(TARGET)
# Tests
$(TEST): $(OBJECTS)
#echo " Compiling test..."
$(CC) $(CFLAGS) test/tester.cpp $(INC) -c -o build/$(TEST).o
#echo " Linking test..."
$(CC) $(CFLAGS) $(INC) -pthread test/tester.cpp /usr/lib/libgtest.a $(LIB) -L build build/tester.o -o bin/$(TEST)
.PHONY: clean
The compilation of the main application (myapp) works just fine, but I get into trouble compiling/linking the test file located in the test directory.
When I do NOT include any other library (from src or include, respectively) then the following line
$(CC) $(CFLAGS) -pthread test/tester.cpp /usr/lib/libgtest.a $(INC) -o bin/$(TEST)
just works perfect and creates a runnable executable. However, when I try to include some library from my project in tester.cpp like e.g.
#include "MyClass.h"
(which is defined as MyClass.h in include and as MyClass.cpp in src) then, with the above Makefile, I get various undefined reference errors (in what I have labelled as the 'compile' stage for 'tester').
I am not sure if I should compile the file tester.cpp first and then link all the libraries, or if I should do everything in one step? I do not know how to do either.
Any advice on fixing this Makefile above is appreciated...
OBJECTS := $(patsubst $(SRCDIR)/%.$(SRCEXT),$(BUILDDIR)/%.o,$(SOURCES))
OBJECTS := $(filter-out $(BUILDDIR)/main.o, $(OBJECTS))
$(TARGET): $(OBJECTS) $(BUILDDIR)/main.o
#echo " Linking..."
$(CC) $^ -o $# $(LIB)
tester: bin/$(TEST)
bin/$(TEST): build/$(TEST).o $(OBJECTS)
#echo " Linking test..."
$(CC) $(INC) -pthread $^ /usr/lib/libgtest.a $(LIB) -L build -o $#
P.S. Please don't edit the question like that, after you have answers. If you want to make a change (that doesn't render the existing answers meaningless), add new test to the bottom of the question, preferably with "EDIT:".

How to change my makefile to build into a separate folder

I have the following makefile:
CC=g++
CCOPTS=-Wall -Wextra -g
OBJS = manager.o tcpcon.o
TARGETS = manager
.PHONY: all clean
$(TARGETS) : $(OBJS)
$(CC) -o $# $^ $(CFLAGS) $(LIBS)
all: $(TARGETS) $(OBJS)
clean:
rm -f $(TARGETS) $(OBJS)
%: %.cpp
$(CC) $(CCOPTS) -o $# $<
Is there a way I can make my .o and bin files be built into a directory called build? I tried going through some tutorials, but I guess I just don't fully understand makefiles..
Don't feel too bad; I'm not sure anyone fully understands makefiles.
BUILD_DIR = build
OBJS = $(BUILD_DIR)/manager.o $(BUILD_DIR)/tcpcon.o
TARGETS = $(BUILD_DIR)/manager
...
$(BUILD_DIR)/%.o: %.cpp
$(CC) -c $(CCOPTS) -o $# $<

Makefile for fftw3?

So I can compile my code (fftw_ex.c) directly with:
login$ gcc -o -g fftw_ex fftw_ex.c -I$TACC_FFTW3_INC -L$TACC_FFTW3_LIB -lfftw3
However, my professor prefers that we use a Makefile. I am just learning how to use Makefile and make, and I'm having trouble creating the Makefile. So far, this is what I have:
# RULES
EXEC := fftw_ex
SRC := $(wildcard *.c)
OBJ := $(patsubst %.c,%.o,%(SRC))
# OPERATIONS
CC := gcc
CFLAGS := -O3 -I$TACC_FFTW3_INC
LDFLAGS := -L$TACC_FFTW3_LIB
LDLIBS := -lfftw3
$(EXEC): $(OBJ)
$(CC) $(LDFLAGS) $(LDLIBS) -o -g $# $^
%.o: %.c
$(CC) $(CFLAGS) -c $<
# PHONY TARGETS
.PHONY: clean
clean:
#echo Cleaning...;rm -rf *.o fftw_ex
I know there's a problem with the SRC line, as i'm getting the error message:
make: *** No rule to make target `%(SRC)', needed by `fftw_ex'. Stop.
Any help to get this to work would be appreciated.
1)To resolve:
No rule to make target `%(SRC)'
replace %(SRC) in
OBJ := $(patsubst %.c,%.o,%(SRC))
with $(SRC)
2)In line:
$(CC) $(LDFLAGS) $(LDLIBS) -o -g $# $^
you have mistake: -o -g, should be -g -o