web-dev-qa-db-fra.com

Common GNU chemin du répertoire makefile

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

# 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 ça, le répertoire $(TOP) est incorrect et tout le reste suit:

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

Quelle est la meilleure façon d'obtenir que Makefile.common Utilise le sien chemin du répertoire au lieu du _ plus aléatoire pwd?

48
cdleary

Vous devriez pouvoir utiliser la variable MAKEFILE_LIST , comme ceci:

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

De la documentation:

Lorsque make lit divers makefiles, y compris ceux obtenus à partir de la variable MAKEFILES, de la ligne de commande, des fichiers par défaut ou des directives include, leurs noms seront automatiquement ajoutés à la variable MAKEFILE_LIST. Ils sont ajoutés juste avant que make ne 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 makefile courant. Cependant, une fois que le makefile actuel a été utilisé, le dernier mot sera le makefile qui vient d'être inclus.

68
JesperE

Ce 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 installé realpath:

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

Modifier : assurez-vous d'utiliser := au lieu de = car ce dernier oblige make à utiliser la liaison tardive et MAKEFILE_LIST peut avoir changé en raison d'inclusions ultérieures.

9
Bill

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

L'utilisation de la construction? = Empêchera TOP d'être redéfini s'il est déjà défini. 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 cela fait un moment que j'ai utilisé GNU make donc cela peut ne pas fonctionner ou peut avoir besoin de quelques ajustements.

2
tvanfosson

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 Lorsque vous êtes dans /opt/other/path/subdir.

2
MegaSoft

écrivez simplement les choses courantes dans common.mk. Mettez ensuite 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. Rechercher. Vous pouvez également placer le common.mk dans votre dossier de départ, puis taper make -I$HOME à partir de n'importe quel dossier.

À 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 déplacer les choses.

1
Robert H