Псевдоним целевого имени в Makefile

Эта проблема:

Можно ли дать цели другое имя или псевдоним, чтобы ее можно было вызывать, используя либо исходное имя цели, либо псевдоним.

Например что-то вроде

/very/long/path/my_binary: dep_a dep_b dep_c
    # Compile

# Desired command
ALIAS my_binary = /very/long/path/my_binary

# NOTE: Notice the use of 'my_binary' in the dependencies
data1: my_binary datafile
    # Build data file using compiled my_binary

Попытка 1: .ФОНИЯ

Я попытался использовать цель .PHONY:

.PHONY: my_binary
my_binary: /very/long/path/my_binary

Это прекрасно работает при вызове из командной строки:

# Runs rule 'my_binary' and then *only* runs rule '/very/long/path/my_binary'
# if the rule '/very/long/path/my_binary' needs updating.
make my_binary

Однако это не работает, когда псевдоним my_binary указан как зависимость:

# *Always* thinks that rule 'data1' needs updating, because it always thinks that
# the .PHONY target 'my_binary' "needs updating". As a result, 'data1' is
# rebuilt every time.
make /very/long/path/my_binary

Возможен взлом?

Возможный хак - использовать пустую цель, как это предлагается в ответ на этот вопрос, но для этого потребуется ввести поддельные файлы с именами, соответствующими псевдониму:

my_binary: /very/long/path/my_binary
    touch my_binary

Это загромождает главный каталог файлами! Размещение поддельных файлов в подкаталоге лишило бы цели, так как псевдоним должен был бы называться «каталог/my_binary».


person WaelJ    schedule 17.04.2014    source источник


Ответы (2)


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

Почему вы не можете просто установить переменную в make-файле, например:

my_binary = /very/long/path/my_binary

затем использовать $(my_binary) везде в make-файле? Я не вижу смысла в создании реального псевдонима для использования внутри make-файла.

person MadScientist    schedule 17.04.2014

Ладно, мне нужно было что-то подобное. Путь к моим выходным артефактам был довольно длинным, но мне нужны были короткие имена целей, а также легко извлечь выгоду из bash-дополнения.

Вот что я придумал:

os := [arbitrary long path to an artifact]
platform := [arbitrary long path to a differ artifact]
packer := [common parts of my packer build command]

.PHONY: all
all: $(platform)

.PHONY: platform
platform: $(platform)

$(platform): platform.json  $(os)
    @$(packer) $<

.PHONY: os
os: $(os)

$(os): os.json
    @$(packer) $<

.PHONY: clean
clean:
    rm -fr build/

С Makefile выше вы можете сказать:

$ make os
$ make platform

Которые будут псевдонимами для длинных имен артефактов. Я сделал приведенный выше фрагмент довольно длинным, потому что важно увидеть взаимосвязь между псевдонимами .PHONY и реальными целями. Я надеюсь, что это работает для вас.

Примечание. Я не удалял чистую цель из приведенного выше примера, потому что многие люди не делают ее целью .PHONY. Однако по смыслу так и должно быть.

person frncmx    schedule 08.11.2015
comment
Обратите внимание, что важно, чтобы зависимости зависели от реальных целей, а не от их псевдонимов (например, $(platform): platform.json $(os), а не $(platform): platform.json os. - person Vladimir Panteleev; 23.08.2019
comment
Разве это не то же самое, что ОП, описанный в Попытке 1: .PHONY? - person André Chalella; 03.10.2019
comment
Я считаю, что это не то же самое. В моей попытке представить цель .PHONY как интерфейс только для конечного пользователя, т. е. использовать цель .PHONY только при вызове make <target> из оболочки. Используйте «настоящую» цель всякий раз, когда вы описываете свое дерево зависимостей в make-файле. =› Удобно для конечного пользователя; немного утомительно для разработчика, пишущего файл make. Результат: правильный расчет зависимости; хороший UX. Если у вас есть что-то вроде binary: my-phony-target, ваш двоичный файл будет перестраиваться при каждом вызове, поскольку фальшивые цели всегда устаревают по определению, и применяется транзитивность. - person frncmx; 08.10.2019
comment
Конечно, создать псевдонимы, которые можно использовать из командной строки, несложно. Это очень распространено. Но OP хотел также использовать псевдоним из внутри файла makefile (укажите его как предварительное условие). Здесь вы этого не делаете, вы используете полный путь в качестве предварительного условия (через переменную). - person MadScientist; 05.04.2020
comment
@MadScientist Я не уверен, что понимаю, что ты имеешь в виду. Мое решение только добавляет к вашему решению. Два отличия: 1. Я использую := (просто расширенная переменная) вместо = (рекурсивная переменная) 2. Я также добавил трюк, чтобы иметь псевдоним командной строки (а не просто сокращение в Makefile). Помимо двух вышеупомянутых , переменную можно использовать в качестве предварительного условия так же, как и в вашем решении, например, $(platform): platform.json $(os), где os была переменной. - person frncmx; 06.04.2020