Makefile - 编译所有子目录并在单独的目录中输出 .o 文件
Makefile - Compile all sub directories and output .o files in a separate directory
我的 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 中执行等效任务?
这不是微不足道的,因为您的源代码位于不同的目录中,简单的 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
替换为 warning
或 info
):
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
returns 其字符串参数中 space 分隔的单词数)。
我的 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 中执行等效任务?
这不是微不足道的,因为您的源代码位于不同的目录中,简单的 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
替换为 warning
或 info
):
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
returns 其字符串参数中 space 分隔的单词数)。