Общий путь к каталогу makefile для GNU - PullRequest
48 голосов
/ 27 ноября 2008

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

# 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?

Ответы [ 5 ]

68 голосов
/ 28 ноября 2008

Вы можете использовать переменную MAKEFILE_LIST , например:

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

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

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

9 голосов
/ 30 марта 2010

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

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

Если у вас не установлен реальный путь:

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

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

2 голосов
/ 29 января 2015

Мое решение:

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

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

2 голосов
/ 27 ноября 2008

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

# 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, так что это может не сработать или может потребоваться некоторые настройки.

1 голос
/ 22 апреля 2012

просто напишите общие вещи в common.mk. Затем поместите common.mk - это папка по умолчанию, которую Make ищет, когда встречает оператор include common.mk.

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

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

include common.mk

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...