使用GNU Make迭代文件目录

时间:2016-05-05 23:41:14

标签: c makefile gnu-make

我的项目有一个名为tests/的目录,其中包含任意数量的C源文件,每个文件都是一个用于测试库的自包含程序。对于每个源文件,我想在我的build/目录中创建一个同名的可执行文件。

E.g。 tests/test_init.c将编译为可执行文件build/test_init

目前,我的Makefile代码段如下所示:

BUILD_DIR = build
TEST_DIR = tests

test_sources:= $(TEST_DIR)/*.c
test_executables:= $(patsubst %.c, %, $(test_sources))

.PHONY: tests

tests: $(test_executables)
    $(CC) $^ -o $@ -g

但是这不能产生预期的结果。任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:2)

首先,您需要wildcard function来查找来源:

test_sources:= $(wildcard $(TEST_DIR)/*.c)

然后是可执行文件的正确名称:

test_executables:= $(patsubst $(TEST_DIR)/%.c, $(BUILD_DIR)/%, $(test_sources))

然后使用pattern rule从相应的源构建测试可执行文件:

$(BUILD_DIR)/%: $(TEST_DIR)/%.c
    $(CC) $< -o $@ -g

(A static pattern rule可能有点整洁,但它是一种更高级的方法。)

最后建立phony目标来构建所有测试:

.PHONY: tests
tests: $(test_executables)

如果您希望Make 运行所有这些测试,您可以制作虚假模式规则run_test_%,但这可以等待另一天。

答案 1 :(得分:0)

此Makefile将检测test/*.c中的所有文件,并提供build_testsrun_testsclean_tests任务。

all: build_tests

define test_template

build_tests: test/$(1)

run_tests: build_tests run_test_$(1)

test/$(1) : test/$(1).c
    $$(CC) $$^ -o $$@

.PHONY : run_test_$(1)
run_test_$(1) : test/$(1)
    test/$(1)

endef

clean: clean_tests

clean_tests:
    rm -fv $(foreach test, $(tests),test/$(test))

# Auto detect the tests (any .c file in the test directory),
# and store the list of tests names.
tests := $(foreach test, $(wildcard test/*.c),$(patsubst %.c,%,$(notdir $(test))))

# Add information about each test to the Makefile.
$(foreach test, $(tests), $(eval $(call test_template,$(test))))

注意:我不确定如何在markdown中的代码块中使标签工作,因此如果您复制并粘贴此标记,则需要在每个缩进行中使用单个标签替换空格。< / p>