4

我有许多源目录的项目。但是需要将所有 .obj 文件保存在一个平面目录中,例如

  • src1
  • src2
  • src3
    • src4
    • src5
      • src6
      • src7
  • src8
  • 对象
  • 生成文件

我有所有源文件及其所在目录的列表。使用 make 版本 3.81,我使用了混合的隐式和普通规则,但使用 make 3.82 我无法做到这一点。目标不是只使用 shell 命令来制作内置函数。

OBJECTS = $(subst .c,.o,$(SRCS))
OBJECTS_OBJ = $(patsubst %.c,$(OBJ_DIR)/%.o,$(notdir $(SRCS)))

SRCDIR = $(dir $(SRCS))

vpath %.c $(SRCDIR)

   ...

$(OBJ_DIR) $(OBJ_DIR)/%.o : %.c
    @echo "======================================================================="
    @echo "COMPILATION:" $< " --> " $@
    @echo "======================================================================="
    @mkdir -p $(dir $@)
    $(CC) $(C_FLAGS) $(INCL) $< -c -o $@

其中 SRCS 是所有源文件的列表。

是否可以在不使用递归 makefile 或不使用 shell 命令的情况下实现它。

4

1 回答 1

0

只需包含一个创建显式依赖项的 makefile:

# Makefile
OBJ_DIR:=objects
SRC_FILES := $(notdir $(SRCS))

all: $(SRC_FILES:%.c=$(OBJ_DIR)/%.o)

tmp_srcs := $(SRCS)

include $(foreach dummy, $(SRCS), object_rule.mk)

$(OBJ_DIR)/.sentinel:
    mkdir -p $(dir $@) && touch $@

诀窍在于 include 语句和 foreach 的组合。foreach 将生成与 SRCS 中列出的文件一样多的“object_rule.mk”。包含的 makefile,object_rule.mk 只是为相应的源文件生成对象规则,如下所示:

ifeq (,$(tmp_srcs))
$(error this makefile requires the variable tmp_srcs to be set)
endif

src_path:=$(word 1, $(tmp_srcs))
ifeq (1, $(words $(tmp_srcs)))
tmp_srcs:=
else
tmp_srcs:=$(wordlist 2, $(words $(tmp_srcs)), $(tmp_srcs))
endif

src_file:=$(notdir $(src_path))
obj_file:=$(src_file:%.c=%.o)

$(OBJ_DIR)/$(obj_file): $(src_path) $(OBJ_DIR)/.sentinel
        $(CC) $(C_FLAGS) $(INCL) $< -c -o $@

请注意,我已向 $(OBJ_DIR)/.sentinel 添加了一个依赖项,以实现正确和准确的依赖项。

此解决方案不需要手工制作。您可能会使用GNU Make 标准库

于 2013-09-06T09:26:04.287 回答