2008-11-27 2 views
44

Я пытаюсь консолидировать некоторую информацию о сборке, используя общий make-файл. Моя проблема заключается в том, что я хочу использовать этот make-файл из разных уровней подкаталогов, что делает значение рабочего каталога (pwd) непредсказуемым. Например:Общий путь к файлу makefile GNU

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

Если я включаю Makefile.common из подкаталога, как это так, каталог $(TOP) неверен и все остальное следует примеру:

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

Какой самый лучший способ получить Makefile.common использовать его собственный путь к каталогу вместо более изменчивого pwd?

ответ

62

Вы должны быть в состоянии использовать MAKEFILE_LIST variable, как это:

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

Из документации:

Как делают читает различные мейкфайлы, в том числе любой полученной из переменной MAKEFILES, в командной строке , файлы по умолчанию или из директив include, их имена будут автоматически добавлены к переменной MAKEFILE_LIST. Они добавляются прямо перед тем, как make начинает их анализировать. Это означает, что если первое, что делает makefile, это проверка последнего слова в этой переменной, это будет имя текущего файла makefile. Однако, если текущий make-файл был включен, последнее слово будет являться только что включенным make-файлом.

+1

Это отлично работало в моей dev-блоке, но я понял, что целевая машина работает 3,79, а функция MAKEFILE_LIST была добавлена ​​в make 3.80: http://www.mail-archive.com/[email protected]/ msg05902.html – cdleary 2008-12-12 01:52:48

+1

Кажется, MAKEFILE_LIST не содержит полных путей, только относительные пути. – kbyrd 2010-02-11 14:31:27

+15

Многое после факта, но если это кому-то помогает: вот фрагмент, который даст вам абсолютный путь, но не зависит от realpath (на основе этого ответа и [этого сообщения в блоге] (http: //blog.jgc .org/2007/01/what-makefile-am-i-in.html)): `TOP: = $ (dir $ (CURDIR)/$ (слово $ (слова $ (MAKEFILE_LIST)), $ (MAKEFILE_LIST))) ` – 2012-02-14 19:26:08

2

Вы пробовали делать?

# 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 

Использование = сооружать будет держать TOP от переопределяется, если он уже установлен. Вы можете установить его на соответствующее значение в зависимости от того, где вы находитесь в дереве при вызове make. Я признаюсь, что прошло некоторое время с тех пор, как я использовал GNU make, поэтому это может не сработать или может потребоваться некоторые настройки.

+0

Согласен, что сработает. Я надеюсь, что есть способ сделать это, что не требует подготовки со стороны файла makefile (кроме включения), но это, безусловно, хороший откат. – cdleary 2008-11-27 04:53:33

9

Это не хороший стиль, потому что он добавляет другую зависимость (т. Е. Бинарный файл realpath). В зависимости от вашего варианта использования это может быть приемлемым.

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

Если вам не Realpath установлены:

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

Edit: Обязательно используйте := вместо =, поскольку последние причины make использовать позднее связывание и MAKEFILE_LIST может быть изменен из-за более позднего включения.

1

просто напишите обычный материал в common.mk. Затем поместите common.mk в папку по умолчанию, которую выполняет Make look, когда он встречает оператор common.mk.

См. Справку по общим папкам. Ищет. Вы также можете поместить common.mk в свою домашнюю папку, а затем введите make -I$HOME из любой папки.

Внутри Makefile в каждой подпапке, вы просто делаете

include common.mk 

То есть все.Не нужно беспокоиться о пути и перемещать вещи.

2

Мое решение:

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

Это также работает для звонков как make -f /opt/some/dir/Makefile в ваш Когда N /opt/other/path/subdir.