Следующее будет делать, если, как я предполагаю, вы используете ./a.outплатформу UNIX.
for number in 1 2 3 4 ; do \
./a.out $$number ; \
done
Тест следующим образом:
target:
for number in 1 2 3 4 ; do \
echo $$number ; \
done
производит:
1
2
3
4
Для больших диапазонов используйте:
target:
number=1 ; while [[ $$number -le 10 ]] ; do \
echo $$number ; \
((number = number + 1)) ; \
done
Это выводит от 1 до 10 включительно, просто измените whileусловие завершения с 10 на 1000 для гораздо большего диапазона, как указано в вашем комментарии.
qwert - это просто целевое имя, которое вряд ли будет настоящим файлом. Правилам Makefile нужна цель. Что касается синтаксической ошибки, вам не хватает некоторых вещей - смотрите обновление.
paxdiablo
2
Поскольку вы предполагаете, что его оболочка распознает ((...)), почему бы не использовать гораздо более простое для ((i = 0; i <WHATEVER; ++ i)); делать ...; сделано ?
Idelic
1
Обратите внимание, что seqкоманда, которая генерирует последовательность чисел, существует в большинстве (всех?) Unix-систем, поэтому вы можете написать for number in ``seq 1 1000``; do echo $$number; done(Поставьте один знак обратной галочки на каждой стороне команды seq, а не две, я не знаю, как правильно отформатировать это используя синтаксис stackoverflow)
Сюзанна Дюперон,
3
Спасибо, мне не хватало двойного $$ для ссылки на переменную цикла for.
Лейф Грюнвольдт
1
@Jonz: символ продолжения строки объясняется тем, что makeобычно каждая строка обрабатывается как отдельная суб-оболочка. Без продолжения он попытался бы запустить подоболочку только с (например) for number in 1 2 3 4 ; do, без остальной части цикла. С ним это фактически становится единственной линией формы while something ; do something ; done, которая является полным утверждением. $$Вопрос ответил здесь: stackoverflow.com/questions/26564825/... , с кодом , казалось бы , извлеченным из этого самого ответа :-)
paxdiablo
267
Если вы используете GNU make, вы можете попробовать
НОМЕРА = 1 2 3 4
сделай это:
$ (foreach var, $ (NUMBERS),. / a.out $ (var);)
Этот ответ ИМХО лучше, потому что он не требует использования какой-либо оболочки, это чистый make-файл (даже если он специфичен для GNU).
Джоселин Делаланде
7
точка с запятой имеет решающее значение, иначе будет выполнена только первая итерация
Джереми Лейпциг
7
Это решение скрывает код выхода ./a.out 1. ./a.out 2будет выполняться независимо.
bobbogo
1
@ Александр: не могли бы вы уточнить, на какое ограничение вы ссылаетесь?
Идеально
1
@ Идеально, да. Для следующих make-файлов и сценариев шеллскрипт работает (передает аргумент ls), в то время как make-файл выдает ошибку: make: execvp: / bin / sh: список аргументов слишком длинный Makefile: ix.io/d5L шеллскрипт: ix.io / d5M Это проблема в функции foreach, с которой я столкнулся на работе, когда необычно длинный список имен файлов (также с длинными путями) был передан команде. Мы должны были найти обходной путь.
Александр
107
Основная причина использования делают ИМХО это -jфлаг. make -j5будет запускать 5 команд оболочки одновременно. Это хорошо, если у вас 4 процессора, и хороший тест любого make-файла.
По сути, вы хотите, чтобы make увидел что-то вроде:
для того же эффекта (да, это то же самое, что и предыдущая формулировка, что касается make , только немного более компактно).
Еще немного о параметризации, так что вы можете указать ограничение в командной строке (утомительно, поскольку makeне имеет хороших арифметических макросов, поэтому я буду жульничать здесь и использовать $(shell ...))
LAST := 1000
NUMBERS := $(shell seq 1 ${LAST})
JOBS := $(addprefix job,${NUMBERS})
.PHONY: all ${JOBS}
all: ${JOBS} ; echo "$@ success"
${JOBS}: job%: ; ./a.out $*
Вы запускаете это make -j5 LAST=550со значением по LASTумолчанию 1000.
Это, безусловно, лучший ответ, по той причине, что упомянут Боббого ( -j ).
д.б.н.
По какой-то конкретной причине это использует суффиксы .PHONY? Они требуются для чего-нибудь?
Себ
6
@seb: без .PHONY: all, make будет искать файл с именем all. Если такой файл существует, make затем проверяет время последнего изменения этого файла, и makefile почти наверняка не будет выполнять то, что вы хотели. .PHONYДекларация говорит сделать , что allявляется символической мишенью. Поэтому Make будет считать allцель всегда устаревшей. Отлично. Смотрите руководство.
@JoeS gnu.org/software/make/manual/make.html#Static-Pattern (я думаю , что ты имел в виду , что это вторая * * двоеточие для ). Не путайте их с нехорошими (ИМХО) шаблонными правилами . Правила статических шаблонов действительно полезны всякий раз, когда список целей может быть сопоставлен с одним из шаблонов make noddy (то же самое относится и к зависимостям). Здесь я использую один только для удобства, что все, что соответствует %в правиле, доступно как $*в рецепте.
Боббого
22
Я понимаю, что этому вопросу уже несколько лет, но этот пост все еще может быть полезен кому-то, поскольку он демонстрирует подход, который отличается от вышеупомянутого и не зависит ни от операций оболочки, ни от необходимости для разработчика выделять жестко закодированный строка числовых значений.
встроенный макрос $ (eval ....) - ваш друг. Или может быть по крайней мере.
Это упрощенный пример. При больших значениях он не будет хорошо масштабироваться - он работает, но поскольку строка ITERATE_COUNT будет увеличиваться на 2 символа (пробел и точка) для каждой итерации, когда вы поднимаетесь на тысячи, для подсчета слов требуется все больше времени. Как написано, он не обрабатывает вложенные итерации (для этого вам понадобится отдельная функция итерации и счетчик). Это чисто gnu make, не требующий оболочки (хотя, очевидно, OP пытался запустить программу каждый раз - здесь я просто отображаю сообщение). If в ITERATE предназначено для перехвата значения 0, потому что в противном случае $ (word ...) выдаст ошибку.
Обратите внимание, что растущая строка, служащая счетчиком, используется потому, что встроенная переменная $ (words ...) может обеспечить арабский счет, но в противном случае make не поддерживает математические операции (вы не можете присвоить 1 + 1 чему-либо и получить 2, если вы не вызываете что-то из оболочки, чтобы выполнить это для вас, или используете не менее сложную макрооперацию). Это прекрасно работает для счетчика ИНКРЕМЕНТОВ, но не так хорошо для счетчика УМЕНЬШЕНИЯ.
Я сам этим не пользуюсь, но в последнее время мне нужно было написать рекурсивную функцию для оценки библиотечных зависимостей в многобинарной, многобиблиотечной среде сборки, где вам нужно знать, чтобы использовать ДРУГИЕ библиотеки, когда вы включаете какую-то библиотеку, которая сам по себе имеет другие зависимости (некоторые из которых варьируются в зависимости от параметров сборки), и я использую метод $ (eval) и counter, аналогичный приведенному выше (в моем случае счетчик используется, чтобы гарантировать, что мы каким-то образом не перейдем к бесконечному цикл, а также в качестве диагностики, чтобы сообщить, сколько итераций было необходимо).
Что-то еще ничего не стоящее, хотя и незначительное для Q оператора Q: $ (eval ...), предоставляет метод, позволяющий обойти внутреннее отвращение make к циклическим ссылкам, что хорошо и хорошо для применения, когда переменная является типом макроса (инициализируется с помощью =), по сравнению с немедленным назначением (инициализируется с помощью: =). Иногда вы хотите иметь возможность использовать переменную в своем собственном присваивании, и $ (eval ...) позволит вам сделать это. Здесь важно учесть, что во время запуска eval переменная разрешается, а разрешенная часть больше не рассматривается как макрос. Если вы знаете, что делаете, и пытаетесь использовать переменную RHS для присвоения себе, это, как правило, то, что вы хотите в любом случае произойти.
SOMESTRING = foo
# will error. Comment out and re-run
SOMESTRING = pre-${SOMESTRING}
# works
$(eval SOMESTRING = pre${SOMESTRING}
default:
@echo ${SOMESTRING}
Я застрял на шаг при написании Makefile. У меня есть следующий код: set_var: @ NUM = 0; while [[$$ NUM <1]]; do \ echo "Я здесь"; \ echo $$ NUM dump $$ {NUM} .txt; \ var = "SSA_CORE $$ {NUM} _MAINEXEC"; \ echo $$ var; \ var1 = eval echo \$${$(var)}; \ echo $$ var1; \ ((NUM = NUM + 1)); \ done all: set_var here SSA_CORE0_MAINEXEC - это переменная среды, которая уже установлена. Поэтому я хочу, чтобы это значение было оценено или напечатано с использованием переменной var1. Я попробовал это, как показано выше, но не работает. пожалуйста помоги.
XYZ_Linux
2
Это действительно простой обходной путь, однако он не позволяет использовать хорошую опцию «make -j 4» для параллельного запуска процессов.
TabeaKischka
1
@TabeaKischka: действительно. Это не был « рекомендуемый » способ, но он более важен, если нужны некоторые функции, которые не предлагаются в Makefile, тогда можно вернуться к реализации bashи, таким образом, использовать эти функции. Цикл является одной из особенностей, для которой это можно продемонстрировать.
Хотя инструментарий таблиц GNUmake имеет истинный whileцикл (что бы это ни значило в программировании GNUmake с его двумя или тремя фазами выполнения), если вещь, которая необходима, - это итеративный список, есть простое решение с помощью interval. Для удовольствия мы также конвертируем числа в шестнадцатеричные:
include gmtt/gmtt.mk
# generate a list of 20 numbers, starting at 3 with an increment of 5
NUMBER_LIST := $(call interval,3,20,5)
# convert the numbers in hexadecimal (0x0 as first operand forces arithmetic result to hex) and strip '0x'
NUMBER_LIST_IN_HEX := $(foreach n,$(NUMBER_LIST),$(call lstrip,$(call add,0x0,$(n)),0x))
# finally create the filenames with a simple patsubst
FILE_LIST := $(patsubst %,./a%.out,$(NUMBER_LIST_IN_HEX))
$(info $(FILE_LIST))
#I have a bunch of files that follow the naming convention
#soxfile1 soxfile1.o soxfile1.sh soxfile1.ini soxfile1.txt soxfile1.err
#soxfile2 soxfile2.o soxfile2.sh soxfile2.ini soxfile2.txt soxfile2.err
#sox... .... ..... .... .... ....
#in the makefile, only select the soxfile1.. soxfile2... to install dir
#My GNU makefile solution follows:
tgt=/usr/local/bin/ #need to use sudo
tgt2=/backup/myapplication/ #regular backup
install:
for var in $$(ls -f sox* | grep -v '\.' ) ; \
do \
sudo cp -f $$var ${TGT} ; \
cp -f $$var ${TGT2} ; \
done
#The ls command selects all the soxfile* including the *.something
#The grep command rejects names with a dot in it, leaving
#My desired executable files in a list.
Ответы:
Следующее будет делать, если, как я предполагаю, вы используете
./a.out
платформу UNIX.Тест следующим образом:
производит:
Для больших диапазонов используйте:
Это выводит от 1 до 10 включительно, просто измените
while
условие завершения с 10 на 1000 для гораздо большего диапазона, как указано в вашем комментарии.Вложенные циклы можно сделать так:
производство:
источник
seq
команда, которая генерирует последовательность чисел, существует в большинстве (всех?) Unix-систем, поэтому вы можете написатьfor number in ``seq 1 1000``; do echo $$number; done
(Поставьте один знак обратной галочки на каждой стороне команды seq, а не две, я не знаю, как правильно отформатировать это используя синтаксис stackoverflow)make
обычно каждая строка обрабатывается как отдельная суб-оболочка. Без продолжения он попытался бы запустить подоболочку только с (например)for number in 1 2 3 4 ; do
, без остальной части цикла. С ним это фактически становится единственной линией формыwhile something ; do something ; done
, которая является полным утверждением.$$
Вопрос ответил здесь: stackoverflow.com/questions/26564825/... , с кодом , казалось бы , извлеченным из этого самого ответа :-)Если вы используете GNU make, вы можете попробовать
который будет генерировать и выполнять
источник
./a.out 1
../a.out 2
будет выполняться независимо.Основная причина использования делают ИМХО это
-j
флаг.make -j5
будет запускать 5 команд оболочки одновременно. Это хорошо, если у вас 4 процессора, и хороший тест любого make-файла.По сути, вы хотите, чтобы make увидел что-то вроде:
Это
-j
дружелюбно (хороший знак). Можете ли вы определить котельную плиту? Мы могли бы написать:для того же эффекта (да, это то же самое, что и предыдущая формулировка, что касается make , только немного более компактно).
Еще немного о параметризации, так что вы можете указать ограничение в командной строке (утомительно, поскольку
make
не имеет хороших арифметических макросов, поэтому я буду жульничать здесь и использовать$(shell ...)
)Вы запускаете это
make -j5 LAST=550
со значением поLAST
умолчанию 1000.источник
.PHONY: all
, make будет искать файл с именемall
. Если такой файл существует, make затем проверяет время последнего изменения этого файла, и makefile почти наверняка не будет выполнять то, что вы хотели..PHONY
Декларация говорит сделать , чтоall
является символической мишенью. Поэтому Make будет считатьall
цель всегда устаревшей. Отлично. Смотрите руководство.%
в правиле, доступно как$*
в рецепте.Я понимаю, что этому вопросу уже несколько лет, но этот пост все еще может быть полезен кому-то, поскольку он демонстрирует подход, который отличается от вышеупомянутого и не зависит ни от операций оболочки, ни от необходимости для разработчика выделять жестко закодированный строка числовых значений.
встроенный макрос $ (eval ....) - ваш друг. Или может быть по крайней мере.
Это упрощенный пример. При больших значениях он не будет хорошо масштабироваться - он работает, но поскольку строка ITERATE_COUNT будет увеличиваться на 2 символа (пробел и точка) для каждой итерации, когда вы поднимаетесь на тысячи, для подсчета слов требуется все больше времени. Как написано, он не обрабатывает вложенные итерации (для этого вам понадобится отдельная функция итерации и счетчик). Это чисто gnu make, не требующий оболочки (хотя, очевидно, OP пытался запустить программу каждый раз - здесь я просто отображаю сообщение). If в ITERATE предназначено для перехвата значения 0, потому что в противном случае $ (word ...) выдаст ошибку.
Обратите внимание, что растущая строка, служащая счетчиком, используется потому, что встроенная переменная $ (words ...) может обеспечить арабский счет, но в противном случае make не поддерживает математические операции (вы не можете присвоить 1 + 1 чему-либо и получить 2, если вы не вызываете что-то из оболочки, чтобы выполнить это для вас, или используете не менее сложную макрооперацию). Это прекрасно работает для счетчика ИНКРЕМЕНТОВ, но не так хорошо для счетчика УМЕНЬШЕНИЯ.
Я сам этим не пользуюсь, но в последнее время мне нужно было написать рекурсивную функцию для оценки библиотечных зависимостей в многобинарной, многобиблиотечной среде сборки, где вам нужно знать, чтобы использовать ДРУГИЕ библиотеки, когда вы включаете какую-то библиотеку, которая сам по себе имеет другие зависимости (некоторые из которых варьируются в зависимости от параметров сборки), и я использую метод $ (eval) и counter, аналогичный приведенному выше (в моем случае счетчик используется, чтобы гарантировать, что мы каким-то образом не перейдем к бесконечному цикл, а также в качестве диагностики, чтобы сообщить, сколько итераций было необходимо).
Что-то еще ничего не стоящее, хотя и незначительное для Q оператора Q: $ (eval ...), предоставляет метод, позволяющий обойти внутреннее отвращение make к циклическим ссылкам, что хорошо и хорошо для применения, когда переменная является типом макроса (инициализируется с помощью =), по сравнению с немедленным назначением (инициализируется с помощью: =). Иногда вы хотите иметь возможность использовать переменную в своем собственном присваивании, и $ (eval ...) позволит вам сделать это. Здесь важно учесть, что во время запуска eval переменная разрешается, а разрешенная часть больше не рассматривается как макрос. Если вы знаете, что делаете, и пытаетесь использовать переменную RHS для присвоения себе, это, как правило, то, что вы хотите в любом случае произойти.
Счастливый макияж.
источник
Для кроссплатформенной поддержки настройте разделитель команд (для выполнения нескольких команд в одной строке).
Если вы используете MinGW на платформе Windows, например, разделитель команд
&
:Это выполняет объединенные команды в одну строку:
Как уже упоминалось, на платформе * nix
CMDSEP = ;
.источник
Это не совсем чистый ответ на вопрос, а разумный способ обойти такие проблемы:
вместо того, чтобы писать сложный файл, просто делегируйте управление, например, скрипту bash, например: makefile
и script.sh выглядит так:
источник
eval echo \$${$(var)}
; \ echo $$ var1; \ ((NUM = NUM + 1)); \ done all: set_var here SSA_CORE0_MAINEXEC - это переменная среды, которая уже установлена. Поэтому я хочу, чтобы это значение было оценено или напечатано с использованием переменной var1. Я попробовал это, как показано выше, но не работает. пожалуйста помоги.bash
и, таким образом, использовать эти функции. Цикл является одной из особенностей, для которой это можно продемонстрировать.Может быть, вы можете использовать:
источник
Вы можете использовать
set -e
в качестве префикса для цикла for. Пример:make
выйдет сразу с кодом выхода<> 0
.источник
Хотя инструментарий таблиц GNUmake имеет истинный
while
цикл (что бы это ни значило в программировании GNUmake с его двумя или тремя фазами выполнения), если вещь, которая необходима, - это итеративный список, есть простое решение с помощьюinterval
. Для удовольствия мы также конвертируем числа в шестнадцатеричные:Вывод:
источник
Простое, не зависящее от оболочки / платформы, чистое макро-решение ...
источник
источник