Ответы:
Следующее будет делать, если, как я предполагаю, вы используете ./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 для гораздо большего диапазона, как указано в вашем комментарии.
Вложенные циклы можно сделать так:
target:
num1=1 ; while [[ $$num1 -le 4 ]] ; do \
num2=1 ; while [[ $$num2 -le 3 ]] ; do \
echo $$num1 $$num2 ; \
((num2 = num2 + 1)) ; \
done ; \
((num1 = num1 + 1)) ; \
done
производство:
1 1
1 2
1 3
2 1
2 2
2 3
3 1
3 2
3 3
4 1
4 2
4 3
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, вы можете попробовать
НОМЕРА = 1 2 3 4 сделай это: $ (foreach var, $ (NUMBERS),. / a.out $ (var);)
который будет генерировать и выполнять
./a.out 1; ./a.out 2; ./a.out 3; ./a.out 4;
./a.out 1
. ./a.out 2
будет выполняться независимо.
Основная причина использования делают ИМХО это -j
флаг. make -j5
будет запускать 5 команд оболочки одновременно. Это хорошо, если у вас 4 процессора, и хороший тест любого make-файла.
По сути, вы хотите, чтобы make увидел что-то вроде:
.PHONY: all
all: job1 job2 job3
.PHONY: job1
job1: ; ./a.out 1
.PHONY: job2
job2: ; ./a.out 2
.PHONY: job3
job3: ; ./a.out 3
Это -j
дружелюбно (хороший знак). Можете ли вы определить котельную плиту? Мы могли бы написать:
.PHONY: all job1 job2 job3
all: job1 job2 job3
job1 job2 job3: job%:
./a.out $*
для того же эффекта (да, это то же самое, что и предыдущая формулировка, что касается 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.
.PHONY: all
, make будет искать файл с именем all
. Если такой файл существует, make затем проверяет время последнего изменения этого файла, и makefile почти наверняка не будет выполнять то, что вы хотели. .PHONY
Декларация говорит сделать , что all
является символической мишенью. Поэтому Make будет считать all
цель всегда устаревшей. Отлично. Смотрите руководство.
%
в правиле, доступно как $*
в рецепте.
Я понимаю, что этому вопросу уже несколько лет, но этот пост все еще может быть полезен кому-то, поскольку он демонстрирует подход, который отличается от вышеупомянутого и не зависит ни от операций оболочки, ни от необходимости для разработчика выделять жестко закодированный строка числовых значений.
встроенный макрос $ (eval ....) - ваш друг. Или может быть по крайней мере.
define ITERATE
$(eval ITERATE_COUNT :=)\
$(if $(filter ${1},0),,\
$(call ITERATE_DO,${1},${2})\
)
endef
define ITERATE_DO
$(if $(word ${1}, ${ITERATE_COUNT}),,\
$(eval ITERATE_COUNT+=.)\
$(info ${2} $(words ${ITERATE_COUNT}))\
$(call ITERATE_DO,${1},${2})\
)
endef
default:
$(call ITERATE,5,somecmd)
$(call ITERATE,0,nocmd)
$(info $(call ITERATE,8,someothercmd)
Это упрощенный пример. При больших значениях он не будет хорошо масштабироваться - он работает, но поскольку строка 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}
Счастливый макияж.
Для кроссплатформенной поддержки настройте разделитель команд (для выполнения нескольких команд в одной строке).
Если вы используете MinGW на платформе Windows, например, разделитель команд &
:
NUMBERS = 1 2 3 4
CMDSEP = &
doit:
$(foreach number,$(NUMBERS),./a.out $(number) $(CMDSEP))
Это выполняет объединенные команды в одну строку:
./a.out 1 & ./a.out 2 & ./a.out 3 & ./a.out 4 &
Как уже упоминалось, на платформе * nix CMDSEP = ;
.
Это не совсем чистый ответ на вопрос, а разумный способ обойти такие проблемы:
вместо того, чтобы писать сложный файл, просто делегируйте управление, например, скрипту bash, например: makefile
foo : bar.cpp baz.h
bash script.sh
и script.sh выглядит так:
for number in 1 2 3 4
do
./a.out $number
done
eval echo \$${$(var)}
; \ echo $$ var1; \ ((NUM = NUM + 1)); \ done all: set_var here SSA_CORE0_MAINEXEC - это переменная среды, которая уже установлена. Поэтому я хочу, чтобы это значение было оценено или напечатано с использованием переменной var1. Я попробовал это, как показано выше, но не работает. пожалуйста помоги.
bash
и, таким образом, использовать эти функции. Цикл является одной из особенностей, для которой это можно продемонстрировать.
Вы можете использовать set -e
в качестве префикса для цикла for. Пример:
all:
set -e; for a in 1 2 3; do /bin/false; echo $$a; done
make
выйдет сразу с кодом выхода <> 0
.
Хотя инструментарий таблиц 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))
Вывод:
./a3.out ./a8.out ./ad.out ./a12.out ./a17.out ./a1c.out ./a21.out ./a26.out ./a2b.out ./a30.out ./a35.out ./a3a.out ./a3f.out ./a44.out ./a49.out ./a4e.out ./a53.out ./a58.out ./a5d.out ./a62.out
#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.