целевой шаблон не содержит ‘%’. Остановка. При использовании $(shell sh -c «./ » ) (текущий рабочий каталог)

#gcc #makefile #gnu-make

#gcc #makefile #gnu-make

Вопрос:

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

TARGETS = sr_flipflop_clk_async_rst_tb sr_flipflop_tb

Ошибка возникает в моей test цели, где находится следующий код:

     $(foreach src, $(TARGETS), 
        printf '33[33m'; 
        echo "Running tests on target" $(src); 
        printf '33[39m'; 
        $(eval $(shell sh -c "echo "Results" >> ../output/${src}.out")) 
        $(eval $(shell ./${src})))
 

Ошибка генерируется из этой строки:
$(eval $(shell ./${src})))

По какой-то причине ошибка возникает только тогда, когда цель находится sr_flipflop_tb , но не на второй цели. Ошибка также не возникает, если я удаляю точку, указывающую текущий рабочий каталог. Я попробовал обходной путь, изменив строку на: $(eval $(shell ../build/${src}))) (текущий каталог называется build)

Это также генерирует ошибку. Я не могу понять, почему это происходит, генерируемая ошибка:

Makefile:28: *** target pattern contains no '%'. Stop.

где строка 28 относится к началу test целевого объекта.

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

На случай, если это будет полезно, вот моя структура каталогов:

 .
|-- build
|   |-- Makefile
|   |-- e~sr_flipflop_clk_async_rst_tb.o
|   |-- e~sr_flipflop_tb.o
|   |-- gather_errors.sh
|   |-- hello.txt
|   |-- sed.out
|   |-- sr_flipFlop.o
|   |-- sr_flipFlop_clk_async_rst.o
|   |-- sr_flipFlop_clk_async_rst_tb.o
|   |-- sr_flipFlop_tb.o
|   |-- sr_flipflop_clk_async_rst_tb
|   |-- sr_flipflop_tb
|   `-- work-obj93.cf
|-- output
|   |-- cat_test.out
|   |-- sr_flipflop_clk_async_rst_tb.out
|   `-- sr_flipflop_tb.out
 

Спасибо,
EJ

Редактировать: по-видимому, если я изменю имя sr_flipflop_tb буквально на что-нибудь другое, это сработает. Может кто-нибудь сказать мне, что здесь происходит? Это буквально связано с именем этого конкретного файла.

Комментарии:

1. Я также заметил, что когда я меняю строку-нарушитель на: $(shell sh -c "./${src}" ) ) я получаю другую ошибку: /bin/sh: 1: Syntax error: word unexpected (expecting ")") Makefile:28: recipe for target 'test' failed

2. Вы используете функции make ( foreach , eval , shell ) в рецепте make, в то время как рецепты make обычно являются сценариями оболочки. Это действительно странно. Независимо от вашей ошибки, вы должны сначала использовать make более стандартным способом. Например, $(eval $(shell ./${src}))) вообще не имеет смысла. И, кстати, вы должны предоставить нам больше информации: поскольку ошибка говорит, что это связано с целевым шаблоном, но вы показываете только рецепт, а не цель. Мы не можем помочь без полного понимания.

Ответ №1:

Этот код неверен. Вы не должны использовать $(eval ...) , потому что он ожидает, что будет задан синтаксис makefile (правила и настройки переменных makefile).

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

Во-вторых, вы не должны использовать $(shell ...) , потому что все переменные и функции make СНАЧАЛА разворачиваются, перед выполнением любых других команд. Это означает, что все ваши вызовы $(shell ...) будут выполняться, тогда все printfs будут выполняться.

Для этого вы должны использовать синтаксис оболочки, а не синтаксис make. Вы можете использовать foreach от make, если вы действительно хотите:

 $(foreach src, $(TARGETS), 
    printf '33[33m'; 
    echo "Running tests on target" $(src); 
    printf '33[39m'; 
    echo "Results" >> ../output/${src}.out; 
    ./${src};)
 

или вы можете записать его с помощью цикла оболочки:

 for src in $(TARGETS); do 
    printf '33[33m'; 
    echo "Running tests on target $src"; 
    printf '33[39m'; 
    echo "Results" >> "../output/$src.out"; 
    "./$src"; 
done
 

Но на самом деле, это ОЧЕНЬ не похоже на создание. Зацикливание внутри рецептов практически всегда является плохой идеей. Вместо этого вы должны использовать правила make, чтобы сделать это правильно:

 test: $(addprefix test-,$(TARGETS))

test-%:
        @printf '33[33m'; 
        echo "Running tests on target" $*; 
        printf '33[39m'; 
        echo "Results" >> ../output/$*.out; 
        ./$*
 

Комментарии:

1. Я исправил вызов оболочки; Я предполагаю, что вы хотели использовать $$src вместо ${src} или $(src) (sic) повсюду, но, пожалуйста, просмотрите.