взаимоисключающее планирование заданий в GNU make?

Можно ли с помощью GNU make создать набор целей, которые никогда не будут планироваться одновременно при использовании опции «--jobs»?

Фон:

Чтобы сделать это немного более конкретным, рассмотрим make-файл формы

p1: ...deps... # no parallelization conflicts (can run at the same time as p*, e*)
        ...rules...

p2: ...deps... # no parallelization conflicts (can run at the same time as p*, e*)
        ...rules...

p3: ...deps... # no parallelization conflicts (can run at the same time as p*, e*)
        ...rules...

e1: ...deps... # cannot run at same time as any other e*
        ...rules...

e2: ...deps... # cannot run at same time as any other e*
        ...rules...

e3: ...deps... # cannot run at same time as any other e*
        ...rules...

Главное, что мне нужно сделать, это убедиться, что e1, e2 и e3 никогда не обрабатываются одновременно, потому что они выполняют некоторую работу на встроенном устройстве с ограниченными ресурсами. Они аварийно завершают работу, если несколько из них выполняются одновременно. p1, p2 и p3 могут выполняться параллельно с чем угодно, включая любое задание e*.

Обратите внимание, что фактический make-файл имеет несколько тысяч целей с деревом зависимостей, которое имеет около 10 уровней в глубину, поэтому я надеюсь, что есть способ сделать это, который (а) не требует последовательного запуска make и (б) сохраняет преимущества кодирование дерева зависимостей в make-файле.


person Mr Fooz    schedule 23.02.2009    source источник


Ответы (2)


Один из вариантов для вас — использовать «flock» для запуска правил «e» под монопольной блокировкой. Подробности смотрите в man flock(1). Например, вместо

e2: deps
    my_cmd foo bar

Вы можете иметь

e2: deps
    flock .embedded-device-lock -c my_cmd foo bar

Что происходит тогда, так это то, что все цели "e" запускаются make параллельно (возможно), но фактические команды будут выполняться последовательно.

person Antti Huima    schedule 23.02.2009

Это не идеальное решение, но вы можете использовать предварительное условие только для порядка, чтобы наложить определенный порядок на цели e *:

e1: ...deps...
    ...commands...
e2: ...deps... | e1
    ...commands...
e3: ...deps... | e2 e1
    ...commands...

Предварительные условия после символа вертикальной черты '|' действуют только по порядку: они не заставляют, скажем, обновлять e3, если e1 или e2 изменились, но требуют, чтобы все команды для e1 и e2 завершились до запуска команд для e3.

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

person David Z    schedule 23.02.2009
comment
Спасибо за подсказку о механизме только заказа. Предположительно, это сработает и для некоторых более сложных ситуаций, таких как не более 2-доступа. - person Mr Fooz; 23.02.2009
comment
Я полагаю, да, но у него всегда есть один недостаток. Я просмотрел документацию по make, чтобы узнать, есть ли лучшее решение, но я его не нашел. - person David Z; 23.02.2009