Цель Makefile, выполняющая параллельные цели и ожидающая их завершения, прежде чем делать больше вещей - PullRequest
0 голосов
/ 24 октября 2018

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

В следующем примере сообщение @echo "Print this only after *ALL* the previous PARALLEL tasks are done!" должен быть напечатан только после все цели foo-task1, foo-task2 и foo-task3 завершены.

Если я удалю амперсанд (&) в конце этих "дочерних целей" затем они становятся последовательными , но это не ожидаемое поведение.Они должны вести себя как «пул потоков» или «пул процессов».Я не знаю заранее, какая из этих целей будет выполнена последней, поэтому я не могу удалить амперсанд (&) из цели узкого места.

Эти цели представляют собой HTTP-вызовы удаленного API REST, которые могуттребуется переменное количество времени для завершения.Я хотел бы подождать, пока эти «параллельные вызовы REST» покажутся ли они успешными, перед печатью окончательного сообщения в foo-parallel.

Эти «параллельные цели» возвращают stdout / stderr, поэтому я бы хотел, чтобы родительская цель могладождаться их и потерпеть неудачу в случае возникновения ошибок.

Как я могу это сделать?

foo-task1:
    @bash -c 'sleep 1 && echo "task1" &'

foo-task2:
    @bash -c 'sleep 1 && echo "task2" &'

foo-task3:
    @bash -c 'sleep 2 && echo "task3" &'

foo-parallel: foo-task3 foo-task2 foo-task1
    @echo "Print this only after *ALL* the previous PARALLEL tasks are done!"

Команда make версия:

$ make --version
GNU Make 4.1
Built for x86_64-pc-linux-gnu
Copyright (C) 1988-2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

edit:

Это немного отличающееся определение цели (я изменил sleep раз просто для того, чтобы убедиться, что сообщения печатаются в задержанном порядке, а не в порядке кода):

foo-parallel:
    @bash -c 'sleep 5 && echo "task1" & \
                        sleep 1 && echo "task2" & \
                        sleep 2 && echo "task3" & \
                        wait; \
                        echo "done here!"'

печатает:

$ make foo-parallel 
task2
task3
task1
done here!

, но мне нужно поместить логику всех этих task1, task2 и task3 в одну цель.Я хотел бы разделить эти задачи на разные цели.

Ответы [ 2 ]

0 голосов
/ 24 октября 2018

Вы не можете сделать это без использования опции make -j.По умолчанию make создает одну цель, ожидает ее завершения, а затем создает следующую.Только с -j он будет поддерживать несколько одновременно работающих целей.

foo-parallel: foo-task3 foo-task2 foo-task1
        @echo "Print this only after *ALL* the previous PARALLEL tasks are done!"

foo-task1:
        @sleep 1 && echo "task1"

foo-task2:
        @sleep 1 && echo "task2"

foo-task3:
        @sleep 2 && echo "task3"

Затем запустите: make -j Или, если вы хотите ограничить количество параллельных сборок, используйте make -j2 или сколько угодновы хотите.

Если вы ДЕЙСТВИТЕЛЬНО хотите не набирать -j, вы можете использовать рекурсивный make:

foo-parallel:
        @$(MAKE) -j foo-task1 foo-task2 foo-task3
        @echo "Print this only after *ALL* the previous PARALLEL tasks are done!"

foo-task1:
        @sleep 1 && echo "task1"

foo-task2:
        @sleep 1 && echo "task2"

foo-task3:
        @sleep 2 && echo "task3"

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

0 голосов
/ 24 октября 2018

Я думаю, что вы хотите использовать опцию -j:

foo-task1:
    @sleep 1
    @echo "task1"

foo-task2:
    @sleep 1
    @echo "task2"

foo-task3:
    @sleep 2
    @echo "task3"

foo-parallel: foo-task3 foo-task2 foo-task1
    @echo "Print this only after *ALL* the previous PARALLEL tasks are done!"

И запустить make -j3 foo-parallel - make будет работать параллельно с правильной зависимостью.Подробнее Параллельное выполнение раздел:

GNU make знает, как выполнять несколько рецептов одновременно.Обычно, make будет выполнять только один рецепт за раз, ожидая его завершения, прежде чем выполнить следующий.Тем не менее, опция '-j' или '--jobs' указывает make выполнять несколько рецептов одновременно.

...