【问题标题】:gnu make: how to automatically list and build all targetsgnu make:如何自动列出和构建所有目标
【发布时间】:2013-10-05 06:27:46
【问题描述】:

假设我有以下 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 -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 本身中。

嗯,make 在这里似乎很神秘。我发现最合理的解决方案是创建一个脚本并使用它:

$ 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

似乎不可能将其创建为制造目标,或者这方面的投资回报率非常低......

【问题讨论】:

标签: makefile


【解决方案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)*

【讨论】:

  • 您假设我的所有目标都称为示例。现在哪个好,当我开始有其他名字时会怎么样?
  • 它会尝试自己执行文件。
  • 对不起,我的错。我想现在我遇到了问题。检查新的编辑。
  • 您正在搜索 .h 文件,我正在尝试编译 .pas 文件。为什么要添加 .targets 这个词?最后,它只是回显文件列表,但不执行编译器
  • el_tenedor,您的解决方案现在可以很容易地在一个 make 文件中编译多个 pascal 程序,谢谢!
【解决方案2】:

我一直在用

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

应该做这项工作(这假设没有包含空格的目标名称)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-11
    • 1970-01-01
    • 1970-01-01
    • 2011-05-01
    • 2020-11-17
    • 2018-02-14
    • 1970-01-01
    相关资源
    最近更新 更多