IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Visual C++ Discussion :

Autres répertoires Include sur librairies statiques


Sujet :

Visual C++

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Février 2007
    Messages
    73
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 73
    Points : 69
    Points
    69
    Par défaut Autres répertoires Include sur librairies statiques
    Bonjour à tous,

    Alors voila ce que je souhaite faire:
    un projet qui est utilise une librairie statique qui elle même pointe sur une autre librairie statique.
    On obtient donc le projet MonProjet qui possède une dépendance sur le projet MaLib1 qui possède une dépendance sur MaLib2
    Ce qui donne l'ordre de compilation suivant (vu que les dépendances sont correctes):
    MaLib2
    MaLib1
    MonProjet

    Le problème, c'est que la propriété "Autres Répertoires Include" qui se trouve dans la feuille de propriété de mon projet MaLib1 (Propriété de Configuration > C/C++) ne semble fonctionner correctement. Toute tentave d'include d'un fichier de MaLib2 foire (alors que la même technique entre MonProjet et MaLib1 fonctionne).
    Par exemple j'ai un fichier dans MaLib2 qui se nomme foo.cpp. He bien #include "foo.cpp" ne fonctionne pas dans MaLib1.

    Alors pour bien vérifier que ce n'est pas un mauvais chemin d'accès qui a été donné, j'ai fais les tests suivants: regarder la ligne de commande (pour générer MaLib1) qui produit bien le résultat escompté a coté de /I (copier-coller le chemin dans l'explorateur me donne bien le dossier MaLib2 avec foo.cpp dedans).
    J'ai aussi refais 2 fois la solution complète avec a chaque fois des noms différents et impossible de le rendre fonctionnel, elles bloquent de la même façon.

    Seul #include "c:\\<mon chemin absolu>\\foo.cpp" fonctionne... mais bravo pour la portabilité (c'est vachement utile après de s'emmerder à synchro une équipe sur SVN comme c'est le cas escompté pour ce projet).

    Voici un zip de la solution afin que vous puissiez en attester par vous même (et comprendre pourquoi ca ne fonctionne pas): http://dl.free.fr/teHZpimAN (mirroir: http://lucyberad.googlepages.com/MaSolution.zip).

    Merci d'avance pour toute l'aide que vous pourriez apporter (et/ou le temps dépensé à comprendre).
    Lucyberad.

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 175
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 175
    Points : 12 302
    Points
    12 302
    Par défaut
    Faire un include de .cpp, c'est pas vraiment propre tout ça.

    Pour compiler le projet de l'exe, il suffit de mettre le chemin vers les includes de Matlib2 en plus de ceux de Matlib1 dans les setting du projet de l'EXE.
    Le préprocesseur suit les liens includes lors de la compilation de l'exe.

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Février 2007
    Messages
    73
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 73
    Points : 69
    Points
    69
    Par défaut
    Citation Envoyé par bacelar
    Faire un include de .cpp, c'est pas vraiment propre tout ça.
    C'est sale en effet, mais c'est juste pour des test... je l'ai nommé CPP au lieu de H sinon visual ne repère aucun fichier CPP et ne le gère pas comme un projet C/C++ (dans les propriétés, le noeud C/C++ disparait). Au final on aura des beaux objets avec un Header en bon et dûe forme.
    Ajouter un fichier .cpp vide pour dire que c'est un projet C++ et changer le fichier actuel en .H ne change pas le fait que l'include du .H ne fonctionne pas...

    Citation Envoyé par bacelar
    Pour compiler le projet de l'exe, il suffit de mettre le chemin vers les includes de Matlib2 en plus de ceux de Matlib1 dans les setting du projet de l'EXE.
    Le préprocesseur suit les liens includes lors de la compilation de l'exe.
    Sinon pourquoi l'exe (MonProjet) devrait s'occuper de l'include de MaLib2 alors qu'il n'y fais pas référence? Mais dans le doute j'ai quand même fait le test d'inclure MaLib2 dans "Autres Repertoires Include" de mon projet (ce qui fait: "$(SolutionDir)\MaLib1";"$(SolutionDir)\MaLib2"). Sans résultats positif...

  4. #4
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 50
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par Lucyberad Voir le message
    Sinon pourquoi l'exe (MonProjet) devrait s'occuper de l'include de MaLib2 alors qu'il n'y fais pas référence? Mais dans le doute j'ai quand même fait le test d'inclure MaLib2 dans "Autres Repertoires Include" de mon projet (ce qui fait: "$(SolutionDir)\MaLib1";"$(SolutionDir)\MaLib2"). Sans résultats positif...
    Parce que tu as des dépendances de librairies STATIQUES, et que c'est donc totalement inévitable (et que tu as des inclusions publiques de "MaLib2" dans les entêtes de "MaLib1" bien sûr).

    Si tu veux résoudre le problème :
    • Pré-requis : supprimer toute dépendance PUBLIQUE de MaLib2 dans les entêtes de MaLib1.
    • Option DLL :
      • Compiler MaLib1 en DLL.
      • L'édition de liens sera complète au niveau DLL, donc ton exécutable ne demandera plus la librairie MaLib2.
    • Option statique :
      • Inclure dans les entêtes PUBLICS de MaLib1 un "#pragma comment(lib,"MaLib2")" afin d'automatiser le link de MaLib2 quand on linke MaLib1.
      • Toujours faire attention à mettre "MaLib2.lib" dans le même répertoire que le projet MaLib1, afin que Visual puisse le trouver correctement.

    La clé du problème reste quand même de rendre l'utilisation de MaLib2 au sein de MaLib1 totalement privée, sans AUCUNE référence publique. Encapsulation totale, donc.

  5. #5
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 175
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 175
    Points : 12 302
    Points
    12 302
    Par défaut
    Votre manipulation ne marche pas car c'est :
    "$(SolutionDir)MaLib1";"$(SolutionDir)MaLib2"

    pas de "\"

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Février 2007
    Messages
    73
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 73
    Points : 69
    Points
    69
    Par défaut
    Citation Envoyé par Mac LAK
    Parce que tu as des dépendances de librairies STATIQUES, et que c'est donc totalement inévitable (et que tu as des inclusions publiques de "MaLib2" dans les entêtes de "MaLib1" bien sûr).
    Donc si je comprend bien: comme on inclue dans MaLib1 le contenu de MaLib2, sa présence est "obligatoire" dans MonProjet et donc la dépendance doit être faite (vu que implicitement le compilateur en a besoin).

    Citation Envoyé par Mac LAK
    La clé du problème reste quand même de rendre l'utilisation de MaLib2 au sein de MaLib1 totalement privée, sans AUCUNE référence publique. Encapsulation totale, donc.
    Il n'y a pas de solution pour effectuer une encapsulation privée?

    Citation Envoyé par Mac LAK
    Inclure dans les entêtes PUBLICS de MaLib1 un "#pragma comment(lib,"MaLib2")" afin d'automatiser le link de MaLib2 quand on linke MaLib1.
    En gros on ne fait pas un include des fichiers de la librairie mais la librairie elle même est incluse... ce n'est pas portable j'imagine (GCC/XCode) car pragma est réservé à Visual si je me souvient bien.
    Donc au lieu de faire #include "malib2.h" j'utilise à la place #pragma comment(lib,"MaLib2").
    Et ce système n'est-il pas qu'un substitut au niveau du code link spécifié dans les options du projet.

    Citation Envoyé par Mac LAK
    Compiler MaLib1 en DLL.
    Donc le lien entre MonProjet et MaLib1 serait dynamique et la DLL elle même serait MaLib1 qui serait compilé avec MaLib2 en statique?
    J'aurais voulu faire tout en statique mais si je n'ai le choix...

    Citation Envoyé par bacelor
    Votre manipulation ne marche pas car c'est :
    "$(SolutionDir)MaLib1";"$(SolutionDir)MaLib2"

    pas de "\"
    J'ai aussi supsconné ce problème et j'ai testé avec et sans. Aucun changement puisque visual arrive à supprimer les \ en doublon. Du moins ca s'est vérifié avec un test sur une autre solution. C'est pas très propre mais personnellement je préfère le mettre afin de bien distinguer que c'est un dossier (et qui sait, la macro SolutionDir peux ne pas avoir le \ terminal même si ce serait étonnant).

  7. #7
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 175
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 175
    Points : 12 302
    Points
    12 302
    Par défaut
    Chez moi, en renommant les 2 cpp en .h et en modifiant l'include directory du projet de l'EXE selon "mes" préconisation, tout compile et l’exe est généré.

    Je parle du projet posté dans l'article.

  8. #8
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 50
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par Lucyberad Voir le message
    Donc si je comprend bien: comme on inclue dans MaLib1 le contenu de MaLib2, sa présence est "obligatoire" dans MonProjet et donc la dépendance doit être faite (vu que implicitement le compilateur en a besoin).
    Yep, c'est bien ça.

    Citation Envoyé par Lucyberad Voir le message
    Il n'y a pas de solution pour effectuer une encapsulation privée?
    Si, une DLL. Une librairie statique n'a pas, par nature, de notion d'édition de liens.

    Citation Envoyé par Lucyberad Voir le message
    En gros on ne fait pas un include des fichiers de la librairie mais la librairie elle même est incluse... ce n'est pas portable j'imagine (GCC/XCode) car pragma est réservé à Visual si je me souvient bien.
    Oui, c'est pour VS uniquement, mais vu que l'on est dans le forum VC++...

    Citation Envoyé par Lucyberad Voir le message
    Donc au lieu de faire #include "malib2.h" j'utilise à la place #pragma comment(lib,"MaLib2").
    Le "#include" en partie privée (dans un CPP uniquement, donc), le "#pragma" dans l'entête principal de MaLib1 (celui qu'il est impossible de ne pas inclure).

    Citation Envoyé par Lucyberad Voir le message
    Et ce système n'est-il pas qu'un substitut au niveau du code link spécifié dans les options du projet.
    Complètement. L'avantage (voire le seul...), c'est qu'il est alors impossible d'oublier, et qu'au lieu d'avoir des "undefined references" (parfois difficile de trouver à quelle librairie ils appartiennent), tu as une erreur explicite disant que la librairie MaLib2 est introuvable.

    Citation Envoyé par Lucyberad Voir le message
    Donc le lien entre MonProjet et MaLib1 serait dynamique et la DLL elle même serait MaLib1 qui serait compilé avec MaLib2 en statique?
    J'aurais voulu faire tout en statique mais si je n'ai le choix...
    Si tu veux planquer totalement MaLib2, pas le choix. Ceci étant dit, il faut d'abord commencer par supprimer les dépendances publiques à MaLib2 !!
    Ensuite, tu peux éventuellement voir dans la rubrique des évènements post-compilation, afin de forcer l'inclusion de MaLib2 au sein du fichier "MaLib1.lib", via l'appel en ligne de commande de "lib.exe" (ar sous Linux, de mémoire).

    Citation Envoyé par Lucyberad Voir le message
    (et qui sait, la macro SolutionDir peux ne pas avoir le \ terminal même si ce serait étonnant).
    VS supprime les doubles "\" inutiles, et $(SolutionDir) est garanti avoir son anti-slash terminal.

  9. #9
    Membre du Club
    Profil pro
    Inscrit en
    Février 2007
    Messages
    73
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 73
    Points : 69
    Points
    69
    Par défaut
    Citation Envoyé par bacelar
    Chez moi, en renommant les 2 cpp en .h et en modifiant l'include directory du projet de l'EXE selon "mes" préconisation, tout compile et l’exe est généré.
    J'avais fait l'un et l'autre mais pas les deux ! Donc effectivement ca fonctionne.
    Et avec les conseils de Mac LAK, ceci explique pourquoi je peux faire: appellib2() dans le main de MonProjet\Program.cpp.

    Citation Envoyé par Mac LAK
    Si, une DLL. Une librairie statique n'a pas, par nature, de notion d'édition de liens.
    encapsulation privée en static ^^. Donc non .

    Citation Envoyé par Mac LAK
    Oui, c'est pour VS uniquement, mais vu que l'on est dans le forum VC++...
    Pas faux, mais un bon dev se doit de toujours lorgner du coin de l'oeil chez les voisins technologiques ^^.

    Citation Envoyé par Mac LAK
    Le "#include" en partie privée (dans un CPP uniquement, donc)
    D'enseignement scolaire, j'ai toujours mis les includes dans le header (partie publique). Je m'y était fixé mais c'est plus pratique dans le CPP. Au moins tu comfirme le fait que je peux le faire !

    Citation Envoyé par Mac LAK
    Complètement. L'avantage (voire le seul...), c'est qu'il est alors impossible d'oublier, et qu'au lieu d'avoir des "undefined references" (parfois difficile de trouver à quelle librairie ils appartiennent), tu as une erreur explicite disant que la librairie MaLib2 est introuvable.
    Comme je compte faire du multiplateforme, je vais faire des macro préprocesseur en fonction du compilateur. Donc au pire: ca me dérange pas, je mettrait le pragma dans la macro qu'active Visual.

    Citation Envoyé par Mac LAK
    Si tu veux planquer totalement MaLib2, pas le choix. Ceci étant dit, il faut d'abord commencer par supprimer les dépendances publiques à MaLib2 !!
    Ensuite, tu peux éventuellement voir dans la rubrique des évènements post-compilation, afin de forcer l'inclusion de MaLib2 au sein du fichier "MaLib1.lib", via l'appel en ligne de commande de "lib.exe" (ar sous Linux, de mémoire).
    C'est une solution en effet. S'y j'y suis amené pourquoi pas mais vu que l'intégration de MaLib2 dans MonProject ne me dérange pas plus que ca, je vais continuer a faire en sorte que ce soit public à MonProjet.

    Citation Envoyé par Mac LAK
    VS supprime les doubles "\" inutiles, et $(SolutionDir) est garanti avoir son anti-slash terminal.
    plus précisément c'est DOS qui les supprimes (car Visual appelle bel et bien ce qu'il inscrit dans les options au noeud "ligne de commande").
    Pour la garantie je me doute bien.


    En tout cas, merci pour votre aide précieuse, ca me permet d'avancer et de copier tout ce que j'ai déjà fait dans mon projet actuel (où il y a le problème) de MaLib1 à MaLib2 (c'était la solution temporaire que j'avais trouvée).
    Merci,
    Lucyberad.



    [EDIT1]

    N'ayant pas eu de réponse depuis pas mal de temps avec ce post sur ce site, j'ai aussi fait une copie sur StackOverflow.com (http://stackoverflow.com/questions/1...de-another-one) et quelqu'un m'y a fournit une réponse avec un projet fonctionnel dont l'encapsulation de MaLib2 est privée à MaLib1 et fonctionnelle.
    Je test son projet modifié qui est fonctionnel et regarde ce qui change...

    [EDIT2]

    Alors en fait, le fait d'ajouter une dépendance permet d'avoir le code de la librairie dépendante ajouté au projet.
    C'est à dire que définir une dépendance (avec un bouton droit sur la solution et "dépendance du projet") permet d'avoir les signature recopiée. Il suffit pour cela de les redéclarer et c'est bon.

    Par exemple, je ne fais plus #include "foo.cpp"
    mais directement la signature de la fonction qu'il contient:
    void foo();

    Dès lors c'est utilisable en mode encapsulation privée.

    Finalement, votre solution et la sienne se valent, il suffit d'adapter au besoin.

  10. #10
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 50
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Content que ça fonctionne, alors.

    Pour les dépendances VS, ça permet effectivement d'automatiser les inclusions de librairies statiques (y compris celles d'importation de DLL), mais ce n'est effectivement pas une solution portable (pas plus que le #pragma).
    Pour GCC, sous Windows ou Linux, c'est le makefile qui devra résoudre ce point. Attention, dans ce cas, à bien linker MaLib1 AVANT MaLib2, sinon tu auras des dépendances non résolues.

    Pour info, la stratégie d'édition de liens fonctionne ainsi :
    • Visual C++ :
      • Le compilateur donne la liste de toutes les fonctions absentes.
      • Pour chaque fonction absente, on cherche dans TOUTES les librairies si une signature correspond.
      • L'inconvénient est qu'en cas de multiples réponses, un warning est généré.
      • Une même librairie peut être parcourue plusieurs fois lors de l'édition de liens.
      • L'avantage est que l'ordre d'inclusion des librairies n'a pas d'importance.
    • GCC :
      • Pour chaque librairie fournie dans la liste des dépendances, chaque symbole exporté est examiné.
      • Si le symbole correspond à un symbole manquant, le lien est effectué.
      • Avantage : chaque librairie n'est examinée qu'une seule fois.
      • Inconvénient : l'ordre des librairies est d'une importance cruciale. Un symbole peut être déclaré non résolu malgré la présence de la bonne librairie sur la ligne de commande, si elle a été spécifiée avant une librairie dépendante.
      • Les dépendances circulaires peuvent imposer de spécifier une librairie donnée DEUX FOIS sur la ligne de commande de l'éditeur de liens.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 1
    Dernier message: 23/12/2009, 16h41
  2. Réponses: 4
    Dernier message: 22/06/2009, 11h10
  3. Réponses: 0
    Dernier message: 02/06/2009, 19h28
  4. Changer le répertoire de destination d'une librairie statique
    Par vanitom dans le forum Eclipse C & C++
    Réponses: 1
    Dernier message: 04/05/2009, 11h34
  5. Probleme : Autres répertoires includes
    Par Julian11 dans le forum Visual C++
    Réponses: 0
    Dernier message: 25/03/2009, 20h41

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo