2017-09-19 11 views
2

Je compile un programme simple qui utilise la bibliothèque SDL2.
MWE (une version simplifiée de Lazy Foo's tutorial):Adaptation d'un Makefile pour inclure SDL2

// 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; 
} 

Je voudrais adapter le Makefile de this tutorial à manipuler.
C'est ce que j'ai essayé:

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 

Cependant, je reçois plusieurs erreurs de l'éditeur de liens:

$ 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 

Je compris de this answer que l'ordre des arguments qui compte maintenant. Appel

$ g++ -I/usr/include/SDL2 -c -o main.o main.cpp 
$ g++ main.o -lSDL2 -o main 

directement à partir de la ligne de commande fonctionne.

Donc finalement ma question: quelle est la bonne façon d'adapter le Makefile? (Par "correct" je veux dire évitant le type de pièges que le tutoriel Makefile mentionne ci-dessus.)

Répondre

0

Il y a une erreur dans le fichier makefile que vous avez trouvé. Pour fixer le makefile, remplacez la ligne:

LDFLAGS += $(foreach library,$(program_LIBRARIES),-l$(library)) 

avec:

LDLIBS += $(foreach library,$(program_LIBRARIES),-l$(library)) 

et remplacez la ligne:

$(LINK.cc) $(program_OBJS) -o $(program_NAME) 

avec:

$(LINK.cc) $(program_OBJS) -o $(program_NAME) $(LDLIBS) 

ou plus normal style:

$(LINK.cc) $^ -o [email protected] $(LDLIBS) 

(Voir 10.5.3 Automatic Variables en the manual)

L'erreur dans le makefile tutoriel est c'est qu'il ne fonctionne pas correctement emploi (ou expliquer) les maquillages variables canoniques LDFLAGS et LDLIBS. Il regroupe toutes les options de bibliothèque de l'éditeur de liens (-l<name>) dans la valeur LDFLAGS. Ils ne sont pas censés y aller. Ils devraient aller dans la valeur de LDLIBS.

La variable marque prédéfinie LINK.cc étend à:

LINK.cc = $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH) 

qui ne pas comprennent $(LDLIBS), précisément parce que l'éditeur de liens GNU, comme utilisé dans la plupart des distributions du CCG (y compris le vôtre), nécessite des fichiers d'objets à apparaître plus tôt dans la séquence de liaison que les bibliothèques dont ils dépendent, et ignore une bibliothèque à un emplacement dans la séquence où il ne résout aucun symbole références que le lieur doit déjà résoudre.

Si LDLIBS est employé correctement pour les -l options et correctement utilisés dans une recette de liaison - comme dans la recette de liaison corrigée ci-dessus - alors toutes les bibliothèques apparaîtront en toute sécurité après tous les fichiers objets. En regroupant les options -l en $(LDFLAGS), le tutoriel obtient toutes les bibliothèques avant tous les fichiers objet; Par conséquent, dans votre liaison, -lSDL2 est ignoré et votre lien échoue tel qu'observé.

Voici un lit d'enfant à la GNU canonique make-variables qui sont généralement fonctionnant en C ou C++ compilation et liens:

CC commande qui appelle votre compilateur C (par défaut cc)

CXX de commande qui C++ invoque compilateur (par défaut g++)

CPPFLAGS vos options pour le C/C++ préprocesseur

CFLAGS Vos options pour le compilateur C

CXXFLAGS Vos options pour le compilateur C de

LDFLAGS Vos options de Liaison, à l'exclusion des bibliothèques et (- l) Options

LDLIBS vos bibliothèques de liaison ou bibliothèque (-l) options

La valeur par défaut est vide sauf indication contraire.

Voir 10.2 Catalogue of Built-In Rules pour savoir comment ces variables fonctionnent dans les règles intégrées de make. Ou enregistrez la sortie de make --print-data-base dans un fichier et étudiez-la.