C:Unix SDL2 库:未定义的引用,Makefile 中的问题?
C : Unix SDL2 library : undefined reference, issue in the Makefile?
我正在寻找可以在 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 函数的未定义引用?
您颠倒了一些 compiler/linker 选项:
# 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
您以错误的顺序指定了链接器标志。
这是错误的:
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 的工作方式,你会坚持使用它。
其他修复
您需要 $^
而不是 $<
,因为 $<
只是 first 依赖项。
可能最好使用 pkg-config
可以为您找到 SDL2_image:
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)
可以看出Catalogue of Built-In Rules:
Linking a single object file
n
is made automatically from n.o
by running the linker (usually called
ld
) via the C compiler. The precise recipe used is:
$(CC) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS)
和Variables Used by Implicit Rules:
LDFLAGS
Extra flags to give to compilers when they are supposed to invoke the linker,
ld
, such as -L
. Libraries (-lfoo
) should be added to the LDLIBS variable
instead.
所以在这种情况下 -lSDL2_image
应该设置或添加到 LDLIBS,而不是 LDFLAGS。
我正在寻找可以在 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 函数的未定义引用?
您颠倒了一些 compiler/linker 选项:
# 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
您以错误的顺序指定了链接器标志。
这是错误的:
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 的工作方式,你会坚持使用它。
其他修复
您需要
$^
而不是$<
,因为$<
只是 first 依赖项。可能最好使用
pkg-config
可以为您找到 SDL2_image: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)
可以看出Catalogue of Built-In Rules:
Linking a single object file
n
is made automatically fromn.o
by running the linker (usually calledld
) via the C compiler. The precise recipe used is:$(CC) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS)
和Variables Used by Implicit Rules:
LDFLAGS
Extra flags to give to compilers when they are supposed to invoke the linker,
ld
, such as-L
. Libraries (-lfoo
) should be added to the LDLIBS variable instead.
所以在这种情况下 -lSDL2_image
应该设置或添加到 LDLIBS,而不是 LDFLAGS。