调整 Makefile 以包含 SDL2
Adapting a Makefile to include SDL2
我正在编译一个使用 SDL2 库的简单程序。
MWE(Lazy Foo's tutorial 的简化版):
// main.cpp
#include <SDL.h>
int main(int argc, char* args[])
{
SDL_Window* window = NULL;
SDL_Surface* screenSurface = NULL;
SDL_Init(SDL_INIT_VIDEO);
window = SDL_CreateWindow("The exciting white window", DL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_SHOWN);
screenSurface = SDL_GetWindowSurface(window);
SDL_FillRect(screenSurface, NULL, SDL_MapRGB( screenSurface->format, 0xFF, 0xFF, 0xFF));
SDL_UpdateWindowSurface(window);
SDL_Delay(2000);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
我想修改 this tutorial 的 Makefile 来处理它。
这是我试过的:
program_NAME := main
program_CXX_SRCS := $(wildcard *.cpp)
program_CXX_OBJS := ${program_CXX_SRCS:.cpp=.o}
program_OBJS := $(program_CXX_OBJS)
program_INCLUDE_DIRS := /usr/include/SDL2
program_LIBRARY_DIRS :=
program_LIBRARIES := SDL2
CPPFLAGS += $(foreach includedir,$(program_INCLUDE_DIRS),-I$(includedir))
LDFLAGS += $(foreach librarydir,$(program_LIBRARY_DIRS),-L$(librarydir))
LDFLAGS += $(foreach library,$(program_LIBRARIES),-l$(library))
.PHONY: all clean distclean
all: $(program_NAME)
$(program_NAME): $(program_OBJS)
$(LINK.cc) $(program_OBJS) -o $(program_NAME)
clean:
@- $(RM) $(program_NAME)
@- $(RM) $(program_OBJS)
distclean: clean
但是,我遇到了几个链接器错误:
$ make
g++ -I/usr/include/SDL2 -c -o main.o main.cpp
g++ -I/usr/include/SDL2 -lSDL2 main.o -o myprogram
main.o: In function `main':
main.cpp:(.text+0x25): undefined reference to `SDL_Init'
main.cpp:(.text+0x4a): undefined reference to `SDL_CreateWindow'
main.cpp:(.text+0x5a): undefined reference to `SDL_GetWindowSurface'
main.cpp:(.text+0x7d): undefined reference to `SDL_MapRGB'
main.cpp:(.text+0x90): undefined reference to `SDL_FillRect'
main.cpp:(.text+0x9c): undefined reference to `SDL_UpdateWindowSurface'
main.cpp:(.text+0xa6): undefined reference to `SDL_Delay'
main.cpp:(.text+0xb2): undefined reference to `SDL_DestroyWindow'
main.cpp:(.text+0xb7): undefined reference to `SDL_Quit'
collect2: error: ld returned 1 exit status
Makefile:18: recipe for target 'myprogram' failed
make: *** [myprogram] Error 1
我从 this answer 了解到参数的顺序现在很重要。调用
$ g++ -I/usr/include/SDL2 -c -o main.o main.cpp
$ g++ main.o -lSDL2 -o main
直接从命令行工作。
最后我的问题:正确调整 Makefile 的方法是什么? ("correct" 我的意思是避免上述 Makefile 教程中提到的陷阱类型。)
您找到的教程 makefile 中有错误。要修复 makefile,请替换行:
LDFLAGS += $(foreach library,$(program_LIBRARIES),-l$(library))
与:
LDLIBS += $(foreach library,$(program_LIBRARIES),-l$(library))
并替换行:
$(LINK.cc) $(program_OBJS) -o $(program_NAME)
与:
$(LINK.cc) $(program_OBJS) -o $(program_NAME) $(LDLIBS)
或更正常的样式:
$(LINK.cc) $^ -o $@ $(LDLIBS)
(参见 10.5.3 Automatic Variables
在 the manual)
教程 makefile 中的错误是它不正确
使用(或解释)规范生成变量 LDFLAGS
和 LDLIBS
。它
将所有链接器的库选项 (-l<name>
) 捆绑到 LDFLAGS
的值中。
他们不应该去那里。他们应该输入 LDLIBS
.
的值
预定义的 make 变量 LINK.cc
扩展为:
LINK.cc = $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)
不包含$(LDLIBS)
,正是因为 GNU 链接器,如
在大多数 GCC 发行版(包括你的)中使用,需要目标文件出现
在链接序列中比它们所依赖的库更早,并且将
在序列中不解析任何符号的位置忽略库
链接器 已经需要解析的引用 。
如果 LDLIBS
被正确地用于 -l
选项,并在链接配方中正确使用 - 如上面更正的链接配方
- 然后所有库将安全地出现在所有目标文件之后。
通过将 -l
选项捆绑到 $(LDFLAGS)
,教程获取所有库
在所有目标文件之前;所以在你的链接中, -lSDL2
被忽略了,你的
如观察到的那样,链接失败。
这是典型的 GNU make 变量的摘要
在 C 或 C++ 编译和链接中运行:
CC
调用 C 编译器的命令(默认 cc
)
CXX
调用 C++ 编译器的命令(默认 g++
)
CPPFLAGS
C/C++ 预处理器的选项
CFLAGS
C 编译器的选项
CXXFLAGS
C++ 编译器的选项
LDFLAGS
您的链接选项,不包括库和库 (-l
) 选项
LDLIBS
你的链接库或库(-l
)选项
除非另有说明,否则默认值为空。
见10.2 Catalogue of Built-In Rules
了解这些变量如何在 make 的内置规则中工作。或者保存输出
make --print-data-base
到一个文件并研究它。
我正在编译一个使用 SDL2 库的简单程序。
MWE(Lazy Foo's tutorial 的简化版):
// main.cpp
#include <SDL.h>
int main(int argc, char* args[])
{
SDL_Window* window = NULL;
SDL_Surface* screenSurface = NULL;
SDL_Init(SDL_INIT_VIDEO);
window = SDL_CreateWindow("The exciting white window", DL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_SHOWN);
screenSurface = SDL_GetWindowSurface(window);
SDL_FillRect(screenSurface, NULL, SDL_MapRGB( screenSurface->format, 0xFF, 0xFF, 0xFF));
SDL_UpdateWindowSurface(window);
SDL_Delay(2000);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
我想修改 this tutorial 的 Makefile 来处理它。
这是我试过的:
program_NAME := main
program_CXX_SRCS := $(wildcard *.cpp)
program_CXX_OBJS := ${program_CXX_SRCS:.cpp=.o}
program_OBJS := $(program_CXX_OBJS)
program_INCLUDE_DIRS := /usr/include/SDL2
program_LIBRARY_DIRS :=
program_LIBRARIES := SDL2
CPPFLAGS += $(foreach includedir,$(program_INCLUDE_DIRS),-I$(includedir))
LDFLAGS += $(foreach librarydir,$(program_LIBRARY_DIRS),-L$(librarydir))
LDFLAGS += $(foreach library,$(program_LIBRARIES),-l$(library))
.PHONY: all clean distclean
all: $(program_NAME)
$(program_NAME): $(program_OBJS)
$(LINK.cc) $(program_OBJS) -o $(program_NAME)
clean:
@- $(RM) $(program_NAME)
@- $(RM) $(program_OBJS)
distclean: clean
但是,我遇到了几个链接器错误:
$ make
g++ -I/usr/include/SDL2 -c -o main.o main.cpp
g++ -I/usr/include/SDL2 -lSDL2 main.o -o myprogram
main.o: In function `main':
main.cpp:(.text+0x25): undefined reference to `SDL_Init'
main.cpp:(.text+0x4a): undefined reference to `SDL_CreateWindow'
main.cpp:(.text+0x5a): undefined reference to `SDL_GetWindowSurface'
main.cpp:(.text+0x7d): undefined reference to `SDL_MapRGB'
main.cpp:(.text+0x90): undefined reference to `SDL_FillRect'
main.cpp:(.text+0x9c): undefined reference to `SDL_UpdateWindowSurface'
main.cpp:(.text+0xa6): undefined reference to `SDL_Delay'
main.cpp:(.text+0xb2): undefined reference to `SDL_DestroyWindow'
main.cpp:(.text+0xb7): undefined reference to `SDL_Quit'
collect2: error: ld returned 1 exit status
Makefile:18: recipe for target 'myprogram' failed
make: *** [myprogram] Error 1
我从 this answer 了解到参数的顺序现在很重要。调用
$ g++ -I/usr/include/SDL2 -c -o main.o main.cpp
$ g++ main.o -lSDL2 -o main
直接从命令行工作。
最后我的问题:正确调整 Makefile 的方法是什么? ("correct" 我的意思是避免上述 Makefile 教程中提到的陷阱类型。)
您找到的教程 makefile 中有错误。要修复 makefile,请替换行:
LDFLAGS += $(foreach library,$(program_LIBRARIES),-l$(library))
与:
LDLIBS += $(foreach library,$(program_LIBRARIES),-l$(library))
并替换行:
$(LINK.cc) $(program_OBJS) -o $(program_NAME)
与:
$(LINK.cc) $(program_OBJS) -o $(program_NAME) $(LDLIBS)
或更正常的样式:
$(LINK.cc) $^ -o $@ $(LDLIBS)
(参见 10.5.3 Automatic Variables 在 the manual)
教程 makefile 中的错误是它不正确
使用(或解释)规范生成变量 LDFLAGS
和 LDLIBS
。它
将所有链接器的库选项 (-l<name>
) 捆绑到 LDFLAGS
的值中。
他们不应该去那里。他们应该输入 LDLIBS
.
预定义的 make 变量 LINK.cc
扩展为:
LINK.cc = $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)
不包含$(LDLIBS)
,正是因为 GNU 链接器,如
在大多数 GCC 发行版(包括你的)中使用,需要目标文件出现
在链接序列中比它们所依赖的库更早,并且将
在序列中不解析任何符号的位置忽略库
链接器 已经需要解析的引用 。
如果 LDLIBS
被正确地用于 -l
选项,并在链接配方中正确使用 - 如上面更正的链接配方
- 然后所有库将安全地出现在所有目标文件之后。
通过将 -l
选项捆绑到 $(LDFLAGS)
,教程获取所有库
在所有目标文件之前;所以在你的链接中, -lSDL2
被忽略了,你的
如观察到的那样,链接失败。
这是典型的 GNU make 变量的摘要 在 C 或 C++ 编译和链接中运行:
CC
调用 C 编译器的命令(默认 cc
)
CXX
调用 C++ 编译器的命令(默认 g++
)
CPPFLAGS
C/C++ 预处理器的选项
CFLAGS
C 编译器的选项
CXXFLAGS
C++ 编译器的选项
LDFLAGS
您的链接选项,不包括库和库 (-l
) 选项
LDLIBS
你的链接库或库(-l
)选项
除非另有说明,否则默认值为空。
见10.2 Catalogue of Built-In Rules
了解这些变量如何在 make 的内置规则中工作。或者保存输出
make --print-data-base
到一个文件并研究它。