I seem to be going from one problem to the next ever since I decided to organize my code into subdirectories. The problems are naturally arising from the Makefile. So here's what I've currently got:
UNAME := $(shell uname)
# Directories
SOURCEDIR = src/
BUILDDIR = build/
# Compiler options
CC = clang++
DEBUG = -g
CFLAGS = -std=c++11 -Wall -c $(DEBUG)
LFLAGS = -Wall $(DEBUG)
# Files
SRC = $(wildcard $(SOURCEDIR)*.cpp) $(wildcard $(SOURCEDIR)**/*.cpp)
OBJS = $(SRC:$(SOURCEDIR)%.cpp=$(BUILDDIR)%.o)
ifeq ($(UNAME), Darwin)
LIBS = -lglfw3 -framework OpenGL -lglew -framework IOKit -framework CoreFoundation -framework ApplicationServices -framework Foundation -framework AppKit
BUILDDIR = ./build/osx/
endif
ifeq ($(UNAME), Linux)
LIBS = -lglfw -lGL -lGLEW
BUILDDIR = ./build/linux/
endif
# Build target
TARGET = test
all: $(TARGET)
$(TARGET): $(OBJS)
$(CC) $(LFLAGS) $? -o $(TARGET) $(LIBS)
$(OBJS): $(BUILDDIR)%.o : $(SOURCEDIR)%.cpp
#mkdir -p $(dir $#)
$(CC) $(CFLAGS) $< -o $#
clean:
rm -rf $(BUILDDIR)*.o $(BUILDDIR)**/*.o $(TARGET)
I was really glad when it actually compiled everything! Except when I made a change to a file, and tried to make it again, it spat this at me:
Undefined symbols for architecture x86_64:
"_main", referenced from:
implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [test] Error 1
Thing is, when I make it once more, it works just fine. The problem seems to be with resolving dependencies? And for that, I need to specify a VPATH? Well, that's the closest I've gotten, except trying to specify a VPATH hasn't made a difference. I'm probably specifying it incorrectly, or then I'm taking the wrong approach to this.
I'm pretty inexperienced when it comes to Makefiles, so I'd really appreciate some guidance!
Thanks to Etan Reisner for the solution. The problem was with the difference between $? and $^. Here's the fixed version:
UNAME := $(shell uname)
# Directories
SOURCEDIR = src/
BUILDDIR = build/
# Compiler options
CC = clang++
DEBUG = -g
CFLAGS = -std=c++11 -Wall -c $(DEBUG)
LFLAGS = -Wall $(DEBUG)
# Files
SRC = $(wildcard $(SOURCEDIR)*.cpp) $(wildcard $(SOURCEDIR)*/*.cpp)
OBJS = $(SRC:$(SOURCEDIR)%.cpp=$(BUILDDIR)%.o)
ifeq ($(UNAME), Darwin)
LIBS = -lglfw3 -framework OpenGL -lglew -framework IOKit -framework CoreFoundation -framework ApplicationServices -framework Foundation -framework AppKit
BUILDDIR = ./build/osx/
endif
ifeq ($(UNAME), Linux)
LIBS = -lglfw -lGL -lGLEW
BUILDDIR = ./build/linux/
endif
# Build target
TARGET = test
all: $(TARGET)
$(TARGET): $(OBJS)
$(CC) $(LFLAGS) $^ -o $(TARGET) $(LIBS)
$(OBJS): $(BUILDDIR)%.o : $(SOURCEDIR)%.cpp
#mkdir -p $(dir $#)
$(CC) $(CFLAGS) $< -o $#
clean:
rm -rf $(BUILDDIR)*.o $(BUILDDIR)*/*.o $(TARGET)
Related
Hi this is my make file (I have very little make file experience sorry)
PROJECT_ROOT = $(dir $(abspath $(firstword $(MAKEFILE_LIST))))
OBJS = Angle.o \
AppControlTimer.o \
CableAngle.o \
CFunctionObject.o \
SonarDGCUArrayData.o \
SonarDGCUCommsTCP.o \
SonarDGCUEthernetClient.o \
SonarDGCUFinsPacket.o \
SonarDGCUMotorMemoryArea.o \
SonarDGCUSensorsData.o \
SonarDGCUSensorsMemoryArea.o \
SonarDGCUThread.o
LIB = libFins.a
INCPATH = ../../
INSTALL_DIR = /opt/s2193/lib64
ifeq ($(BUILD_MODE),debug)
CFLAGS += -g
else ifeq ($(BUILD_MODE),run)
CFLAGS += -O2
else ifeq ($(BUILD_MODE),linuxtools)
CFLAGS += -g -pg -fprofile-arcs -ftest-coverage
LDFLAGS += -pg -fprofile-arcs -ftest-coverage
else
$(error Build mode $(BUILD_MODE) not supported by this Makefile)
endif
CFLAGS += -MMD -Wall -Wextra -Wpedantic -Wno-vla
CFLAGS += -I$(PROJECT_ROOT)../target/nar/log4cxx-0.11.0.TUS1-noarch/include/ -c -Wall
CFLAGS += -I${INCPATH}include -DLINUX
LDFLAGS += -L$(PROJECT_ROOT)../target/libs/ -llog4cxx
CXXFLAGS += -DBUILD_WITHOUT_HAL -DDBG_LVL=7
CXX += -std=c++11
CC += -std=c11
.PHONY: all clean install
all: $(LIB)
$(LIB): $(OBJS)
$(AR) $(ARFLAGS) -o $# $^
%.o: $(PROJECT_ROOT)src/%.cpp
#echo ".cpp.o!! "$<
$(CXX) -c $(CFLAGS) $(CXXFLAGS) $(CPPFLAGS) -o $# $<
%.o: $(PROJECT_ROOT)src/%.c
#echo ".c.o!! $<"
$(CC) -c $(CFLAGS) $(CPPFLAGS) -o $# $<
clean:
rm -fr $(LIB) $(OBJS) $(OBJS:.o=.d)
install: $(LIB)
install -m 755 -d $(INSTALL_DIR)
install -m 644 $(LIB) $(INSTALL_DIR)
-include $(OBJS:.o=.d)
when I use the file I get undefined reflectances I'm trying to use the library
LDFLAGS += -L$(PROJECT_ROOT)../target/libs/ -llog4cxx
but I'm not sure how to add it to the file for reference when building libfins.a
thanks in advance
liblog4cxx supports pkg-config like any other sanely packaged library.
Stop writing flags by hand for libraries that you haven't made.
CXXFLAGS += $(shell pkg-config --cflags liblog4cxx)
LDFLAGS += $(shell pkg-config --libs liblog4cxx)
If you are really curious about flags your library needs, go ahead and run these two commands in your terminal, then leave it at that. Flags needed on your system are not necessarily flags needed on mine, that's why pkg-config exists, and people who made the library know better than you what it needs or does not need.
At the same time, pkg-config allows to expect a specific version of a library and all dependencies of your dependency are resolved transparently, without you having to do anything about it, and in fact you cannot do anything about it, because you don't know when or how the library or any of its dependencies will change, this becomes even more insane to manage yourself if you're linking statically. When using pkg-config, you just tack on --static and it gives you all the extra necessary flags.
When I make the Makefile everything works fine, I get a library in the directory dir. And when I run "Make test" I get a testfile that I want to run. But when I want to run this file I get this weird error: ./programma: error while loading shared libraries: libprogramma.so: cannot open shared object file: No such file or directory. I have tried running the program on both WSL and Linux, but nothing makes this error go away. Can anyone help me?
Here I have my Makefile which makes the library and the executable:
INC_DIR = include
SRC_DIR = src
SOURCES = $(sort $(shell find $(SRC_DIR) -name '*.cc'))
OBJECTS = $(SOURCES:.cc=.o)
DEPS = $(OBJECTS:.o=.d)
TARGET = programma
CXX = g++
CFLAGS = -Wall -Wextra -Wpedantic -std=c++11
CPPFLAGS = $(addprefix -I, $(INC_DIR))
.PHONY: all clean debug release
release: CFLAGS += -O3 -DNDEBUG
release: all
debug: CFLAGS += -O0 -DDEBUG -ggdb3
debug: all
all: $(TARGET)
clean:
rm -f $(OBJECTS) $(DEPS) lib/*.so programma *.d
$(TARGET): $(OBJECTS)
$(CXX) $(CFLAGS) $(CPPFLAGS) -fPIC -shared -o lib/lib$#.so $^
-include $(DEPS)
%.o: %.cc
$(CXX) $(CFLAGS) $(CPPFLAGS) -fPIC -MMD -o $# -c $<
test:
$(CXX) $(CFLAGS) -L./lib $(CPPFLAGS) -MMD -o programma tests/main.cc -l$(TARGET)
Executables on Linux don't look for shared libraries in the directory they're located in, at least by default.
You can either fix that at link-time, by passing -Wl,-rpath='$ORIGIN', or at runtime, by setting LD_LIBRARY_PATH env variable to the directory with the library. (LD_LIBRARY_PATH=path/to/lib ./programma)
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}
I'm trying to create a makefile that will works on both OSX and Linux.
My problem is I need to change cflags and ldflags depending on OS the makefile is executed but I can't make it work. That's my makefile :
OS:=$(shell uname)
DST=hello
SRC=$(wildcard *.cpp)
OBJ=$(SRC:.cpp=.o)
CFLAGS=
all: clean DetectOS $(DST)
DetectOS:
ifeq ($(OS),Darwin)
#echo OS : $(OS)
CC=g++
LDFLAGS="-lm -framework OpenCL"
CFLAGS+=-O3
endif
ifeq ($(OS),Linux)
#Coming soon...
endif
$(DST): $(OBJ)
$(CC) -o $# $^ $(LDFLAGS)
%.o: %.cpp
$(CC) -o $# -c $< $(CFLAGS)
clean:
rm -rf *.o $(DST)
But when I run this code, neither cflags, ldflags or CC are updated in the ifeq conditional block. I get the following result :
$ make
rm -rf *.o hello
OS : Darwin
CC=g++
LDFLAGS="-lm -framework OpenCL"
CFLAGS+=-O3
cc -o opencl.o -c opencl.cpp
cc -o hello opencl.o
Undefined symbols for architecture x86_64:....
As you can see, the OS is detected because we went in the ifeq conditional block, but CC isn't updated and keep a non-initialized value of cc. Finally the linker process fails because OpenCL is not referenced in ldflags.
An other little point, if I don't put quotes in LDFLAGS="-lm -framework OpenCL" I get the error :
LDFLAGS=-lm -framework OpenCL
/bin/sh: -framework: command not found
make: *** [DetectOS] Error 127
And based on multiple exemples (here on stackoverflow) I should do it without quotes.
I'm currently on Mac OS X Yosemite.
I think the ifeq block should not go into the make target, but just to the front of the makefile (before all:).
I.e. like this:
OS:=$(shell uname)
DST=hello
SRC=$(wildcard *.cpp)
OBJ=$(SRC:.cpp=.o)
CFLAGS=
ifeq ($(OS),Darwin)
$(info OS is $(OS))
CC=g++
LDFLAGS=-lm -framework OpenCL
CFLAGS+=-O3
endif
ifeq ($(OS),Linux)
#Coming soon...
endif
all: clean $(DST)
...
(no "DetectOS" target, using info instead of echo)
I have an SDL game I have been working on as my first somewhat real project. I decided to introduce Box2D physics as I was not happy with the collision detection. So I installed it to /usr/local/lib/Box2D and in the folder is Box2D.h and supporting folders. I am using MacVim to code on OSX 10.9.2 to develop, and clang++ compiler from the command line.
In my game code I am just trying to create a simple world to test things out:
#include <Box2D/Box2D.h>
.......
world = new b2World(b2Vec2(0.0,9.81));
My make command finds the library, but errors out trying to build.
$ make clean && make
rm -rf obj bin
clang++ -Wall -c -std=c++11 -I/usr/local/lib src/Ball.cpp -o obj/Ball.o
clang++ -Wall -c -std=c++11 -I/usr/local/lib src/Game.cpp -o obj/Game.o
clang++ -Wall -c -std=c++11 -I/usr/local/lib src/Paddle.cpp -o obj/Paddle.o
clang++ -Wall -c -std=c++11 -I/usr/local/lib src/TextureManager.cpp -o obj/TextureManager.o
clang++ -Wall -c -std=c++11 -I/usr/local/lib src/main.cpp -o obj/main.o
clang++ -framework SDL2 -framework SDL2_image -F /Library/Frameworks -L/usr/local/lib/Box2D obj/Ball.o obj/Game.o obj/Paddle.o obj/TextureManager.o obj/main.o -o bin/game
Undefined symbols for architecture x86_64:
"b2World::b2World(b2Vec2 const&)", referenced from:
Game::init() in Game.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [game] Error 1
And here is my Makefile. Box2D is in /usr/local/lib/Box2D/Box2D.h. I am pretty sure my issue is somewhere in the Makefile.
CXX = clang++
CXXFLAGS = -Wall -c -std=c++11 -I/usr/local/lib
SDL = -framework SDL2 -framework SDL2_image
LDFLAGS = $(SDL) -F /Library/Frameworks -L/usr/local/lib/Box2D
SRC_DIR = src
SOURCES = $(wildcard $(SRC_DIR)/*.cpp)
OBJ_DIR = obj
OBJECTS = $(subst $(SRC_DIR)/, $(OBJ_DIR)/, $(patsubst %.cpp, %.o, $(SOURCES)))
#$(warning $(OBJECTS))
BIN_DIR = bin
EXE = game
# run these no matter what
.PHONY: all clean run
all: $(EXE)
$(EXE): $(OBJECTS)
#mkdir -p $(BIN_DIR)
$(CXX) $(LDFLAGS) $(OBJECTS) -o $(BIN_DIR)/$(EXE)
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
#mkdir -p $(OBJ_DIR)
$(CXX) $(CXXFLAGS) $< -o $#
clean:
rm -rf obj bin
run:
./$(BIN_DIR)/$(EXE)
It does not appear that you ever actually link the Box2D library anywhere? You use -L to specify directories to search while linking, but I don't see a -l option to actually link the Box2D library (whatever it's called).
Your output line seems to bear this out:
clang++ -framework SDL2 -framework SDL2_image -F /Library/Frameworks -L/usr/local/lib/Box2D obj/Ball.o obj/Game.o obj/Paddle.o obj/TextureManager.o obj/main.o -o bin/game
You need to get -lbox2d (or whatever the correct name for the Box2D library is) in there.