GNU Make:如何自动列出和构建所有目标

9

假设我有以下的Makefile:

RM = rm -f
FLAGS =  -Cr -O1 -gv -gw -g -vw
builddir = ./build/
TD = ./tasks/

all: example1 example3 example5

example1:  

    fpc 01_Kreisumfang.pas $(FLAGS) -o$(builddir)01_Kreisumfang

example3:

    fpc 03_EuroBetrag3.pas $(FLAGS) -o$(builddir)03_EuroBetrag3

example5:

    fpc 05_Dreiecke.pas $(FLAGS) -o$(builddir)05_Dreieck

clean:

    $(RM) $(builddir)*

在某个时候,我的 Makefile 变得越来越大,例如 example112 ...,有没有一种方法可以自动定义所有目标,而不需要手动输入所有的目标?我不想这样做:
all: example1 example3 example5 ... example112

我可以像这样做吗?
all: (MAGIC to Exclude clean)?

因此,我希望make能够检测所有目标并排除特定列表,而不必手动输入所有目标。

更新:

我找到了以下可能的线索:

 make -rpn | sed -n -e '/^$/ { n ; /^[^ ]*:/p }' |egrep -v -E '(all|clean)' 

我不知道如何将这个单独作为目标,我已经尝试过以下方法:

TARGETS =: $(shell make -rpn | sed -n -e '/^$$/ { n ; /^[^ ]*:/p }' |egrep -v -E '(all|clean)')

但是它似乎是错误的。不仅如此,它还会引起愚蠢的递归调用。

因此,这个解决方案只能作为一个Shell命令使用,不能在Makefile本身内部使用。

好吧,看起来Makefile非常神秘。我发现最合理的解决方案是创建一个脚本并使用它:

$ cat doall.sh 
#!/bin/bash
for i in `make -rpn | sed -n -e '/^$/ { n ; /^[^ ]*:/p }' | sed -e 's/://' | egrep -v -E '(all|clean)'`; 
    do make $i; 
done

似乎不可能将其创建为make目标,或者这个投资回报率非常低...


可能是重复的问题:如何在Makefile中获取目标列表? - Shimon Rachlenko
您需要在Makefile中复制任何字面上的美元符号。 - tripleee
@tripleee,即使我改变了那个,仍然无法避免 make 调用自身... 你会怎么做? - oz123
2个回答

1
我使用了一个for循环来尝试这个。看看这个简单的例子是否适合你。这个命令来自this的帖子。
RM = rm -f
FLAGS =  -Cr -O1 -gv -gw -g -vw
builddir = ./build/
TD = ./tasks/
SHELL := /bin/bash

targets=$(shell for file in `find . -name '*.pas' -type f -printf "%f\n" | sed 's/\..*/\.out/'`; do echo "$$file "; done;)

all: $(targets)

%.out:%.pas
  fpc $< $(FLAGS) -o (builddir)$@

clean:
    $(RM) $(builddir)*

你假设我所有的目标都叫做example。现在这样还好,但是当我开始有其他名称时会怎么样? - oz123
它将尝试执行文件本身。 - oz123
抱歉,是我的错。我现在认为我找到了问题所在。请查看新的编辑。 - el_tenedor
你在寻找.h文件,而我正在尝试编译.pas文件。为什么要添加.targets这个词?最后,它只是回显文件列表,但并没有执行编译器。 - oz123
el_tenedor,你的解决方案现在使得将许多Pascal程序编译到一个make文件中变得容易了,谢谢! - oz123

0

我一直在使用

make -qp | awk -F':' '/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ {split($1,A,/ /);for(i in A)print A[i]}'     

(保存为make-t)列出所有目标。

如果您想构建所有真实目标,则获取所有非虚拟目标的列表:

make -qp | grep -P '^[.a-zA-Z0-9][^$#\/\t=]*:([^=]|$)' |
tee >(cut -d: -f1 ) >(grep '^\s*\.PHONY\s*:' |cut -d: -f2) >/dev/null|
tr ' ' '\n' | sed '/^\s*\./ d; /^\s*$/ d' |sort |uniq -u

应该可以完成任务(假设目标名称中没有空格)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接