Estoy buscando hacer un Makefile que pueda compilar un programa C en Unix (Ubuntu). Ese Makefile debe incluir la biblioteca SDL (2.0), así como SDL_image.
Así que aquí está mi Makefile actual:
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)Y aquí está mi código actual (código mínimo solo para probar el 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; }Así que cuando escribo el comando: hacer
Recibo errores en todas las funciones de SDL. Aquí hay un ejemplo: referencia indefinida a `SDL_Init'
He intentado muchas cosas (como diferentes rutas para Incluir y Vincular en el Makefile), pero nada parece funcionar.
Entonces mi pregunta es: ¿Cómo puedo resolver estas referencias indefinidas a funciones SDL2?
Está especificando las banderas del enlazador en el orden incorrecto.
Esto está mal:
LDFLAGS = `sdl2-config --libs` -L/usr/lib -lSDL2_image $(EXEC): $(OBJECTS) $(CC) $(LDFLAGS) $< -o $@Esto es correcto:
LIBS = `sdl2-config --libs` -L/usr/lib -lSDL2_image $(EXEC): $(OBJECTS) $(CC) $(LDFLAGS) $^ $(LIBS) -o $@Con GNU Binutils, el orden de las bibliotecas es importante. Las bibliotecas deben ir después de los objetos que tienen referencias indefinidas a símbolos en esas bibliotecas. Apesta, es estúpido, pero es la forma en que funciona GNU Binutils y estás atascado con eso.
Desea $^ en lugar de $< , porque $< es solo la primera dependencia.
Probablemente sea mejor usar pkg-config que puede encontrar SDL2_image por usted:
LIBS = `pkg-config --libs sdl2 SDL2_image` Probablemente desee := no = cuando invoque programas de shell, esto expandirá la variable una vez, en lugar de cada vez que se use:
LIBS := $(shell pkg-config --libs sdl2 SDL2_image) CFLAGS := $(shell pkg-config --cflags sdl2 SDL2_image)Aquí hay un ejemplo limpio, cerca de cómo lo escribiría:
# 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)Invirtió algunas opciones del compilador/enlazador:
# linker options LDFLAGS = `sdl2-config --libs` -I/usr/include/SDL_image.h # compiler options CCFLAGS = `sdl2-config --cflags` -L/usr/lib -lSDL2_imageDebería ser:
# linker options LDFLAGS = `sdl2-config --libs` -L/usr/lib -lSDL2_image # compiler options CCFLAGS = `sdl2-config --cflags` -I/usr/includeDetalles:
-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 filesComo se puede ver en el Catálogo de Reglas Incorporadas :
Vincular un solo archivo de objeto
nse crea automáticamente desdenoejecutando el enlazador (generalmente llamadold) a través del compilador de C. La receta precisa utilizada es:$(CC) $(LDFLAGS) no $(LOADLIBES) $(LDLIBS)
y variables utilizadas por reglas implícitas :
LDFBANDERAS
Indicadores adicionales para dar a los compiladores cuando se supone que deben invocar el enlazador,
ld, como-L. En su lugar, se deben agregar bibliotecas (-lfoo) a la variable LDLIBS.
Entonces, en este caso, se debe establecer o agregar -lSDL2_image a LDLIBS, no a LDFLAGS.