2008-11-27 6 views
44

J'essaie de consolider certaines informations de construction en utilisant un fichier makefile commun. Mon problème est que je veux utiliser ce makefile de différents niveaux de sous-répertoire, ce qui rend la valeur du répertoire de travail (pwd) imprévisible. Par exemple:Chemin d'accès commun du répertoire makefile GNU

# Makefile.common 
TOP := $(shell pwd) 
COMPONENT_DIR := $(TOP)/component 
COMPONENT_INC := $(COMPONENT_DIR)/include 
COMPONENT_LIB := $(COMPONENT_DIR)/libcomponent.a 

Si j'inclus Makefile.common à partir d'un sous-répertoire, comme si, le répertoire $(TOP) est incorrect et tout le reste suit costume:

# other_component/Makefile 
include ../Makefile.common 
# $(COMPONENT_LIB) is incorrectly other_component/component 

Quelle est la meilleure façon d'obtenir Makefile.common d'utiliser son propre chemin de répertoire au lieu de la plus inconstante pwd?

Répondre

62

Vous devriez être en mesure d'utiliser le MAKEFILE_LIST variable, comme ceci:

# This must be the first this in Makefile.common 
TOP := $(dir $(lastword $(MAKEFILE_LIST))) 

De la documentation:

Comme make lit différents makefiles, y compris tout obtenu à partir de la variable Makefiles, la ligne de commande , les fichiers par défaut ou les directives include, leurs noms seront automatiquement ajoutés à la variable MAKEFILE_LIST. Ils sont ajoutés juste avant que make commence à les analyser. Cela signifie que si la première chose qu'un makefile fait est d'examiner le dernier mot de cette variable, ce sera le nom du fichier makefile courant. Une fois que le fichier makefile courant a été utilisé, le dernier mot sera le fichier makefile juste inclus.

+1

Cela a fonctionné à merveille sur ma boîte de dev, mais j'ai réalisé que la machine cible tournait make 3.79, et la fonctionnalité MAKEFILE_LIST a été ajoutée dans make 3.80: http://www.mail-archive.com/[email protected]/ msg05902.html – cdleary

+1

Il semble que MAKEFILE_LIST ne contienne pas de chemins complets, mais seulement des chemins relatifs. – kbyrd

+15

Bien après le fait, mais si cela aide quelqu'un: Voici un extrait qui vous donnera un chemin absolu, mais ne dépend pas de realpath (basé sur cette réponse et [ce blog]) (http: //blog.jgc .org/2007/01/what-makefile-am-i-in.html)): 'HAUT: = $ (dir $ (CURDIR)/$ (mot $ (mots $ (MAKEFILE_LIST)), $ (MAKEFILE_LIST))) ' –

2

Avez-vous essayé de faire:

# Makefile.common 
TOP ?= $(shell pwd) 
COMPONENT_DIR := $(TOP)/component 
COMPONENT_INC := $(COMPONENT_DIR)/include 
COMPONENT_LIB := $(COMPONENT_DIR)/libcomponent.a 

# other_component/Makefile 
TOP ?= .. 
include ../Makefile.common 

= Utilisation de la construction gardera TOP d'être redéfini si elle est déjà définie. Vous pouvez le définir sur la valeur appropriée en fonction de l'endroit où vous vous trouvez dans l'arborescence lorsque vous appelez make. J'avoue que ça fait longtemps que j'ai utilisé GNU make alors ça ne marchera peut-être pas ou il faudra peut-être quelques ajustements.

+0

D'accord, cela fonctionnerait. J'espère qu'il y a un moyen de le faire qui ne nécessite pas de préparation de la part du makefile (autre que l'inclusion), mais c'est certainement une bonne solution de rechange. – cdleary

9

Ceci n'est pas un bon style car il ajoute une autre dépendance (c'est-à-dire le binaire realpath). Selon votre cas d'utilisation, cela peut être acceptable.

ROOT_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) 

Si vous n'avez pas realpath installé:

$ sudo apt-get install realpath # on debian and derivatives 

Modifier: Assurez-vous d'utiliser := au lieu de = parce que ce dernier provoque make d'utiliser la liaison tardive et MAKEFILE_LIST peuvent avoir changé en raison de comprend plus tard.

+0

Je devrais noter que ceci se base sur le formulaire d'exemple de JesperE ci-dessus. Cependant, il fournit un chemin absolu pour construire au-dessus de. – Bill

+0

+1 Cette solution est parfaite et portable. Je l'ai testé avec succès sur UNIXes et Windows/Cygwin. Notez également la variable/directive [VPATH] (http://www.gnu.org/software/make/manual/make.html#General-Search). –

+0

Il me semble que 'realpath' est un builtin de' make' - pas une dépendance sur un binaire installé ([docs] (https://www.gnu.org/software/make/manual/html_node/File- Name-Functions.html # index-realpath)). – nobar

1

écrivez simplement les choses courantes dans common.mk. Ensuite, mettez le common.mk est le dossier par défaut que Make recherche lorsqu'il rencontre une instruction include common.mk.

Voir l'aide pour les dossiers communs Faire des recherches. Vous pouvez également placer common.mk dans votre dossier de départ, puis tapez make -I$HOME à partir de n'importe quel dossier.

A l'intérieur du Makefile dans chaque sous-dossier, vous faites simplement

include common.mk 

C'est tout.Pas besoin de s'inquiéter du chemin et de faire bouger les choses.

+1

Intéressant, mais trop naïf pour les projets et les déploiements complexes. –

2

Ma solution:

cwd := $(shell readlink -en $(dir $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST)))) 

Cela fonctionne également pour les appels comme make -f /opt/some/dir/Makefile whenn votre à /opt/other/path/subdir.

Questions connexes