2008-11-27 13 views
44

Estoy tratando de consolidar cierta información de compilación utilizando un archivo MAKE común. Mi problema es que quiero usar ese archivo MAKE desde diferentes niveles de subdirectorio, lo que hace que el valor del directorio de trabajo (pwd) sea impredecible. Por ejemplo:Ruta de directorio común del archivo MAKE

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

Si incluyo Makefile.common de un subdirectorio, como tal, el directorio $(TOP) es incorrecto y todo lo demás sigue su ejemplo:

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

Cuál es la mejor manera de conseguir Makefile.common utilizar su propia ruta de directorio en lugar de la más voluble pwd?

Respuesta

62

Usted debe ser capaz de utilizar el MAKEFILE_LIST variable, así:

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

De la documentación:

Como marca lee diversos archivos make, incluyendo cualquier partir de la variable archivos make, la línea de comandos obtenida , los archivos predeterminados o las directivas include, sus nombres se anexarán automáticamente a la variable MAKEFILE_LIST. Se agregan justo antes de que make comience a analizarlos. Esto significa que si lo primero que hace un archivo MAKE es examinar la última palabra en esta variable, será el nombre del archivo MAKE actual. Una vez que se haya utilizado el archivo MAKE actual, sin embargo, la última palabra será el archivo MAKE recién incluido.

+1

Esto funcionó maravillosamente en mi cuadro dev, pero me di cuenta de que la máquina de destino se estaba ejecutando make 3.79, y la característica MAKEFILE_LIST se agregó en make 3.80: http://www.mail-archive.com/[email protected]/ msg05902.html – cdleary

+1

Parece que MAKEFILE_LIST no contiene rutas completas, solo rutas relativas. – kbyrd

+15

Mucho después del hecho, pero si ayuda a alguien: aquí hay un fragmento que le dará una ruta absoluta, pero no depende de realpath (en función de esta respuesta y [esta publicación del blog] (http: //blog.jgc .org/2007/01/what-makefile-am-i-in.html)): 'TOP: = $ (dir $ (CURDIR)/$ (palabra $ (palabras $ (MAKEFILE_LIST)), $ (MAKEFILE_LIST))) ' –

2

¿Ha intentado hacer:?

# 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 

= Uso de la construcción mantendrá TOP de ser redefinido si ya está establecido. Puede establecerlo en el valor apropiado en función de dónde se encuentre en el árbol cuando invoque make. Confieso que ha pasado un tiempo desde que usé GNU make, por lo que es posible que esto no funcione o necesite algunos ajustes.

+0

De acuerdo, eso funcionaría. Espero que haya una manera de hacerlo que no requiera preparación por parte del archivo makefile (que no sea la inclusión), pero ciertamente es una buena alternativa. – cdleary

9

Esto no es un buen estilo porque agrega otra dependencia (es decir, el binario de realpath). Dependiendo de su caso de uso, eso puede ser aceptable.

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

Si todavía no ha instalado la ruta real:

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

Edición: Asegúrese de utilizar := en lugar de = porque las últimas causas make utilizar enlace tardío y MAKEFILE_LIST puede haber cambiado debido a más tarde incluye.

+0

Debo señalar que esto se basa en el formulario de ejemplo de JesperE anterior. Sin embargo, proporciona una ruta absoluta para construir encima. – Bill

+0

+1 Esta solución es perfecta y portátil. Lo probé con éxito en UNIXes y Windows/Cygwin. Tenga en cuenta también la variable/directiva [VPATH] (http://www.gnu.org/software/make/manual/make.html#General-Search). –

+0

Me parece que 'realpath' es un built-in de' make', no una dependencia de un binario instalado ([docs] (https://www.gnu.org/software/make/manual/html_node/File- Name-Functions.html # index-realpath)). – nobar

1

simplemente escribe las cosas en común en common.mk. A continuación, coloque el campo common.mk es la carpeta predeterminada que Make busca cuando encuentra una instrucción include common.mk.

Ver ayuda para carpetas comunes Buscar. También puede colocar common.mk en su carpeta de inicio y luego escribir make -I$HOME desde cualquier carpeta.

Dentro del Makefile en cada subcarpeta, sólo tiene que hacer

include common.mk 

Eso es todo.No hay necesidad de preocuparse por el camino y mover las cosas.

+1

Interesante, pero demasiado ingenuo para proyectos complejos e implementaciones. –

2

Mi solución:

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

Esto también funciona para las llamadas como make -f /opt/some/dir/Makefile whenn tu en /opt/other/path/subdir.

Cuestiones relacionadas