未能 link 使用 Makefile 到 SFML 库,即使它作为一个衬里工作
Failing to link to SFML libraries using Makefile even though it works as a one liner
这是我的目录结构:
.
├── a.out
├── assets
│ └── ...
├── build
│ ├── apps
│ └── objects
├── include
│ └── engine
│ └── Class.h
├── Makefile
└── src
├── engine
│ └── Class.cpp
└── program.cpp
我可以使用以下命令将 program.cpp
编译成 a.out
:
g++ src/engine/*.cpp src/program.cpp -Iinclude/ -L/usr/lib -lstdc++ -lm -lsfml-graphics -lsfml-window -lsfml-system -Wall
虽然这行得通,但该项目可能会增长,显然制作一个严肃的 Makefile 比直接使用单行编译更可取。所以我使用了一种我以前多次使用过的 Makefile 格式,它工作得很好,但我过去从未 link 将它编辑到外部库。这是我正在使用的 Makefile :
CXX := -g++
CXXFLAGS := -std=gnu++0x -g -Wall
LDFLAGS := -L/usr/lib -lstdc++ -lm -lsfml-graphics -lsfml-window -lsfml-system
BUILD := ./build
OBJ_DIR := $(BUILD)/objects
APP_DIR := $(BUILD)/apps
TARGET := program
INCLUDE := -Iinclude/
SRC := $(wildcard src/engine/*.cpp) $(wildcard src/*.cpp)
OBJECTS := $(SRC:%.cpp=$(OBJ_DIR)/%.o)
all: build $(APP_DIR)/$(TARGET)
$(OBJ_DIR)/%.o: %.cpp
@mkdir -p $(@D)
$(CXX) $(CXXFLAGS) $(INCLUDE) -o $@ -c $<
$(APP_DIR)/$(TARGET): $(OBJECTS)
@mkdir -p $(@D)
$(CXX) $(CXXFLAGS) $(INCLUDE) $(LDFLAGS) -o $(APP_DIR)/$(TARGET) $(OBJECTS)
.PHONY: all build clean debug release
build:
@mkdir -p $(APP_DIR)
@mkdir -p $(OBJ_DIR)
debug: CXXFLAGS += -DDEBUG -g
debug: all
release: CXXFLAGS += -O2
release: all
clean:
-@rm -rvf $(OBJ_DIR)/*
-@rm -rvf $(APP_DIR)/*
但是,这会导致编译错误,形式为对 SFML 方法的未定义引用:
./build/objects/src/engine/Class.o: In function `Class::draw()':
/dir/Class.cpp:60: undefined reference to `sf::RenderTarget::getView() const'
我很困惑为什么会发生这种情况,因为上面的一个衬里编译得很好。如果我从我的代码中删除所有对 SFML 的引用,Makefile 也能正常工作。添加的 LDFLAGS
是否不够,即使它们是使我的一个班轮 link 成为 SFML 所需要的全部?如果是这样,还需要什么?
-llibrary
It makes a difference where in the command you write this option; the linker searches and processes libraries and object files in the order they are specified. Thus, foo.o -lz bar.o
searches library z
after file foo.o
but before bar.o
. If bar.o
refers to functions in z
, those functions may not be loaded.
所以将库 (-l<lib_1> ... -l<lib_x>
) 放在最后一行,在目标文件之后。
这是我的目录结构:
.
├── a.out
├── assets
│ └── ...
├── build
│ ├── apps
│ └── objects
├── include
│ └── engine
│ └── Class.h
├── Makefile
└── src
├── engine
│ └── Class.cpp
└── program.cpp
我可以使用以下命令将 program.cpp
编译成 a.out
:
g++ src/engine/*.cpp src/program.cpp -Iinclude/ -L/usr/lib -lstdc++ -lm -lsfml-graphics -lsfml-window -lsfml-system -Wall
虽然这行得通,但该项目可能会增长,显然制作一个严肃的 Makefile 比直接使用单行编译更可取。所以我使用了一种我以前多次使用过的 Makefile 格式,它工作得很好,但我过去从未 link 将它编辑到外部库。这是我正在使用的 Makefile :
CXX := -g++
CXXFLAGS := -std=gnu++0x -g -Wall
LDFLAGS := -L/usr/lib -lstdc++ -lm -lsfml-graphics -lsfml-window -lsfml-system
BUILD := ./build
OBJ_DIR := $(BUILD)/objects
APP_DIR := $(BUILD)/apps
TARGET := program
INCLUDE := -Iinclude/
SRC := $(wildcard src/engine/*.cpp) $(wildcard src/*.cpp)
OBJECTS := $(SRC:%.cpp=$(OBJ_DIR)/%.o)
all: build $(APP_DIR)/$(TARGET)
$(OBJ_DIR)/%.o: %.cpp
@mkdir -p $(@D)
$(CXX) $(CXXFLAGS) $(INCLUDE) -o $@ -c $<
$(APP_DIR)/$(TARGET): $(OBJECTS)
@mkdir -p $(@D)
$(CXX) $(CXXFLAGS) $(INCLUDE) $(LDFLAGS) -o $(APP_DIR)/$(TARGET) $(OBJECTS)
.PHONY: all build clean debug release
build:
@mkdir -p $(APP_DIR)
@mkdir -p $(OBJ_DIR)
debug: CXXFLAGS += -DDEBUG -g
debug: all
release: CXXFLAGS += -O2
release: all
clean:
-@rm -rvf $(OBJ_DIR)/*
-@rm -rvf $(APP_DIR)/*
但是,这会导致编译错误,形式为对 SFML 方法的未定义引用:
./build/objects/src/engine/Class.o: In function `Class::draw()':
/dir/Class.cpp:60: undefined reference to `sf::RenderTarget::getView() const'
我很困惑为什么会发生这种情况,因为上面的一个衬里编译得很好。如果我从我的代码中删除所有对 SFML 的引用,Makefile 也能正常工作。添加的 LDFLAGS
是否不够,即使它们是使我的一个班轮 link 成为 SFML 所需要的全部?如果是这样,还需要什么?
-llibrary
It makes a difference where in the command you write this option; the linker searches and processes libraries and object files in the order they are specified. Thus,
foo.o -lz bar.o
searches libraryz
after filefoo.o
but beforebar.o
. Ifbar.o
refers to functions inz
, those functions may not be loaded.
所以将库 (-l<lib_1> ... -l<lib_x>
) 放在最后一行,在目标文件之后。