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

Systèmes de compilation Discussion :

[GCC/Make] Détection des fichiers orphelins lors d'une compilation


Sujet :

Systèmes de compilation

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre Expert
    Avatar de Aspic
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2005
    Messages
    3 905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Août 2005
    Messages : 3 905
    Par défaut [GCC/Make] Détection des fichiers orphelins lors d'une compilation
    Bonjour,

    Je travaille sur un programme de compilation automatique de différents code.

    Je souhaiterais savoir s'il est possible avec les outils GCC, ou make de détecter les fichiers n'appartenant pas au projet. (des fichier sources temporaires par exemple) car ils sont inclus de base et donc la compilation plante alors que le programme sans ces fichiers parasites compile parfaitement...

    J'espère que je suis clair

    Merci
    Qui ne tente rien n'a rien !
    Ce qui ne nous tue pas nous rends plus fort !!
    Mon projet ZELDA en C++/Allegro
    http://www.tutoworld.com - Le Forum -
    Mes ressources Dotnet (cours, sources, tutos)
    --------------------------------------------
    + + =

    Ne pas oublier le Tag !

  2. #2
    Membre Expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Par défaut
    Bonsoir,

    oui et non Tout dépend comment tu repères les fichiers qui appartiennent au projet et si tu n'utilises que gcc et make ou si tu t'autorises d'autres outils pour créer un makefile par exemple.

    Une solution lourde serait :
    1. créer une liste de fichiers contenant une fonction main
    2. pour chacun de ces fichiers, créer une cible qui construit un exécutable ainsi que les dépendances avec gcc et pour chaque dépendances (fichier.h) vérifier si un source est associé (fichier.c) puis pour chacun de ces fichier.c ajouter une dépendance sur l'exécutable ...

    Autant utiliser autoconf

    J'ai une sorte de makefile générique (mono exécutable) que je voulais déjà poster ici ... je relaisserai un petit message quand je l'aurai fait

    Edit: Et voilà ... vite fait, espérant bien fait et utile Makefile générique

  3. #3
    Membre Expert
    Avatar de Aspic
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2005
    Messages
    3 905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Août 2005
    Messages : 3 905
    Par défaut
    Bonjour,

    Alors déjà, ma méthode est de récupérer tous les fichiers sources dans le répertoire src (les fichiers headers étant dans un dossier headers) et de tout compiler donc forcément avec ma méthode c'est pas possible...

    Il faut savoir que je suis sous Windows 7 avec GnuWin32 l'équivalent de make sous Linux. Est ce que ton makefile générique pourrait fonctionner avec GnuWin32 ?

    Sinon, je ne pense pas pouvoir utiliser autoconf sous Windows

    Une solution lourde serait :
    1. créer une liste de fichiers contenant une fonction main => OK (j'ai une idée de comment faire avec un grep sous windows ^^)
    2. pour chacun de ces fichiers, créer une cible qui construit un exécutable ainsi que les dépendances avec gcc et pour chaque dépendances (fichier.h) vérifier si un source est associé (fichier.c) puis pour chacun de ces fichier.c ajouter une dépendance sur l'exécutable ...
    Même si c'est lourd, comment on pourrait faire le deuxième point ? Je suis vraiment un newbie en makefile (et même en Linux de manière générale ^^)

    Voilà, merci
    Qui ne tente rien n'a rien !
    Ce qui ne nous tue pas nous rends plus fort !!
    Mon projet ZELDA en C++/Allegro
    http://www.tutoworld.com - Le Forum -
    Mes ressources Dotnet (cours, sources, tutos)
    --------------------------------------------
    + + =

    Ne pas oublier le Tag !

  4. #4
    Membre Expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Par défaut
    Citation Envoyé par Aspic Voir le message
    Bonjour,

    Alors déjà, ma méthode est de récupérer tous les fichiers sources dans le répertoire src (les fichiers headers étant dans un dossier headers) et de tout compiler donc forcément avec ma méthode c'est pas possible...

    Il faut savoir que je suis sous Windows 7 avec GnuWin32 l'équivalent de make sous Linux. Est ce que ton makefile générique pourrait fonctionner avec GnuWin32 ?

    Sinon, je ne pense pas pouvoir utiliser autoconf sous Windows
    J'ai regardé ce qu'était GnuWin32. C'est assez étrange car dans liste des packages je n'ai trouvé nulle part un shell. C'est ce qui sera le plus embêtant, car la plupart des commandes prérequises (rm, echo, ...) sont disponibles.
    Donc oui, il devrait pouvoir fonctionner avec de légères modifications (séparateur / transformé en \ je suppose) sous réserve que les commandes fonctionnent dans cmd.

    Pour autoconf (qui est bien plus puissant que mon simple Makefile, autant comparer une bombe H et un couteau à beurre) tu peux l'utiliser sous windows7. GnuWin32 propose un package.
    Il y a aussi la solution d'utiliser MSYS ou cygwin qui eux proposent un shell. Avec mingw tu peux aussi assez aisément cross-compiler depuis linux. Le désavantages de cygwin est sans doute la couche posix supplémentaire ...
    Pourquoi avoir choisi GnuWin32 ?
    Citation Envoyé par Aspic Voir le message
    Même si c'est lourd, comment on pourrait faire le deuxième point ? Je suis vraiment un newbie en makefile (et même en Linux de manière générale ^^)

    Voilà, merci
    Si on n'utilise qu'un makefile c'est très lourd car ça revient à écrire un script dans le Makefile, et un script qui ne pourra jamais être parfait Si tu veux on peut creuser plus loin.

  5. #5
    Membre Expert
    Avatar de Aspic
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2005
    Messages
    3 905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Août 2005
    Messages : 3 905
    Par défaut
    J'utilise GnuWin32 car je ne connais que cela

    Citation Envoyé par kwariz Voir le message
    Si on n'utilise qu'un makefile c'est très lourd car ça revient à écrire un script dans le Makefile, et un script qui ne pourra jamais être parfait Si tu veux on peut creuser plus loin.
    En fait pour l'instant, j'aurais besoin d'une méthode rapide pour trouver les dépendances entre les fichiers C et virer les fichiers orphelins.
    Donc même si ce n'est pas très propre, je veux bien de l'aide

    J'ai mis en pièce jointe un code exemple bidon avec un fichier débile "InitialisationDUMMY.c" qui lorsqu'il est compilé provoque une erreur de linkage car ce fichier est orphelin (ce fichier redéfinie la fonction load()). (la compilation marche si ce fichier est supprimé).

    Voilà donc le but serait de détecter automatiquement que "InitialisationDUMMY.c" ne sert à rien et donc de ne pas le prendre en compte au linkage et/ou à la compilation.

    Merci beaucoup
    Fichiers attachés Fichiers attachés
    Qui ne tente rien n'a rien !
    Ce qui ne nous tue pas nous rends plus fort !!
    Mon projet ZELDA en C++/Allegro
    http://www.tutoworld.com - Le Forum -
    Mes ressources Dotnet (cours, sources, tutos)
    --------------------------------------------
    + + =

    Ne pas oublier le Tag !

  6. #6
    Membre Expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Par défaut
    J'ai un peu cogité sur le problème. À partir du moment où tu disposes d'un shell (regarde si tu penses pouvoir utiliser MSYS) tu pourrais essayer d'améliorer mon premier jet (qui est loin d'être parfait ni même propre, sorry).
    Je suis parti du principe qu'étant donné tu as un répertoire src et un autre headers, ça te dirait d'avoir tes objets placés dans obj et ton exécutable dans [codeinline]bin/codeinline]. Je suis aussi parti du principe que tu ne construis qu'un seul exécutable.

    Le premier pas est de pouvoir construire la liste des dépendances au format Makefile : cible: liste des dépendances. Pour cela j'ai écris un petit script shell. On part du fichier qui contient le main et on utilise gcc pour fournir les dépendances. On les obtient avec les options -E (pour ne faire que la passe préprocesseur) -MM (on ne s'occupe que des headers qui ne sont pas des headers système) -MT pour customiser le nom de la cible car elle est dans un répertoire spécifique. Il ne faudra pas oublier de passer à gcc les options pour le préprocesseur (en gros les -D et les -I en général), ici je n'ai que passé un -I vers le répertoire contenant les headers.
    Donc on part du fichier c qui contient le main, on en demande les dépendances à gcc et on les sauve dans un fichier que l'on place dans le répertoire dep. On lit ensuite le fichier pour trouver tous les .h inclus et pour chaque .h inclus on recommence l'opération avec le fichier .c correspondant si on ne l'a pas déjà traité.
    À la fin, on crée un fichier dep/dep.inc qui est la concaténation de toutes les dépendances créées, plus une ligne pour ton exécutable et une ligne pour regénérer les dépendances si on modifie un des fichiers source trouvé.
    En gros, le script checkdeps.sh
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    #!/bin/bash                                                                                                                                     
     
    HEADER_DIR=headers/
    SOURCE_DIR=src/
    OBJECT_DIR=obj/
    BIN_DIR=bin/
    DEP_DIR=dep/
     
    MAIN_SOURCE=main.c
    MAIN_TARGET=monprog
    MAIN_SOURCE_LIST=""
    MAIN_OBJECT_LIST=""
    MAIN_DEP=dep.inc
     
    filesToCheck=${SOURCE_DIR}${MAIN_SOURCE}
    until [ "${filesToCheck}" == "" ]
    do
      nextRun=""
      for file in ${filesToCheck}
      do
        MAIN_SOURCE_LIST="$file ${MAIN_SOURCE_LIST}"
        MAIN_OBJECT_LIST="${OBJECT_DIR}$(basename ${file} .c).o ${MAIN_OBJECT_LIST}"
        echo -n "GENDEP $(basename ${file}) ( "
        gcc -I ${HEADER_DIR} -E -MM -MT ${OBJECT_DIR}$(basename ${file} .c).o -o ${DEP_DIR}$(basename ${file} .c).d ${file}
        for dep in $(cat ${DEP_DIR}$(basename ${file} .c).d)
        do
          if [ ${dep:$((${#dep}-2))} = .h ] && [ -e ${SOURCE_DIR}$(basename ${dep} .h).c ] && [ ! -e ${DEP_DIR}$(basename ${dep} .h).d ]
          then
            echo -n "$(basename ${dep} .h).c "
            nextRun="${SOURCE_DIR}$(basename ${dep} .h).c ${nextRun}"
          fi
        done
      done
      echo ")"
      filesToCheck="${nextRun}"
    done
    echo "${DEP_DIR}${MAIN_DEP}: ${MAIN_SOURCE_LIST}" > ${DEP_DIR}${MAIN_DEP}
    echo "${BIN_DIR}${MAIN_TARGET}: ${MAIN_OBJECT_LIST}" >> ${DEP_DIR}${MAIN_DEP}
    cat ${DEP_DIR}*.d >> ${DEP_DIR}${MAIN_DEP}
    rm ${DEP_DIR}*.d
    Le résultat avec le projet tel que tu l'as zippé :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    dep/dep.inc: src/checkMemory.c src/main.c 
    bin/monprog: obj/checkMemory.o obj/main.o 
    obj/checkMemory.o: src/checkMemory.c headers/checkMemory.h
    obj/main.o: src/main.c headers/checkMemory.h
    La première ligne est importante car c'est elle qui permet de relancer la création des dépendances si on modifie un source (il faudrait peut-être rajouter les headers ? ça va dépendre de ton style)
    La seconde explique que tous les sources compilés participent à la création de l'exécutable.
    Les suivantes décrivent les dépendances découvertes par gcc.

    Le makefile est ensuite relativement simple, on commence par quelques variables d'usage :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    SOURCE_DIR = src/
    HEADER_DIR = headers/
    OBJECT_DIR = obj/
    BIN_DIR    = bin/
    DEP_DIR    = dep/
     
    SOURCE_MAIN = main.c
    TARGET      = monprog
     
    .DEFAULT_GOAL := $(BIN_DIR)$(TARGET)
     
    CC = gcc
    CPPFLAGS = -I $(HEADER_DIR)
    Et c'est ensuite que ca devient intéressant. On demande à make d'inclure le fichier dep/dep.inc. La première fois il ne va pas le trouver, alors il va essayer de le créer. On lui donne la recette : lancer notre script
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $(DEP_DIR)dep.inc:
            @echo GENDEP
            @./checkdeps.sh

    Les fois suivantes il ne le générera que s'il faut (cf première ligne de dep/dep.inc).
    À partir de là on a géré les dépendances. Reste à expliquer comment créer l'exécutable et les objets :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    $(BIN_DIR)$(TARGET):
            @echo "CCLD   $@ <- $?"
            @touch $@
     
    $(OBJECT_DIR)%.o: $(SOURCE_DIR)%.c
            @echo "CC     $@ <- $?"
            @touch $@
    Bon ici je ne fais rien de spécial sinon afficher quelles dépendances déclenchent quelles recettes. À toi de mettre les bonnes commandes

    Remarque: ton main appelle la fonction load qui n'est dans un aucun header -> ça va bugguer. Avec ce genre d'automatisation il faut faire gaffe car on se repose sur le fait que toute fonction visible d'un source est déclarée dans un header de même de nom et qu'on inclue ce header partout où on utilise les fonctions.

    J'ai fait ça à main levée alors c'est sans garantie ... si ça va dans la direction voulue on pourra mettre ça au propre. Je joins le zip modifé.

    test_projet.zip

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

Discussions similaires

  1. Réponses: 3
    Dernier message: 12/08/2014, 17h48
  2. Réponses: 0
    Dernier message: 16/09/2010, 08h55
  3. Mise à jour des fichiers syst lors d'une installation
    Par Asdorve dans le forum Installation, Déploiement et Sécurité
    Réponses: 3
    Dernier message: 03/07/2006, 15h27
  4. Accès à des fichiers pour ouverture d'une image
    Par noutnout53 dans le forum C++
    Réponses: 4
    Dernier message: 02/06/2006, 15h44

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