我使用Makefiles.
我有一个目标run,它运行构建目标.简化后,它看起来如下:
prog: ....
...
run: prog
./prog
Run Code Online (Sandbox Code Playgroud)
坐下来.我知道这是巧妙的,但不需要起立鼓掌.
现在,我的问题是 - 有没有办法传递参数?以便
make run asdf --> ./prog asdf
make run the dog kicked the cat --> ./prog the dog kicked the cat
Run Code Online (Sandbox Code Playgroud)
谢谢!
Jak*_*org 234
我不知道如何完全按照您的意愿行事,但解决方法可能是:
run: ./prog
./prog ${ARGS}
Run Code Online (Sandbox Code Playgroud)
然后:
make ARGS="asdf" run
Run Code Online (Sandbox Code Playgroud)
Ide*_*lic 182
这个问题差不多有三年了,但无论如何......
如果你正在使用GNU make,这很容易做到.唯一的问题是make将命令行中的非选项参数解释为目标.解决方案是将它们变成无所事事的目标,所以make不要抱怨:
# If the first argument is "run"...
ifeq (run,$(firstword $(MAKECMDGOALS)))
# use the rest as arguments for "run"
RUN_ARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS))
# ...and turn them into do-nothing targets
$(eval $(RUN_ARGS):;@:)
endif
prog: # ...
# ...
.PHONY: run
run : prog
@echo prog $(RUN_ARGS)
Run Code Online (Sandbox Code Playgroud)
运行这个给出:
$ make run foo bar baz
prog foo bar baz
Run Code Online (Sandbox Code Playgroud)
Joh*_*ler 45
对于标准make,您可以通过定义这样的宏来传递参数
make run arg1=asdf
Run Code Online (Sandbox Code Playgroud)
然后像这样使用它们
run: ./prog $(arg1)
etc
Run Code Online (Sandbox Code Playgroud)
ken*_*orb 31
您可以将变量传递给Makefile,如下所示:
run:
@echo ./prog $$FOO
Run Code Online (Sandbox Code Playgroud)
用法:
$ make run FOO="the dog kicked the cat"
./prog the dog kicked the cat
Run Code Online (Sandbox Code Playgroud)
要么:
$ FOO="the dog kicked the cat" make run
./prog the dog kicked the cat
Run Code Online (Sandbox Code Playgroud)
或者使用Beta提供的解决方案:
run:
@echo ./prog $(filter-out $@,$(MAKECMDGOALS))
%:
@:
Run Code Online (Sandbox Code Playgroud)
用法:
$ make run the dog kicked the cat
./prog the dog kicked the cat
Run Code Online (Sandbox Code Playgroud)
les*_*ana 17
TL; DR不会尝试这样做
$ make run arg
Run Code Online (Sandbox Code Playgroud)
而是创建脚本:
#! /bin/sh
# rebuild prog if necessary
make prog
# run prog with some arguments
./prog "$@"
Run Code Online (Sandbox Code Playgroud)
这样做:
$ ./buildandrunprog.sh arg
Run Code Online (Sandbox Code Playgroud)
回答所述问题:
你可以在食谱中使用一个变量
run: prog
./prog $(var)
Run Code Online (Sandbox Code Playgroud)
然后将变量赋值作为参数传递给make
$ make run var=arg
Run Code Online (Sandbox Code Playgroud)
这将执行./prog arg.
但要小心陷阱.我将详细说明这种方法的缺陷以及其他方法.
回答问题背后的假设意图:
假设:您希望运行prog一些参数,但必须在运行之前重建它.
答案:创建一个脚本,必要时重建然后用args运行prog
#! /bin/sh
# rebuild prog if necessary
make prog
# run prog with some arguments
./prog "$@"
Run Code Online (Sandbox Code Playgroud)
这个脚本使意图非常明确.它使用make来做它有用的东西:建筑.它使用shell脚本来执行它的优点:批处理.
调用语法现在几乎完全相同:
$ ./buildandrunprog.sh foo "bar baz"
Run Code Online (Sandbox Code Playgroud)
相比于:
$ ./prog foo "bar baz"
Run Code Online (Sandbox Code Playgroud)
此外,您可以使用shell脚本的完全灵活性和表现力来执行您可能需要的任何其他操作,而无需makefile的所有注意事项.
背景:
make不是为运行目标而设计的,而是将参数传递给该目标.命令行上的所有参数都被解释为目标(也称为目标),选项或变量赋值.
所以如果你运行这个:
$ make run foo bar --wat var=arg
Run Code Online (Sandbox Code Playgroud)
make将解释run,foo并bar作为目标(目标)根据他们的食谱进行更新.--wat作为制造的选择.并var=arg作为变量赋值.
有关详细信息,请参阅:https://www.gnu.org/software/make/manual/html_node/Goals.html#Goals
对于术语,请参阅:https://www.gnu.org/software/make/manual/html_node/Rule-Introduction.html#Rule-Introduction
关于变量赋值方法以及我推荐它的原因
$ make run var=arg
Run Code Online (Sandbox Code Playgroud)
和食谱中的变量
run: prog
./prog $(var)
Run Code Online (Sandbox Code Playgroud)
这是将参数传递给配方的最"正确"和直接的方法.但是虽然它可以用来运行带有参数的程序,但它当然不是设计成以这种方式使用的.请参阅https://www.gnu.org/software/make/manual/html_node/Overriding.html#Overriding
在我看来,这有一个很大的缺点:你想做的是prog用参数运行arg.但不是写作:
$ ./prog arg
Run Code Online (Sandbox Code Playgroud)
你在写:
$ make run var=arg
Run Code Online (Sandbox Code Playgroud)
当尝试传递包含空格的多个参数或参数时,这会变得更加尴尬:
$ make run var="foo bar\ baz"
./prog foo bar\ baz
argcount: 2
arg: foo
arg: bar baz
Run Code Online (Sandbox Code Playgroud)
相比于:
$ ./prog foo "bar baz"
argcount: 2
arg: foo
arg: bar baz
Run Code Online (Sandbox Code Playgroud)
为了记录这是我的prog样子:
#! /bin/sh
echo "argcount: $#"
for arg in "$@"; do
echo "arg: $arg"
done
Run Code Online (Sandbox Code Playgroud)
请注意,当您$(var)在makefile中输入引号时:
run: prog
./prog "$(var)"
Run Code Online (Sandbox Code Playgroud)
然后prog总会得到一个参数:
$ make run var="foo bar\ baz"
./prog "foo bar\ baz"
argcount: 1
arg: foo bar\ baz
Run Code Online (Sandbox Code Playgroud)
所有这些都是我推荐这条路线的原因.
为了完整性,这里有一些"传递参数来运行"的其他方法.
方法1:
run: prog
./prog $(filter-out $@, $(MAKECMDGOALS))
%:
@true
Run Code Online (Sandbox Code Playgroud)
超短解释:从目标列表中筛选出当前目标.create catch all target(%),它不会无声地忽略其他目标.
方法2:
ifeq (run, $(firstword $(MAKECMDGOALS)))
runargs := $(wordlist 2, $(words $(MAKECMDGOALS)), $(MAKECMDGOALS))
$(eval $(runargs):;@true)
endif
run:
./prog $(runargs)
Run Code Online (Sandbox Code Playgroud)
超短解释:如果目标是run删除第一个目标并创建为剩余目标创建任何目标使用eval.
为了更深入的解释研究制作手册:https://www.gnu.org/software/make/manual/html_node/index.html
方法1的问题:
以破折号开头的参数将由make解释,而不是作为目标传递.
$ make run arg1 arg2
Run Code Online (Sandbox Code Playgroud)
解决方法
$ make run --foo --bar
Run Code Online (Sandbox Code Playgroud)如果一个参数碰巧run(等于目标),它也将被删除
$ make run -- --foo --bar
Run Code Online (Sandbox Code Playgroud)
将运行./prog foo bar而不是./prog foo bar run
方法2可能的解决方法
如果参数是合法目标,它也将被运行.
$ make run foo=bar
Run Code Online (Sandbox Code Playgroud)
将运行,./prog foo bar clean但也是目标的配方clean(假设它存在).
方法2可能的解决方法
用空格传递参数很尴尬
$ make run foo "bar\ baz"
Run Code Online (Sandbox Code Playgroud)
没有解决方法
当你错误输入一个合法的目标时,由于捕获所有目标,它将被默默地忽略.
$ make run foo bar run
Run Code Online (Sandbox Code Playgroud)
只会默默地忽略celan.
解决方法是让一切都变得冗长.所以你看看会发生什么.但这会给合法输出带来很多噪音.
方法2的问题:
如果参数与现有目标具有相同的名称,那么make将打印一条警告,表明它已被覆盖.
没有我知道的解决方法
用空格传递参数仍然很尴尬.
没有解决方法
eval尝试创建空间中断的参数不做任何目标.
解决方法:创建全局捕获所有目标,如上所述.如上所述,它将再次默默地忽略错误的合法目标.
它用于eval在运行时修改makefile.在可读性和可调试性以及最小惊讶原则方面你能走多远.
解决方法:不要这样做!! 1而是编写一个运行make然后运行的shell脚本prog.
我只测试过使用gnu make.其他品牌可能会有不同的行为.
TL; DR不会尝试这样做
$ make run foo bar clean
Run Code Online (Sandbox Code Playgroud)
而是创建脚本:
$ make celan
Run Code Online (Sandbox Code Playgroud)
这样做:
$ make run arg
Run Code Online (Sandbox Code Playgroud)
djc*_*djc 12
这是另一个可以帮助解决其中一些用例的解决方案:
test-%:
$(PYTHON) run-tests.py $@
Run Code Online (Sandbox Code Playgroud)
换句话说,选择一些前缀(test-在这种情况下),然后将目标名称直接传递给程序/运行器.我想如果涉及一些可以将目标名称解包为对底层程序有用的东西的转子脚本,这大部分都是有用的.
不.查看GNU make手册页的语法
make [-f makefile] [options] ... [targets] ......
你可以指定多个目标,因此'不'(至少没有你指定的确切方式).
run: ./prog看起来有点奇怪,因为正确的部分应该是先决条件,所以run: prog看起来更好。
我简单地建议:
.PHONY: run
run:
prog $(arg1)
Run Code Online (Sandbox Code Playgroud)
我想补充一点,可以传递参数:
make arg1="asdf" runarg1="asdf" make run小智 6
您可以在命令行中显式提取每个第 n 个参数。为此,您可以使用 variable MAKECMDGOALS,它保存提供给“make”的命令行参数列表,它将其解释为目标列表。如果要提取第n个参数,可以将该变量与“word”函数结合使用,例如,如果要提取第二个参数,则可以将其存储在变量中,如下所示:
second_argument := $(word 2, $(MAKECMDGOALS) )
Run Code Online (Sandbox Code Playgroud)
对此并不太自豪,但我不想传递环境变量,所以我反转了运行预设命令的方式:
run:
@echo command-you-want
Run Code Online (Sandbox Code Playgroud)
这将打印您想要运行的命令,因此只需在子 shell 中对其进行评估即可:
$(make run) args to my command
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
189260 次 |
| 最近记录: |