compilation with Makefile fail but success in command line - c++

I was using a Makefile to compile my project and compiled successfully, but when I added a new lib (libbcm2835.a) to linker (-lbcm2835) it fails, otherwise when using the following commands it compile and link with no error :
gcc -c ihome_*.c
gcc -o iHome_Start ihome*.o -lbcm2835 -lpthread
Makefile :
# project name (generate executable with this name)
TARGET = iHome_Start
CC = gcc
# compiling flags here
CFLAGS = -std=c99 -Wall -I.
LINKER = gcc -o
# linking flags here
LFLAGS = -lpthread -lbcm2835
# change these to set the proper directories where each files shoould be
SRCDIR = .
OBJDIR = .
BINDIR = .
SOURCES := $(wildcard $(SRCDIR)/*.c)
INCLUDES := $(wildcard $(SRCDIR)/*.h)
OBJECTS := $(SOURCES:$(SRCDIR)/%.c=$(OBJDIR)/%.o)
rm = rm -f
$(BINDIR)/$(TARGET): $(OBJECTS)
#$(LINKER) $# $(LFLAGS) $(OBJECTS)
#echo "Linking complete!"
$(OBJECTS): $(OBJDIR)/%.o : $(SRCDIR)/%.c
#$(CC) $(CFLAGS) -c $< -o $#
#echo "Compiled "$<" successfully!"
.PHONEY: clean
clean:
#$(rm) $(OBJECTS)
#echo "Cleanup complete!"
.PHONEY: remove
remove: clean
#$(rm) $(BINDIR)/$(TARGET)
#echo "Executable removed!"

The problem is in
#$(LINKER) $# $(LFLAGS) $(OBJECTS)
The linker processes the arguments in an order they appear. By the time it sees the libraries, it hadn't yet seen no object files, hence there are no unresolved symbols, hence it pulls nothing from the libraries. Swap $(OBJECTS) and $(LFLAGS):
#$(LINKER) $# $(OBJECTS) $(LFLAGS)
I would also recommend to rename LFLAGS to LIBRARIES.

Related

Linker errors from makefile

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)

Shared library with freeglut - undefined symbol

I'm actually experiencing some issues while linking an OpenGL/freeglut shared library (.so) with a C++ project. I'm sure that the problem is in my Makefile since the code I use to load (using the dlopen/dlsym/dlclose functions) works fine with other shared libraries.
I thought it comes from headers inclusions but the OpenGL project I'm trying to work with compiles when I create an executable of it. I've also checked the glut FAQ but the solution now redirect to a dead link So there is my Makefile content, does anyone see where I am wrong ?
TARGET = lib_opengl.so
CC = g++
SRC = GL_Handler.cpp \
GL_Utils.cpp
DEVIL_CFLAGS := $(shell pkg-config --cflags IL)
DEVIL_LIBS := $(shell pkg-config --libs IL)
LIBS += -lGL -lGLU -lglut $(DEVIL_CFLAGS) $(DEVIL_LIBS)
CFLAGS = -W -Werror -Wall -ansi -pedantic -fPIC -shared -L/usr/X11R6/lib/ $(LIBS)
SRCDIR = src
OBJDIR = obj
SOURCES := $(addprefix src/, $(SRC))
OBJECTS := $(SOURCES:$(SRCDIR)/%.cpp=$(OBJDIR)/%.o)
rm = rm -rf
mkdir = mkdir -p
$(TARGET): $(OBJECTS)
#$(CC) $(CFLAGS) -o $# $(OBJECTS)
#echo $(TARGET)" compiled !"
$(OBJECTS): $(OBJDIR)/%.o : $(SRCDIR)/%.cpp
#$(mkdir) $(OBJDIR)
#$(CC) $(CFLAGS) -c $< -o $#
all : $(TARGET)
clean :
#$(rm) $(OBJDIR)
#echo "Binary files deleted"
fclean : clean
#$(rm) $(TARGET) $(LINK)
#echo "Binary and executable files are deleted"
re : fclean all
.PHONY: all clean fclean re
And there is the result when I'm trying to link it with my shared libraries loader.
./so_loader ./lib/lib_opengl.so
./so_loader: symbol lookup error: ./lib/lib_opengl.so: undefined symbol: glutInit
I hope that my problem is understandable and thanks for reading.
As a start, use variable LDFLAGS for linking instead of CFLAGS which is meant for compilation. Something like this:
LDFLAGS = -L/usr/X11R6/lib
...
$(TARGET): LDFLAGS += -shared -Wl,--no-undefined
$(TARGET): $(OBJECTS)
#$(CC) $(LDFLAGS) -o $# $(OBJECTS) ${LIBS}

Linker command fail with a bunch of undefined reference

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

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:".

cygwin g++ Linker doesn't find shared library

I have been creating a library. When I compile it as a static library, it works fine. Now I want to turn it into a shared library. The library is created and in the proper place, but when I try to compile the client code, the linking phase says that it can't find the library.
I already tried to rename it to al or dylib but that doesn't help either. When I put the -v flag on the linking, I can see that my library path is there. I also tried different paths. I used a relative path, but even with a full path it doesn't find it.
The Makefile from the library:
.SUFFIXES:
.SUFFIXES: .o .cpp
.SUFFIXES: .o .d
CC := g++
LNK:= g++
CXXFLAGS_RELEASE = -fPIC -shared -O2 -Wall -fmessage-length=0
CXXFLAGS_DEBUG = -fPIC -shared -g -Wall -fmessage-length=0 -D _DEBUG
CXXFLAGS = $(CXXFLAGS_DEBUG)
OBJDIR:= obj
SRCDIR:= src
HDIR:= include
INCLUDE_PATHS:= -Iinclude -Iinclude/interfaces -Iinclude/support
CPP_FILES := propertyfile/propertyfile.cpp \
propertyfile/propertyitem.cpp \
propertyfile/propertyfactory.cpp \
helper/string_helper.cpp
OBJ := $(patsubst %.cpp,$(OBJDIR)/%.o, $(CPP_FILES))
SRC := $(patsubst %.cpp,$(SRCDIR)/%.o, $(CPP_FILES))
LIBS:=
TARGET:= libsupport.so
all: $(TARGET)
$(TARGET): $(OBJ)
$(LNK) -o $(TARGET) $(OBJ) -shared
#cp $(TARGET) ../lib
#cp -r include ..
clean:
rm -f $(OBJ) $(ASM) $(TARGET)
-include $(patsubst %.cpp,$(OBJDIR)/%.d, $(CPP_FILES))
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp $(OBJDIR)/%.d
#mkdir -p `dirname $#`
$(CC) $(CXXFLAGS) -c $< -o $# $(INCLUDE_PATHS)
$(OBJDIR)/%.d: $(SRCDIR)/%.cpp
#mkdir -p `dirname $#`
$(CC) $(CXXFLAGS) -MM -MT $# -MF $(OBJDIR)/$*.d -c $< $(INCLUDE_PATHS)
And here is the Makefile for the application:
.SUFFIXES:
.SUFFIXES: .o .cpp
CC := g++
LD := g++
CXXFLAGS_RELEASE = -O2 -Wall -fmessage-length=0
CXXFLAGS_DEBUG = -g -Wall -fmessage-length=0 -D _DEBUG
CXXFLAGS = $(CXXFLAGS_DEBUG)
OBJDIR:= obj
SRCDIR:= src
INCLUDE_PATHS:= -Iinclude -I../include
LIBS:= -L /cygdrive/d/src/c/lib -lsupport
CPP_FILES := nohupshd.cpp \
daemon.cpp \
task.cpp
OBJ := $(patsubst %.cpp,$(OBJDIR)/%.o, $(CPP_FILES))
SRC := $(patsubst %.cpp,$(SRCDIR)/%.o, $(CPP_FILES))
TARGET:= nohupshd
all: $(TARGET)
$(TARGET): $(OBJ)
$(LD) -o $(TARGET) $(OBJ) $(LIBS)
clean:
rm -f $(OBJ) $(ASM) $(TARGET)
-include $(patsubst %.cpp,$(OBJDIR)/%.d, $(CPP_FILES))
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp $(OBJDIR)/%.d
#mkdir -p `dirname $#`
$(CC) $(CXXFLAGS) -c $< -o $# $(INCLUDE_PATHS)
$(OBJDIR)/%.d: $(SRCDIR)/%.cpp
#mkdir -p `dirname $#`
$(CC) $(CXXFLAGS) -MM -MT $# -MF $(OBJDIR)/$*.d -c $< $(INCLUDE_PATHS)
After some experimenting I found a solution on how to compile a shared library under cygwin.
Apparently the compiler is looking for a DLL file even though it is inside cygwin. so the first step is to add your path, where the library is going to be to the PATH variable.
export PATH=$PATH:/cygdrive/d/src/c/lib
Apparently when linking against a shared library, the linker seems to look for a DLL file by default. I don't know why, because inside cygwin I would expect it to look for a .so file just like on other UNIX systems.
However, there are two solutions to this, which both work.
First, you can create a link to your .so library with the name .dll
ln -s /cygdrive/d/src/lib/libsupport.so libsupport.dll
In this case the makefile doesn't have to be changed and -lsupport will find the library while linking. I prefer this solution.
Second, you can specify the linker option with the full name.
LIBS:= -L /cygdrive/d/src/c/lib -l:libsupport.so
then you don't have to create a link.
So the crucial thing seems to be that the shared library must be in the PATH under cygwin. Using LD_LIBRARY_PATH doesn't help in that case as you can link the executable, but when trying to run it, it will not find it.
ldd nohupshd.exe
libsupport.so => not found
UPDATE: For some reason when I checked with ldd, my library was suddenly gone from the list. I found out that cygwin uses the name to differentiate between MS Windows and Unix shared libraries. So in order to make it work, the name of the library must be cyg.so to make it work, otherwise the exectuable seems to be some Windows build. In this case you don't need to create the link named x.dll as the shared library stays inside the Unix environment.
$(LNK) -o cyg$(TARGET).so $(OBJ) -shared
When using eclipse for debugging, the path to the shared library must also be in the windows path environment variable. Otherwise the debug session immediately terminates without an error.