Відповіді:
Наступне зробить це, якщо, як я припускаю, використовуючи вашу ./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, а не дві, я не знаю, як це правильно відформатувати з використанням синтаксису
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 процесора, скажімо, і хороший тест будь-якого makefile.
В основному, ви хочете, щоб побачити щось на зразок:
.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
не має жодних хороших арифметичних макросів, тому я тут обманюю і використовую $(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
. Якщо такий файл існує, перевірте останній час зміни цього файлу, і 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, не вимагає оболонки (хоча очевидно, що ОП намагався запускати програму кожен раз - ось я просто показую повідомлення). Якщо в межах ITERATE призначено ввести значення 0, оскільки $ (word ...) помилиться інакше.
Зауважте, що зростаюча рядок, яка служить лічильником, використовується тому, що вбудований $ (слова ...) може забезпечити арабську кількість, але це робить інакше не підтримує математичні операції (Ви не можете призначити 1 + 1 чомусь і отримати 2, якщо ви не викликаєте щось із оболонки, щоб виконати це за вас, або не використовуєте однаково сумісну операцію макросу). Це чудово підходить для лічильника НЕПРАВИЛЬНОГО, але не дуже вдалого для ВИЗНАЧЕННЯ.
Я цим самим не користуюся, але останнім часом мені довелося написати рекурсивну функцію для оцінки залежностей бібліотеки в багатобінарному середовищі побудови кількох бібліотек, куди потрібно знати, щоб залучити ІНШІ бібліотеки, коли ви включаєте якусь бібліотеку, яка сама по собі має інші залежності (деякі з яких змінюються залежно від параметрів збірки), і я використовую метод $ (eval) та counter, подібний до вищевказаного (у моєму випадку лічильник використовується для того, щоб ми якось не переходили у нескінченний цикл, а також як діагностика, щоб повідомити, скільки ітерації було потрібно).
Щось ще нічого не варте, хоч і не має значення для Q: $ (eval ...) OP дає метод для обходу внутрішнього відхилення 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)); \ зробили все: set_var тут SSA_CORE0_MAINEXEC - це змінна середовище, яка вже встановлена. Тому я хочу, щоб це значення було оцінено або надруковано за допомогою змінної var1. Я спробував це, як показано вище, але не працює. будь ласка, допоможіть.
bash
та таким чином використовувати функції. Цикл - одна з особливостей, за якою це можна продемонструвати.
Ви можете використовувати set -e
як префікс for-loop. Приклад:
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.