用两个词设定目标

用两个词设定目标

我正在使用 Makefile 来编译我的干净的代码。我的 Clean 文件具有以下格式的文件名*.icl,并编译为具有相同名称但不带.icl.这是通过以下规则完成的:

$(EXE): % : %.icl | copy
    $(CLM) $(CLM_LIBS) $(CLM_INC) $(CLM_OPTS) $@ -o $@

我现在想添加一条允许我运行二进制文件的规则。目前,我经常做

make some_module && ./some_module

我想要一个依赖于上述规则并运行模块的 make 目标。但是,模块的名称本身已经是单独编译的目标,我想保持这种状态。我想要的是一个带有两个单词的目标,我可以用它来调用make run some_module它,然后取决于上面的规则并./some_module随后运行。

是否可以创建包含多个单词的目标?

我尝试制定一条规则(现在仍然没有依赖性),如下所示:

run $(EXE):
    ./$@

运行make run some_module会导致许多配方被“覆盖”和“忽略”,最终./run不存在。

Makefile:24: warning: overriding recipe for target 'tut7_2_2'
Makefile:21: warning: ignoring old recipe for target 'tut7_2_2'
Makefile:24: warning: overriding recipe for target 'support_check'
Makefile:21: warning: ignoring old recipe for target 'support_check'
[...]
Makefile:24: warning: overriding recipe for target 'drawingframe'
Makefile:21: warning: ignoring old recipe for target 'drawingframe'
./run
/bin/bash: ./run: No such file or directory
Makefile:24: recipe for target 'run' failed
make: *** [run] Error 127

答案1

你也许可以使用$(MAKECMD目标)强制run在命令行中指定的其他目标中最后执行。下面的例子使用C,因为我不知道Clean。

EXE = a b c

%: %.c
    $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS)

all: $(EXE)

clean:
    rm -f $(EXE)

run: $(filter-out run, $(MAKECMDGOALS))
    @for i in $^; do ./$$i; done

.PHONY: all clean run

make run program可能看起来有点笨拙,因为它总是产生不必要的输出program is up to date

$ cat a.c
#include <stdio.h>
int main(int argc, char **argv) { printf("This is %s\n", argv[0]); return 0; }
$ cp a.c b.c
$ cp a.c c.c

$ make run a b
cc  -o a a.c
cc  -o b b.c
This is ./a
This is ./b
make: 'a' is up to date.
make: 'b' is up to date.

make program run没有这样的输出,它可能像英语一样更自然。

$ make c run
cc  -o c c.c
This is ./c

答案2

你可以检查MAKECMDGOALS在建立另一个目标的同时检测一个目标的存在。要么让%: %.icl运行检测目标的存在run,要么让run目标检查哪些可执行文件被称为目标。如果您传递多个可执行文件作为目标,第一个方法会导致每个文件在构建后立即运行,而第二个方法会导致所有运行在最后发生。

这种方法的缺点是它不能很好地与其他功能一起扩展。例如,如果您定义一个具有多个可执行文件作为依赖项的目标,则具有run目标的方法将不起作用。

EXE = foo bar experimental
released: foo bar
run: $(filter $(EXE), $(MAKECMDGOALS))
        set -e; for x in $^; do ./$x; done

这里make released run不会运行任何东西。

对于这种情况,我通常做的是为每个可执行文件定义一个“运行”目标。这使得每个目标都表达为单个单词,这是一个主要优点。它很简单并且不会破坏其他功能。

$(EXE): %.run: %
        ./$(@:.run=)
all.run: $(EXE:=.run)

make {foo,bar}.run然后,如果我想构建并测试foobar,或者make all.run构建并运行它们,我就运行它们。

相关内容