10
votes

Comment utiliser correctement SDL2 dans mes programmes?

Je souhaite créer un jeu en SDL2, mais je ne parviens pas à compiler et / ou exécuter mon code, aidez-moi!

SDL2 est notoirement difficile à mettre en place, et c'est souvent la première bibliothèque que les développeurs de jeux en herbe essaient d'utiliser.

Cet article est conçu comme un doublon canonique pour les problèmes courants liés à la configuration de SDL2.


4 commentaires

Je suis fatigué de répondre aux mêmes questions SDL chaque semaine, alors j'ai fait ceci. Aide recherchée: ma réponse se concentre sur MinGW, et nous en avons probablement besoin qui se concentre sur Visual Studio.


Génial, utilisera comme cible de dupe pour les problèmes fréquemment signalés à l'avenir. C'est sur ma liste de favoris maintenant ;-)


Le mérite de cette question est impliqué dans une discussion sur la méta .


" SDL2 est notoirement difficile à mettre en place " Convivial [citation nécessaire] :-) S'il y a vraiment autant de questions comme ça, alors je pense que le projet SDL devrait améliorer sa documentation.


3 Réponses :


10
votes

Cette réponse traite de MinGW / GCC et non de Visual Studio.

Cette réponse concerne principalement Windows. Les choses sont plus faciles sur les autres OS, voir le bas de la réponse pour un résumé.

J'ai essayé de garder cette réponse très simple, afin que même un débutant puisse l'utiliser.


Erreurs courantes

Les erreurs courantes que vous pouvez obtenir sont:

  • SDL.h: No such file or directory (lors de la compilation)
  • undefined reference to diverses fonctions (lors de la liaison)
  • Erreurs mystérieuses liées à .dll (lors de l'exécution de votre programme).

Cette liste est triée de mauvais à bon. Si vous changez quelque chose et obtenez une erreur différente, utilisez cette liste pour savoir si vous avez amélioré ou empiré les choses.

Voir la réponse ci-dessous pour savoir comment résoudre tous ces problèmes.


Le préambule

Voici certaines choses que je souhaite vous dire avant de corriger les erreurs.

0. Ne suivez pas les mauvais conseils.

Certaines ressources vous suggéreront de faire #define SDL_MAIN_HANDLED ou #undef main . Ne fais pas ça. Ces solutions diffèrent de la façon dont SDL2 est censé être utilisé, et avec la bonne configuration, elles ne sont JAMAIS nécessaires.

Certains soutiennent que ceux-ci sont meilleurs que la manière prévue, mais je suggère d'abord d'apprendre la manière prévue, puis de savoir quelle est la différence, puis de prendre une décision éclairée.

1. Découvrez comment compiler directement à partir de la console, vous pouvez commencer à utiliser un IDE plus tard. Si vous utilisez un IDE, je suggère de vous assurer d'abord que vous êtes en mesure de compiler votre programme directement à partir de la console, pour exclure tout problème de configuration IDE. Une fois que vous avez compris cela, vous pouvez utiliser les mêmes options de compilateur dans votre IDE.

Je suggère également d'éviter CMake si vous venez de commencer, pour exclure tout problème lié à CMake. Vous pouvez commencer à l'utiliser plus tard.

2. Téléchargez les bons fichiers SDL2 . Assurez-vous d'avoir les bons fichiers. Vous avez besoin de l'archive appelée SDL2-devel-2.0.x-mingw.tar.gz partir d' ici .

Décompressez-le dans n'importe quel répertoire, de préférence quelque part près de votre code source. Déballer directement dans le répertoire du compilateur est souvent considéré comme une mauvaise pratique.

3. Connaissez la différence entre les indicateurs du compilateur et les indicateurs de l'éditeur de liens . Un "drapeau" est une option que vous spécifiez dans la ligne de commande lors de la construction de votre programme. Lorsque vous utilisez une seule commande, comme g++ foo.cpp -o foo.exe , tous vos indicateurs sont ajoutés au même endroit (à cette commande unique).

Mais lorsque vous construisez votre programme en deux étapes, par exemple:

  • g++ foo.cpp -c -o foo.o (compilation)
  • g++ foo.o -o foo.exe (liaison)

vous devez savoir à laquelle des deux commandes ajouter un indicateur. Les indicateurs qui doivent être ajoutés à la première commande sont des «indicateurs de compilateur» et les indicateurs qui doivent être ajoutés à la seconde sont des «indicateurs de l'éditeur de liens». Dans la réponse ci-dessous, lorsque vous vous demandez d'ajouter un indicateur, je spécifierai s'il s'agit d'un indicateur de compilateur ou d'un indicateur d'éditeur de liens.

La plupart des IDE vous demanderont de spécifier les indicateurs du compilateur et de l'éditeur de liens séparément, donc même si vous utilisez une seule commande maintenant , il est bon de savoir quel indicateur va où.

Sauf indication contraire, l'ordre des indicateurs n'a pas d'importance.


SDL.h: No such file or directory

Ou toute erreur similaire liée à l'inclusion de SDL.h ou SDL2/SDL.h

Vous devez indiquer à votre compilateur le répertoire où SDL.h trouve SDL.h Il se trouve dans les fichiers SDL que vous avez téléchargés (voir préambule).

Ajoutez ce qui suit à vos indicateurs de compilateur: -I , suivi d'un répertoire.

Exemple: -IC:/Users/HolyBlackCat/Downloads/SDL2-2.0.12/x86_64-w64-mingw32/include/SDL2 . (Les chemins relatifs fonctionnent également, par exemple -ISDL2-2.0.12/x86_64-w64-mingw32/include/SDL2 .)

Notez que l'indicateur peut être différent selon la façon dont vous écrivez le #include :

  • Si vous faites #include <SDL.h> , le chemin doit se terminer par .../include/SDL2 (comme ci-dessus). C'est la méthode recommandée.
  • Si vous faites #include <SDL2/SDL.h> , le chemin doit se terminer par .../include .

undefined reference to diverses fonctions

Le message d'erreur mentionnera diverses fonctions SDL_... (souvent celles que vous utilisez dans votre programme) et / ou WinMain . S'il mentionne SDL_main , consultez la section " undefined reference to SDL_main uniquement" ci-dessous.

Vous devez ajouter les indicateurs de l'éditeur de liens suivants: -lmingw32 -lSDL2main -lSDL2 . L'ordre compte. Les drapeaux doivent apparaître après toute .c / .cpp / .o fichiers.

L'écriture -lSDL2main -lSDL2 indique à l'éditeur de liens d'utiliser les fichiers appelés libSDL2main.a , libSDL2.a (ou libSDL2.dll.a ) qui sont inclus dans les fichiers SDL que vous avez téléchargés. Vous avez besoin d'un indicateur supplémentaire pour indiquer à l'éditeur de liens où rechercher ces fichiers .a . Ajoutez ce qui suit à vos indicateurs de l'éditeur de liens: -L , suivi du répertoire.

Exemple: -LC:/Users/HolyBlackCat/Desktop/SDL2-2.0.12/x86_64-w64-mingw32/lib . (Les chemins relatifs fonctionnent aussi, par exemple -LSDL2-2.0.12/x86_64-w64-mingw32/lib .)

J'ai ajouté tous ces drapeaux et rien n'a changé:

Si vous avez fait cela et que vous obtenez toujours les mêmes erreurs de undefined reference , vous utilisez probablement les mauvais fichiers SDL .a . L'archive que vous avez téléchargée contient deux ensembles de fichiers: i686-w64-mingw32 (32 bits) et x86_64-w64-mingw32 (64 bits). Vous devez utiliser les fichiers correspondant à votre compilateur, qui peuvent également être 32 bits ou 64 bits. Imprimez (8*sizeof(void*)) pour voir si votre compilateur est 32 bits ou 64 bits. Même si vous pensez utiliser les bons fichiers, essayez les autres pour être sûr.

Quelques - unes des versions MinGW peut être commuté entre 32 bits et les modes 64 bits en utilisant -m32 et -m64 drapeaux (ceux -ci ont sans doute à ajouter aux deux drapeaux du compilateur et l' éditeur de liens). Vous pouvez aussi les essayer.

undefined reference à une fonction spécifique:

undefined reference to WinMain uniquement

Il existe trois possibilités, qui ont toutes été couvertes dans la section précédente:

  • Vous avez oublié l'indicateur -lSDL2main .
  • Le fichier libSDL2main.a que vous utilisez ne correspond pas à votre compilateur (fichier 32 bits avec un compilateur 64 bits, ou vice versa).
  • Vous mettez le -lSDL2main drapeau à gauche de certains .c / .cpp / .o fichiers. Il doit toujours être à droite.

Essayez d'éviter #define SDL_MAIN_HANDLED ou #undef main lors de la résolution de ce problème, voir le préambule pour l'explication.

undefined reference to SDL_main uniquement

Vous devez avoir une fonction main . Votre fonction main doit ressembler à int main(int, char **) . NOT int main() et NOT void main() . C'est l'une des bizarreries SDL2.

L'ajout de tout nom de paramètre est autorisé, par exemple int main(int argc, char **argv) . Le deuxième paramètre peut également être écrit sous la forme char *[] ou avec un nom: char *argv[] . Aucun autre changement n'est autorisé.

Essayez d'éviter #define SDL_MAIN_HANDLED ou #undef main lors de la résolution de ce problème, voir le préambule pour l'explication.


Erreurs liées aux .dll

Vous avez réussi à .exe un .exe , mais vous ne pouvez pas l'exécuter en raison d'erreurs mystérieuses mentionnant des .dll . Tu y es presque!

Le .exe vous avez créé a besoin de quelques .dll pour s'exécuter. S'il ne les trouve pas, il vous le dira et refusera de courir. C'est facile. Il peut également trouver de mauvaises versions laissées par certains autres programmes que vous avez installés, puis vous obtiendrez des erreurs très cryptiques.

Votre programme recherchera les .dll à différents endroits, mais la solution la plus fiable est de les placer dans le même répertoire que le .exe . Ce répertoire est recherché en premier, donc les autres versions de .dll vous pourriez avoir ailleurs n'interféreront pas.

Vous devez déterminer les .dll dont votre programme a besoin et les placer dans le répertoire où se trouve votre .exe (à l'exception des .dll système, que vous n'avez pas besoin de copier).

Vous pouvez obtenir deux types d'erreurs:

  • Une erreur qui vous indique simplement ce qui manque .dll .

    • SDL2.dll est manquant. - C'est dans les fichiers SDL que vous avez téléchargés.

      Sachez que les fichiers contiennent deux SDL2.dll différents: un 32 bits (dans le i686-w64-mingw32 ) et un 64 bits (dans x86_64-w64-mingw32 ). Obtenez le bon, si nécessaire, essayez les deux.

    • Un autre .dll est manquant. - Il est livré avec votre compilateur. Regardez dans le répertoire où se trouve votre gcc.exe .

      Si vous copiez un .dll et qu'il en demande plus, c'est normal, vous devrez peut-être répéter cela ~ 3 fois.

  • Une erreur cryptique liée à .dll . - Votre programme a trouvé une mauvaise version d'un .dll quelque part dans votre système.

    Vous devez copier tous les .dll non-système dont il a besoin dans le répertoire où se trouve votre .exe .

    Copiez d'abord SDL2.dll (voir la section « SDL2.dll est manquant» ci-dessus pour savoir où le trouver).

    Ensuite, copiez les .dll suivants à partir du répertoire de votre compilateur (le répertoire où se trouve gcc.exe ):

    • libgcc_s_seh-1.dll (le nom peut varier en fonction de votre version MinGW, mais commencera toujours par libgcc )
    • libstdc++-6.dll (pour C ++ uniquement, ignorer si vous écrivez en C)
    • libwinpthread-1.dll (le nom peut varier en fonction de votre version MinGW, mais mentionnera toujours thread ; certaines versions ne l'utilisent pas du tout)

Cela devrait corriger toutes vos erreurs. Si vous voulez en savoir plus ou que cela n'a pas aidé:

Plus d'informations sur les .dll

Il est possible de créer un .exe qui ne dépend d'aucun .dll (non-système) en utilisant l' -static éditeur de liens -static , c'est ce qu'on appelle «liaison statique». Cela est rarement fait et vous ne devriez pas avoir besoin de le faire si vous avez correctement suivi les étapes ci-dessus. Cela nécessite des indicateurs de l'éditeur de liens différents que d'habitude (environ 20 d'entre eux), voir le fichier sdl2.pc livré avec SDL pour les indicateurs exacts (ils se trouvent dans la section Libs.private ).

Dans la section précédente, je vous ai dit de quoi dépend votre programme .dll . Comment ai-je su? Il existe plusieurs façons de le découvrir par vous-même:

  • La manière brute:

    Ouvrez la console, cd dans le répertoire où se trouve votre .exe , puis tapez set PATH= (ne vous inquiétez pas, cela ne change pas le paramètre PATH votre système et n'affecte que la session de console en cours).

    Supprimez tous les .dll que vous y avez peut-être déjà copiés.

    Maintenant, si vous exécutez le .exe partir de cette console, il ne pourra trouver que les .dll du système. Il ne recherchera les fichiers non-système que dans le répertoire courant (qui n'en a pas). Vous obtiendrez maintenant des messages d'erreur clairs indiquant les .dll requis, et vous pourrez les copier un par un jusqu'à ce qu'il commence à fonctionner. De cette façon, vous saurez tous les .dll non-système que votre programme utilise.

    Notez que cette méthode n'est pas totalement infaillible. C:\Windows et certains des répertoires imbriqués sont toujours recherchés, même dans ce cas. Normalement, peu importe si les seuls .dll qu'il contient sont ceux du système, mais si un installateur de merde y a copié un .dll personnalisé, cette méthode ne fonctionnera pas correctement.

    C'est une bonne idée de rechercher dans C:\Windows et les répertoires imbriqués les .dll qui ne devraient pas être là, et de les supprimer. Recherchez SDL2.dll et tous les SDL2.dll .dll également fournis avec votre compilateur (dans le répertoire où se trouve votre gcc.exe ).

  • La voie civilisée:

    Utilisez un outil comme Dependency Walker ou ntldd . Vous devrez par leur sortie et déterminer si chaque .dll est un système ou un non-système. Si un .dll est livré avec votre compilateur ou appartient à une bibliothèque que vous utilisez ( SDL2.dll ), il s'agit d'une bibliothèque non système. Tous les .dll restants sont ceux du système, ignorez-les.


D'autres problèmes

  • Q: Mon programme ouvre toujours une fenêtre de console lorsque je l'exécute, en plus de toutes les fenêtres que j'ouvre à l'aide de SDL. Comment m'en débarrasser?

    • R: Ajoutez -mwindows aux -mwindows de l'éditeur de liens.
  • Q: Mon programme a l'icône de fichier par défaut , mais je veux une icône personnalisée.

    • R: Votre icône doit être au format .ico . Créez un fichier avec l'extension .rc (disons icon.rc ), tapez ce qui suit: MAINICON ICON "icon.ico" (la première partie est un nom arbitraire, vous pouvez le changer; la deuxième partie doit toujours être ICON , le la troisième partie est le chemin vers l'icône). Convertissez le fichier en .o utilisant windres -i icon.rc -o icon.o (le programme windres est livré avec votre compilateur). Spécifiez le fichier .o résultant lors de la liaison, par exemple g++ foo.cpp icon.o -o foo.exe .

      Les versions récentes de SDL2 ont une belle propriété d'utiliser la même icône que l'icône de fenêtre, vous n'avez donc pas besoin d'utiliser SDL_SetWindowIcon .

  • Q: 'SDL_VideoMode' wasn't declared in this scope que l' erreur 'SDL_VideoMode' wasn't declared in this scope .

    • R: SDL_VideoMode existait dans SDL1.2, mais ne fait pas partie de SDL2. Votre code a été écrit pour le SDL1.2 obsolète. Trouvez un meilleur didacticiel qui traite du nouveau SDL2.

Je ne suis pas sous Windows, que dois-je faire différemment?

L'ensemble de la réponse ci-dessus est principalement destiné à MinGW et Windows. Si vous n'êtes pas sous Windows, les choses deviennent plus faciles:

  • Aucun problème lié à .dll .

  • Pas besoin de télécharger manuellement SDL2, il devrait être dans votre gestionnaire de paquets.

  • Pas besoin de penser aux indicateurs de compilateur ou d'éditeur de liens à utiliser:

    • pkg-config --cflags sdl2 vous indiquera les drapeaux du compilateur.

    • pkg-config --libs sdl2 vous indiquera les indicateurs de l'éditeur de liens. Ajoutez --static si vous voulez des indicateurs pour la liaison statique.

  • Vous n'avez pas besoin de -lSDL2main , et il n'y a aucun problème lié à SDL_main .

D'autre part:

  • Distribuer vos programmes à d'autres personnes devient plus difficile, vous ne pouvez pas simplement expédier un tas de .dll avec votre programme.

  • Le processus de définition d'une icône personnalisée est différent.


Approche alternative: utilisez un environnement de type Linux sous Windows

La partie de la section précédente sur l'installation des bibliothèques et la détermination des indicateurs de compilateur semble-t-elle automatiquement pratique? Vous pouvez également l'avoir sur Windows.

Téléchargez MSYS2. Vous aurez un gestionnaire de paquets (à partir duquel vous pouvez installer SDL), des compilateurs à jour et un ensemble d'utilitaires courants portés depuis Linux (y compris pkg-config ). Cela résout la plupart des problèmes spécifiques à Windows.


3 commentaires

Eh bien, les temps ont changé. Vous pouvez également utiliser le propre gestionnaire de packages de Microsoft, qui fonctionne également sur Linux et MacO, et compiler SDL (ou presque tous les packages importants). la chose s'appelle vcpkg et est open source. vcpkg


@arfneto Je me demande si cela vaut la peine d'être utilisé avec MinGW. Semble cibler principalement MSVC, et nous avons déjà MSYS2 qui traite spécifiquement de MinGW.


HolyBlackCat vous avez raison. C'est génial sous Visual Studio ou CMake car il télécharge les sources et compile tout sans intervention de l'utilisateur et même définit les inclusions et les liens. Une fois installé, il vous suffit d'inclure les en-têtes sur les nouveaux projets. Cela fonctionne sous Linux ou Mac mais je n'en avais pas encore besoin donc je ne peux pas en dire beaucoup.



1
votes

Sur Mac, voici ce que je suis pour XCode (il faut installer g ++):

liaison sdl:

g++ main.cpp -o main $(sdl2-config --cflags --libs)

Étapes du projet XCODE:

  1. application de terminal ouverte (macOS)

  2. PARAMÈTRES DE CONSTRUCTION (sélectionnez «tous» et la barre de recherche «combinée» entrez: «recherche»)

  3. cliquez sur "chemins de recherche d'en-tête (chemin clic droit)

  4. ajouter: /usr/local/include

  5. PHASES DE CONSTRUCTION -> LIER LES BIBLIOTHÈQUES BINAIRES (cliquez sur plus)

  6. tapez SDL -> cliquez sur "ajouter un autre"

  7. appuyez sur: commande + SHIFT + g (pour faire apparaître la barre de recherche)

  8. tapez: usr/local/Cellar

  9. accédez à: SDL2 -> 2.0.8 -> lib -> libSDL2-2.2.0.dylib (assurez-vous qu'il n'y a pas de raccourci)


0 commentaires

0
votes

Une solution pour Visual Studio:

Pourquoi ne pas utiliser un gestionnaire de packages? J'utilise vcpkg , et cela facilite la consommation de bibliothèques tierces. Récupérez la source de vcpkg et extrayez-la dans un endroit sûr, comme C:/ , puis exécutez son script de bootstrap-vcpkg.bat , cela générera l'exécutable vcpkg . Ensuite, exécutez vcpkg integrate install pour rendre les bibliothèques installées avec vcpkg disponibles dans Visual Studio.

Recherchez la bibliothèque dont vous avez besoin:

vcpkg search sdl

imgui[sdl2-binding]                   Make available SDL2 binding
libwebp[vwebp-sdl]                    Build the vwebp viewer tool.
magnum[sdl2application]               Sdl2Application library
sdl1                 1.2.15#12        Simple DirectMedia Layer is a cross-platform development library designed to p...
sdl1-net             1.2.8-3          Networking library for SDL
sdl2                 2.0.12-1         Simple DirectMedia Layer is a cross-platform 
...

Installez-le avec: vcpkg install sdl2 .

Il ne vous reste plus qu'à inclure les en-têtes SDL2, et tout fonctionnera immédiatement. La bibliothèque sera liée automatiquement.

Vous pouvez en savoir plus sur vcpkg ici .


3 commentaires

Il vous manque une étape: vous devez lier manuellement SDL2main (voir ce fil de discussion ), ou utiliser une solution de contournement pour l'éviter.


@HolyBlackCat Je viens d'essayer et cela me semble plus être un truc SDL. Si vous ajoutez #define SDL_MAIN_HANDLED avant d'inclure les en-têtes SDL, cela fonctionne #define SDL_MAIN_HANDLED et il n'est pas nécessaire de lier manuellement quoi que ce soit.


Voir le préambule, partie 0 de ma longue réponse ci-dessus. La solution recommandée (par les développeurs SDL) est de lier SDL2main . #define SDL_MAIN_HANDLED fonctionne également, mais ce n'est pas recommandé. C'est une question différente de savoir si la méthode recommandée est raisonnable, et certaines personnes pensent que ce n'est pas le cas (cela inclut apparemment les conditionneurs vcpkg).