Here is my directory structure :
.
├── a.out
├── assets
│ └── ...
├── build
│ ├── apps
│ └── objects
├── include
│ └── engine
│ └── Class.h
├── Makefile
└── src
├── engine
│ └── Class.cpp
└── program.cpp
I can compile program.cpp
into a.out
using the following command :
g++ src/engine/*.cpp src/program.cpp -Iinclude/ -L/usr/lib -lstdc++ -lm -lsfml-graphics -lsfml-window -lsfml-system -Wall
While this works, this project is likely to grow and obviously making a serious Makefile would be preferable to direct compiling with a one liner. So I've used a Makefile format that I've used many times before, and that works perfectly fine but I've never linked it to outside libraries in the past. Here is the Makefile I'm using :
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)/*
However, this leads to compilation errors, in the form of undefined references to SFML methods :
./build/objects/src/engine/Class.o: In function `Class::draw()':
/dir/Class.cpp:60: undefined reference to `sf::RenderTarget::getView() const'
I'm confused as to why this happens given that the one liner above compiles fine. The Makefile also works just fine if I remove all references to SFML from my code. Were the added LDFLAGS
not enough even though they're all that's needed to make my one liner link to SFML ? If so, what else is needed ?
From 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 libraryz
after filefoo.o
but beforebar.o
. Ifbar.o
refers to functions inz
, those functions may not be loaded.
So put the libraries (-l<lib_1> ... -l<lib_x>
) last on the line, after your object files.