我正在寻找一个可以在Unix上编译C程序的Makefile(Ubuntu)。 Makefile应该包括SDL库(2.0)以及SDL_image。
所以这是我目前的Makefile:
CC = gcc
OBJECTS = $(patsubst %.c,%.o,$(wildcard *.c))
EXEC = main
LDFLAGS = `sdl2-config --libs` -L/usr/lib -lSDL2_image
CCFLAGS = `sdl2-config --cflags` -I/usr/include/SDL_image.h
$(EXEC): $(OBJECTS)
$(CC) $(LDFLAGS) $< -o $@
%.o: %.c
$(CC) -c $(CCFLAGS) $< -o $@
.PHONY: clean
clean:
rm -f $(OBJECTS) $(EXEC)
这是我当前的代码(仅用于测试Makefile的最小代码):
#include <stdio.h>
#include <SDL.h>
#include <SDL2/SDL_image.h>
int main(int argc, char **argv) {
SDL_Window* window = NULL;
SDL_Surface* screenSurface = NULL;
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
printf("Initialization error: %s\n",SDL_GetError());
return 1;
}
window = SDL_CreateWindow("Test",SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,640, 480,SDL_WINDOW_SHOWN);
SDL_Quit();
return 0;
}
所以当我写命令时:make
我在所有SDL功能上都出错了。 这是一个例子:未定义的对“SDL_Init”的引用
我尝试了很多东西(比如Makefile中Include和Link的路径不同),但似乎没什么用。
所以我的问题是:如何解决这些对SDL2函数的未定义引用?
答案 0 :(得分:2)
您正在以错误的顺序指定链接器标志。
这是错误的:
LDFLAGS = `sdl2-config --libs` -L/usr/lib -lSDL2_image
$(EXEC): $(OBJECTS)
$(CC) $(LDFLAGS) $< -o $@
这是正确的:
LIBS = `sdl2-config --libs` -L/usr/lib -lSDL2_image
$(EXEC): $(OBJECTS)
$(CC) $(LDFLAGS) $^ $(LIBS) -o $@
使用GNU Binutils,库的顺序很重要。库必须在具有对这些库中的符号的未定义引用的对象之后。它太糟糕了,这很愚蠢,但这就是GNU Binutils的工作方式而你却坚持下去。
您希望$^
代替$<
,因为$<
只是第一个依赖关系。
可能最好使用可以找到SDL2_image的pkg-config
:
LIBS = `pkg-config --libs sdl2 SDL2_image`
调用shell程序时,您可能希望:=
不是=
,这会将变量展开一次,而不是每次都使用它:
LIBS := $(shell pkg-config --libs sdl2 SDL2_image)
CFLAGS := $(shell pkg-config --cflags sdl2 SDL2_image)
这是一个清理过的例子,接近我写的方式:
# use := not =
# convention: objects, exec are lower-case because they're private
objects := $(patsubst %.c,%.o,$(wildcard *.c))
CFLAGS := $(shell pkg-config --cflags sdl2 SDL2_image)
LIBS := $(shell pkg-config --libs sdl2 SDL2_image)
# Don't define CC, because the default (cc) is fine
# It's probably linked to gcc on your system anyway
# = or := doesn't matter here
exec = main
# must use = here
depflags = -MF $(patsubst %.o,%.d,$@) -MMD -MP
-include $(wildcard *.d)
$(exec): $(objects)
$(CC) $(LDFLAGS) $^ $(LIBS) -o $@
%.o: %.c
$(CC) $(depflags) -c $(CCFLAGS) $< -o $@
.PHONY: clean
clean:
rm -f *.o *.d $(exec)
答案 1 :(得分:1)
您反转了一些编译器/链接器选项:
# linker options
LDFLAGS = `sdl2-config --libs` -I/usr/include/SDL_image.h
# compiler options
CCFLAGS = `sdl2-config --cflags` -L/usr/lib -lSDL2_image
应该是:
# linker options
LDFLAGS = `sdl2-config --libs` -L/usr/lib -lSDL2_image
# compiler options
CCFLAGS = `sdl2-config --cflags` -I/usr/include
详细说明:
-L Is to indicate to the linker where to find .so files
-l Is to link to a given library
-I Is to indicate to the compiler where to find .h files
答案 2 :(得分:0)
链接单个目标文件
n
是通过运行链接器(通常称为n.o
自动生成的ld
)通过C编译器。使用的精确配方是:$(CC) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS)
和Variables Used by Implicit Rules:
LDFLAGS
当编译器应该调用链接器时给出的额外标志,
ld
,例如-L
。应将库(-lfoo
)添加到LDLIBS变量中 代替。
因此,在这种情况下,应将-lSDL2_image
设置或添加到LDLIBS,而不是LDFLAGS。