Общий путь каталога файлов GNU
Я пытаюсь консолидировать некоторую информацию сборки, используя общий make файл. Моя проблема в том, что я хочу использовать этот makefile из разных уровней подкаталога, что делает непредсказуемым значение рабочего каталога (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
?
Ответы
Ответ 1
Вы должны использовать MAKEFILE_LIST переменную, например:
# This must be the first this in Makefile.common
TOP := $(dir $(lastword $(MAKEFILE_LIST)))
Из документации:
Как make читает различные make файлы, в том числе любые, полученные из переменной MAKEFILES, командной строки, файлов по умолчанию или из директив include, их имена будут автоматически добавляться к переменной MAKEFILE_LIST. Они добавляются прямо перед тем, как make начинает их анализировать. Это означает, что если первое, что делает makefile, это проверка последнего слова в этой переменной, это будет имя текущего файла makefile. Однако, если текущий make файл был включен, последнее слово будет являться только что включенным make файлом.
Ответ 2
Это не хороший стиль, потому что он добавляет другую зависимость (т.е. бинарный файл realpath). В зависимости от вашего варианта использования, это может быть приемлемым.
ROOT_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
Если у вас не установлен realpath:
$ sudo apt-get install realpath # on debian and derivatives
Изменить: Обязательно используйте :=
вместо =
, потому что последнее приводит к тому, что make
использует позднюю привязку, а MAKEFILE_LIST
может быть изменен из-за более позднего включения.
Ответ 3
Вы пробовали:
# 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, так что это может не сработать или может потребоваться некоторые настройки.
Ответ 4
Мое решение:
cwd := $(shell readlink -en $(dir $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))))
Это также работает для вызовов типа make -f /opt/some/dir/Makefile
, когда вы находитесь в /opt/other/path/subdir
.
Ответ 5
просто напишите обычный материал в common.mk
. Затем поместите common.mk в папку по умолчанию, которая выполняет поиск, когда встречается с выражением common.mk.
См. справку об общих папках. Вы также можете поместить common.mk в свою домашнюю папку, а затем введите make -I$HOME
из любой папки.
Внутри Makefile в каждой подпапке вы просто делаете
include common.mk
Вот и все. Не нужно беспокоиться о пути и двигаться вокруг.