161 votes

Makefiles avec des fichiers sources dans différents répertoires

J'ai un projet dont la structure de répertoire est la suivante :

                         $projectroot
                              |
              +---------------+----------------+
              |               |                |
            part1/          part2/           part3/
              |               |                |
       +------+-----+     +---+----+       +---+-----+
       |      |     |     |        |       |         |
     data/   src/  inc/  src/     inc/   src/       inc/

Comment puis-je écrire un makefile qui serait dans part/src (ou n'importe où en fait) qui pourrait compléter/lien sur les fichiers sources c/c++ dans part?/src ?

Puis-je faire quelque chose comme -I$projectroot/part1/src -I$projectroot/part1/inc -I$projectroot/part2/src ...

Si cela fonctionne, y a-t-il un moyen plus simple de le faire ? J'ai vu des projets où il y a un makefile dans chacun des dossiers part ? correspondants. [dans ce post, j'ai utilisé le point d'interrogation comme dans la syntaxe bash].

0 votes

2 votes

Dans le manuel original de gnu ( gnu.org/software/make/manuel/html_node/Phony-Targets.html ) sous Phony Targets il y a un échantillon sur recursive invocation cela pourrait être très élégant.

0 votes

Quel outil avez-vous utilisé pour créer ce graphique de texte ?

6voto

IlDan Points 4104

Je pense qu'il est préférable de souligner que l'utilisation de Make (récursif ou non) est quelque chose que l'on veut généralement éviter, car par rapport aux outils actuels, il est difficile à apprendre, à maintenir et à faire évoluer.

C'est un outil merveilleux mais son utilisation directe devrait être considérée comme obsolète en 2010+.

À moins, bien sûr, que vous ne travailliez dans un environnement particulier, par exemple dans le cadre d'un ancien projet, etc.

Utilisez un IDE, CMake ou, si vous avez le cœur dur, le Autotools .

(édité en raison des downvotes, merci à Honza de l'avoir signalé)

1 votes

Ce serait bien que les votes négatifs soient expliqués. J'avais l'habitude de faire mes Makefiles moi-même aussi.

3 votes

Je vote pour la suggestion "ne faites pas ça" -- KDevelop a une interface très graphique pour configurer Make et d'autres systèmes de compilation, et bien que j'écrive moi-même des Makefiles, KDevelop est ce que je donne à mes collègues -- mais je ne pense pas que le lien Autotools aide. Pour comprendre Autotools, vous devez comprendre m4, libtool, automake, autoconf, shell, make, et fondamentalement la pile entière.

8 votes

Les votes négatifs sont probablement dus au fait que vous répondez à votre propre question. La question n'était pas de savoir si on devait ou non utiliser des Makefiles. Elle portait sur la façon de les écrire.

4voto

Je cherchais quelque chose comme ça et après quelques essais et chutes j'ai créé mon propre makefile, je sais que ce n'est pas la "manière idiomatique" mais c'est un début de compréhension de make et cela fonctionne pour moi, peut-être que vous pourriez essayer dans votre projet.

PROJ_NAME=mono

CPP_FILES=$(shell find . -name "*.cpp")

S_OBJ=$(patsubst %.cpp, %.o, $(CPP_FILES))

CXXFLAGS=-c \
         -g \
        -Wall

all: $(PROJ_NAME)
    @echo Running application
    @echo
    @./$(PROJ_NAME)

$(PROJ_NAME): $(S_OBJ)
    @echo Linking objects...
    @g++ -o $@ $^

%.o: %.cpp %.h
    @echo Compiling and generating object $@ ...
    @g++ $< $(CXXFLAGS) -o $@

main.o: main.cpp
    @echo Compiling and generating object $@ ...
    @g++ $< $(CXXFLAGS)

clean:
    @echo Removing secondary things
    @rm -r -f objects $(S_OBJ) $(PROJ_NAME)
    @echo Done!

Je sais que c'est simple et que pour certains mes drapeaux sont faux, mais comme je l'ai dit c'est mon premier Makefile pour compiler mon projet dans plusieurs répertoires et les lier tous ensemble pour créer mon bin.

J'accepte les suggestions :D

3voto

jvriesem Points 357

Le post de RC était SUPER utile. Je n'avais jamais pensé à utiliser la fonction $(dir $@), mais elle a fait exactement ce dont j'avais besoin.

Dans le répertoire parent, il y a un tas de répertoires contenant des fichiers sources : dirA, dirB, dirC. Plusieurs fichiers dépendent des fichiers objets dans d'autres répertoires, donc je voulais pouvoir créer un fichier à partir d'un répertoire, et faire en sorte qu'il crée cette dépendance en appelant le makefile associé à cette dépendance.

Essentiellement, j'ai créé un Makefile dans parentDir qui avait (parmi beaucoup d'autres choses) une règle générique similaire à celle de RC :

%.o : %.cpp
        @mkdir -p $(dir $@)
        @echo "============="
        @echo "Compiling $<"
        @$(CC) $(CFLAGS) -c $< -o $@

Chaque sous-répertoire inclut ce makefile de niveau supérieur afin d'hériter de cette règle générique. Dans le Makefile de chaque sous-répertoire, j'ai écrit une règle personnalisée pour chaque fichier afin de pouvoir garder la trace de tout ce dont dépend chaque fichier individuel.

Chaque fois que j'avais besoin de créer un fichier, j'utilisais (essentiellement) cette règle pour créer récursivement toutes les dépendances. Parfait !

NOTE : il existe un utilitaire appelé "makepp" qui semble faire cette tâche de manière encore plus intuitive, mais pour des raisons de portabilité et pour ne pas dépendre d'un autre outil, j'ai choisi de le faire de cette manière.

J'espère que cela vous aidera !

1voto

EhevuTov Points 6010

Utilisation récursive de Make

all:
    +$(MAKE) -C part1
    +$(MAKE) -C part2
    +$(MAKE) -C part3

Cela permet make pour se diviser en tâches et utiliser plusieurs cœurs

2 votes

En quoi est-ce mieux que de faire quelque chose comme make -j4 ?

1 votes

Devin, comme je le vois, ce n'est pas meilleur c'est juste permet à make d'utiliser le contrôle des tâches du tout. Lors de l'exécution d'un processus séparé de make, il n'est pas soumis au contrôle des tâches.

-1voto

user2763812 Points 1

Je suggère d'utiliser autotools :

//## Placez les fichiers objets générés (.o) dans le même répertoire que leurs fichiers sources, afin d'éviter les collisions lorsque le make non récursif est utilisé.

AUTOMAKE_OPTIONS = subdir-objects

en l'incluant dans Makefile.am avec les autres trucs assez simples.

Voici le tutoriel .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X