Je suis un tout nouveau makefiles et je veux créer des répertoires en utilisant makefile. Mon répertoire de projet est comme ça
+--Project
+--output
+--source
+Testfile.cpp
+Makefile
Je veux mettre tous les objets et la sortie dans le dossier de sortie respectif. Je veux créer une structure de dossier qui ressemblerait à ceci après la compilation.
+--Project
+--output
+--debug (or release)
+--objs
+Testfile.o
+Testfile (my executable file)
+--source
+Testfile.cpp
+Makefile
J'ai essayé avec plusieurs options, mais je n'ai pas réussi. Aidez-moi à créer des répertoires en utilisant make file. Je publie mon Makefile pour votre considération.
#---------------------------------------------------------------------
# Input dirs, names, files
#---------------------------------------------------------------------
OUTPUT_ROOT := output/
TITLE_NAME := TestProj
ifdef DEBUG
TITLE_NAME += _DEBUG
else
ifdef RELEASE
TITLE_NAME += _RELEASE
endif
endif
# Include all the source files here with the directory tree
SOURCES := \
source/TestFile.cpp \
#---------------------------------------------------------------------
# configs
#---------------------------------------------------------------------
ifdef DEBUG
OUT_DIR := $(OUTPUT_ROOT)debug
CC_FLAGS := -c -Wall
else
ifdef RELEASE
OUT_DIR := $(OUTPUT_ROOT)release
CC_FLAGS := -c -Wall
else
$(error no build type defined)
endif
endif
# Put objects in the output directory.
OUT_O_DIR := $(OUT_DIR)/objs
#---------------------------------------------------------------------
# settings
#---------------------------------------------------------------------
OBJS = $(SOURCES:.cpp=.o)
DIRS = $(subst /,/,$(sort $(dir $(OBJS))))
DIR_TARGET = $(OUT_DIR)
OUTPUT_TARGET = $(OUT_DIR)/$(TITLE_NAME)
CC_FLAGS +=
LCF_FLAGS :=
LD_FLAGS :=
#---------------------------------------------------------------------
# executables
#---------------------------------------------------------------------
MD := mkdir
RM := rm
CC := g++
#---------------------------------------------------------------------
# rules
#---------------------------------------------------------------------
.PHONY: all clean title
all: title
clean:
$(RM) -rf $(OUT_DIR)
$(DIR_TARGET):
$(MD) -p $(DIRS)
.cpp.o:
@$(CC) -c $< -o $@
$(OBJS): $(OUT_O_DIR)/%.o: %.cpp
@$(CC) -c $< -o $@
title: $(DIR_TARGET) $(OBJS)
Merci d'avance. Veuillez me guider si j'ai également fait des erreurs.
output/debug', needed by
répertoires cibles ". Stop. " Mais je ne vais pas m'inquiéter de ça maintenant. s'en tiendra aux règles de base. :). Merci d'avoir guidé. Et j'exécute "make" à partir du répertoire de niveau supérieur uniquement.directories
sans lesÀ mon avis, les répertoires ne devraient pas être considérés comme des cibles de votre makefile, que ce soit au sens technique ou au sens de la conception. Vous devez créer des fichiers et si une création de fichier nécessite un nouveau répertoire, créez tranquillement le répertoire dans la règle pour le fichier concerné.
Si vous ciblez un fichier habituel ou "modelé", utilisez simplement
make
la variable interne de$(@D)
, cela signifie "le répertoire dans lequel réside la cible actuelle" (cmp. Avec$@
pour la cible). Par exemple,Ensuite, vous faites effectivement la même chose: créez des répertoires pour tous
$(OBJS)
, mais vous le ferez de manière moins compliquée.La même politique (les fichiers sont des cibles, les répertoires ne le sont jamais) est utilisée dans diverses applications. Par exemple,
git
le système de contrôle des révisions ne stocke pas les répertoires.Remarque: si vous comptez l'utiliser, il peut être utile d'introduire une variable de commodité et d'utiliser
make
les règles d'expansion de.la source
Ou, KISS.
Cela créera tous les répertoires une fois le Makefile analysé.
la source
$(info $(shell mkdir -p $(DIRS)))
sans le$(info ...)
, la sortie de lamkdir
commande sera collée dans le Makefile , conduisant au mieux à des erreurs de syntaxe. L'$(info ...)
appel garantit que a) les erreurs (le cas échéant) sont visibles pour l'utilisateur, et b) que l'appel de fonction se développe en rien.make
dans et hors de lui-même, gère les cibles de répertoire de la même manière que les cibles de fichier. Donc, il est facile d'écrire des règles comme celle-ci:Le seul problème avec cela est que l'horodatage des répertoires dépend de ce qui est fait aux fichiers à l'intérieur. Pour les règles ci-dessus, cela conduit au résultat suivant:
Ce n'est certainement pas ce que vous voulez. Chaque fois que vous touchez le fichier, vous touchez également le répertoire. Et comme le fichier dépend du répertoire, le fichier semble par conséquent obsolète, ce qui oblige à le reconstruire.
Cependant, vous pouvez facilement interrompre cette boucle en disant à make d'ignorer l'horodatage du répertoire . Cela se fait en déclarant le répertoire comme un pré-site de commande uniquement:
Cela donne correctement:
TL; DR:
Écrivez une règle pour créer le répertoire:
Et faire en sorte que les cibles pour les choses à l'intérieur dépendent de l'ordre du répertoire uniquement:
la source
touch
modifier des données statistiques sur le répertoire parent? Cela n'a pas de sens pour moi. Le mtime d'un répertoire ne dépend que des noms de fichiers qu'il contient. Je n'ai pas pu reproduire votre problème.Toutes les solutions, y compris celle acceptée, présentent des problèmes comme indiqué dans leurs commentaires respectifs. La réponse acceptée par @ jonathan-leffler est déjà assez bonne mais ne prend pas en compte le fait que les prérequis ne doivent pas nécessairement être construits dans l'ordre (pendant
make -j
par exemple). Cependant, le simple fait de déplacer ledirectories
prérequis deall
àprogram
provoque des reconstructions à chaque exécution d'AFAICT. La solution suivante n'a pas ce problème et AFAICS fonctionne comme prévu.la source
Je viens de proposer une solution assez raisonnable qui vous permet de définir les fichiers à construire et de créer automatiquement des répertoires. Tout d'abord, définissez une variable
ALL_TARGET_FILES
contenant le nom de chaque fichier que votre makefile sera construit. Ensuite, utilisez le code suivant:Voici comment ça fonctionne. Je définis une fonction
depend_on_dir
qui prend un nom de fichier et génère une règle qui fait dépendre le fichier du répertoire qui le contient, puis définit une règle pour créer ce répertoire si nécessaire. Puis - je utiliserforeach
àcall
cette fonction sur chaque nom de fichier eteval
le résultat.Notez que vous aurez besoin d'une version de GNU make qui prend en charge
eval
, qui, je pense, sont les versions 3.81 et supérieures.la source
étant donné que vous êtes un débutant, je dirais que n'essayez pas encore de faire ça. c'est certainement possible, mais compliquera inutilement votre Makefile. tenez-vous-en aux méthodes simples jusqu'à ce que vous soyez plus à l'aise avec make.
ceci dit, une façon de construire dans un répertoire différent du répertoire source est VPATH ; je préfère les règles de modèle
la source
L'indépendance du système d'exploitation est essentielle pour moi, ce
mkdir -p
n'est donc pas une option. J'ai créé cette série de fonctions qui permettenteval
de créer des cibles de répertoire avec le prérequis sur le répertoire parent. Cela a l'avantage demake -j 2
fonctionner sans problème puisque les dépendances sont correctement déterminées.Par exemple, exécuter ce qui précède créera:
la source
Voir https://www.oreilly.com/library/view/managing-projects-with/0596006101/ch12.html
Comme j'utilise Ubuntu, j'avais également besoin d'ajouter ceci en haut de mon Makefile:
la source