[Résolu] Embarquer une librairie dynamique externe dans une application ?

mybofymybofy Membre
décembre 2015 modifié dans Xcode et Developer Tools #1

Bonjour


 


Xcode 7


 


Mon application A.app utilise des librairies dynamiques externes. Prenons l'exemple de libpqxx-4.0.dylib, qui est un container  en C++ de la librairie C libpq standard, et qui est installée dans dans /usr/local/lib.


En local, tout marche bien, après avoir paramétré les Build settings (Library path search) et les Build phases (Link binary with libraries + Copy file).


 


Quand je copie A.app avec "Product->Archive->Export as mac application" et que je lance cette copie sur une autre machine avec le même OSX (10.11 en l'occurence) aucune des librairies externes n'est trouvée. 


 


C'est un gros problème s'il faut que j'installe toutes les librairies externes sur chaque machine où mon application doit être utilisée ! Je coyais que le "Copy file" des "Build phases" les incluait dans le A.app.


 


Comment faire pour embarquer mes librairies dynamiques externes dans le A.app ?


 


Merci.


Réponses

  • AliGatorAliGator Membre, Modérateur
    1) Fais une capture de ta configuration en particulier de tes Build Phases pour qu'on voit comment tu as configuré ça
    2) Es-tu sûr que les dylibs n'ont pas été correctement copiées dans le .app ? Je me demande si elles n'ont pas été correctement copiées, mais que le install_name de la dylib n'est pas bon (genre path en dur dans la dylib qui ne colle qu'avec ton Mac au lieu d'avoir un path relatif à  @rpath)... et que c'est pour ça qu'il n'arrive pas à  la loader sur un autre Mac même si elles sont dans le .app...

    Donc en regardant le contenu du bundle .app généré ça pourrait aussi donner des pistes... parce que là  on manque un peu d'infos.
  • Voilà  toujours les Builds phases.


     


    Le 2) me paraà®t vraisemblable, notamment parce que j'ai compilé les librairies à  partir des sources. Je cherche dans ce sens, avant de poser d'autres question... 


     


     


  • mybofymybofy Membre
    février 2016 modifié #4

    AliGator


    Ton diagnostic était bon.


    Grand merci.


     


     


    Voici ce que j'ai fait et qui marche.


     


    Soit la librairie libToto.dylib


     


    1. elle est dans la liste du panneau qui s'affiche quand on clique sur + de Link Binary with Librairies


        on sélectionne et c'est bon


     


    2. sinon


     


    2.0 préparer libToto.dylib :


        cp  path-to/libToto.dylib  path-to/ref.libToto.dylib 


        install_name_tool  -id @rpath/libToto.dylib  path-to/libToto.dylib


        (attention la librairie n'est peut-être pas utilisable pour une autre application, d'où la copie de sauvegarde)


     


    2.1 faire un Copy Files de libToto.dylib


        clic sur +


        rechercher libToto.dylib avec Add Other...


     


    2.2 faire un Link Binary with Librairies


        clic sur +


        clic sur Add Other


        en principe les fichiers copiés, dont libToto.dylib, apparaissent en premier


        sélectionner libToto.dylib


     


    3. en principe c'est bon (sauf oubli d'une étape...)


        en tout cas chez moi


        notamment in n'y a rien à  faire dans Build Setting > Search Paths


     


     


     


    Erreur : cela marche pour une librarie qui ne dépend pas d'autres librairies


  • Après beaucoup de recherches et d'essais, je crois avoir trouvé une (la ?) solution.


    C'est bien plus compliqué que ce que j'avais proposé et mal documenté.


    Le site qui m'a permis d'embarquer une dylib dans mon application Mac OSX : http://lessons.livecode.com/m/4071/l/15029-linking-an-osx-external-bundle-with-a-dylib-library


     


    Soit une application "Wherbarium" qui marche dans XCode. 


     


    1. copier la librairie dynamique "libToto.dylib" à  la racine du répertoire "Wherbarium" au même niveau que Wherbarium.xcodeproj et DerivedData.


     


    2. faire un Add File to "Wherbarium"... de  "libToto.dylib"


     


    3. dans Build Phases faire un Copy Files de  "libToto.dylib"


     


    4. ajouter un RunScript :



    export DYLIB=libToto.dylib

    if [ ! -e $TARGET_BUILD_DIR/$TARGET_NAME.app/Contents/Frameworks ]
    then mkdir $TARGET_BUILD_DIR/$TARGET_NAME.app/Contents/Frameworks
    else continue
    fi

    cp -f "$SRCROOT/$DYLIB" "$TARGET_BUILD_DIR/$TARGET_NAME.app/Contents/Frameworks"

    install_name_tool -id @rpath/$DYLIB $DYLIB

    install_name_tool -change /opt/local/lib/$DYLIB @rpath/$DYLIB "$TARGET_BUILD_DIR/$TARGET_NAME.app/Contents/MacOS/$PRODUCT_NAME"


    C'est ce script qui permet de changer le chemin initial de /opt/local/lib/libToto.dylib en @rpath/libToto.dylib ( -id ).


     


    Et de modifier ce même chemin dans l'exécutable Wherbarium* ( -change ) ...  qu'on trouve dans .../MacOs/


     


    A la réflexion c'est assez logique. Mais que c'est tordu d'avoir dans le dylib le chemin du fichier d'origine, en tout cas je ne comprends pas pourquoi ? XCode offre la possibilité de manipuler tout ça avec les Run Scripts, ce qui est loin d'être facile à  touver : en fait tout doit se passer à  l'intérieur de Xcode...


     


    Voilà  pour le principe.


     


    A CONDITION que libToto.dylib n'appelle pas lui-même d'autres dylib.


     


    Pour moi cela ne marche pas directement avec :



    rn@Lorien : ~/Apps/AppWx/Wherbarium/DerivedData/Wherbarium/Build/Products/Debug/Wherbarium.app/Contents >> otool -L Frameworks/libexiv2.13.0.0.dylib
    Frameworks/libexiv2.13.0.0.dylib:
    @rpath/libexiv2.13.0.0.dylib (compatibility version 13.0.0, current version 13.0.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1226.10.1)
    /opt/local/lib/libexpat.1.dylib (compatibility version 8.0.0, current version 8.0.0)
    /opt/local/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.8)
    /opt/local/lib/libiconv.2.dylib (compatibility version 8.0.0, current version 8.1.0)
    /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 120.1.0)


    Je pense qu'il faut procéder de la même manière  dans le RunScript pour les dylib incluses. Je n'ai pas essayé pour le moment...

  • AliGatorAliGator Membre, Modérateur
    Tu as un Build Setting normalement pour changer le install_name.
    Et de toute façon si tu link avec une dylib qui est bien faite cette dylib se base sur @executable_path ou @rpath donc ne dépend pas du chemin d'origine, seulement du chemin relatif au binaire exécutable. Et du coup tu n'es dans ce cas pas sensé avoir à  manipuler install_name_tool toi-même.
Connectez-vous ou Inscrivez-vous pour répondre.