Créer des répertoires à l'aide de fichier de créer
Je suis très nouveau pour les makefiles et je veux créer des répertoires à l'aide de makefile. Mon répertoire de projet, c'est comme cela
+--Project
+--output
+--source
+Testfile.cpp
+Makefile
J'ai envie de mettre tous les objets et de sortie dans le dossier de sortie. Je veux créer la structure de dossier qui serait comme cette après compilation.
+--Project
+--output
+--debug (or release)
+--objs
+Testfile.o
+Testfile (my executable file)
+--source
+Testfile.cpp
+Makefile
J'ai essayé avec plusieurs options, mais ne pouvait pas réussir. Merci de m'aider à faire les répertoires à l'aide de fichier make. Je poste 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 à l'avance. Merci de me guider si j'ai fait des erreurs aussi.
Vous devez vous connecter pour publier un commentaire.
Ce serait de le faire - en supposant un environnement de type Unix.
Cela devrait être exécuté dans le répertoire de niveau supérieur ou la définition de ${OUT_DIR} devrait être correct par rapport à où il est exécuté. Bien sûr, si vous suivez les édits de Peter Miller "Version Récursive Considéré Comme Nocif du papier", puis vous serez en exécution de make dans le répertoire de niveau supérieur de toute façon.
Je suis en train de jouer avec ce (RMCH) pour le moment. Il avait besoin d'un peu d'adaptation, à la suite d'un logiciel que j'utilise comme un terrain d'essai. La suite dispose d'une douzaine de programmes distincts construit avec une source de propagation à travers 15 répertoires, certains de il partagé. Mais avec un peu de soins, il peut être fait. Otoh, que, il pourrait ne pas être appropriée pour un débutant.
Comme indiqué dans les commentaires, l'inscription de l' 'mkdir' de la commande que l'action pour "annuaires" est faux. Comme noté dans les commentaires, il y a d'autres façons de résoudre le 'ne sais pas comment faire des sortie/debug' erreur qui en résulte. L'un est de supprimer la dépendance sur les "annuaires" de ligne. Cela fonctionne parce que "mkdir -p" ne pas générer des erreurs si tous les répertoires, il est demandé de créer existe déjà. L'autre est le mécanisme de la montre, qui ne pourra que tenter de créer le répertoire s'il n'existe pas. Le "modifiée" version " est ce que j'ai dans la tête la nuit dernière, mais les deux techniques de travail (et les deux ont des problèmes si la sortie/debug existe mais est un fichier plutôt que d'un répertoire).
output/debug', needed by
des répertoires. Arrêt". Mais je ne vais pas à vous soucier de cela maintenant. coller avec les règles de base. :). Merci pour le guide. Et je suis en cours d'exécution "faire" de l'interprète du répertoire seulement.directories
sans causer de toujours reconstruire..make -j<N>
.À mon avis, les répertoires ne doivent pas être considérés comme des cibles de votre makefile, que ce soit dans la technique ou dans le sens du design. Vous devez créer fichiers et si un fichier besoins de création d'un nouveau répertoire, puis tranquillement créer le répertoire à l'intérieur de la règle pour le fichier concerné.
Si vous ciblez une habitude ou "motifs" de fichier, il suffit d'utiliser
make
's variable interne$(@D)
, qui signifie "le répertoire de la cible actuelle réside dans" (cpm. avec$@
pour la cible). Par exemple,Puis, vous êtes effectivement faire le même: créer des répertoires pour tous les
$(OBJS)
, mais vous allez le faire dans une voie moins compliquée.La même politique (les fichiers sont des cibles, des répertoires ne le sont jamais) est utilisé dans diverses applications. Par exemple,
git
révision du système de contrôle ne stocke pas les répertoires.Remarque: Si vous allez l'utiliser, il pourrait être utile d'introduire un confort variable et utiliser
make
expansion de règles.Ou, BAISER.
Cela va créer tous les répertoires après le Makefile est analysée.
$(info $(shell mkdir -p $(DIRS)))
Sans$(info ...)
, la sortie de lamkdir
de la commande sera collé dans le fichier Makefile, conduisant à des erreurs de syntaxe, au mieux. Le$(info ...)
appel s'assure que: a) les erreurs (le cas échéant) sont visibles pour l'utilisateur, et b) que l'appel de la fonction se développe pour rien.make
dans, et hors de lui-même, poignées répertoire des cibles tout de même que les cibles de fichier. Ainsi, il est facile d'écrire des règles comme ceci:Le seul problème avec cela est que les répertoires d'horodatage dépend de ce qui est fait pour les fichiers à l'intérieur. Pour les règles ci-dessus, ce qui conduit au résultat suivant:
Ce n'est certainement pas ce que vous voulez. Chaque fois que vous touchez le fichier, vous touchez aussi le répertoire. Et depuis le fichier dépend du répertoire, le fichier, par conséquent, ne semble pas à jour, en les forçant à être reconstruit.
Cependant, vous pouvez facilement sortir de cette boucle par - dire faire d'ignorer le timestamp de l'annuaire. Ceci est fait en déclarant le répertoire comme un ordre seule condition sine qua non:
Cela correctement, on obtient:
TL;DR:
Écrire une règle pour créer le répertoire:
Et ont les cibles pour les trucs à l'intérieur dépendent de l'annuaire de commande uniquement:
touch
modifier aucune stat de données sur le répertoire parent? Qui fait non sens pour moi. Le mtime d'un dir dépend uniquement sur le nom des fichiers qu'il contient. Je ne pouvais pas reproduire votre problème.Toutes les solutions, y compris la accepté un problème comme indiqué dans leurs commentaires. Le accepté de répondre par @jonathan-leffler est déjà très bon, mais ne prend pas en effet que les conditions ne sont pas nécessairement à être construit dans l'ordre (au cours de
make -j
par exemple). Toutefois, simplement en déplaçant ledirectories
préalable deall
àprogram
provoque reconstruit sur chaque course AFAICT.La solution suivante n'a pas ce problème et AFAICS fonctionne comme prévu.
J'ai juste de venir avec un assez raisonnable solution qui vous permet de définir les fichiers à construire et avoir des répertoires sont créés automatiquement. Tout d'abord, définir une variable
ALL_TARGET_FILES
qui détient le nom de fichier de chaque dossier que votre fichier makefile sera de construire. Ensuite, utilisez le code suivant:Voici comment cela fonctionne. Je définir une fonction
depend_on_dir
qui prend un nom de fichier et génère une règle qui rend le fichier dépend du répertoire qui le contient et 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
, je pense que c'est les versions 3,81 et plus.étant donné que vous êtes un débutant, je dirais: ne pas essayer de le faire encore. c'est certainement possible, mais il inutilement compliquer votre Makefile. tenir à la simple manières jusqu'à ce que vous êtes plus à l'aise avec le faire.
cela dit, une façon de construire dans un répertoire différent du répertoire source est VPATH; je préfère modèle de règles
OS indépendance est essentielle pour moi, donc
mkdir -p
n'est pas une option. J'ai créé cette série de fonctions qui utilisenteval
à créer un répertoire des objectifs avec les pré-requis sur le répertoire parent. Cela a pour avantage demake -j 2
fonctionne sans problème depuis les dépendances sont correctement déterminés.Par exemple, l'exécution de la ci-dessus va créer:
Voir https://www.oreilly.com/library/view/managing-projects-with/0596006101/ch12.html
Que j'utilise Ubuntu, j'ai aussi besoin de l'ajouter en haut de mon Makefile: