Reputation: 3127
I am trying to compile the below test program:
#include <GL/glfw.h>
int main(int argc, char** argv) {
if(!glfwInit()) {
return -1;
}
if(!glfwOpenWindow(640, 480, 8, 8, 8, 0, 24, 0, GLFW_WINDOW)) {
return -1;
}
while(glfwGetWindowParam(GLFW_OPENED)) {
glfwSwapBuffers();
}
return 0;
}
but I always get undefined reference
errors in regards to the GLFW functions.
Below is my makefile:
CXX = clang++
CXXFLAGS = -Wall -std=c++0x
LDFLAGS = -lglfw
OBJ_DIR = bin
LIB_DIR = -L/usr/lib
INC_DIR = -I/usr/include
SOURCE = main.cpp
OBJECTS = ${SOURCE:%.cpp=$(OBJ_DIR)/%.o}
EXECUTABLE = hello
all: init $(OBJECTS) $(EXECUTABLE)
$(EXECUTABLE):
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(LIB_DIR) -o $@ $(OBJECTS)
$(OBJ_DIR)/%.o: %.cpp
$(CXX) $(INC_DIR) -c $< -o $@
init:
@mkdir -p "$(OBJ_DIR)"
clean:
@rm -rf $(OBJ_DIR) $(EXECUTABLE)
I definitely have glfw.h
and libglfw.a/.so
as when I run locate glfw
I get:
:~$ locate glfw
/usr/include/GL/glfw.h
/usr/lib/libglfw.a
/usr/lib/libglfw.so
/usr/lib/libglfw.so.2
/usr/lib/libglfw.so.2.6
The output of nm /usr/lib/libglfw.a | grep glfwInit
:
:~$ nm /usr/lib/libglfw.a | grep glfwInit
U _glfwInitialized
U _glfwInitialized
U _glfwInitialized
U _glfwInitialized
0000000000000000 B _glfwInitialized
0000000000000000 T glfwInit
U _glfwInitialized
U _glfwInitialized
U _glfwInitialized
U _glfwInitialized
U _glfwInitialized
U _glfwInitJoysticks
U _glfwInitTimer
00000000000000c0 T _glfwInitJoysticks
0000000000000000 T _glfwInitTimer
and the verbose message from clang:
clang++ -I/usr/include -c main.cpp -o bin/main.o
clang++ -Wall -std=c++0x -Wl --verbose -lglfw -lGL -lGLU -L/usr/lib -o hello bin/main.o
Ubuntu clang version 3.0-6ubuntu3 (tags/RELEASE_30/final) (based on LLVM 3.0)
Target: x86_64-pc-linux-gnu
Thread model: posix
clang: warning: argument unused during compilation: '-std=c++0x'
"/usr/bin/ld" -z relro --hash-style=gnu --as-needed --build-id --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o hello /usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu/crt1.o /usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.6/crtbegin.o -L/usr/lib -L/usr/lib/gcc/x86_64-linux-gnu/4.6 -L/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu -L/lib/x86_64-linux-gnu -L/lib/../lib64 -L/usr/lib/x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/4.6/../../.. -L/lib/x86_64-linux-gnu -L/lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib -lglfw -lGL -lGLU bin/main.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-linux-gnu/4.6/crtend.o /usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu/crtn.o
bin/main.o: In function `main':
main.cpp:(.text+0x17): undefined reference to `glfwInit'
main.cpp:(.text+0x76): undefined reference to `glfwOpenWindow'
main.cpp:(.text+0x97): undefined reference to `glfwGetWindowParam'
main.cpp:(.text+0xa7): undefined reference to `glfwSwapBuffers'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [hello] Error 1
It seems to not be finding the library?
Upvotes: 8
Views: 12918
Reputation: 340218
The problem is that the glfw libraries are being specified to the linker before the object file that depends on them. ld
searches libraries to resolve dependencies only for the dependencies that it knows about at the point in list of files it's processing. So when ld
is searching libglfw.a
it doesn't know about the glfwInit
dependency in main.o
yet. ld
(by default) doesn't go back an search the library again.
Try:
$(EXECUTABLE):
$(CXX) $(CXXFLAGS) $(LIB_DIR) -o $@ $(OBJECTS) $(LDFLAGS)
Also the libraries should probably be specified in a LDLIBS
(or LIBS
) variable - LDFLAGS
is conventionally use for linker options:
CXX = clang++
CXXFLAGS = -Wall -std=c++0x
LDLIBS = -lglfw -lGL -lGLU
OBJ_DIR = bin
LIB_DIR = -L/usr/lib
INC_DIR = -I/usr/include
SOURCE = main.cpp
OBJECTS = ${SOURCE:%.cpp=$(OBJ_DIR)/%.o}
EXECUTABLE = hello
all: init $(OBJECTS) $(EXECUTABLE)
$(EXECUTABLE):
$(CXX) $(LDFLAGS) $(LIB_DIR) -o $@ $(OBJECTS) $(LDLIBS)
$(OBJ_DIR)/%.o: %.cpp
$(CXX) $(INC_DIR) -c $< -o $@
init:
@mkdir -p "$(OBJ_DIR)"
clean:
@rm -rf $(OBJ_DIR) $(EXECUTABLE)
Upvotes: 12