Makefile-编译所有子目录并在单独目录中输出.o文件

时间:2018-09-26 13:05:52

标签: bash makefile compilation rules subdirectory

我的bash脚本中有此命令

find . -type f -name "*.c" -execdir bash -c "f={}; kos-cc $KOS_CFLAGS -c {} -o $PWD/\${f%.c}.o" \;

它的工作是递归地在当前目录($ PWD)中搜索.c文件,用我的“ kos-cc”编译器进行编译,然后将所有.o文件输出到当前工作目录中。

我想将我的bash脚本的一部分移到一个makefile中,这行是最后一个使我难堪的行。我知道如何制定规则来编译目录A中的c文件并将.o文件输出到目录B中,但是这里目录A并不总是相同的(因为我也需要处理子目录)。如何使用规则或命令在Makefile中执行等效任务?

1 个答案:

答案 0 :(得分:0)

这不是一件容易的事,因为您的源位于不同的目录中,简单的make模式规则无法轻松地处理此问题。但是使用slightly more advanced make features可以做到:

SRC := $(shell find . -type f -name "*.c")
OBJ := $(patsubst %.c,%.o,$(notdir $(SRC)))

.PHONY: all    
all: $(OBJ)

define COMPILE_rule
$$(patsubst %.c,%.o,$$(notdir $(1))): $(1)
    kos-cc $$(KOS_CFLAGS) -c -o $$@ $$<
endef
$(foreach s,$(SRC),$(eval $(call COMPILE_rule,$(s))))

.PHONY: clean
clean:
    rm -f $(OBJ)

当心:您可能在不同目录中有多个具有相同基本名称的源文件。如果发生这种情况,最终将导致对象文件名的致命冲突...

编辑(添加冲突检测):

以下内容可检测到冲突情况并发出错误消息(将error替换为warninginfo,具体取决于您为这些冲突分配的严重性级别):

SRC := $(shell find . -type f -name "*.c")
OBJ := $(patsubst %.c,%.o,$(notdir $(SRC)))

ifneq ($(words $(OBJ)),$(words $(sort $(OBJ))))
$(error object file name conflicts detected)
endif

({sort进行排序并删除重复项,words返回其字符串参数中以空格分隔的单词数)。