【问题标题】:Using Static Pattern Rule causes single source change to rebuild all使用静态模式规则会导致单个源更改重建所有
【发布时间】:2020-01-13 21:55:58
【问题描述】:

我正在尝试修复由于缺乏对 .c 源文件的依赖而导致当前无法检测到源文件更改的 Makefile。我已经实现了一个静态模式规则,但是当单个源文件更改时,它无法重建单个目标文件。它将重建所有更改。

我有以下几点:

ARCHITECTURE_DIR = arm
BUILD_DIR = build
OUTPUT_DIR = $(BUILD_DIR)/$(ARCHITECTURE_DIR)
SDK_DIR     = sdks/v4.0

SOURCE_FILES = \
  $(SDK_DIR)/alarm.c \
  ...

CSOURCES = $(filter %.c, $(SOURCE_FILES))

COBJS = $(addprefix $(OUTPUT_DIR)/,$(CSOURCES:.c=.o))
all: PROLOGUE $(COBJS)
  $(LD) $(COBJS) -o ...

以前,该文件具有以下内容:

$(COBJS): %.o:
  @echo 'Building $(notdir $(@:%.o=%.c))...'
  @$(CC) $(CFLAGS) -o $@ $(filter %$(@:$(OUTPUT_DIR)/%.o=%.c),$(CSOURCES)) > /dev/null \

但这不依赖于 .c 文件,因此无法识别所做的更改和重建。我不想在进行源更改时进行清理。我将其更改为以下内容:

COBJS = $(CSOURCES:.c=.o)

$(COBJS): %.o: %.c
    @echo 'Building $(notdir $(@:%.o=%.c))...'
    @$(CC) $(CFLAGS) -o $(addprefix $(OUTPUT_DIR)/,$@) $< > /dev/null \

但这会导致它每次都重新构建,因为目标文件被放入不同的目录。有没有办法让它可以找到这些目标文件并且在必要时不重建?

感谢您的帮助!

【问题讨论】:

  • 发布的make文件包含:COBJS = $(addprefix $(OUTPUT_DIR)/,$(CSOURCES:.c=.o))但是没有宏命名:CSOURCES
  • OT:定义宏时,使用= 会导致每次引用宏时都会重新评估它。建议使用::=,因为这将消除重新评估宏的无用步骤
  • 啊,对不起。 CSOURCES 只是一个$(filter %.c, $(SOURCE_FILES)) 我会编辑它。

标签: c makefile compilation gnu-make


【解决方案1】:

我不确定我是否完全了解您想在哪里存放不同的产品,但让我们试一试。根据您对 Makefile 的展示,我假设您希望与 sdks/v4.0/alarm.c 对应的目标文件为 build/arm/sdks/v4.0/alarm.o。我还将假设您的目标可执行文件是build/arm/sdks/v4.0/my_executable

  1. 您可以修改编译模式规则以使用真正的源文件和目标文件:

    $(OUTPUT_DIR)/%.o: %.c
        @echo 'Building $(@F)...'
        @mkdir -p $(@D)
        @$(CC) $(CFLAGS) -o $@ $<
    

    请注意,配方会在编译前创建目标目录 (mkdir -p ...),并使用自动变量($(@F)$(@D))来获取目标的基本名称和目录。

  2. 你可以使用真正的目标文件作为你的链接规则来避免无用的重建;当然,您也可以将假目标用作真实目标的别名:

    EXEC := $(OUTPUT_DIR)/$(SDK_DIR)/my_executable
    ...
    .PHONY: all
    all: $(EXEC)
    ...    
    $(EXEC): PROLOGUE $(COBJS)
        $(LD) $(COBJS) -o $@
    

总而言之,您可以尝试以下方法:

ARCHITECTURE_DIR := arm
BUILD_DIR        := build
OUTPUT_DIR       := $(BUILD_DIR)/$(ARCHITECTURE_DIR)
SDK_DIR          := sdks/v4.0
SOURCE_FILES     := \
    $(SDK_DIR)/alarm.c \
    ...
CSOURCES         := $(filter %.c,$(SOURCE_FILES))
COBJS            := $(patsubst %.c,$(OUTPUT_DIR)/%.o,$(CSOURCES))
EXEC             := $(OUTPUT_DIR)/$(SDK_DIR)/my_executable

.PHONY: all
all: $(EXEC)

$(EXEC): PROLOGUE $(COBJS)
    $(LD) $(COBJS) -o $@

$(OUTPUT_DIR)/%.o: %.c
    @echo 'Building $(@F)...'
    @mkdir -p $(@D)
    @$(CC) $(CFLAGS) -c -o $@ $<

【讨论】:

    猜你喜欢
    • 2015-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多