【问题标题】:Makefile - Compile all sub directories and output .o files in a separate directoryMakefile - 编译所有子目录并在单独的目录中输出 .o 文件
【发布时间】:2018-09-26 13:05:51
【问题描述】:

我的 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 中执行等效任务?

【问题讨论】:

    标签: bash makefile compilation rules subdirectory


    【解决方案1】:

    这不是微不足道的,因为您的源代码位于不同的目录中,而简单的 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)
    

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

    EDIT(添加冲突检测):

    以下检测冲突情况并发出错误(将 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 在其字符串参数中返回以空格分隔的单词数)。

    【讨论】:

    • 我认为括号有一些问题。 OBJ 定义的末尾应该有一个额外的右括号,然后当我运行 make 时,它​​会显示“对函数 'patsubst' 的未终止调用:缺少 ')'。”但我不知道右括号在那个位置的确切位置。编辑:它在冒号之前,它可以工作,谢谢:)
    • 另外我没有考虑同名文件的情况。这将被其他人稍后使用,所以我需要考虑一下。不过现在这不是问题。
    • 抱歉缺少括号,我没有测试。它们应该在编辑后的答案中得到修复。关于名称冲突,有一种方法可以检测它们并发出警告或错误。但这是一个不同的问题。
    • 我终于找到了一些时间来添加冲突检测机制(见编辑的答案)。
    • 谢谢,太好了
    猜你喜欢
    • 2015-01-16
    • 2018-02-02
    • 1970-01-01
    • 2016-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-07
    • 2017-01-06
    相关资源
    最近更新 更多