#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) повсюду, но, пожалуйста, просмотрите.