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