如何精简Makefile并避免重复编译未修改的源码
解决Makefile全量编译问题(多文件夹源码场景)
原Makefile将所有源码一次性编译链接,每次执行make都会从头编译所有文件,效率极低。以下是修改后的Makefile,实现增量编译(仅重新编译修改过的文件),同时适配多文件夹的源码结构:
TARGET=analyser CC=arm-none-eabi-gcc OBJCPY=arm-none-eabi-objcopy OBJ_DIR := obj CFLAGS= -DNDEBUG -DCPU_MK64FN1M0VLL12 -DUSE_RTOS=1 -DPRINTF_ADVANCED_ENABLE=1 \ -DFRDM_K64F -DFREEDOM -DFSL_RTOS_FREE_RTOS -Os -Wall -fno-common \ -ffunction-sections -fdata-sections -ffreestanding -fno-builtin \ -mthumb -mapcs -std=gnu99 -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -MMD -MP \ --specs=nano.specs --specs=nosys.specs -Xlinker --gc-sections \ -Xlinker -static -Xlinker -z -Xlinker muldefs -Xlinker -Map=output.map \ -Xlinker --defsym=__stack_size__=2048 -Xlinker --defsym=__heap_size__=25600 LDSCRIPT=linker/MK64FN1M0xxx12_flash.ld # 源文件列表(保留原手动维护的列表) SRC=\ startup/startup_MK64F12.S \ fsl/fsl_uart.c \ fsl/fsl_uart_freertos.c \ fsl/fsl_dspi_freertos.c \ fsl/fsl_gpio.c \ fsl/fsl_phy.c \ fsl/fsl_dspi.c \ fsl/fsl_ftfx_controller.c \ fsl/fsl_assert.c \ fsl/fsl_smc.c \ fsl/fsl_common.c \ fsl/fsl_debug_console.c \ fsl/fsl_ftfx_cache.c \ fsl/fsl_sbrk.c \ fsl/fsl_ftfx_flash.c \ fsl/fsl_sim.c \ fsl/fsl_str.c \ fsl/fsl_ftfx_flexnvm.c \ fsl/fsl_clock.c \ fsl/fsl_enet.c \ drivers/lists/generic_list.c \ drivers/serial_manager/serial_manager.c \ drivers/serial_manager/serial_port_uart.c \ drivers/uart/uart_adapter.c \ FreeRTOS/src/list.c \ FreeRTOS/src/event_groups.c \ FreeRTOS/src/timers.c \ FreeRTOS/src/stream_buffer.c \ FreeRTOS/src/portable/MemMang/heap_3.c \ FreeRTOS/src/portable/GCC/ARM_CM4F/port.c \ FreeRTOS/src/tasks.c \ FreeRTOS/src/queue.c \ startup/startup_MK64F12.c \ app/config/board.c \ app/config/clock_config.c \ app/config/pin_mux.c \ app/modules/gpio.c \ app/modules/lwip.c \ app/network_analyser.c \ lwip/src/core/stats.c \ lwip/src/core/netif.c \ lwip/src/core/mem.c \ lwip/src/core/inet_chksum.c \ lwip/src/core/altcp.c \ lwip/src/core/memp.c \ lwip/src/core/tcp_out.c \ lwip/src/core/raw.c \ lwip/src/core/dns.c \ lwip/src/core/ipv4/autoip.c \ lwip/src/core/ipv4/ip4_frag.c \ lwip/src/core/ipv4/icmp.c \ lwip/src/core/ipv4/dhcp.c \ lwip/src/core/ipv4/etharp.c \ lwip/src/core/ipv4/ip4.c \ lwip/src/core/ipv4/ip4_addr.c \ lwip/src/core/ipv4/igmp.c \ lwip/src/core/sys.c \ lwip/src/core/altcp_tcp.c \ lwip/src/core/pbuf.c \ lwip/src/core/ipv6/ip6.c \ lwip/src/core/ipv6/ip6_addr.c \ lwip/src/core/ipv6/icmp6.c \ lwip/src/core/ipv6/ethip6.c \ lwip/src/core/ipv6/inet6.c \ lwip/src/core/ipv6/mld6.c \ lwip/src/core/ipv6/dhcp6.c \ lwip/src/core/ipv6/nd6.c \ lwip/src/core/ipv6/ip6_frag.c \ lwip/src/core/tcp_in.c \ lwip/src/core/tcp.c \ lwip/src/core/def.c \ lwip/src/core/ip.c \ lwip/src/core/altcp_alloc.c \ lwip/src/core/udp.c \ lwip/src/core/timeouts.c \ lwip/src/core/init.c \ lwip/src/api/err.c \ lwip/src/api/netdb.c \ lwip/src/api/netifapi.c \ lwip/src/api/if_api.c \ lwip/src/api/api_msg.c \ lwip/src/api/sockets.c \ lwip/src/api/netbuf.c \ lwip/src/api/api_lib.c \ lwip/src/api/tcpip.c \ lwip/src/netif/lowpan6_ble.c \ lwip/src/netif/lowpan6_common.c \ lwip/src/netif/bridgeif_fdb.c \ lwip/src/netif/lowpan6.c \ lwip/src/netif/ppp/lcp.c \ lwip/src/netif/ppp/auth.c \ lwip/src/netif/ppp/multilink.c \ lwip/src/netif/ppp/ipv6cp.c \ lwip/src/netif/ppp/pppos.c \ lwip/src/netif/ppp/pppcrypt.c \ lwip/src/netif/ppp/eui64.c \ lwip/src/netif/ppp/ccp.c \ lwip/src/netif/ppp/vj.c \ lwip/src/netif/ppp/pppol2tp.c \ lwip/src/netif/ppp/mppe.c \ lwip/src/netif/ppp/ppp.c \ lwip/src/netif/ppp/chap-md5.c \ lwip/src/netif/ppp/fsm.c \ lwip/src/netif/ppp/eap.c \ lwip/src/netif/ppp/magic.c \ lwip/src/netif/ppp/polarssl/arc4.c \ lwip/src/netif/ppp/polarssl/des.c \ lwip/src/netif/ppp/polarssl/md5.c \ lwip/src/netif/ppp/polarssl/md4.c \ lwip/src/netif/ppp/polarssl/sha1.c \ lwip/src/netif/ppp/chap_ms.c \ lwip/src/netif/ppp/pppapi.c \ lwip/src/netif/ppp/upap.c \ lwip/src/netif/ppp/chap-new.c \ lwip/src/netif/ppp/utils.c \ lwip/src/netif/ppp/demand.c \ lwip/src/netif/ppp/lwip_ecp.c \ lwip/src/netif/ppp/ipcp.c \ lwip/src/netif/ppp/pppoe.c \ lwip/src/netif/bridgeif.c \ lwip/src/netif/slipif.c \ lwip/src/netif/ethernet.c \ lwip/src/netif/zepif.c \ lwip/port/enet_ethernetif_kinetis.c \ lwip/port/sys_arch.c \ lwip/port/enet_ethernetif.c \ INCLUDES=\ -Iapp/include \ -ICMSIS \ -Ifsl \ -IFreeRTOS/include \ -IFreeRTOS/include/private \ -IFreeRTOS/src/portable/GCC/ARM_CM4F \ -Iinclude \ -Idrivers/uart \ -Idrivers/serial_manager \ -Idrivers/lists \ -Ilwip/port \ -Ilwip/src \ -Ilwip/src/include \ # 拆分C和汇编源文件 C_SOURCES := $(filter %.c,$(SRC)) ASM_SOURCES := $(filter %.S,$(SRC)) # 生成目标文件路径(映射到obj目录) OBJ_C := $(patsubst %.c,$(OBJ_DIR)/%.o,$(C_SOURCES)) OBJ_ASM := $(patsubst %.S,$(OBJ_DIR)/%.o,$(ASM_SOURCES)) OBJS := $(OBJ_C) $(OBJ_ASM) # 生成依赖文件路径 DEPS := $(OBJS:.o=.d) # 主目标:先编译所有目标文件,再链接生成ELF和BIN all: $(TARGET).elf $(TARGET).bin # 链接目标文件生成ELF $(TARGET).elf: $(OBJS) $(CC) $(OBJS) $(CFLAGS) -T $(LDSCRIPT) -o $@ # 从ELF提取BIN文件 $(TARGET).bin: $(TARGET).elf $(OBJCPY) $< $@ -O binary # 编译C文件:自动创建obj下的子目录,单独编译每个源文件 $(OBJ_DIR)/%.o: %.c @mkdir -p $(dir $@) $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ # 编译汇编文件:规则同C文件 $(OBJ_DIR)/%.o: %.S @mkdir -p $(dir $@) $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ # 自动包含依赖文件,修改头文件时自动重新编译对应源文件 -include $(DEPS) # 清理所有生成文件 clean: rm -rf $(OBJ_DIR) $(TARGET).elf $(TARGET).bin output.map
关键改动说明
- 目标文件统一管理:新增
OBJ_DIR变量,将所有目标文件输出到obj目录,避免污染源码目录,同时自动匹配源码的子文件夹结构 - 增量编译实现:拆分编译与链接步骤,仅重新编译修改过的源文件(通过
-MMD -MP生成的依赖文件自动追踪头文件变化) - 自动目录创建:编译时自动创建
obj下对应的子文件夹,适配多目录源码结构 - 保留原有参数:完全保留原有的编译、链接参数,确保程序功能不变
内容的提问来源于stack exchange,提问作者IceMarek
相关产品推荐
相关产品推荐

