Mettre mon .dylib là  où je le souhaite

ManawenuzManawenuz Membre
juin 2010 modifié dans Objective-C, Swift, C, C++ #1
Bonjour,

Je débarque sur ce forum avec plein de question :)
Pour aujourd'hui ce sera comment linker un .dylib issu d'un d'une partie de mon projet avec la partie principale de celui-ci?
En clair, j'ai l'application qui charge au démarrage le module graphique, le module son, etc. qui sont sous forme de .dylib Ils sont localisés dans le dossier "Modules", lui-même au même niveau que le .app final.
Comment la compilation du programme principal peut-elle prendre en compte cet emplacement "custom"?
J'ai cherché sur pas mal de site, mais partout ils disent "Modifier telle variable d'environnement..." et sans dire où est-ce qu'on le fait dans XCode...

Merci d'avance!

EDIT : Solution finale (pour ceux qui n'ont pas envie de cherche dans tout le file où est la solution)

La bonne configuration est :
-Dans le .dylib : Dynamic Library Install Name = @loader_path/../Frameworks/myDylib.dylib
Installation Directory est vide
-Dans le programme final : Runpath Search Paths est vide
-Il faut bien créer une Copy Files Build Phase, qui se charge de copier la librairie dans le .app final

And that's all!!!

Réponses

  • CéroceCéroce Membre, Modérateur
    07:04 modifié #2
    - Séléctionne la cible (Target) concernée.
    - Affiche les infos
    - Onglet Build

    ça doit être la rubrique Library Search Path.

    Fais gaffe, il y a un lot de réglage pour la configuration "Debug" et un pour la conf "Release" -> Change le Search path pour Debug et quand ça marche, copie-le dans Release.
  • Philippe49Philippe49 Membre
    07:04 modifié #3
    Bienvenu sur Pomme Dev !

    La solution de Ceroce , ou utiliser le tout fait  :
    CLic Droit sur le groupe Frameworks du projet et choisir Add > Existing Framework
    Dans le panel qui t'est proposé ensuite, tu as les dylibs standards, et tu peux aller en chercher un autre ailleurs avec Add Other
  • CéroceCéroce Membre, Modérateur
    07:04 modifié #4
    C'est vrai que ta solution est un poil plus simple, Philippe 
  • ManawenuzManawenuz Membre
    07:04 modifié #5
    Merci pour vos réponses!!!
    Euh en fait ça marche pas... A l'exécution, il me dit qu'elle ne trouve pas le dylib (il le cherche dans /usr/local/lib ...)
  • tabliertablier Membre
    avril 2010 modifié #6
    "A l'exécution, il me dit qu'elle ne trouve pas le dylib"
    Chez moi ça marche très bien.

    ??? J'ai une question complémentaire:
    Je voudrais, pour des raisons d'usage unique, embarqué une dylib dans mon application et ne pas la mettre dans usr/local/lib
    je pensais la mettre dans le dossier Resources/Framework puis faire un dlopen avec son chemin d'accès. Devrais-je utiliser dlsym et dlclose. Je n'ai jamais fait ça! est-ce que ça marche et, si oui, quelles sont les précautions à  prendre?
  • ManawenuzManawenuz Membre
    07:04 modifié #7
    La question de tablier rejoint la mienne. Mais normalement, si j'ai bien compris, on n'a pas besoin de dlopen et dlsym avec un .dylib
    Mais l'ajout d'un .dylib (ou d'un .framework) marche avec la solution de Phillippe49 mais seulement si la lib est installée dans les dossiers standards pour une lib (resp. /usr/local/lib et ~/Library/Frameworks
  • Philippe49Philippe49 Membre
    avril 2010 modifié #8
    Je
    dans 1272352914:

    Merci pour vos réponses!!!
    Euh en fait ça marche pas... A l'exécution, il me dit qu'elle ne trouve pas le dylib (il le cherche dans /usr/local/lib ...)

    Si XCode a mis un bouton Add Other, c'est qu'il a du prévoir de mémoriser le chemin d'accès adéquat, je crois que Tablier a raison ...
    Sinon, mais cela serait étonnant, il faut rajouter un Search Path pour les librairies comme l'a indiqué Ceroce.
  • Philippe49Philippe49 Membre
    avril 2010 modifié #9
    Un essai qui me semble concluant :
    - J'ai transporté libedit.dylib sur le bureau, et changé son nom en libtruc.dylib
    - fait Add > ... sur cette dylib
    - rajouté un fichier "el.h" qui est une partie de un des headers , un peu massacrée en ne gardant que le nécessaire à  l'expérience.
    - fait #include "el.h", et fait un appel à  une des fonctions de cette librairie el_editmode( )

    Cela marche avec l'inclusion de libtruc.dylib, cela ne marche pas sans cette référence.

    [EDIT] Cela marche en mode release. Si on déplace l'exécutable, et si on détruit la dylib, cela continue de fonctionner, ce qui semble indiquer que la librairie perd son aspect dynamique dans l'histoire.
    Pour donner à  un exécutable la possibilité de rechercher dynamiquement  une librairie, c'est autre chose.
  • ManawenuzManawenuz Membre
    07:04 modifié #10
    Merci Philippe pour avoir pris le temps pour faire l'expérience
    Tu as le même problème que moi. C'est vrai que donner à  un exécutable la possibilité de rechercher dynamiquement une librairie, ça doit pas être de la tarte. Mais je n'ai pas besoin d'autant : il faudrait que l'exécutable recherche dans un dossier dont le chemin d'accès est donné relativement à  lui-même ... Du genre @executable_path/../../Frameworks (cette ligne est tirée de mes lectures sur différents forum, mais comme indiqué plus haut, il n'est jamais expliqué où écrire ça :( )
  • AliGatorAliGator Membre, Modérateur
    avril 2010 modifié #11
    Peut-être auras-tu ta réponse dans ce post du forum ?
    Sinon, cherche "executable_path" dans tout le forum PommeDev, y'a pas mal de sujets qui en causent. Beaucoup sont liés à  la création d'un framework (et l'embarcation d'un .dylib dans un framework, etc) mais au final ça cause du même souci.

    Entre autres ce passage dans le post de Chacha me semble très intéressant :
    dans 1223106354:
    Il y a un modèle de projet "dynamic library". Quasiment tous les paramètres sont réglés. Il faut cependant envisager de changer l'option "Dynamic Library Install name", qui est par défaut un chemin absolu vers /usr/local.

    Pour plus de renseignements vers les install_name relatifs (utilisant @executable_path, @loader_path ou @rpath), je te redirige vers un autre post : http://forum.pommedev.com/index.php?topic=2728.0
  • ManawenuzManawenuz Membre
    07:04 modifié #12
    Génial! Merci AliGator! J'essaie ça ce soir, et je vous tiens au courant
  • ManawenuzManawenuz Membre
    07:04 modifié #13
    Bon Après tant d'espoir, tant d'essais et tant de temps perdu :( je ne trouve pas.
    J'aimerais avoir "Essai Utilisation dylib.app/Contents/Frameworks/MonFrameworkPerso.framework", et qu'il soit linké correctement à  l'exécution, et rien à  faire
    J'ai créé une "New Copy Files Build Phase" qui copie effectivement bien mon .dylib là  où il faut.
    J'ai essayé toutes les versions de Installation Directory, Dynamic Library Install Name, et Runpath Search Paths possibles, rien ne marche A chaque fois, j'ai ça (cas où Installation Directory = Dynamic Library Install Name = @rpath):

    dyld: Library not loaded: @rpath<br />&nbsp; Referenced from: /Users/Manawenuz/Documents/XCode-Projects/Essai Utilisation dylib/build/Release/Essai Utilisation dylib.app/Contents/MacOS/Essai Utilisation dylib<br />&nbsp; Reason: image not found
    


    Je ne comprends rien.

    Merci d'avance pour toute idée!!!
  • zoczoc Membre
    avril 2010 modifié #14
    dylib ou Framework, même combat: Lors de la compilation/l'édition de lien, il faut indiquer au linker où va se trouver la librairie (paramètre "Installation Directory" dans la configuration de la librairie sous XCode) afin que le système sache où aller la chercher lors de du linkage dynamique à  l'exécution du programme.


    Il est possible de changer ce chemin après coup en utilisant la commande "install_name_tool", comme expliqué notamment ici, section "Shared Libraries"...

    Mais encore une fois, le plus simple c'est de mettre "@loader_path/../Frameworks" dans les paramètres de configuration du dylib, la seconde solution étant à  réserver aux cas où on utilise une dylib tierce pour laquelle on ne dispose pas du code source.



    Edit: Accessoirement j'ai trouvé un plugin Quicklook bien pratique (http://macdylibbundler.sourceforge.net/) pour récupérer rapidement un tas d'infos intéressantes sur entre autre les chemins de recherche des librairies dynamiques utilisées par un exécutable (attention, ne fonctionne pas sur un Bundle, uniquement sur des dylib et binaires contenus dans un Bundle).
  • ManawenuzManawenuz Membre
    07:04 modifié #15
    @zoc : merci pour la réponse!
    Peux-tu détailler? Pk tu dis de mettre  "@loader_path/../Frameworks" dans les paramètres de config du dylib. ça je vois a quoi ça correspond. Mais ensuite? Que faut-il indiquer au programme final qui utilise ce dylib?
    Perso, je remettais "@loader_path/../Frameworks", mais ça ne marchait pas (alors que le dylib est bien copié à  l'emplacement indiqué... 
  • tabliertablier Membre
    07:04 modifié #16
    question annexe:
    J'utilise la "libusb" qui marche bien. La raison en est que l'informaticien qui fait le programme d'origine l'utilise sous linux, et je ne veux pas tout refaire!!
    Dans l'installation de la libusb je trouve des .dylib, des .a, et des .la. Les dylib sont les bibliothèques dynamiques, les .a sont les résultats des compilations non "linké", mais les .la, qu'est-ce que c'est?
  • zoczoc Membre
    07:04 modifié #17
    dans 1272435308:

    Mais ensuite? Que faut-il indiquer au programme final qui utilise ce dylib?

    Rien à  part linker avec le dylib. Lors de l'édition de lien, le linker va chercher dans le dylib le chemin où ce dylib se trouve(ra) et copie ce chemin dans l'exécutable final afin qu'au lancement le linker dynamique sache où chercher.

    Donc à  partir du moment où le dylib a été compilé correctement (ou modifié après coup avec la commande install_name_tool), il suffit qu'il apparaisse dans la phase de link du projet XCode (et évidemment, qu'il se trouve au final à  l'endroit pointé par ce fameux chemin...).
  • zoczoc Membre
    avril 2010 modifié #18
    dans 1272438921:

    question annexe:
    J'utilise la "libusb" qui marche bien. La raison en est que l'informaticien qui fait le programme d'origine l'utilise sous linux, et je ne veux pas tout refaire!!
    Dans l'installation de la libusb je trouve des .dylib, des .a, et des .la. Les dylib sont les bibliothèques dynamiques, les .a sont les résultats des compilations non "linké", mais les .la, qu'est-ce que c'est?

    • "dylib" = version dynamique "MacOS X" de la librairie. la résolution réelle des liens s'effectue au lancement de l'application.
    • "a" = version statique de la librairie (la résolution des liens s'effectue statiquement lors de la production de l'exécutable, et le code contenu dans le .a est au final copié dans l'exécutable).
    • "la" = "machin" généré par "libtool", un outil permettant de simplifier la génération de librairies dynamiques sur plein de systèmes (car contrairement aux librairies statiques plutôt standardisées, chaque plateforme a sa propre manière de gérer les librairies dynamiques: "dylib" sous MacOS X, "so" sous Linux, "dll" sous Windows. Il existe même des systèmes qui ne supportent pas les librairies dynamiques). Le fichier "la" est le moyen d'abstraire tout ce bordel, et donc en théorie il faut linker avec le fichier "la" quand on veut avoir un process de génération d'exécutable portable. Sous MacOS X, linker avec le "la" revient à  linker avec le "dylib". Avec d'autres systèmes ça peut être différent (Sur les systèmes ne supportant pas les librairies dynamiques, linker avec le "la" revient à  linker avec le "a" par exemple). L'unique but est de pouvoir écrire des Makefiles n'ayant pas besoin de se poser la question de comment linker en fonction de la plateforme.
    Personnellement, quand j'utilise du code portable, je choisis systématiquement de linker avec la version statique des librairies (sauf lorsque je développe des applications complexes composées de plusieurs exécutables/frameworks/plugins utilisant la même librairie): Ca simplifie franchement les choses. Pas de prise de tête avec ces problèmes de chemin de recherche, pas de fichier supplémentaire à  distribuer (bien qu'avec les Bundles ce soit facile, mais les bundles n'existent pas sur toutes les plateformes).
  • ManawenuzManawenuz Membre
    07:04 modifié #19
    Je me permet de recentrer la discussion :
    dans 1272440985:

    Rien à  part linker avec le dylib. Lors de l'édition de lien, le linker va chercher dans le dylib le chemin où ce dylib se trouve(ra) et copie ce chemin dans l'exécutable final afin qu'au lancement le linker dynamique sache où chercher.

    Donc à  partir du moment où le dylib a été compilé correctement (ou modifié après coup avec la commande install_name_tool), il suffit qu'il apparaisse dans la phase de link du projet XCode (et évidemment, qu'il se trouve au final à  l'endroit pointé par ce fameux chemin...).



    Mon projet est configuré de cette manière :
    Le dylib (c'est moi qui le génère) a pour Installation Directory '@executable_path/../Frameworks'
    Le programme principal qui utilise ce dylib a pour Runpath Search Paths '@executable_path/../Frameworks'
    Une 'New Copy Files Build Phase' se charge de copier le dylib dans le .app final (vérifié)

    Donc... Désespoir Moi qui vantais XCode (et Mac OS X en général) pour sa simplicité incomparable par rapport à  d'autres solutions, je dois avouer que je suis déçu :)
    Plus sérieusement, je ne vois pas ce qui m'échappe. Je pourrai envoyer (pas avant ce soir) mon projet d'essai pour que ceux qui veulent puissent donner leur avis, mais là  je ne vois pas quoi faire à  part trouver un expert qui puisse m'aider!
  • tabliertablier Membre
    07:04 modifié #20
      Merci de l'explication. Au moins c'est clair!
    Je crois que je vais essayer de faire comme tu le fais, je vais embarquer la librairie libusb.a et la placer dans un dossier Frameworks de l'exécutable. Pour l'instant la dylib est en usr/local/lib et ça marche. Mais demander à  un utilisateur d'installer une librairie, ça ne me paraà®t pas très Mac-simple-pour-l'utilisateur.
  • ManawenuzManawenuz Membre
    07:04 modifié #21
    Bonne nouvelle!!! Je viens de trouver.

    La bonne configuration est :
    -Dans le .dylib : Dynamic Library Install Name = @loader_path/../Frameworks/myDylib.dylib
    Installation Directory est vide
    -Dans le programme final : Runpath Search Paths est vide
    -Il faut bien créer une Copy Files Build Phase, qui se charge de copier la librairie dans le .app final

    And that's all!!!
  • zoczoc Membre
    07:04 modifié #22
    dans 1272451507:

      Merci de l'explication. Au moins c'est clair!
    Je crois que je vais essayer de faire comme tu le fais, je vais embarquer la librairie libusb.a et la placer dans un dossier Frameworks de l'exécutable. Pour l'instant la dylib est en usr/local/lib et ça marche. Mais demander à  un utilisateur d'installer une librairie, ça ne me paraà®t pas très Mac-simple-pour-l'utilisateur.

    J'ai pas du être assez clair apparemment  ;)


    Quand tu linkes avec un .a, ce n'est pas la peine de le distribuer avec l'application !! Le code binaire contenu dans le .a est "copié" automatiquement dans le binaire de l'exécutable...

  • tabliertablier Membre
    07:04 modifié #23
    Mais je suis bien obligé de donner son chemin pour que le linker s'y retrouve et que le code soit copié ?
  • zoczoc Membre
    07:04 modifié #24
    Oui, une référence vers le .a doit se trouver dans la phase de "Link" de l'application sous XCode, mais pas besoin de le copier ensuite dans le Bundle comme on le ferait avec les frameworks.

Connectez-vous ou Inscrivez-vous pour répondre.