Получение gmake, чтобы закончить рецепт рано - PullRequest
0 голосов
/ 06 июня 2018

Я знаю, что об этом уже спрашивали, но ни одно из решений, которые я нашел, не сработало для меня, потому что они анти-СУХИЕ.

У меня есть ряд целей, которые зависят от того, что может 't легко помечаются метками времени - например, файлы, скопированные из другой системы.То, что я хотел бы , чтобы иметь возможность делать, - это перечислять зависимости в переменной, например nobuild=this,that, и иметь эти цели , предполагаемые актуальными.Так как у меня их много, я не хочу ifdef вокруг каждого;то, что было бы псевдокодически предпочтительнее, было бы что-то вроде

ignorable-target: dependencies
        $(call ifnobuild,$@)
        .. rest of normal build steps ..

, где макрос ifnobuild расширился до какой-то инструкции выхода из этого рецепта с успехом gmakeесли ignorable-target было упомянуто в переменной nobuild.

Я также не хочу войти в многострочные продолженные команды оболочки, чтобы отложить условие на сам рецепт;Я хочу сказать make: «Предположим, что эти цели актуальны, и не пытайтесь их создавать», поэтому я могу проверить другие аспекты с помощью локальных копий, уже полученных из проблемных рецептов.

Там нет какого-либо механизма выхода-рецепта-с-успехом в gmake, есть?

[Отредактировано, чтобы, надеюсь, сделать ситуацию болееясно.]

Вот пример.Каждая из целей remote1 и remote2 предполагает использование ssh для выполнения чего-то трудоемкого в удаленной системе, а затем копирование результатов локально.Цель local1 создана локально и не требует временных затрат.target-under-work зависит от всех трех вышеперечисленных.

local1: local1.c Makefile

remote1: local1
        scp local1 remote-host:/tmp/
        ssh remote-host /tmp/local1 some-args # takes a long time
        scp remote-host:/tmp/local1.out remote1

remote2: local1
        scp local1 other-host:/tmp/
        ssh other-host /tmp/local1 other-args # takes a long time
        scp other-host:/tmp/local1.out remote2

target-under-work: local1 remote1 remote2
        do-something-with remote1,remote2

Теперь, когда я просто запустите make target-under-work, он будет запускать рецепты для remote1 и remote2.Однако локальные копии этих файлов «достаточно хороши» для моего тестирования, поэтому я не хочу, чтобы они запускались каждый раз.Как только все пойдет в производство, они будут запускаться каждый раз, но пока я занимаюсь разработкой target-under-work, я просто хочу использовать уже созданные копии, и я могу перестраивать их ежедневно (или что-то еще) длянеобходимая гранулярность тестирования.

Вышеуказанное упрощено;Есть несколько шагов и целей, которые зависят от remote1 и / или remote2.Я вижу, как получить желаемый эффект, создав для них предварительные условия только для заказа, но это будет означать изменение списка зависимостей каждой цели, для которой они есть в качестве предварительных условий, вместо того, чтобы single изменить на remote1 и remote2, поэтому я могу использовать некоторую переменную из командной строки, чтобы сказать их рецептам «притвориться, что это было сделано, на самом деле не собирать его, если уже есть копия».

Я надеюсь, что это делаетмой вопрос более понятен.

1 Ответ

0 голосов
/ 08 июня 2018

Нет, эта функция раннего выхода не существует.

Обратите внимание, что ваша проблема, вероятно, недостаточно указана, потому что вы не объясняете, какое поведение вы хотите, когда цель медленная делаетеще не существует.

Предположим, что медленные цели, перечисленные в nobuild, должны быть восстановлены, если и только если они не существуют.Вместо использования функций make для досрочного выхода из их рецепта вы можете использовать функции make, чтобы «скрыть» их список предпосылок.Таким образом, если они уже существуют, они не будут восстановлены, даже если они устарели.Единственная тонкость в том, что вам понадобится второе расширение, чтобы использовать автоматическую переменную $@ в списках предварительных условий.В следующем примере slow (ваш remoteX) зависит от fast1 (ваш local1).fast2 (ваш target-under-work) зависит от fast1 и slow:

host> cat Makefile
# Expands as empty string if $(1) exists and
# listed in $(nobuild). Else expands as $(2).
# $(1): target
# $(2): prerequisites
define HIDE_IF_NOBUILD
$(if $(wildcard $(1)),$(if $(filter $(1),$(nobuild)),,$(2)),$(2))
endef

nobuild :=

fast1:
    @echo 'build $@'
    @touch $@

fast2: fast1 slow
    @echo 'build $@'
    @touch $@

.SECONDEXPANSION:

slow: $$(call HIDE_IF_NOBUILD,$$@,fast1)
    @echo 'build $@'
    @touch $@

# Case 1: slow target not listed in nobuild and not existing
host> rm -f slow; touch fast1; make fast2
build slow
build fast2

# Case 2: slow target not listed in nobuild and existing and outdated
host> touch slow; sleep 2; touch fast1; make fast2
build slow
build fast2

# Case 3: slow target listed in nobuild and not existing
host> rm -f slow; touch fast1; make nobuild="slow" fast2
build slow
build fast2

# Case 4: slow target listed in nobuild and existing and outdated
host> touch slow; sleep 2; touch fast1; make nobuild="slow" fast2
build fast2
...