this is my makefile:
### OUTPUT ###
BUILD = Build
### SOURCES ###
SRC = Src/main\
Src/Game/Game\
Src/Shader/Shader
### OBJECTS ###
OBJ = $(addsuffix .o, $(addprefix $(BUILD)/, $(SRC)))
### INCLUDES ###
INC = -ID:/Development/OpenGL/Glfw/include/GLFW\
-ID:/Development/OpenGL/Glew/glew-2.1.0/include/GL\
-ID:/Development/OpenGL/Glm/glm-0.9.9.8/glm\
-ISrc/Game\
-ISrc/Shader/
### LIBRARIES ###
LIB = -LD:/Development/OpenGL/Glew/glew-2.1.0/lib/Release/Win32 -lglew32s\
-LD:/Development/OpenGL/Glfw/lib-mingw -lglfw3\
-lopengl32
### LINKER FLAGS ###
LFLAGS = $(LIB)
### COMPILER FLAGS
CFLAGS = $(INC)
### COMPILER ###
CC = g++
all: $(BUILD)/test.exe
$(BUILD)/test.exe: $(OBJ)
#echo LINKING $^
#$(CC) $(LFLAGS) -o $# $^
$(BUILD)/%.o: %.cpp
#echo COMPILING $<
#mkdir -p $(subst /,\,$(dir $#))
#$(CC) $(CFLAGS) -M -MT $# -o $(patsubst %.o, %.d, $#) $<
#$(CC) $(CFLAGS) -o $# -c $<
-include $(OBJ:.o=.d)
.PHONY: clean
clean:
#echo CLEANING......
##rm -rf $(BUILD)/*
i am specifying the needed libraries here:
### LIBRARIES ###
LIB = -LD:/Development/OpenGL/Glew/glew-2.1.0/lib/Release/Win32 -lglew32s\
-LD:/Development/OpenGL/Glfw/lib-mingw -lglfw3\
-lopengl32
and linking them here:
$(BUILD)/test.exe: $(OBJ)
#echo LINKING $^
#$(CC) $(LFLAGS) -o $# $^
the errors i am getting are:
LINKING Build/Src/main.o Build/Src/Game/Game.o Build/Src/Shader/Shader.o
Build/Src/Shader/Shader.o:Shader.cpp:(.text+0xb): undefined reference to `__glewUseProgram'
Build/Src/Shader/Shader.o:Shader.cpp:(.text+0x33): undefined reference to `__glewCreateShader'
Build/Src/Shader/Shader.o:Shader.cpp:(.text+0x48): undefined reference to `__glewShaderSource'
Build/Src/Shader/Shader.o:Shader.cpp:(.text+0x70): undefined reference to `__glewCompileShader'
Build/Src/Shader/Shader.o:Shader.cpp:(.text+0xdf): undefined reference to `__glewCreateShader'
Build/Src/Shader/Shader.o:Shader.cpp:(.text+0xf4): undefined reference to `__glewShaderSource'
Build/Src/Shader/Shader.o:Shader.cpp:(.text+0x11c): undefined reference to `__glewCompileShader'
also i have defined GLEW_STATIC:
#define GLEW_STATIC
#include "glew.h"
i am using mingw32 and i'm calling the makefile with mingw32-make all
I have no idea why it can't find those symbols...i've been trying to figure it out for 2 hours..
EDIT:
Here is the actual linking command:
g++ -LD:/Development/OpenGL/Glew/glew-2.1.0/lib/Release/Win32 -lglew32s -LD:/Development/OpenGL/Glfw/lib-mingw -lglfw3 -lopengl32 -o Build/test.exe Build/Src/main.o Build/Src/Game/Game.o Build/Src/Shader/Shader.o
In a single-pass linker (like almost all linkers today) the order of items is critical. In particular, you have to make sure that all your object files appear on the link line first, before any libraries. Secondly you have to make sure that libraries are ordered correctly, so that the higher level libraries come earlier and the lower level libraries (that other libraries depend on) come afterwards.
You need to extract your library flags into two distinct parts: one part that has linker control options (such as -L) and another part that contains the actual libraries themselves (such as -l).
In standard makefiles these parts are placed into the variables LDFLAGS and LDLIBS, respectively:
LDFLAGS = -LD:/Development/OpenGL/Glew/glew-2.1.0/lib/Release/Win32 \
-LD:/Development/OpenGL/Glfw/lib-mingw
LDLIBS = -lglew32s -lglfw3 -lopengl32
I don't know enough about GLEW to know if the LDLIBS are ordered properly you may need to experiment.
Then, write your link rule like this:
$(BUILD)/test.exe: $(OBJ)
#echo LINKING $^
#$(CC) $(LDFLAGS) -o $# $^ $(LDLIBS)
Related
I can compile the project just fine if I run the project by hand with g++ source/* -lSDL2 -o bin/fly_fishing. When I do run make, I get
mkdir -p bin
g++ -lSDL2 -o bin/fly_fishing
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/12/../../../x86_64-linux-gnu/Scrt1.o: in function `_start':
(.text+0x17): undefined reference to `main'
collect2: error: ld returned 1 exit status
make: *** [Makefile:20: bin/fly_fishing] Error 1
Which tells me that it's not populating from $^ for linking. So what have I missed here? Here's the makefile for reference.
SRC_DIR := source
OBJ_DIR := objects
BIN_DIR := bin
EXE := $(BIN_DIR)/fly_fishing
SRC := $(wildcard $(SRC_DIR)/*.c)
OBJ := $(SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
CXXFLAGS := -Wall
#CFLAGS := -Wall
LDLIBS := -lSDL2a
LDFLAGS :=
.PHONY: all clean
all: $(EXE)
$(EXE): $(OBJ) | $(BIN_DIR)
$(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $#
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c | $(OBJ_DIR)
$(CXX) -c $(CXXFLAGS) $(CFLAGS) $< -o $#
$(BIN_DIR) $(OBJ_DIR):
mkdir -p $#
clean:
#$(RM) -rv $(BIN_DIR) $(OBJ_DIR)
-include $(OBJ:.o=.d)
Which tells me that it's not populating from $^ for linking.
That seems unlikely. Much more likely would be that $^ expands to nothing. Which would be the case if $(OBJ) expands to nothing. Which seems plausible because I don't see any corresponding objects being built (though perhaps you've omitted that, or they were built on a previous run). And $(OBJ) expanding to nothing implies that $(SRC) expands to nothing.
So what have I missed here?
That $(SRC) expands to nothing is not inconsistent with the data presented. I observe that the manual compilation command you present is
g++ source/* -lSDL2 -o bin/fly_fishing
That does seem to suggest that there are indeed source files in source/, but do they match the pattern source/*.c? Since you're compiling with g++, I bet not. It would be highly unconventional to name C++ source files to end with .c, and surely you would not attempt to compile C source files with a C++ compiler. I infer, then, that your source files are all named with .cpp, or maybe .cc or .C, all of which forms are conventions for C++ source names.
If all your source names follow one or another of those patterns then indeed, this ...
SRC := $(wildcard $(SRC_DIR)/*.c)
... will result in $(SRC) being empty.
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'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 have been asked to port our product into another application.(our s/w is running on linux virtualbox)
I have got a directory of their interface files and also a example code on trying to configure their software/hardware. I see their interface files under the s/w directory. In the reference code directory, I see a makefile with the reference to their reference code.
Trying to run their reference code makefile. getting error that
make: *** No rule to make target `../ main.o" :(
Btw donot understand why SIMUDIR = -I\..\custom_simcode\ this is done in the makefile ?
Also not much familiar with crosscompiler syntax !
ifndef CROSS_CC_PREFIX
CROSS_CC_PREFIX=$(CROSS_COMPILE)
endif
PROGRAM = customer_sim
CC=$(CROSS_CC_PREFIX)gcc
LD=$(CROSS_CC_PREFIX)ld
RANLIB=$(CROSS_CC_PREFIX)corelib
CFLAGS= -g
all: $(PROGRAM)
## Include path
SIMUDIR = -I\..\custom_simcode\
CUST_INT_INC = -I./../cust_Intf/DecHandler/inc \
-I./../CCPU
LIBDIR = -L./../cust_Intf \
-L./../cust_IntfApi
LIBS = -lpthread -customercif -customerapi
LDFLAGS= $(LIBDIR) $(LIBS)
SOURCE = ./../custom_simcode/main.c \
./../custom_simcode/custcode_primitives_init.c \
./../custom_simcode/custccp_primitives_init.c
CFLAGS += $(SIMUDIR) $(CUST_INT_INC) -DPRINT_IO_CONSOLE -UADAPT_CCPU_CUSTIF
OBJS = $(SOURCE:.c=.o)
$(PROGRAM): $(OBJS)
$(CC) -o $# $(OBJS) $(LDFLAGS)
main.o: $(SIMUDIR)/main.c $(SIMUDIR) $(CUST_INT_INC)
$(CC) -c -o /main.o $(SIMUDIR)/main.c
clean:
-rm -f $(OBJS) $(OBJS) $(PROGRAM)
Your $(OBJS) list dependencies for $(PROGRAMs) with directories included but your rule for main.o doesn't have same path.
It would be better to have a generic rule to compile C files like
%.o: %.c
$(CC) -c -o $# $<
Then simply assign extra dependencies for each file like:
$(OBJS): $(SIMUDIR) $(CUST_INT_INC)
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.