Partage
  • Partager sur Facebook
  • Partager sur Twitter

include <> , "" et dossiers

    19 janvier 2015 à 17:14:49

    Bonjour à tous,

    Bon déjà je vous rassure je ne viens pas demander la différence entre 

    #include "ClassA.h"

    et

    #include <ClassA.h>


    D'ailleurs autant mettre un bon lien pour ça tant qu'on y est si ça peut en éclairer certains :

    http://msdn.microsoft.com/en-us/library/36k2cdd4.aspx

    Ma problématique est la suivante :

    J'ai actuellement un monstrueux projet (246 fichiers .h et .cpp) contenant donc des liens "#include" sur les fichiers nécessaires interne au projet. Ces classes sont réparties dans plusieurs sous-dossiers du dossier "src/" et pour l'instant j'utilisais mes liens d'include d'une façon carrément pas pratique :

    #include "../../engine/voxel/Block.h"

    Bref le genre de lien très difficile à mettre à jour en cas de restructuration des dossiers du projet ^^' !

    Je souhaite donc faire un bon gros ménage et là je me retrouve avec deux choix dont j'aimerais connaître les points forts/faibles ! On m'a conseillé ces deux points suivants :

    - N'utiliser que les <> en partant du root et en descendant dans les sous-dossiers. Après avoir renseigné "src/" dans les settings de mon IDE (Eclipse) en Include, cela me donnerait donc en reprenant l'exemple précédent :

    #include <engine/voxel/Block.h>

    - L'autre solution que l'on m'a proposé c'est d'inclure tous mes sous-dossiers au niveau des Includes du projet, et de n'utiliser que des appels directs vers les fichiers recherché avec les guillemets, ce qui donnerait :

    #include "Block.h"
    (et en rajoutant donc -I"D:\projet\src\engine\voxel" et donc aussi tous les autres dossiers du projets au final)
    Voilà j'aurais aimé connaître un peu les différences entre ces deux méthodes car cela attire carrément ma curiosité ^^ !
    (et que j'aimerais éviter un choix peut être un peu plus problématique avant de me lancer dans la modif de mes 246 fichiers ><) !

    -
    Edité par Dragonic 20 janvier 2015 à 15:13:07

    • Partager sur Facebook
    • Partager sur Twitter
      19 janvier 2015 à 17:34:02

      Pour ma part, ça serait:

      #include "engine/voxel/Block.h"

      A combiner avec le -I.

      Après, je réserve les chevrons aux lib externes. Pas à celle que je suis en train de définir.

      • Partager sur Facebook
      • Partager sur Twitter
      C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
        20 janvier 2015 à 10:04:39

        Pour tous vous dire les deux parties qui m'ont proposé ces deux solutions continuent de défendre corps et âme leur affirmation chacun de leur côté ^^ ! Ce qui est marrant (ou pas), c'est que je me fais limite engueuler des deux côtés car y a pas photo pour chaque partie qu'on y gagne avec leur méthode >< ! Enfin bref ^^ !

        Ayant recueillit un peu plus d'information, et bien pour l'instant ça serait la solution proposée juste au-dessus qui y gagnerait pour l'instant de mon côté !

        #include "engine/voxel/Block.h"

         (en n'incluant que le dossier root src avec -I) 

        Bon déjà au niveau de détails aussi critique que le temps de compilation par exemple, de ce côté il n'y a bien aucune différence, ce n'était pas précisé dans le premier post !

        Aussi, l'utilisation des guillemets ou des <> revient au même à ce niveau. Quitte donc à choisir pour ça je préfère les guillemets pour séparé les fichiers du projet des fichiers des libs externes aussi.

        Après il faut savoir que les deux solutions se valent à priori, et que ça dépend vraiment du besoin et du ressenti de chacun. Je vais pas forcément allé piocher dans des exemples de gros projets open-sources pour justifier une des méthodes, mais je vais simplement essayer de détailler les différences des deux méthodes pour un développeur Alpha qui code son projet perso !

        Rappel 1ère méthode : inclure tous les sous-dossiers au niveau des dossiers inclus du projet, et n'utiliser que des appels directs vers les fichiers utilisés :

        #include "Block.h"

        Avec cette méthode on y gagne quelques secondes pour écrire la ligne d'include par rapport au fait d'inclure tous les sous-dossiers en partant du root avec l'autre méthode. De même si on devait déplacer un fichier dans un autre dossier, si le nouveau dossier est déjà renseigné dans les includes du projet on a rien à faire, sinon on aurait juste à rajouter le dossier aux dossiers inclus au projet (-I/). L'autre méthode elle n'est pas bien plus lente puisqu'il suffirait d'un simple ctrl-h pour appliquer un fichier déplacé, par exemple "#include <dossier1/fichier.h>" en "#include <nouveauDossier/fichier.h>" ! Bref encore une histoire de quelques secondes sans doute, dans le cas où l'on restructure son projet et c'est pas quelquechose qu'on fait tous les jours ^^ !

        Rappel 2ème méthode: renseigner simplement le root dans les dossiers inclus du projet et mettre les liens des fichiers avec leurs sous-dossiers :

        #include <engine/voxel/Block.h>

        ou plutôt donc pour moi :

        #include "engine/voxel/Block.h"

        L'avantage de cette méthode c'est d'avoir une meilleure visibilité sur ce qu'on appelle exactement au niveau du code. Cela peut paraître anecdotique peut être pour certains face à un petit gain de temps avec l'autre méthode. Prenons un exemple pour mieux montrer comment cela pourrait être utile dans un certains cas ! Imaginons que vous avez un "xml/export.h" et un "json/export.h" (possible avec deux namespace différents par exemple). Et bien en lisant un autre code, par exemple dans un main.cpp, avec la 1ère méthode je me demande si il n'y aurait pas déjà un souci d'inclusion avec :

        #include "export.h"

        Et tout simplement je serais bien content de savoir à quel "export.h" j'ai affaire avec la seconde méthode :

        #include "json/export.h"


        C'est vraiment qu'un bête exemple, et qu'on peut facilement contourner ou corriger avec la 1ère méthode. N'empêche que cela reste donc pour moi plus "clean" de lire d'où vient un fichier que j'inclus que d'inclure le fichier directement. Enfin bref je choisirais donc plutôt la seconde méthode, même si je perds quelques secondes pour écrire les sous-dossiers si il y en a ! Et cela sera aussi plus simple à relire pour un autre collaborateur si il devait travailler sur le projet et analyser mon code !

        Voilà pour mon opinion actuelle, n'hésitez pas à donner la votre pour voir si l'une des méthodes semble être vraiment plus utilisée que l'autre !

        -
        Edité par Dragonic 20 janvier 2015 à 11:19:33

        • Partager sur Facebook
        • Partager sur Twitter
          20 janvier 2015 à 10:52:58

          Je n'aime pas avoir à faire plus de 20 -I pour utiliser une lib externe. Une lib externe, c'est un -I et basta. Quand on multiplie les -I, on se retrouve avec des lignes de compilation franchement longues et quand il y a une erreur de ce côté là, c'est l'enfer à investiguer.

          Certes, c'est plus de boulot pour les dév de la lib que de devoir toujours préciser où sont leurs fichiers. En ce qui me concerne c'est un faux argument car mon vim est configuré pour rajouter automatiquement le bon chemin lors des includes (et il n'y a pas de raison pour qu"un "IDE" ne sache pas le faire -- désolé, je sais, on n'est pas encore trolldi). Mais surtout, on sait vite où retrouver les fichiers, on peut se permettre d'avoir des homonymes dans les noms de fichiers (un sous-répertoire agit comme un espace de noms). D'ailleurs on pourrait se demander à quoi bon cloisonner dans des sous-répertoires si c'est pour tout inclure à plat.

          • Partager sur Facebook
          • Partager sur Twitter
          C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
            20 janvier 2015 à 11:14:07

            lmghs a écrit:

            Je n'aime pas avoir à faire plus de 20 -I pour utiliser une lib externe. Une lib externe, c'est un -I et basta. Quand on multiplie les -I, on se retrouve avec des lignes de compilation franchement longues et quand il y a une erreur de ce côté là, c'est l'enfer à investiguer.


            Ah mais là je parle bien que des "#include ..." des fichiers internes du projet, et non de l'inclusion de fichier de libs externes ou de leur renseignement en -I ! De ce côté je suis tout à fait d'accord qu'il faut généralement un -I par lib externe.

            Je veux dire, si j'ai une arborescence du genre sur mon projet :

            -src (contenant main.cpp)

            -src/dossier1 (contenant A.h)

            -src/dossier2 (contenant B.h)

            -src/dossier2/dossierA (contenant C.h)

            Avec la méthode 1, il faudrait ajouter ça au niveau compilation :

            -I".../src" -I".../src/dossier1" -I".../src/dossier2" -I".../src/dossier2/dossierA"

            Et ensuite ça serait d'utiliser les includes de cette façon partout :

            #include "A.h"
            #include "B.h"
            #include "C.h"

            Méthode 2, niveau compilation on a que le dossier root src :

            -I".../src"

            Et on utiliserait ceci pour les includes :

            #include "dossier1/A.h" 
            #include "dossier2/B.h" 
            #include "dossier2/dossierA/C.h"

            Pour les libs externes c'est à part je n'en fais pas mention ici !

            -
            Edité par Dragonic 20 janvier 2015 à 11:18:52

            • Partager sur Facebook
            • Partager sur Twitter
              20 janvier 2015 à 11:18:46

              C'est pratiquement la même chose. Et s'il y a des templates, c'est exactement la même chose -- quand on développe des libs. Car notre lib est appelée à devenir externe. Et du coup l'utilisateur devra faire 50 -I.

              Si notre projet est juste un binaire, certes il n'y aura pas des utilisateurs qui vont batailler à régler les -I. Cela reste juste nous, et cela pollue toujours la ligne de compilation.

              EDIT: Autre problème avec les 50 -I, il devient bien plus compliqué d'utiliser des outils (bâtis autour de clang p.ex.) qui font des choses avec le code (refactoring, completion, indexage, ...). Dans le meilleur des cas notre projet est géré avec CMake, et ces outils savent exploiter la base de données json. Mais quand ce n'est pas le cas, profiter de ces outils relève de l'enfer -- en présence de 50 -I.

              -
              Edité par lmghs 20 janvier 2015 à 11:24:19

              • Partager sur Facebook
              • Partager sur Twitter
              C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
                20 janvier 2015 à 11:22:23

                Oui en effet je n'avais pas précisé que dans mon cas que je ne parle bien que d'un binaire et que cela ne risque pas de finir en tant que lib (du moins dans l'état actuel du projet ^^ ) !

                Merci pour les détails en tout cas !

                -
                Edité par Dragonic 20 janvier 2015 à 11:23:36

                • Partager sur Facebook
                • Partager sur Twitter
                  22 janvier 2015 à 1:13:04

                  Il faut que l'architecture des répertoires du projet reflète l'architecture du projet lui-même (couches logicielles, modules, sous modules, ...).

                  Les headers des classes du même sous-modules sont directement accessible, celui du module englobant l'est facilement ainsi que des sous-module de celui-ci. Il est facile de regrouper les headers publiques des modules et couches dans des répertoires dédiés à ce type de publication d'API pour les appels transverse. Cela permet de bien distinguer les API publiques de ces composants des interfaces à usages internes.

                  En appliquant cela, la recherche de l'emplacement l'architecture du projet transparait directement dans l'explorateur de fichier et on ne passe pas plombes à chercher où est ce foutu header.

                  Le déplacement d'une classe dans un autre module demande à revoir les fichiers qui l'inclus mais cela permet surtout de faire automatiquement une étude d'impact de cette migration, qui permet de vérifier qu'on fout pas le bordel entre les dépendances entre module ou couche logiciel.

                  • Partager sur Facebook
                  • Partager sur Twitter
                  Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.

                  include <> , "" et dossiers

                  × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                  × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                  • Editeur
                  • Markdown