Makefile должен выручить, если цель терпит неудачу - PullRequest
0 голосов
/ 23 апреля 2019

У меня есть make-файл следующего формата -

all: target_1 target_2 target_3

target_1:
    TASK_A1 | tee ta.log
    TASK_A2 | tee -a ta.log

target_2:
    TASK_B | tee tb.log

target_3:
    TASK_C | tee tc.log

TASK_A генерирует вывод журнала в этом формате -

<some lines of output>
Errors: 0, Warnings: 12
<some more lines of output>
Errors: 5, Warnings: 10

Когда я создаю все в идеале makefile должен выручить, если target_1 завершится неудачно, но он продолжит target_2.

Одним из возможных решений, которое я могу придумать, является извлечение «Errors: 0» из файлов журнала в каждой цели, а затем проверка возвращаемого значенияgrep (и выход, если grep возвращает ненулевое значение).Я не считаю это очень эффективным решением, так как мне нужно выполнить вышеуказанные шаги для каждой цели.

Есть ли более эффективный и разумный способ, которым я могу решить эту проблему?

Ответы [ 2 ]

1 голос
/ 23 апреля 2019

Ничего больше не зная об отдельных задачах, вы ничего не можете сделать, кроме как обработать вывод «Ошибки: 0».Однако вы можете применить принцип СУХОЙ так:

runtask = $(1) | tee -a $(2) | awk '{ print; if (/Errors: 0/) y=1; } END { if (y) { exit 0 } else { exit 1 } }'

all: target_1 target_2 target_3

target_1:
        @$(call runtask, TASK_A1, ta.log)
        @$(call runtask, TASK_A2, ta.log)

target_2:
        @$(call runtask, TASK_B, tb.log)

target_3:
        @$(call runtask, TASK_C, tc.log)

По крайней мере, таким образом вам не нужно проходить каждую строку, если вам нужно изменить шаблон поиска.

0 голосов
/ 23 апреля 2019

Итак, прежде всего, если target_2 зависит от target_1, вы должны явно указать это в вашем make-файле:

target_2: target_1

В противном случае, если кто-то строит с -j, тогда target_2 скорее всего будет работать независимо от того, успешно ли target_1.

Далее, вы хотите, чтобы make потерпел неудачу, если одна из целей потерпит неудачу.Make завершится, если возврат из строки рецепта будет ложным (ненулевым).Я предполагаю, что TASK_A1 и друзья возвращаются ложь, если они порождают ошибки (в противном случае остальная часть этого поста спорно)

1013 * К сожалению, у вас есть труба, которая усложняет вещи -. А именно, возвращение изрецепт будет возвращаемым значением от tee, а не TASK_A1.См. Ниже:
bash> false
bash> echo $?
1
bash> false | tee blah
bash> echo $?
0

В этом случае tee blah вернул true (0), поэтому $? (код возврата) равно 0. К счастью, вы можете использовать PIPESTATUS, чтобы получитькод возврата из первой части канала.

bash> false | tee blah; [ ${PIPESTATUS[0]} -eq 0 ]
bash> echo $?
1
bash> true | tee blah; [ ${PIPESTATUS[0]} -eq 0 ]
bash> echo $?
0

Итак ... В заключение, вы можете сделать что-то вроде:

all: target_3

target_1: 
    TASK_A1 | tee ta.log; [ $${PIPESTATUS[0]} -eq 0 ]
    TASK_A2 | tee -a ta.log; [ $${PIPESTATUS[0]} -eq 0 ]

target_2: target1
    TASK_B | tee tb.log; [ $${PIPESTATUS[0]} -eq 0 ]

target_3: target2
    TASK_C | tee tc.log; [ $${PIPESTATUS[0]} -eq 0 ]

Как только make выполнит задание, которое не выполнится, это не удастся.Обратите внимание, что в этом решении, если TASK_A1 завершится ошибкой, TASK_A2 не будет запущен.Я не был уверен, что это то, что вы хотите.Если вы хотите, чтобы оба запускались независимо, вы можете изменить target1 на:

target1:
   ( TASK_A1; TASK_A2 ) | tee ta.log; [ $${PIPESTATUS[0]} -eq 0 ]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...