2016-09-30 3 views
0

Je tente de compiler une application OpenGl qui utilise SDL2 et GLEW de telle sorte qu'elle s'exécute sur n'importe quelle version de Linux qu'elle peut trouver elle-même - pas seulement là où elle a été compilée à l'origine. Pour ce faire, j'ai essayé plusieurs choses qui ne fonctionnent pas.Comment compiler les applications SDL2 et GLEW de manière statique sous Linux?

J'ai essayé de créer un lien direct vers les fichiers .a produits en exécutant make dans le répertoire racine extrait de GLEW et SDL à partir du téléchargement du site Web de chaque bibliothèque. Cela produit les erreurs suivantes:

/usr/bin/ld: /opt/SDL2-2.0.4/build/.libs/libSDL2.a(SDL_syssem.o): undefined reference to symbol '[email protected]@GLIBC_2.2.5' 
//lib/x86_64-linux-gnu/libpthread.so.0: error adding symbols: DSO missing from command line 

J'ai essayé la construction comme je le fais avec les bibliothèques liées dynamiquement, qui fonctionne très bien, sauf pour les capacités multiplateformes, (avec pkg-config --libs sdl2 et pkg-config --libs glew), mais en ajoutant -static, à quel point je obtenir les erreurs suivantes:

/usr/bin/ld: cannot find -lGLEW 
/usr/bin/ld: cannot find -lGL 

Quand je change le scénario précédent pour pointer vers mes bibliothèques Glew compilés statiquement, je reçois des erreurs de référence non définies aux fonctions OpenGl ainsi que des erreurs de référence non définies comme suit à partir de nombreuses fonctions SDL. Ajouter -lGL ne change rien.

/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libSDL2.a(SDL_dynapi.o): In function `SDL_InitDynamicAPI': 
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libSDL2.a(SDL_dynapi.o): In function `SDL_InitDynamicAPI': 
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libSDL2.a(SDL_dynapi.o): In function `SDL_InitDynamicAPI': 
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libSDL2.a(SDL_sysloadso.o): In function `SDL_LoadObject_REAL': 
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libSDL2.a(SDL_sysloadso.o): In function `SDL_LoadObject_REAL': 
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libSDL2.a(SDL_sysloadso.o): In function `SDL_LoadFunction_REAL': 
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libSDL2.a(SDL_sysloadso.o): In function `SDL_LoadFunction_REAL': 
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libSDL2.a(SDL_sysloadso.o): In function `SDL_LoadFunction_REAL': 
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libSDL2.a(SDL_sysloadso.o): In function `SDL_UnloadObject_REAL': 

Quand j'essayer d'utiliser pkg-config --libs --static <library name> pour toutes les bibliothèques, je reçois l'erreur suivante:

/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libSDL2.a(SDL_dynapi.o): In function `SDL_InitDynamicAPI': 
/usr/bin/ld: cannot find -lasound 
/usr/bin/ld: cannot find -lpulse-simple 
/usr/bin/ld: cannot find -lpulse 
/usr/bin/ld: cannot find -lsndio 
/usr/bin/ld: cannot find -lwayland-egl 
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libwayland-cursor.a(libwayland_cursor_la-xcursor.o): In function `XcursorImagesDestroy': 
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libXcursor.a(file.o):(.text+0x7d0): first defined here 
/usr/bin/ld: cannot find -lGLEW 
/usr/bin/ld: cannot find -lGL 
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libX11.a(GetDflt.o): In function `GetHomeDir.part.0': 
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libX11.a(GetDflt.o): In function `GetHomeDir.part.0': 
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libX11.a(xim_trans.o): In function `_XimXTransSocketINETConnect': 
collect2: error: ld returned 1 exit status 

NOTE: Tous la sortie ci-dessus est de la commande g++ -o /path/to/outputExecutable <list of object files>.o <libraries as described above>

NOTE: Je ne suis pas pense que cette question est une copie de toute autre question sur le réseau Stack Exchange parce que j'ai essayé de comprendre cela pendant environ un mois et demi et j'ai vu un très grand nombre de ces questions et j'ai tout essayé en eux, ainsi, même si le s ymptoms sont les mêmes que le problème sous-jacent est différent.

REMARQUE: Il s'agit d'une application à code source fermé, de sorte que la liaison dynamique n'est pas une option car elle nécessite la distribution du code source pour permettre aux utilisateurs de créer les fichiers binaires sur leurs propres systèmes.

NOTE: Je suis actuellement en train d'essayer de compiler avec Linux via g ++, mais j'ai l'intention d'utiliser mingw pour distribuer cette application pour Windows. Tout conseil qui fonctionne là-bas est préférable aux conseils de Linux seulement, mais, je peux poser une autre question si je ne peux pas comprendre cette partie de ce qui se terminera ici.

REMARQUE: j'utilise Ubuntu 16.04 LTS x64 pour compiler.

Nous vous remercions d'avance d'avoir déjà fait un bon bout de chemin dans cette question. Désolé pour le mur de texte, mais, je voulais fournir autant d'informations que possible. J'ai hâte de recevoir des réponses!

+1

"J'utilise Ubuntu 16.04 LTS x64 pour compiler." nah, je dois laisser tomber et tout construire sur Debian oldstable. – genpfault

Répondre

3

Les anciens jeux Loki faisaient une liaison statique complète. Cela ne vaut probablement plus la peine, et beaucoup plus difficile si vous utilisez des bibliothèques externes.

Les bibliothèques ne sont souvent pas autonomes, nécessitant d'autres bibliothèques, .... La bibliothèque dynamique contient des informations de dépendance, mais la bibliothèque statique est juste une archive de .o fichiers - cela peut dépendre de quelque chose mais il n'y a pas de spécial section qui décrit quelles bibliothèques supplémentaires doivent être utilisées. Votre première erreur indique que libSDL2.a utilise le symbole [email protected]@GLIBC_2.2.5 (sem_getvalue fonction, marqué avec la version glibc) qui ne peut pas être résolu - probablement parce que vous n'avez pas ajouté -lpthread à vos indicateurs d'éditeur de liens.(libSDL.so dépend entre autres de certaines versions de pthrtead - c'est pourquoi vous n'avez pas besoin de les lier manuellement si vous ne les utilisez pas directement).

GLEW ne devrait pas avoir de problèmes avec la liaison statique. Vous devez être plus précis sur les erreurs que vous obtenez. Vous avez peut-être mal commandé votre bibliothèque et l'éditeur de liens ne peut pas résoudre les fonctions GL. Besoin de voir la ligne de liaison réelle et certaines erreurs de «référence non définie» pour être plus précis.

pkg-config « s drapeau --static devrait vous donner la liste des dépendances (par exemple -lpthread devrait être dans la sortie de sdl2-config --static-libs parmi beaucoup d'autres), mais il ne produit pas en soi la liaison statique avec une bibliothèque donnée. Pour demander une liaison statique, il existe -static drapeau gcc qui génère un exécutable statique (dur!) Et -Bstaticlinker flag pour utiliser la version statique pour toutes les bibliothèques spécifiées après (de cette façon vous pouvez utiliser des bibliothèques statiques et certaines dynamiques). -Bdynamic est une contrepartie, demandant d'utiliser des bibliothèques dynamiques. Par exemple. pour utiliser SDL statique et GLEW mais ligne de liaison dynamique GL devrait être quelque chose comme (si vous utilisez gcc pour lier, pas ld directement) gcc ${OBJECT_FILES} -Wl,-Bstatic -lSDL2 -lGLEW -Wl,-Bdynamic -lGL -lpthread -ldl -lm <everything else SDL2 requires - query with sdl2-config>.

Vos /usr/bin/ld: cannot find -lasound lignes peuvent avoir deux raisons - la liaison statique ou en relation avec le fait que vous ne disposez pas des bibliothèques de développement installés (par exemple libasound2-dev, libpulse-dev, ... - au moins ils ont appelé que sur debian, il est peu probable ubuntu avoir des noms différents). Les bibliothèques 'utilisateur' contiennent généralement par ex. libasound.so.2 mais l'éditeur de liens ne trouvera pas cette bibliothèque car elle contient une version. Le package de développement contient des en-têtes et un lien symbolique libasound.so -> libasound.so.2 - de cette manière, le lieur sait utiliser quoi que ce soit. Si vous l'utilisez indirectement via SDL2 - vous n'avez pas besoin de cela, SDL2 partagé a déjà un lien vers la bibliothèque versionnée.

Cependant, il peut être inutile de le faire. Vous pouvez distribuer des bibliothèques partagées requred avec votre logiciel et les utiliser soit via rpath ou LD_LIBRARY_PATH variable d'environnement (maya, steam, etc ... - presque tout le monde fait ces derniers jours). De plus, même avec un SDL2 statique, l'utilisateur final peut remplacer le SDL2 par le sien (c'est une fonctionnalité intentionnellement implémentée dans SDL2). S'il y a un bogue (ou un environnement très différent) et que votre logiciel ne reçoit plus de mises à jour, il est possible que ce problème soit résolu en remplaçant simplement les bibliothèques partagées. Souhaitez-vous vraiment les gens qui exécutent votre programme sur wayland ou mir si votre SDL2 d'origine avait seulement le support X11?

in such a way that it will run on any version of Linux it may find itself -- not just where it was originally compiled est beaucoup plus compliqué, et honnêtement presque irréaliste (sauf si vous avez un programme assez petit et n'utilisez qu'un ensemble très limité de bibliothèques avec une bonne compatibilité avant/arrière - mais même alors, il peut être difficile). Un des gros problèmes est la glibc; Habituellement, c'est une bonne idée d'utiliser la version la plus basse possible de la glibc pour compiler votre programme. En résumé, c'est possible, mais ça n'aide pas beaucoup.

+0

Quand vous dites distribuer des fichiers .so avec mon application, ce qui semble être une bonne idée pour les raisons que vous avez mentionnées, comment puis-je savoir quelles bibliothèques j'ai besoin d'inclure et quelles bibliothèques sont sûres d'inclure? Par exemple, dois-je inclure toutes les dépendances de SDL? Si oui, comment puis-je trouver une liste de tous? Aussi, devrais-je lier statiquement libstdC++ en tant que [this] (https://insanecoding.blogspot.com/2012/07/creating-portable-linux-binaries.html) article recommande (car il semble que la simple distribution de mon propre peut ne pas fonctionner car il ne peut pas remplacer la version de l'utilisateur)? – john01dav

+1

Vous pouvez utiliser [ldd] (https://linux.die.net/man/1/ldd) pour obtenir la liste des dépendances (fonctionne pour les bibliothèques exécutables et partagées). Cela fonctionne récursivement donc ce que vous obtenez pour l'exécutable est une liste complète.'libc',' libm', 'libdl' et' libpthread' sont très susceptibles d'être présents, mais il y a des implications avec les versions de glibc (le commentaire de genpfault adresse cela - c'est ce que je voulais dire par "glibc le plus bas possible" plus loin). Ensuite, vous devrez appliquer une pensée critique - par ex. il y a un petit avantage à apporter 'libX11' si votre programme ne fonctionne qu'en mode graphique. – keltar