Percorso di directory makefile GNU comune

Sto cercando di consolidare alcune informazioni di build utilizzando un makefile comune. Il mio problema è che voglio usare quel makefile da diversi livelli di sottodirectory, il che rende il valore della directory di lavoro ( pwd ) imprevedibile. Per esempio:

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

Se includo Makefile.common da una sottodirectory, in questo modo, la directory $(TOP) non è corretta e tutto il resto lo segue:

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

Qual è il modo migliore per fare in modo che Makefile.common usi il proprio percorso di directory invece del più volubile pwd ?

Dovresti essere in grado di utilizzare la variabile MAKEFILE_LIST , in questo modo:

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

Dalla documentazione:

Poiché make legge vari makefile, inclusi quelli ottenuti dalla variabile MAKEFILES, dalla riga di comando, dai file predefiniti o dalle direttive include, i loro nomi verranno automaticamente aggiunti alla variabile MAKEFILE_LIST. Vengono aggiunti subito prima che make inizi a analizzarli. Ciò significa che se la prima cosa che fa un makefile è esaminare l’ultima parola in questa variabile, sarà il nome del makefile corrente. Una volta che il makefile corrente è stato utilizzato, tuttavia, l’ultima parola sarà il makefile appena incluso.

Questo non è un buon stile perché aggiunge un’altra dipendenza (cioè il binario di realpath). A seconda del caso d’uso, potrebbe essere accettabile.

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

Se non hai installato RealPath:

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

Modifica : assicurati di utilizzare := invece di = perché quest’ultimo causa l’utilizzo di late-binding e MAKEFILE_LIST potrebbe essere cambiato a causa di MAKEFILE_LIST successive.

Hai provato a fare:

 # 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’uso del costrutto? = Manterrà TOP da essere ridefinito se è già impostato. Puoi impostarlo sul valore appropriato in base a dove ti trovi nell’albero quando invochi make. Confesso che è passato un po ‘di tempo da quando ho usato GNU make, quindi potrebbe non funzionare o potrebbe aver bisogno di qualche ritouch.

La mia soluzione:

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

Questo funziona anche per le chiamate come make -f /opt/some/dir/Makefile quando si è in /opt/other/path/subdir .

scrivi semplicemente le cose comuni in common.mk . Quindi metti common.mk è la cartella predefinita che Make cerca quando incontra un’istruzione common.mk di inclusione.

Vedi la guida per le cartelle comuni. Cerca. Puoi anche inserire common.mk nella tua cartella home, quindi digitare make -I$HOME da qualsiasi cartella.

All’interno del Makefile in ogni sottocartella, lo fai semplicemente

 include common.mk 

Questo è tutto. Non c’è bisogno di preoccuparsi del percorso e di spostare le cose.