You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Makefile中根据编译参数排除未使用的源文件?

项目结构
[22:58:45] BasicProject$ tree -l
.
├── Makefile
└── SourceCode
    ├── Controllers
    │   ├── MenuPage.cpp
    │   ├── MenuPage.hpp
    │   └── Unused.cpp
    ├── main.cpp
    ├── main.hpp
    └── Visuals -> ../AnotherProject/SourceCode/Visuals
        ├── Components
        │   └── Text.hpp
        ├── MenuPage.cpp
        └── MenuPage.hpp
问题描述

在BasicProject/SourceCode/Controllers目录下存在未被任何源文件引用的Unused.cpp,希望将这类未使用的文件排除出编译流程。且未使用的文件会随目标架构、库选择等编译参数变化而改变。

当前使用的简化版Makefile
PRJ_NAME := BasicProject

### Paths ###
PRJ_ROOT        := ./
PRJ_SOURCE_CODE := ${PRJ_ROOT}/SourceCode
PRJ_OUTPUT_DIR  := ${PRJ_ROOT}/Outputs
PRJ_OBJECTS_DIR := ${PRJ_OUTPUT_DIR}/Objects
INCLUDES        += -I${PRJ_SOURCE_CODE}

### Derived Variables ###
CPP_SRC_FILES   := $(shell find -L $(PRJ_SOURCE_CODE) -type f -name "*.cpp"  -print)
CPP_OBJECTS     := $(patsubst $(PRJ_SOURCE_CODE)/%.cpp,$(PRJ_OBJECTS_DIR)/%.o, $(CPP_SRC_FILES))

### Targets ###
all: $(CPP_OBJECTS)    
    @g++ -o ${PRJ_OUTPUT_DIR}/${PRJ_NAME}.elf $(CPP_OBJECTS)
    
clean:     
    rm -rf ${PRJ_OBJECTS_DIR}

${PRJ_OBJECTS_DIR}/%.o : $(PRJ_SOURCE_CODE)/%.cpp
    @mkdir -p $(@D)
    @g++ $(INCLUDES) -c $< -o $@
解决方案

针对动态变化的未使用文件,有三种可行的处理方式:

1. 基于编译依赖自动推导(推荐)

利用Make的依赖管理特性,从入口文件(如main.cpp)递归推导所有被引用的源文件,替代全量收集的方式:

PRJ_NAME := BasicProject

### Paths ###
PRJ_ROOT        := ./
PRJ_SOURCE_CODE := ${PRJ_ROOT}/SourceCode
PRJ_OUTPUT_DIR  := ${PRJ_ROOT}/Outputs
PRJ_OBJECTS_DIR := ${PRJ_OUTPUT_DIR}/Objects
INCLUDES        += -I${PRJ_SOURCE_CODE}

# 入口文件,从这里开始推导依赖
MAIN_SRC := $(PRJ_SOURCE_CODE)/main.cpp
CPP_SRC_FILES := $(MAIN_SRC)

# 递归查找所有被引用的源文件(基于头文件与源文件的命名对应关系)
define find_deps
    $(foreach h,$(shell g++ $(INCLUDES) -MM $1 | sed 's/.*://; s/\\//g; s/ /\n/g'), \
        $(if $(filter %.hpp,$h), \
            $(if $(wildcard $(patsubst %.hpp,%.cpp,$h)), \
                $(eval CPP_SRC_FILES += $(patsubst %.hpp,%.cpp,$h)) \
                $(call find_deps,$(patsubst %.hpp,%.cpp,$h)) \
            ) \
        ) \
    )
endef

$(call find_deps,$(MAIN_SRC))
# 对收集到的源文件去重
CPP_SRC_FILES := $(sort $(CPP_SRC_FILES))

CPP_OBJECTS     := $(patsubst $(PRJ_SOURCE_CODE)/%.cpp,$(PRJ_OBJECTS_DIR)/%.o, $(CPP_SRC_FILES))

### Targets ###
all: $(PRJ_OUTPUT_DIR)/${PRJ_NAME}.elf

$(PRJ_OUTPUT_DIR)/${PRJ_NAME}.elf: $(CPP_OBJECTS)
    @g++ -o $@ $^
    
clean:     
    rm -rf ${PRJ_OBJECTS_DIR} ${PRJ_OUTPUT_DIR}/${PRJ_NAME}.elf

${PRJ_OBJECTS_DIR}/%.o : $(PRJ_SOURCE_CODE)/%.cpp
    @mkdir -p $(@D)
    @g++ $(INCLUDES) -c $< -o $@

2. 动态排除列表

设置可随编译参数调整的排除变量,根据不同编译场景指定要排除的文件:

# 默认排除的文件
EXCLUDE_SRC := 

# 根据编译参数添加对应排除项
ifeq ($(ARCH),arm)
EXCLUDE_SRC += $(PRJ_SOURCE_CODE)/Controllers/Unused.cpp
endif

# 收集所有cpp文件后过滤掉排除列表中的文件
CPP_SRC_FILES   := $(filter-out $(EXCLUDE_SRC), $(shell find -L $(PRJ_SOURCE_CODE) -type f -name "*.cpp"  -print))

使用时通过make ARCH=arm触发对应的排除规则即可。

3. 标记式过滤

在未使用的文件开头添加特定标记(如// UNUSED),然后用grep过滤掉带标记的文件:

CPP_SRC_FILES   := $(shell find -L $(PRJ_SOURCE_CODE) -type f -name "*.cpp" -exec grep -L "// UNUSED" {} \;)

这种方式需要手动标记文件,但实现简单,适合小型项目。

内容的提问来源于stack exchange,提问作者Caglayan Dokme

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 11:35:39