Partage
  • Partager sur Facebook
  • Partager sur Twitter

Probleme Compilation multifichiers C++

Avec Visual studio Code

    2 février 2025 à 18:54:28

    Bonjour,

    je suis votre cours C++ et je fais les exercices avec Visual Studio code.

    Pas de soucis si j'ai seulement main.cpp

    Problème de compilation des que je décompose en plusieurs fichiers xx.h et xx.cpp

    message d'erreur :

    *  Executing task: Mingw64 build current file

    Starting build...
    cmd /c chcp 65001>nul && C:\msys64\ucrt64\bin\g++.exe -fdiagnostics-color=always -Wall -g C:\Users\utilisateur\Test_Cpp\TestMulti\main.cpp -o C:\Users\utilisateur\Test_Cpp\TestMulti\main.exe
    C:/msys64/ucrt64/bin/../lib/gcc/x86_64-w64-mingw32/14.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\UTILIS~1\AppData\Local\Temp\ccUnIAEn.o: in function `main':
    C:/Users/utilisateur/Test_Cpp/TestMulti/main.cpp:15:(.text+0x92): undefined reference to `echange(double&, double&)'
    C:/msys64/ucrt64/bin/../lib/gcc/x86_64-w64-mingw32/14.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:/Users/utilisateur/Test_Cpp/TestMulti/main.cpp:19:(.text+0x106): undefined reference to `nombreDeSecondes(int, int, int)'
    collect2.exe: error: ld returned 1 exit status

    Build finished with error(s).

    Il ne voit pas les fonctions dans mon fichier annexe.h & annexe.cpp  (je dois avoir un problème de configuration) ?

    Merci de votre attention

    • Partager sur Facebook
    • Partager sur Twitter
      2 février 2025 à 21:31:41

      Bonjou,

      C'est une erreur assez courante de ceux qui suivent le cours d'OC (et c'est pas notre cours, aucun des auteurs ne vient sur le forum).

      De plus, le cours d'OC est particulièrement vieux dans son approche avec plus de 15 ans de retard sur ce qui se fait maintenant (et même à l'époque il n'était pas terrible).

      Sur le forum, on conseille plutôt celui sur Zeste de Savoir ou C++ Primer 5th edition. De Lippmann (en anglais, et commence à ce faire un peu vieux aussi).

      Pour les arguments de pourquoi le cours d'ici est mauvais: https://openclassrooms.com/forum/sujet/mooc-c?page=7#message-86545267 et https://informaticienzero.github.io/c -avec-openclassrooms-ou-comment-perdre-son-temps/

      Pour l'erreur elle-même, il faut compiler chaque .cpp puis linker tous les .o. Là, tu as fait les 2 opération en 1, mais en ne compilant que main.cpp ; il manque un fichier.

      • Partager sur Facebook
      • Partager sur Twitter
        2 février 2025 à 21:46:03

        bonjour, je ne sais pas si je peux t'aider, je suis aussi débutant et j'utilise codeblocks mais j'ai eu un probleme similaire dans le code du programme qui sert a ajouter deux a une valeur de cette page : https://openclassrooms.com/fr/courses/1894236-programmez-avec-le-langage-c/7565936-utilisez-plusieurs-fichiers

        Avec cette en-tête :

        #ifndef MATH_H_INCLUDED

        #define MATH_H_INCLUDED

        int ajouteDeux(int nombreRecu);

        #endif // MATH_H_INCLUDED

        je ne suis parvenu a rien parce que codeblocks m'indiquait " undefined reference to'ajouteDeux' " et j'ai du rajouter une ligne de code pour le faire tourner :

        #ifndef MATH_H_INCLUDED

        #define MATH_H_INCLUDED

        #include "math.cpp"

        int ajouteDeux(int nombreRecu);

        #endif // MATH_H_INCLUDED

        Cependant maintenant elle ne semble plus nécessaire et je ne comprend pas pourquoi... 

        Voila, je ne sais pas si ca pourra t'aider mais bonne chance 

        • Partager sur Facebook
        • Partager sur Twitter
          2 février 2025 à 21:51:14

          Merci à vous deux, je vais essayer demain
          • Partager sur Facebook
          • Partager sur Twitter
            3 février 2025 à 0:23:27

            Jugr montre un code qui inclut un .cpp... On ne fait pas ça. On ne fait jamais d'include sur des .cpp.

            • Partager sur Facebook
            • Partager sur Twitter
              4 février 2025 à 14:54:44

              Bonjour jugr,

              Sur un outil équivalant a codeblocks (Dev-C++) j'ai réussi a compiler après avoir ajouté les 2 fichiers supplémentaires à mon projet (outil de la barre des taches)  .

              Mais toujours problème avec VS code

              • Partager sur Facebook
              • Partager sur Twitter
                7 février 2025 à 4:22:18

                Hello,

                sauf bonne raison, je conseille vivement de changer d'IDE pour un qui soit plus évolué que VS-code ou code::block.
                Par exemple: Eclipse, QT-Creator, ou la rolls-royce des IDE: Visual Studio (qui, dans sa version Community, est gratuit).

                • Partager sur Facebook
                • Partager sur Twitter
                  7 février 2025 à 12:12:42

                  Pour résumer, le souci c'est que

                  • il compile les deux sources main.cpp et annexe.cpp
                  • mais après il râle qu'il trouve pas les fonctions qui sont pourtant définies dans main.cpp

                  En fait, c'est parce que le "il", c'est pas le même

                  • première étape c'est le compilateur qui traduit les *.cpp en "fichiers objets" *.obj (ou *.o)
                  • seconde, c'est l'éditeur de liens qui ficelle ensemble des fichiers objets et des bibliothèques pour fabriquer un exécutable.

                  Les solutions:

                  • si on tapait soi-même les commandes, il suffirait d'indiquer qu'on veut faire l'édition des liens de main.obj et annexe.obj avec la bibliothèque C++, et voila
                  • si on se fait aider (hum) par un "gestionnaire de projet", il faut lui dire qu'on a aussi besoin de annexe.obj pour fabriquer main.exe, pas seulemen t main.obj

                  Normalement, la notion de projet, c'est le genre de choses qu'on trouve dans un IDE, de nos jours.  Et en s'en sort en lui demandant quelque chose comme "ajouter annexe.cpp au projet".  Ce qui est une formulation un peu vaseuse, parce qu'un projet, ça peut consister à produire une famille d'exécutables, et il faudrait indiquer qui est fabriqué à partir de quoi, pour chaque.

                  > changer d'IDE

                  surtout, comprendre ce que l'IDE fait gentiment pour nous (et essaie autant que possible de nous cacher), quand on clique sur un bouton : compiler, lancer l'édition des liens, lancer l'exécution (et avec quel répertoire courant à ce moment là...).

                  -
                  Edité par michelbillaud 7 février 2025 à 12:17:41

                  • Partager sur Facebook
                  • Partager sur Twitter
                    7 février 2025 à 17:52:37

                    Mouais,

                    Faire de la compilation bas niveau (en ligne de commande par exemple), c'est sympa pour la culture générale, c'est vite gonflant.
                    Lorsque l'on développe, on recherche l'efficacité, et ca passe par les outils de développement (IDE).
                    Tout ce qu'un IDE automatise (nous cache) est le bienvenu.

                    • Partager sur Facebook
                    • Partager sur Twitter
                      7 février 2025 à 18:31:38

                      Certes c'est gonflant, mais pour distinguer (efficacement) les types d'erreur, il faut avoir compris ce qui se passe quand on clique sur [go].

                      Je ne dis pas de le faire tout le temps, c'est une étape utile pour le débutant, ca lui apprend des choses indispensables (plus qu'une "culture générale" qu'on s'empresserait en fait d'oublier)

                      -
                      Edité par michelbillaud 7 février 2025 à 18:34:48

                      • Partager sur Facebook
                      • Partager sur Twitter
                        7 février 2025 à 20:18:01

                        Deedolith a écrit:

                        Mouais,

                        Faire de la compilation bas niveau (en ligne de commande par exemple), c'est sympa pour la culture générale, c'est vite gonflant.
                        Lorsque l'on développe, on recherche l'efficacité, et ca passe par les outils de développement (IDE).
                        Tout ce qu'un IDE automatise (nous cache) est le bienvenu.

                        Tout ce qu'un IDE automatise est, effectivement, le bienvenu ... Surtout lorsque l'on comprend assez ce qu'il fait pour corriger les problèmes qu'il peut rencontrer ;)

                        Ce que je veux dire par là, c'est qu'un IDE n'est jamais qu'un outil.

                        Ou, plus précisément, un outil "principal" qui va faire appel à d'autres outils (appelons les "secondaires", même s'ils font tout le boulot) dans un ordre bien précis afin d'obtenir à chaque étape un résultat bien précis qu'il espère utiliser "plus tard" dans le processus "global".

                        Ce qui implique que, si l'un de ces outils "secondaires" échoue à fournir le résultat attendu et que tu n'as pas une "compréhension minimale" du processus "global", que tu n'a pas la moindre idée de ce qui est fait, pourquoi et à quel moment, lorsque le processus global échouera -- ce qu'il fera forcément, d'après la loi de Murphy -- tu ne sauras pas comment résoudre le problème.

                        Autrement dit, les outils réputés pour "faciliter la vie" ne peuvent réellement le faire que pour les gens qui comprennent le quoi et le quand de chaque étapes mises en oeuvre.

                        C'est peut être extrême, mais j'estime que

                        l'usage d'outils permettant de simplifier par automatisation des tâches la vie des gens devrait être limité à ceux qui sont capables de s'en passer

                        Je n'irai certainement pas jusqu'à imposer à quiconque d'être capable d'écrire un Makefile, fut il simple (je serais sans doute incapable de le faire moi-même).

                        Cependant, j'estime que le fait de savoir ce que font le préprocesseur, le compilateur, l'éditeur de liens, avec quelles données en entrées pour quel résultat en sortie, avec quel forme de message en cas d'erreur représente sans doute le "minimum légal" pour être autorisé à utiliser un IDE ;)

                        -
                        Edité par koala01 7 février 2025 à 20:31:00

                        • Partager sur Facebook
                        • Partager sur Twitter
                        Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs  à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
                          18 février 2025 à 15:13:58

                          > Je n'irai certainement pas jusqu'à imposer à quiconque d'être capable d'écrire un Makefile, fut il simple (je serais sans doute incapable de le faire moi-même).

                          Il ne s'agit pas d'imposer, mais d'indiquer que c'est une possibilité. D'autant que ce n'est pas vraiment très compliqué (faut juste y regarder, c'est pas une révélation qui tombe ou pas sur les élus), quand on veut faire un boulot, c'est mieux d'apprendre à se servir des outils.

                          Un exemple avec deux fichiers C++ plus un fichier d'entête, sous linux (où on ne met pas .exe pour les exécutables)

                          CXXFLAGS = -Wall -Wextra -std=c++11
                          
                          prog: prog.o fun.o
                          	$(LINK.cpp) -o $@ $^
                          
                          prog.o: fun.hpp
                          fun.o: fun.hpp
                          


                          La recette pour prog dit de produire l'exécutable prog à partir des modules fun.o et prog.o, en employant à cet effet la commande qui est dans une macro prédéfinie LINK.cpp

                          Comme il y a des fichiers prog.cpp et fun.cpp dans le répertoire, le commande make  sait comment les compiler pour fabriquer prog.o et fun.o : il faut appeler le compilateur C++, avec les options indiquées.

                          Les deux dernières lignes disent que prog.o et fun.o dépendent aussi du fichier d'entête fun.hpp.

                          Pour que la commande "make run"  soit lancée depuis vscode par la tâche "run", on peut y ajouter la ligne

                          run: prog

                          ou

                          run: prog
                          	./prog

                          si vous voulez que sous VScode, shift-controle-b  fasse à la fois la compilation, l'édition des liens et l'exécution.

                          (attention, en début de ligne c'est une tabulation, pas des espaces. Une idée merdique des débuts de make)


                          Les fichiers

                          // prog.cpp
                          
                          #include <iostream>
                          #include "fun.hpp"
                          
                          int main() {
                          	std::cout << "cube(9) = " << cube(9) << std::endl;
                          	return 0;
                          }
                          // fun.cpp
                          
                          #include "fun.hpp"
                          
                          int cube(int n) {
                          	return n * n * n;
                          }
                          
                          // fun.hpp
                          
                          #ifndef FUN_HPP
                          #define FUN_HPP
                          
                          int cube(int n);
                          
                          #endif


                          Et quand on fait shift-controle-B


                          PS:  La recette

                          prog: prog.o fun.o
                          	$(LINK.cpp) -o $@ $^
                          

                          comporte deux lignes :

                          • la première indique les dépendances: pour construire la cible prog, on a besoin des fichiers progs.o et fun.o, et à jour s'il vous plait
                          • la seconde la commande à exécuter pour fabriquer la cible. Là j'ai utilisé les variables magiques $@  qui représente la cible (prog)  et $^  qui est la liste de dépendances (prog.o fun.o). Comme ça, si besoin d'ajouter un module dans les dépendances, j'ai pas besoin de la faire dans la commande.
                          La commande make, au moins dans sa version GNU, a pas mal de règles par défaut. Si j'avais écrit simplement
                          truc: truc.o machin.o
                          
                          il aurait déduit tout seul qu'il faut faire une édition des liens (parce qu'il y a le nom de l'exécutable + le suffixe .o dans les dépendances). Manque de bol, ça serait l'édition des liens pour _C_,  dans sans les indispensables bibliothèques C++.  Donc je donne explicitement la commande à exécuter.
                          AMES SENSIBLES S'ABSTENIR sur internet, dans les makefiles pour C++  on trouve aussi une "astuce"  : ajouter la ligne

                          CC = g++
                          
                          qui dit à la commande make que le compilateur à utiliser pour ce qu'il pense être du C est le compilateur C++.

                          Une idée géniale pour se tirer dans le pied le jour où on a un projet multi-langages. Conseil, ne jamais prendre les outils à rebrousse-poil.




                          -
                          Edité par michelbillaud 20 février 2025 à 10:03:12

                          • Partager sur Facebook
                          • Partager sur Twitter
                            21 février 2025 à 3:50:54

                            En fait, j'exagérais un peu en disant que je ne serais sans doute pas capable d'écrire un Makefile "simple"...

                            Un truc dans le genre de ce que tu présentes, cela irait en effet sans grosse difficulté ;)

                            Par contre, dés qu'il s'agit de faire des tests, pour savoir si on dispose du binaire d'une bibliothèque ou s'il faut en compiler les sources... Ce sera très vite une autre paire de manches, même si je connais "la théorie" ;)

                            • Partager sur Facebook
                            • Partager sur Twitter
                            Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs  à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
                              21 février 2025 à 12:44:52

                              koala01 a écrit:

                              En fait, j'exagérais un peu en disant que je ne serais sans doute pas capable d'écrire un Makefile "simple"...

                              Un truc dans le genre de ce que tu présentes, cela irait en effet sans grosse difficulté ;)

                              Par contre, dés qu'il s'agit de faire des tests, pour savoir si on dispose du binaire d'une bibliothèque ou s'il faut en compiler les sources... Ce sera très vite une autre paire de manches, même si je connais "la théorie" ;)


                              ça a l'air simple quand je l'explique bien (c'est un métier :-)) mais quand on ne connaît pas un certain nombre de possibilités de make (variables, machins implicites), la version de base ça serait

                              main: main.o fun.o
                                   g++ -Wall -Wextra -std=c++11 -o main main.o fun.o
                              
                              main.o: main.cpp  fun.hpp
                                   g++ -Wall -Wextra -std=c++11 -c main.cpp
                              
                              fun.o: fun.cpp  fun.hpp
                                   g++ -Wall -Wextra -std=c++11 -c fun.cpp
                              

                              (avec des tabulations au lieu d'espaces en début de ligne) ce qui serait déjà pas mal. Les autres concepts, plus tard.


                              Et ça serait déjà bien de ne pas oublier de citer fun.hpp dans les dépendances.

                               Après, quand on connait les variables $@ (cible) $^ (dépendances) et $< (première dépendance) ça devient

                              main: main.o fun.o
                                   g++ -Wall -Wextra -std=c++11 -o $@ $^
                              main.o: main.cpp  fun.hpp
                                   g++ -Wall -Wextra -std=c++11 -c $<
                              fun.o: fun.cpp  fun.hpp
                                   g++ -Wall -Wextra -std=c++11 -c $< 

                              la variable CXXFLAGS

                              CXXFLAGS =  -Wall -Wextra -std=c++11
                              
                              main: main.o fun.o
                                   g++ $(CXXFLAGS) -o $@ $^
                              
                              main.o: main.cpp  fun.hpp
                                   g++ $(CXXFLAGS) -c $<
                              
                              fun.o: fun.cpp  fun.hpp
                                   g++ $(CXXFLAGS) -c $<

                              les variables COMPILE.cc et LINK.cc

                              CXXFLAGS = -Wall -Wextra -std=c++11
                              
                              main: main.o fun.o
                                   $(LINK.cc) -o $@ $^
                              
                              main.o: main.cpp  fun.hpp
                                   $(COMPILE.cc) -c $<
                              
                              fun.o: fun.cpp  fun.hpp
                                   $(COMPILE.cc) -c $<

                              Mais pour ca il fallait savoir avant que c'était  CXXFLAGS qu'il fallait utiliser. Les commandes par défaut

                              CXXFLAGS = -Wall -Wextra -std=c++11
                              
                              main: main.o fun.o
                                   $(LINK.cc) -o $@ $^
                              
                              main.o: main.cpp  fun.hpp
                                
                              fun.o: fun.cpp  fun.hpp
                              

                              et les dépendances implicites

                              CXXFLAGS = -Wall -Wextra -std=c++11
                              
                              main: main.o fun.o
                                   $(LINK.cc) -o $@ $^
                              
                              main.o: fun.hpp
                                
                              fun.o: fun.hpp

                              Ca parait plus simple, en effet. Encore qu'on puisse se simplifier encore plus la vie en demandant au compilateur de générer lui-même les dépendances supplémentaires (option -MMD si je me souviens bien) dans des fichiers *.d, qu'on inclut à la fin

                              CXXFLAGS =  -Wall -Wextra -std=c++11
                              CXXFLAGS += -MMD
                              
                              main: main.o fun.o
                                   $(LINK.cc) -o $@ $^
                              
                              -include $(wildcard *.d)


                              ce qui évite d'en oublier.





                              -
                              Edité par michelbillaud 22 février 2025 à 8:06:00

                              • Partager sur Facebook
                              • Partager sur Twitter

                              Probleme Compilation multifichiers C++

                              × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                              • Editeur
                              • Markdown