Общий путь к каталогу 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

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

Другие вопросы по тегам