未能 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 所需要的全部?如果是这样,还需要什么?

来自gcc link options

-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>) 放在最后一行,在目标文件之后。