如何在Makefile中编写循环?

发布于 2024-08-06 06:26:38 字数 144 浏览 6 评论 0原文

我想执行以下命令:

./a.out 1
./a.out 2
./a.out 3
./a.out 4
.
.
. and so on

如何在 Makefile 中将这个东西写为循环?

I want to execute the following commands:

./a.out 1
./a.out 2
./a.out 3
./a.out 4
.
.
. and so on

How to write this thing as a loop in a Makefile?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(16

稚然 2024-08-13 06:26:39

如果您使用的是 UNIX 类型的平台(我假设您使用 ./a.out),则以下内容将执行此操作。

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

The following will do it if, as I assume by your use of ./a.out, you're on a UNIX-type platform.

for number in 1 2 3 4 ; do \
    ./a.out $number ; \
done

Test as follows:

target:
    for number in 1 2 3 4 ; do \
        echo $number ; \
    done

produces:

1
2
3
4

For bigger ranges, use:

target:
    number=1 ; while [[ $number -le 10 ]] ; do \
        echo $number ; \
        ((number = number + 1)) ; \
    done

This outputs 1 through 10 inclusive, just change the while terminating condition from 10 to 1000 for a much larger range as indicated in your comment.

Nested loops can be done thus:

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

producing:

1 1
1 2
1 3
2 1
2 2
2 3
3 1
3 2
3 3
4 1
4 2
4 3
ぶ宁プ宁ぶ 2024-08-13 06:26:39

如果您使用 GNU make,您可以尝试

NUMBERS = 1 2 3 4
doit:
        $(foreach var,$(NUMBERS),./a.out $(var);)

生成并执行

./a.out 1; ./a.out 2; ./a.out 3; ./a.out 4;

If you're using GNU make, you could try

NUMBERS = 1 2 3 4
doit:
        $(foreach var,$(NUMBERS),./a.out $(var);)

which will generate and execute

./a.out 1; ./a.out 2; ./a.out 3; ./a.out 4;
冷情妓 2024-08-13 06:26:39

使用 make IMHO 的主要原因是 -j 标志。 make -j5 将同时运行 5 个 shell 命令。如果您有 4 个 CPU,那么这很好,并且可以很好地测试任何 makefile。

基本上,您希望 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。

THE major reason to use make IMHO is the -j flag. make -j5 will run 5 shell commands at once. This is good if you have 4 CPUs say, and a good test of any makefile.

Basically, you want make to see something like:

.PHONY: all
all: job1 job2 job3

.PHONY: job1
job1: ; ./a.out 1

.PHONY: job2
job2: ; ./a.out 2

.PHONY: job3
job3: ; ./a.out 3

This is -j friendly (a good sign). Can you spot the boiler-plate? We could write:

.PHONY: all job1 job2 job3
all: job1 job2 job3
job1 job2 job3: job%:
    ./a.out $*

for the same effect (yes, this is the same as the previous formulation as far as make is concerned, just a bit more compact).

A further bit of parameterisation so that you can specify a limit on the command-line (tedious as make does not have any good arithmetic macros, so I'll cheat here and use $(shell ...))

LAST := 1000
NUMBERS := $(shell seq 1 ${LAST})
JOBS := $(addprefix job,${NUMBERS})
.PHONY: all ${JOBS}
all: ${JOBS} ; echo "$@ success"
${JOBS}: job%: ; ./a.out $*

You run this with make -j5 LAST=550, with LAST defaulting to 1000.

兮颜 2024-08-13 06:26:39

我意识到这个问题已经有好几年了,但这篇文章可能仍然对某人有用,因为它演示了一种与上述不同的方法,并且不依赖于 shell 操作,也不需要开发人员删除硬编码数值字符串。

$(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,没有 shell 要求(尽管显然 OP 每次都希望运行一个程序——在这里,我只是显示一条消息)。 ITERATE 中的 if 旨在捕获值 0,因为否则 $(word...) 将出错。

请注意,使用不断增长的字符串作为计数器,因为 $(words...) 内置函数可以提供阿拉伯计数,但 make 不支持数学运算(您不能将 1+1 分配给某物并得到 2,除非您从 shell 调用某些内容来为您完成它,或者使用同样复杂的宏操作)。这对于增量计数器非常有效,但对于减量计数器则不太有效。

我自己不使用这个,但最近,我需要编写一个递归函数来评估多二进制、多库构建环境中的库依赖关系,在该环境中,当您包含某些库时,您需要知道引入其他库本身还有其他依赖项(其中一些依赖项取决于构建参数),我使用类似于上面的 $(eval) 和计数器方法(在我的例子中,计数器用于确保我们不会以某种方式陷入无休止的状态)循环,也可以作为诊断来报告需要多少迭代)。

其他东西毫无价值,尽管对OP的问题并不重要: $(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}

快乐制作。

I realize the question is several years old, but this post may still be of use to someone as it demonstrates an approach which differs from the above, and isn't reliant upon either shell operations nor a need for the developer to schpeel out a hardcoded string of numeric values.

the $(eval ....) builtin macro is your friend. Or can be at least.

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)

That's a simplistic example. It won't scale pretty for large values -- it works, but as the ITERATE_COUNT string will increase by 2 characters (space and dot) for each iteration, as you get up into the thousands, it takes progressively longer to count the words. As written, it doesn't handle nested iteration (you'd need a separate iteration function and counter to do so). This is purely gnu make, no shell requirement (though obviously the OP was looking to run a program each time -- here, I'm merely displaying a message). The if within ITERATE is intended to catch the value 0, because $(word...) will error out otherwise.

Note that the growing string to serve as a counter is employed because the $(words...) builtin can provide an arabic count, but that make does not otherwise support math operations (You cannot assign 1+1 to something and get 2, unless you're invoking something from the shell to accomplish it for you, or using an equally convoluted macro operation). This works great for an INCREMENTAL counter, not so well for a DECREMENT one however.

I don't use this myself, but recently, I had need to write a recursive function to evaluate library dependencies across a multi-binary, multi-library build environment where you need to know to bring in OTHER libraries when you include some library which itself has other dependencies (some of which vary depending on build parameters), and I use an $(eval) and counter method similar to the above (in my case, the counter is used to ensure we don't somehow go into an endless loop, and also as a diagnostic to report how much iteration was necessary).

Something else worth nothing, though not significant to the OP's Q: $(eval...) provides a method to circumvent make's internal abhorrence to circular references, which is all good and fine to enforce when a variable is a macro type (intialized with =), versus an immediate assignment (initialized with :=). There are times you want to be able to use a variable within its own assignment, and $(eval...) will enable you to do that. The important thing to consider here is that at the time you run the eval, the variable gets resolved, and that part which is resolved is no longer treated as a macro. If you know what you're doing and you're trying to use a variable on the RHS of an assignment to itself, this is generally what you want to happen anyway.

  SOMESTRING = foo

  # will error.  Comment out and re-run
  SOMESTRING = pre-${SOMESTRING}

  # works
  $(eval SOMESTRING = pre${SOMESTRING}

default:
  @echo ${SOMESTRING}

Happy make'ing.

毁虫ゝ 2024-08-13 06:26:39

为了跨平台支持,请使命令分隔符(用于在同一行上执行多个命令)可配置。

例如,如果您在 Windows 平台上使用 MinGW,则命令分隔符为 &

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 =;

For cross-platform support, make the command separator (for executing multiple commands on the same line) configurable.

If you're using MinGW on a Windows platform for example, the command separator is &:

NUMBERS = 1 2 3 4
CMDSEP = &
doit:
    $(foreach number,$(NUMBERS),./a.out $(number) $(CMDSEP))

This executes the concatenated commands in one line:

./a.out 1 & ./a.out 2 & ./a.out 3 & ./a.out 4 &

As mentioned elsewhere, on a *nix platform use CMDSEP = ;.

独孤求败 2024-08-13 06:26:39

也许你可以使用:

xxx:
    for i in `seq 1 4`; do ./a.out $i; done;

Maybe you can use:

xxx:
    for i in `seq 1 4`; do ./a.out $i; done;
当梦初醒 2024-08-13 06:26:39

这并不是问题的纯粹答案,而是解决此类问题的一种智能方法:

无需编写复杂的文件,只需将控制权委托给 bash 脚本,例如:
makefile

foo : bar.cpp baz.h
    bash script.sh

和 script.sh 如下所示:

for number in 1 2 3 4
do
    ./a.out $number
done

This is not really a pure answer to the question, but an intelligent way to work around such problems:

instead of writing a complex file, simply delegate control to for instance a bash script like:
makefile

foo : bar.cpp baz.h
    bash script.sh

and script.sh looks like:

for number in 1 2 3 4
do
    ./a.out $number
done
困倦 2024-08-13 06:26:39

您可以使用 set -e 作为 for 循环的前缀。示例:

all:
    set -e; for a in 1 2 3; do /bin/false; echo $a; done

make 将立即退出,退出代码为 <> 0 。

You can use set -e as a prefix for the for-loop. Example:

all:
    set -e; for a in 1 2 3; do /bin/false; echo $a; done

make will exit immediately with an exit code <> 0.

离笑几人歌 2024-08-13 06:26:39

尽管 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

Although the GNUmake table toolkit has a true while loop (whatever that means in GNUmake programming with its two or three phases of execution), if the thing which is needed is an iterative list, there is a simple solution with interval. For the fun of it, we convert the numbers to hex too:

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))

Output:

./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
盗梦空间 2024-08-13 06:26:39

在循环中动态分配变量

for number in 1 2 3 4 的问题; do \ ... - 解决方案是,循环内不能分配变量。仅当在目标执行开始时已知赋值内容时,才能使用 $(eval VAR=...)。如果赋值取决于循环变量,VAR 将为

为了避免这一问题,可以使用目标功能来模拟循环。以下示例从 SRC / OBJ 中获取第 n 个文件并将它们一起处理。使用此结构,您甚至可以使用 $(eval ...) 来处理循环变量,如 VAR3 所示。

生成文件

SRC = f1.c f2.cpp f3.cpp
OBJ = f1.o f2.o f3.o

SRC2 = $(addsuffix _,$(SRC))
JOIN = $(join $(SRC2),$(OBJ))

PHONY: all
all : info loop

loop : $(JOIN)

$(JOIN) :
    @# LOOP - CONTENT
    @echo "TARGET: $@"
    $(eval VAR1=$(word 1,$(subst _, ,$@)))
    @echo "VAR1: "$(VAR1)
    $(eval VAR2=$(word 2,$(subst _, ,$@)))
    @echo "VAR2: "$(VAR2)
    $(eval VAR3=$(subst .o,.x,$(VAR2)))
    @echo "You can even substitute you loop variable VAR3: "$(VAR3)
    #g++ -o $(VAR2) $(VAR1)
    @echo

PHONY: info
info:
    @printf "\n"
    @echo "JOIN: "$(JOIN)
    @printf "\n"

输出

$ make

JOIN: f1.c_f1.o f2.cpp_f2.o f3.cpp_f3.o

TARGET: f1.c_f1.o
VAR1: f1.c
VAR2: f1.o
You can even substitute you loop variable VAR3: f1.x
#g++ -o f1.o f1.c

TARGET: f2.cpp_f2.o
VAR1: f2.cpp
VAR2: f2.o
You can even substitute you loop variable VAR3: f2.x
#g++ -o f2.o f2.cpp

TARGET: f3.cpp_f3.o
VAR1: f3.cpp
VAR2: f3.o
You can even substitute you loop variable VAR3: f3.x
#g++ -o f3.o f3.cpp

Dynamically assign variables in the loop

The promblem with the for number in 1 2 3 4 ; do \ ...-solution is, that no variables can be assigned within the loop. $(eval VAR=...) can only be used, if the content of the assignment is known at the beginning of the target execution. If the assignment depends on the loop-variable, VAR will be empty.

To circumvent this issue, one can use the target functionality to model a loop. The following example takes the n-th file from SRC / OBJ and processes them together. Using this construction you can even use $(eval ...) to process the loop variable, as demonstrated with VAR3.

makefile

SRC = f1.c f2.cpp f3.cpp
OBJ = f1.o f2.o f3.o

SRC2 = $(addsuffix _,$(SRC))
JOIN = $(join $(SRC2),$(OBJ))

PHONY: all
all : info loop

loop : $(JOIN)

$(JOIN) :
    @# LOOP - CONTENT
    @echo "TARGET: $@"
    $(eval VAR1=$(word 1,$(subst _, ,$@)))
    @echo "VAR1: "$(VAR1)
    $(eval VAR2=$(word 2,$(subst _, ,$@)))
    @echo "VAR2: "$(VAR2)
    $(eval VAR3=$(subst .o,.x,$(VAR2)))
    @echo "You can even substitute you loop variable VAR3: "$(VAR3)
    #g++ -o $(VAR2) $(VAR1)
    @echo

PHONY: info
info:
    @printf "\n"
    @echo "JOIN: "$(JOIN)
    @printf "\n"

output

$ make

JOIN: f1.c_f1.o f2.cpp_f2.o f3.cpp_f3.o

TARGET: f1.c_f1.o
VAR1: f1.c
VAR2: f1.o
You can even substitute you loop variable VAR3: f1.x
#g++ -o f1.o f1.c

TARGET: f2.cpp_f2.o
VAR1: f2.cpp
VAR2: f2.o
You can even substitute you loop variable VAR3: f2.x
#g++ -o f2.o f2.cpp

TARGET: f3.cpp_f3.o
VAR1: f3.cpp
VAR2: f3.o
You can even substitute you loop variable VAR3: f3.x
#g++ -o f3.o f3.cpp
轻拂→两袖风尘 2024-08-13 06:26:39

一个简单的、独立于 shell/平台的纯宏解决方案是......

# GNU make (`gmake`) compatible; ref: <https://www.gnu.org/software/make/manual>
define EOL

$()
endef
%sequence = $(if $(word ${1},${2}),$(wordlist 1,${1},${2}),$(call %sequence,${1},${2} $(words _ ${2})))

.PHONY: target
target:
    $(foreach i,$(call %sequence,10),./a.out ${i}${EOL})

A simple, shell/platform-independent, pure macro solution is ...

# GNU make (`gmake`) compatible; ref: <https://www.gnu.org/software/make/manual>
define EOL

$()
endef
%sequence = $(if $(word ${1},${2}),$(wordlist 1,${1},${2}),$(call %sequence,${1},${2} $(words _ ${2})))

.PHONY: target
target:
    $(foreach i,$(call %sequence,10),./a.out ${i}${EOL})
自由如风 2024-08-13 06:26:39

这是动态范围的示例

default: all


.DEFAULT:
    for i in $(shell seq 1 $(RUN_COUNT)) ; do \
        echo "RUN_COUNT $i:" || exit 1; \
    done

使用 || exit 1 在按下 ctrl + c 时退出。它还将确保单个循环执行失败
将退出。 (在这个简单的示例中,这没有用。但如果您运行的命令可能会失败,这会很有帮助)。

使用 RUN_COUNT=10 make 调用

示例输出:

RUN_COUNT 1:
RUN_COUNT 2:
RUN_COUNT 3:
RUN_COUNT 4:
RUN_COUNT 5:
RUN_COUNT 6:
RUN_COUNT 7:
...

Here is an example with dynamic range

default: all


.DEFAULT:
    for i in $(shell seq 1 $(RUN_COUNT)) ; do \
        echo "RUN_COUNT $i:" || exit 1; \
    done

Use || exit 1 to exit when ctrl + c is pressed. It will also make sure that a single loop execution failure
will exit. (In this trivial example, this is not useful. But if you run a command that can fail, this is helpful).

Invoke using RUN_COUNT=10 make

Sample output:

RUN_COUNT 1:
RUN_COUNT 2:
RUN_COUNT 3:
RUN_COUNT 4:
RUN_COUNT 5:
RUN_COUNT 6:
RUN_COUNT 7:
...
孤蝉 2024-08-13 06:26:39

这个答案,就像 @Vroomfondel 的答案一样,旨在以一种优雅的方式规避循环问题。

我的做法是让 make 生成循环本身作为导入的 makefile,如下所示:

include Loop.mk
Loop.mk:Loop.sh
     Loop.sh > $@

shell 脚本可以像您喜欢的那样先进,但可以是一个

#!/bin/bash
LoopTargets=""
NoTargest=5
for Target in `seq $NoTargest` ; do
    File="target_${Target}.dat"
    echo $File:data_script.sh
    echo 

生成文件的

target_1.dat:data_script.sh
    ./data_script.ss 1
target_2.dat:data_script.sh
    ./data_script.ss 2
target_3.dat:data_script.sh
    ./data_script.ss 3
target_4.dat:data_script.sh
    ./data_script.ss 4
target_5.dat:data_script.sh
    ./data_script.ss 5


LoopTargets:= target_1.dat target_2.dat target_3.dat target_4.dat target_5.dat

最小工作示例,优点是make 本身可以跟踪哪些文件已生成以及哪些文件需要(重新)生成。因此,这还使 make 能够使用 -j 标志进行并行化。

\t'./data_script.ss $Target LoopTargets="$LoopTargets $File" done echo;echo;echo LoopTargets:=$LoopTargets

生成文件的

最小工作示例,优点是make 本身可以跟踪哪些文件已生成以及哪些文件需要(重新)生成。因此,这还使 make 能够使用 -j 标志进行并行化。

This answer, just as that of @Vroomfondel aims to circumvent the loop problem in an elegant way.

My take is to let make generate the loop itself as an imported makefile like this:

include Loop.mk
Loop.mk:Loop.sh
     Loop.sh > $@

The shell script can the be as advanced as you like but a minimal working example could be

#!/bin/bash
LoopTargets=""
NoTargest=5
for Target in `seq $NoTargest` ; do
    File="target_${Target}.dat"
    echo $File:data_script.sh
    echo 

which generates the file

target_1.dat:data_script.sh
    ./data_script.ss 1
target_2.dat:data_script.sh
    ./data_script.ss 2
target_3.dat:data_script.sh
    ./data_script.ss 3
target_4.dat:data_script.sh
    ./data_script.ss 4
target_5.dat:data_script.sh
    ./data_script.ss 5


LoopTargets:= target_1.dat target_2.dat target_3.dat target_4.dat target_5.dat

And advantage there is that make can itself keep track of which files have been generated and which ones need to be (re)generated. As such, this also enables make to use the -j flag for parallelization.

\t'./data_script.ss $Target LoopTargets="$LoopTargets $File" done echo;echo;echo LoopTargets:=$LoopTargets

which generates the file

And advantage there is that make can itself keep track of which files have been generated and which ones need to be (re)generated. As such, this also enables make to use the -j flag for parallelization.

脸赞 2024-08-13 06:26:39

这对我有用:

NUM=4

a-out:
    for (( i=1; i<=${NUM}; i++ )) \
    do \
        ./a.out $i ; \
    done

This worked for me:

NUM=4

a-out:
    for (( i=1; i<=${NUM}; i++ )) \
    do \
        ./a.out $i ; \
    done
桃酥萝莉 2024-08-13 06:26:39
#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. 
#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. 
请持续率性 2024-08-13 06:26:39

版本

代码

files := $(wildcard ./*.txt ./**/*.go */**/*.js )

showFileFunc = echo "$(abspath ${1})\${2}"
delFileFunc = del "$(abspath ${1})\${2}"
cmdSplit = &
targetDisplay:
    $(foreach curFile, ${files}, ${call showFileFunc,${dir $(curFile)},${notdir $(curFile)}} ${cmdSplit})
targetDelete:
    $(foreach curFile, ${files}, ${call delFileFunc,${dir $(curFile)},${notdir $(curFile)}} ${cmdSplit})

测试目录

Makefile

Version

Code

files := $(wildcard ./*.txt ./**/*.go */**/*.js )

showFileFunc = echo "$(abspath ${1})\${2}"
delFileFunc = del "$(abspath ${1})\${2}"
cmdSplit = &
targetDisplay:
    $(foreach curFile, ${files}, ${call showFileFunc,${dir $(curFile)},${notdir $(curFile)}} ${cmdSplit})
targetDelete:
    $(foreach curFile, ${files}, ${call delFileFunc,${dir $(curFile)},${notdir $(curFile)}} ${cmdSplit})

Test Directory

Makefile
????1.txt
???? myDir
   - ????foo.go
   - ????bar.go
   - ????subDir
     - ????qoo.js

Test CMD & output

make showFile -s

output:
"C:/...\1.txt"
"C:/.../myDir\bar.go"
"C:/.../myDir\foo.go"          // since `.//**.js`
"C:/.../myDir/subDir\qoo.js"   // `.//**.js` can't but `*/**/*.js` is OK

Reference

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文