Я хочу, чтобы выполнить следующие команды:Как написать цикл в Makefile?
Как написать эту вещь как цикл в Makefile
?
Я хочу, чтобы выполнить следующие команды:Как написать цикл в Makefile?
Как написать эту вещь как цикл в Makefile
?
Следующее будет сделано, если, как я полагаю, используя ваше использование ./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
Но если я хочу дойти до 1000, то не можем ли мы указать предел? – avd
Почему да, вы можете :-) Смотрите мое обновление. – paxdiablo
Одна вещь: что такое использование метки qwert? Другая вещь - вложенные петли. Он показывает синтаксическую ошибку в этом для n1 в 0 1 2; do \ для n2 в 1 2 3; do \ ./a.out $$ n1 $$ n2; \ done done – avd
Если вы используете GNU сделать, вы можете попробовать
NUMBERS = 1 2 3 4 doit: $(foreach var,$(NUMBERS),./a.out $(var);)
, который будет генерировать и выполнить
./a.out 1; ./a.out 2; ./a.out 3; ./a.out 4;
Этот ответ ИМХО лучше, потому что ему не требуется использовать какую-либо оболочку, это чистый makefile (даже если он специфичен для GNU). –
Согласен, @Jocelyn, это определенно лучший ответ. – cvk
ключевое слово с запятой имеет решающее значение, иначе будет выполняться только первая итерация –
Основная причина использования make IMHO - это флаг -j
. make -j5
будет запускать сразу 5 команд оболочки. Это хорошо, если у вас есть 4 процессора, и хороший тест любого 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
не имеет хорошие арифметические макросов, так что я буду обманывать здесь и использовать $(shell ...)
)
LAST := 1000
NUMBERS := $(shell seq 1 ${LAST})
JOBS := $(addprefix job,${NUMBERS})
.PHONY: all ${JOBS}
all: ${JOBS} ; echo "[email protected] success"
${JOBS}: job%: ; ./a.out $*
Вы запускаете это с помощью make -j5 LAST=550
, с LAST
по умолчанию до 1000.
Это, безусловно, лучший ответ по той причине, что bobbogo упомянул (_-j_). – dbn
Любая конкретная причина, по которой это используется. Суффиксы PHONY? Они нужны для чего-нибудь? – Seb
@seb: Без '.PHONY: all', make будет искать файл под названием' all'. Если такой файл существует, сделайте затем проверку последнего изменения времени файла, и make-файл почти наверняка не сделает то, что вы намеревались. В декларации '.PHONY' говорится, что' all' является символической целью. Поэтому Make будет считать цель «все» всегда устаревшей. Отлично. См. Руководство. – bobbogo
Для поддержки кросс-платформенных команд необходимо настроить разделитель команд (для выполнения нескольких команд в одной строке).
Если вы используете 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 = ;
.
& работает на unix тоже. – orkoden
Я понимаю, что вопрос несколько лет, но этот пост все же может быть полезен для кого-то, поскольку он демонстрирует подход, который отличается от вышеизложенного, и не зависит от операций оболочки или от необходимости Измените жестко закодированную строку числовых значений.
$ (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 каждый раз запускал программу - здесь я просто показываю сообщение). Если внутри ITERATE предполагается уловить значение 0, потому что $ (word ...) в противном случае будет ошибкой.
Обратите внимание, что растущая строка, используемая в качестве счетчика, используется потому, что встроенная функция $ (words ...) может обеспечивать арабский счет, но этот make не поддерживает другие математические операции (вы не можете присваивать 1 + 1 чему-либо и получите 2, если вы не вызываете что-то из оболочки, чтобы выполнить его для вас, или используя операцию с одинаково запутанным макросом). Это отлично работает для счетчика INCREMENTAL, но не так хорошо для DECREMENT.
Я не использую это сам, но в последнее время мне пришлось написать рекурсивную функцию для оценки зависимостей библиотек в многобиблиотечной, многобиблиотечной среде сборки, где вам нужно знать, чтобы вносить в ДРУГИЕ библиотеки, когда вы включают в себя некоторую библиотеку, которая сама имеет другие зависимости (некоторые из которых различаются в зависимости от параметров сборки), и я использую метод $ (eval) и счетчика, аналогичный описанному выше (в моем случае счетчик используется, чтобы гарантировать, что мы не так или иначе перейдите в бесконечный цикл, а также как диагностику, чтобы сообщить, сколько итераций было необходимо).
Что-то еще ничего не стоит, хотя и не имеет значения для Q: $ (eval ...) предоставляет метод обхода внутреннего отвращения make к циклическим ссылкам, что является хорошим и хорошим, чтобы обеспечить, когда переменная является макросом type (intialized with =), по сравнению с непосредственным назначением (инициализируется с помощью = =). Иногда вы хотите иметь возможность использовать переменную в пределах своего собственного назначения, а $ (eval ...) позволит вам это сделать. Важно рассмотреть здесь, что в то время, когда вы запускаете eval, переменная становится разрешенной, и эта часть, которая разрешена, больше не рассматривается как макрос. Если вы знаете, что делаете, и вы пытаетесь использовать переменную в RHS для присвоения себе, это, как правило, то, что вы хотите в любом случае.
SOMESTRING = foo
# will error. Comment out and re-run
SOMESTRING = pre-${SOMESTRING}
# works
$(eval SOMESTRING = pre${SOMESTRING}
default:
@echo ${SOMESTRING}
Счастливый make'ing.
Это не совсем чистый ответ на этот вопрос, но разумный способ обойти такие проблемы:
вместо того чтобы писать сложный файл, просто делегировать управление, например, Баш скрипт, как: Makefile
foo : bar.cpp baz.h
bash script.sh
и script.sh выглядит следующим образом:
for number in 1 2 3 4
do
./a.out $number
done
Я застрял на одном шаге, когда писал Makefile. У меня есть следующий код: set_var: @ NUM = 0; while [[$$ NUM <1]]; do \ эхо "Я здесь"; \ 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 здесь SSA_CORE0_MAINEXEC - это переменная среды, которая уже установлена. Поэтому я хочу, чтобы это значение получило оценку или печать с использованием переменной var1. Я попробовал это, как показано выше, но не работал. пожалуйста помоги. –
может быть, вы можете использовать:
xxx:
for i in `seq 1 4`; do ./a.out $$i; done;
нет, он не может :-( – zx1986
#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.
Вы можете использовать set -e
в качестве префикса для петли. Пример:
all:
set -e; for a in 1 2 3; do /bin/false; echo $$a; done
make
немедленно выйти с кодом выхода <> 0
.
Аналогичные, но несколько более общие: [Многострочные команды bash в makefile] (http://stackoverflow.com/q/10121182/86967) – nobar