Makefile 将论点传递给;“使运行”;

Makefile 将论点传递给;“使运行”;,makefile,Makefile,我使用makefile 我有一个名为run的目标,它运行构建目标。简化后,它看起来如下所示: prog: .... ... run: prog ./prog 有什么方法可以传递参数吗?所以 make run asdf --> ./prog asdf make run the dog kicked the cat --> ./prog the dog kicked the cat 谢谢 对于标准make,可以通过如下定义宏来传递参数 make run arg1=asdf

我使用makefile

我有一个名为
run
的目标,它运行构建目标。简化后,它看起来如下所示:

prog: ....
  ...

run: prog
  ./prog
有什么方法可以传递参数吗?所以

make run asdf --> ./prog asdf
make run the dog kicked the cat --> ./prog the dog kicked the cat

谢谢

对于标准make,可以通过如下定义宏来传递参数

make run arg1=asdf
run: ./prog $(arg1)
   etc
$ make run arg1 arg2
然后像这样使用它们

make run arg1=asdf
run: ./prog $(arg1)
   etc
$ make run arg1 arg2
参考
Microsoft的

我不知道如何准确地实现您的目标,但解决方法可能是:

run: ./prog
    ./prog $(ARGS)
然后:


否。请查看GNU make手册页中的语法

make[-f makefile][options]。。。[目标]


您可以指定多个目标,因此“否”(至少以您指定的确切方式为否)。

run:./prog
看起来有点奇怪,因为右侧部分应该是目标,所以
run:prog
看起来更好

我只建议:

.PHONY: run

run:
    prog $(arg1)
我想补充一点,可以传递参数:

  • 作为参数:
    make arg1=“asdf”run
  • 或定义为环境:
    arg1=“asdf”使运行

  • 这个问题已经问了三年了,但无论如何

    如果您使用的是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)
    
    运行此命令将提供:

    $ make run foo bar baz
    prog foo bar baz
    

    这是我的例子。请注意,我是在Windows 7下编写的,使用的是Dev Cpp附带的mingw32-make.exe。(我有c:\Windows\System32\make.bat,因此该命令仍然称为“make”。)

    定期清洁的用法:

    make clean
    
    在mydir/中清理和创建备份的用法:

    make clean backup=mydir
    

    下面是另一个解决方案,它可以帮助解决其中一些用例:

    test-%:
        $(PYTHON) run-tests.py $@
    

    换句话说,选择一些前缀(
    test-
    ,在本例中),然后将目标名称直接传递给程序/运行程序。我想如果涉及到一些运行程序脚本,可以将目标名称展开为对底层程序有用的内容,那么这将非常有用。

    您可以将变量传递到Makefile,如下所示:

    run:
        @echo ./prog $$FOO
    
    用法:

    $ make run FOO="the dog kicked the cat"
    ./prog the dog kicked the cat
    
    $ make run the dog kicked the cat
    ./prog the dog kicked the cat
    
    或:


    或者使用以下提供的解决方案:

    -与任何任务名称匹配的规则; -空配方=什么也不做

    用法:

    $ make run FOO="the dog kicked the cat"
    ./prog the dog kicked the cat
    
    $ make run the dog kicked the cat
    ./prog the dog kicked the cat
    

    可以在命令行中显式提取每个第n个参数。为此,您可以使用变量
    MAKECMDGOALS
    ,它保存给定给“make”的命令行参数列表,并将其解释为目标列表。如果要提取第n个参数,可以将该变量与“word”函数结合使用,例如,如果要提取第二个参数,可以将其存储在变量中,如下所示:

    second_argument := $(word 2, $(MAKECMDGOALS) )
    

    对此不太自豪,但我不想传入环境变量,所以我改变了运行一个固定命令的方式:

    run:
        @echo command-you-want
    
    这将打印您要运行的命令,因此只需在子shell中对其求值:

    $(make run) args to my command
    

    TL;博士,别这么做

    $ make run arg
    
    而是创建脚本
    build\u和\u run\u prog.sh

    #! /bin/sh
    # rebuild prog if necessary
    make prog
    # run prog with some arguments
    ./prog "$@"
    
    这样做:

    $ ./build_and_run_prog.sh arg
    
    请继续阅读,了解为什么这是最合理的选择,以及为什么最好避免其他选择


    对所述问题的回答:如何将参数传递给make目标

    您可以在配方中使用变量

    run: prog
        ./prog $(var)
    
    run: prog
        ./prog $(var)
    
    然后将变量赋值作为参数传递给make

    $ make run var=arg
    
    这将执行
    /prog arg

    但要小心陷阱。我将在下面进一步阐述这种方法和其他方法的缺陷


    回答问题背后的假设意图:您希望运行带有一些参数的
    prog
    ,但如有必要,请在运行之前重新生成它

    创建一个脚本,必要时进行重建,然后使用args运行prog

    构建和运行程序sh

    #! /bin/sh
    # rebuild prog if necessary
    make prog
    # run prog with some arguments
    ./prog "$@"
    
    run: prog
        ./prog $(filter-out $@, $(MAKECMDGOALS))
    
    %:
        @true
    
    ifeq (run, $(firstword $(MAKECMDGOALS)))
      runargs := $(wordlist 2, $(words $(MAKECMDGOALS)), $(MAKECMDGOALS))
      $(eval $(runargs):;@true)
    endif
    
    run:
        ./prog $(runargs)
    
    这个脚本使意图非常清楚。它使用make来做它有好处的事情:建筑。它使用一个shell脚本来做它所擅长的事情:批处理

    此外,您还可以使用shell脚本的充分灵活性和表达能力来执行任何可能需要的操作,而不需要makefile的所有警告

    此外,调用语法现在实际上是相同的:

    $ ./build_and_run_prog.sh foo "bar baz"
    
    与之相比:

    $ ./prog foo "bar baz"
    
    对比

    $ make run var="foo bar\ baz"
    

    make如何处理参数的背景说明

    #! /bin/sh
    # rebuild prog if necessary
    make prog
    # run prog with some arguments
    ./prog "$@"
    
    run: prog
        ./prog $(filter-out $@, $(MAKECMDGOALS))
    
    %:
        @true
    
    ifeq (run, $(firstword $(MAKECMDGOALS)))
      runargs := $(wordlist 2, $(words $(MAKECMDGOALS)), $(MAKECMDGOALS))
      $(eval $(runargs):;@true)
    endif
    
    run:
        ./prog $(runargs)
    
    Make不是为向目标传递参数而设计的。命令行上的所有参数都被解释为目标(也称为目标)、选项或变量赋值

    因此,如果您运行以下命令:

    $ make run foo --wat var=arg
    
    make将
    run
    foo
    解释为目标(targets),根据它们的食谱进行更新<代码>--wat作为make的一个选项。和
    var=arg
    作为变量赋值

    有关更多详细信息,请参阅:

    还有


    为什么我不建议变量赋值

    $ make run var=arg
    
    以及配方中的变量

    run: prog
        ./prog $(var)
    
    run: prog
        ./prog $(var)
    
    这是将参数传递给配方的最“正确”和最直接的方法。但是,虽然它可以用来运行一个带有参数的程序,但它肯定不是设计用来这样使用的。见

    在我看来,这有一个很大的缺点:您要做的是使用参数
    arg
    运行
    prog
    。但不是写:

    $ ./prog arg
    
    你在写:

    $ make run var=arg
    
    当尝试传递多个参数或包含空格的参数时,这会变得更加尴尬:

    $ make run var="foo bar\ baz"
    ./prog foo bar\ baz
    argcount: 2
    arg: foo
    arg: bar baz
    
    与之相比:

    $ ./prog foo "bar baz"
    argcount: 2
    arg: foo
    arg: bar baz
    
    作为记录,这是我的
    prog
    的样子:

    #! /bin/sh
    echo "argcount: $#"
    for arg in "$@"; do
      echo "arg: $arg"
    done
    
    还请注意,您不应在makefile中的引号中添加
    $(var)

    run: prog
        ./prog "$(var)"
    
    因为
    prog
    总是只得到一个参数:

    $ make run var="foo bar\ baz"
    ./prog "foo bar\ baz"
    argcount: 1
    arg: foo bar\ baz
    
    这就是我反对这条路线的原因


    为了完整起见,这里还有一些“传递参数以使其运行”的其他方法

    方法1

    #! /bin/sh
    # rebuild prog if necessary
    make prog
    # run prog with some arguments
    ./prog "$@"
    
    run: prog
        ./prog $(filter-out $@, $(MAKECMDGOALS))
    
    %:
        @true
    
    ifeq (run, $(firstword $(MAKECMDGOALS)))
      runargs := $(wordlist 2, $(words $(MAKECMDGOALS)), $(MAKECMDGOALS))
      $(eval $(runargs):;@true)
    endif
    
    run:
        ./prog $(runargs)
    
    从目标列表中筛选出当前目标。创建catch-all目标(
    %
    ),该目标不做任何事情来默默地忽略另一个goa
    --xyz-enabled=false
    
    # the other technique to invalidate other targets is still required, see linked post
    run:
        @echo ./prog $(-*-command-variables-*-) $(filter-out $@,$(MAKECMDGOALS))`
    
    make run -- config --xyz-enabled=false over=9000 --foo=bar show  isit=alwaysreversed? --help
    
    ./prog isit=alwaysreversed? --foo=bar over=9000 --xyz-enabled=false config show --help
    
    MAKEFLAGS =  -- isit=alwaysreverse? --foo=bar over=9000 --xyz-enabled=false
    MAKEOVERRIDES = isit=alwaysreverse? --foo=bar over=9000 --xyz-enabled=false