【问题标题】:How to build multiple targets with similar name?如何构建具有相似名称的多个目标?
【发布时间】:2017-07-28 11:47:19
【问题描述】:

所以我的问题与下面的问题完全相同,但没有人回答。

Pattern matching Makefile with multiple executable targets

我正在尝试构建一系列小测试文件,每个文件都有一个“test*.c”模式来测试我的库。

我想编写一个生成文件,它可以同时为每个测试文件(每个名称:test1、test2、test3..等)构建可执行文件。但是,我不确定如何实现这一目标。 到目前为止,我有以下内容:

SRC := $(shell find *.c)
ALL_PROG := $(patsubst %.c, %, *.c)
.PHONY: all

all: $(ALL_PROG)

$(ALL_PROG): $(SRC)
    -gcc $< -o $@

这是一个糟糕的尝试,因为目标将所有 .c 文件作为依赖项,这导致了循环依赖。

使用 shell 脚本可以很容易地完成这项工作,但我想知道是否有办法完成同样的工作。

提前致谢。

【问题讨论】:

    标签: c unix makefile gnu-make gnu


    【解决方案1】:

    使用$(ALL_PROG): %: %.c 而不是$(ALL_PROG): $(SRC)


    这是一个我可能在 GNU make 中使用的 Makefile 示例:

    CC      := gcc
    CFLAGS  := -Wall -O2
    LDFLAGS := -lm
    PROGS   := $(patsubst %.c, %, $(wildcard *.c))
    
    .PHONY: all clean test $(patsubst %, test@%, $(PROGS))
    
    all: $(PROGS)
    
    clean:
        rm -f $(PROGS)
    
    $(PROGS): %: %.c
        $(CC) $(CFLAGS) $^ $(LDFLAGS) -o $@
    
    $(patsubst %, test@%, $(PROGS)): test@%: %
        ./$^
    
    test: $(patsubst %, test@%, $(PROGS))
    

    像往常一样,注意缩进应该使用 Tab 而不是空格; stackoverflow.com 上使用的编辑器会自动将它们转换为空格。

    PROGS 变量将包含目录中所有*.c 文件的名称。

    .PHONY: 指令告诉 Make 哪些目标不引用实际文件。 $(patsubst %, test@%, $(PROGS)) 扩展为可执行文件名称列表,每个名称都以test@ 开头:如果目录包含文件foo.cbar.c,则扩展为test@foo test@bar

    $(PROGS): %: %.c 配方将每个 .c 文件编译为相应的二进制文件。

    $(patsubst %, test@%, $(PROGS)): test@%: % 配方为每个二进制文件创建一个测试目标。如果我们有文件foo.cbar.c,则此规则扩展为test@foo test@bar: test@%: %。这意味着对于test@footest@bar 目标,对应的test@% 目标需要% 二进制文件。 ./$^ 又扩展为 ./%,因此是二进制名称。 (如果您不想让 Make 显示正在运行的命令,请使用 @./$^。如果您不在乎测试是否失败,请使用 -./$^。)

    test 配方扩展为 test@foo test@bar 如果我们有 foo.cbar.c;即所有可能的测试目标。

    可以运行make clean test重新编译目录下所有.c文件,并执行。

    如果你只关心一个特定的测试程序,比如foo.c,你可以运行make test@foo,如果foo.cfoo更新,它将重新编译程序。

    【讨论】:

    • 只是想澄清一下,“$(patsubst %, test@%, $(PROGS)): test@%: %” 表示模式产生的每个目标,每个目标(test@ %) 需要 (%)。所以第二个冒号表示依赖关系,但是第一个冒号的正式含义是什么(命名?)有没有你可以指导我的来源?这是我第一次看到两个冒号。非常感谢。
    • @J.S.M:它是targets: target-pattern: prerequisite-pattern,如GNU make documentation 中所述。每当我编写 Makefiles 时,我都会保持一个浏览器窗口打开到 single-page version of GNU make documentation
    • 非常感谢您的意见
    【解决方案2】:

    你可以这样做。我正在更新一个构建多个目标的简单 make 文件。您可以根据需要进行修改。

    TEST1       = test1.exe
    TEST2       = test2.exe
    
    ### Executable Program Files ###
    
    all : $(TEST1) $(TEST2)
    
    $(TEST1) : test1.c
        gcc -o $(TEST1) test1.c 
    
    $(TEST2) : test2.c
        gcc -o $(TEST2) test2.c 
    

    【讨论】:

    • 谢谢,这将适用于少量测试;但是,我想做的是构建一系列测试,比如 20 个或更多。这就是为什么,我想知道是否可以编写一个模式规则来构建更多测试,而无需编写单独的规则。
    猜你喜欢
    • 1970-01-01
    • 2014-09-30
    • 1970-01-01
    • 1970-01-01
    • 2011-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-30
    相关资源
    最近更新 更多