c-避免使用Makefile编译未更改的源代码



我试图编写一个Makefile,它应该根据需要将所有源代码编译到对象中,然后构建输出二进制文件。

我尝试了几个例子,找到了解决方案,但前提是我将所有源放在同一个文件夹中。

但在这个项目中,文件分布在多个目录和子目录中。

我修改后的Makefile如下

TARGET=analyser
CC=arm-none-eabi-gcc
OBJCPY=arm-none-eabi-objcopy
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 -Wall -fno-common -ffunction-sections 
-fdata-sections -ffreestanding -fno-builtin -mthumb -mapcs -Xlinker --gc-sections 
-Xlinker -static -Xlinker -z -Xlinker muldefs -Xlinker -Map=output.map -mcpu=cortex-m4 
-mfloat-abi=hard -mfpu=fpv4-sp-d16 -Xlinker --defsym=__stack_size__=2048 -Xlinker 
--defsym=__heap_size__=25600 -Wall
LDSCRIPT=linker/MK64FN1M0xxx12_flash.ld
ASM_SOURCES := $(shell find . -name "*.S")
GCC_SOURCES := $(shell find . -name "*.c")
ASM_DIRNAME := $(shell dirname $(ASM_SOURCES))
GCC_DIRNAME := $(shell dirname $(GCC_SOURCES))
ASM_OBJECTS := $(patsubst $(ASM_DIRNAME)/%.S, $(ASM_DIRNAME)/%.o, $(ASM_SOURCES))
GCC_OBJECTS := $(patsubst $(GCC_DIRNAME)/%.c, $(GCC_DIRNAME)/%.o, $(GCC_SOURCES))
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 
all:
$(CC) $(INCLUDES) $(GCC_SOURCES) $(ASM_SOURCES) $(CFLAGS) -T $(LDSCRIPT) -o $(TARGET).elf
$(OBJCPY) $(TARGET).elf $(TARGET).bin -O binary
bad: $(GCC_OBJECTS) $(ASM_OBJECTS)                  
$(GCC) $(CFLAGS) -T $(LDSCRIPT) $^ -o $(TARGET) 
$(ASM_DIRNAME)/%.o:$(ASM_DIRNAME)/%.S               
$(GCC) $(INCLUDES) $(CFLAGS) -c $< -o $@        
$(GCC_DIRNAME)/%.o:$(GCC_DIRNAME)/%.c               
$(GCC) $(INCLUDES) $(CFLAGS) -c $< -o $@        
clean:
rm $(TARGET).elf $(TARGET).bin $(TARGET).d output.map 

当我执行";制造";命令通过进行编译

但当我执行";制造坏的";我收到错误

对于经验丰富的编码专家来说,这可能很简单,但我对Makefile世界还很陌生。

有人能帮我弄清楚吗?

修改前的原始Makefile如下所示:

TARGET=analyser
CC=arm-none-eabi-gcc
OBJCPY=arm-none-eabi-objcopy
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 -Wall -fno-common -ffunction-sections 
-fdata-sections -ffreestanding -fno-builtin -mthumb -mapcs -Xlinker --gc-sections 
-Xlinker -static -Xlinker -z -Xlinker muldefs -Xlinker -Map=output.map -mcpu=cortex-m4 
-mfloat-abi=hard -mfpu=fpv4-sp-d16 -Xlinker --defsym=__stack_size__=2048 -Xlinker 
--defsym=__heap_size__=25600 -Wall
LDSCRIPT=linker/MK64FN1M0xxx12_flash.ld
SRCS=
startup/startup_MK64F12.S 
startup/startup_MK64F12.c 
app/network_analyser.c 
app/config/pin_mux.c 
app/config/board.c 
app/config/clock_config.c 
fsl/fsl_sim.c 
fsl/fsl_clock.c 
fsl/fsl_enet.c 
fsl/fsl_ftfx_cache.c 
fsl/fsl_ftfx_controller.c 
fsl/fsl_ftfx_flash.c 
fsl/fsl_ftfx_flexnvm.c 
fsl/fsl_gpio.c 
fsl/fsl_debug_console.c 
fsl/fsl_str.c 
fsl/fsl_uart.c 
fsl/fsl_smc.c 
fsl/fsl_common.c 
fsl/fsl_assert.c 
fsl/fsl_sbrk.c 
fsl/fsl_phy.c 
fsl/fsl_dspi.c 
fsl/fsl_dspi_freertos.c 
fsl/fsl_uart_freertos.c 
FreeRTOS/src/portable/MemMang/heap_3.c 
FreeRTOS/src/event_groups.c 
FreeRTOS/src/list.c 
FreeRTOS/src/portable/GCC/ARM_CM4F/port.c 
FreeRTOS/src/queue.c 
FreeRTOS/src/stream_buffer.c 
FreeRTOS/src/tasks.c 
FreeRTOS/src/timers.c 
drivers/uart/uart_adapter.c 
drivers/serial_manager/serial_manager.c 
drivers/serial_manager/serial_port_uart.c 
drivers/lists/generic_list.c 
lwip/port/enet_ethernetif_kinetis.c 
lwip/port/enet_ethernetif.c 
lwip/port/sys_arch.c 
lwip/src/api/api_lib.c 
lwip/src/api/api_msg.c 
lwip/src/api/err.c 
lwip/src/api/if_api.c 
lwip/src/api/netbuf.c 
lwip/src/api/netdb.c 
lwip/src/api/netifapi.c 
lwip/src/api/sockets.c 
lwip/src/api/tcpip.c 
lwip/src/core/altcp.c 
lwip/src/core/altcp_alloc.c 
lwip/src/core/altcp_tcp.c 
lwip/src/core/def.c 
lwip/src/core/dns.c 
lwip/src/core/inet_chksum.c 
lwip/src/core/init.c 
lwip/src/core/ip.c 
lwip/src/core/ipv4/autoip.c 
lwip/src/core/ipv4/dhcp.c 
lwip/src/core/ipv4/etharp.c 
lwip/src/core/ipv4/icmp.c 
lwip/src/core/ipv4/igmp.c 
lwip/src/core/ipv4/ip4.c 
lwip/src/core/ipv4/ip4_addr.c 
lwip/src/core/ipv4/ip4_frag.c 
lwip/src/core/ipv6/dhcp6.c 
lwip/src/core/ipv6/ethip6.c 
lwip/src/core/ipv6/icmp6.c 
lwip/src/core/ipv6/inet6.c 
lwip/src/core/ipv6/ip6.c 
lwip/src/core/ipv6/ip6_addr.c 
lwip/src/core/ipv6/ip6_frag.c 
lwip/src/core/ipv6/mld6.c 
lwip/src/core/ipv6/nd6.c 
lwip/src/core/mem.c 
lwip/src/core/memp.c 
lwip/src/core/netif.c 
lwip/src/core/pbuf.c 
lwip/src/core/raw.c 
lwip/src/core/stats.c 
lwip/src/core/sys.c 
lwip/src/core/tcp.c 
lwip/src/core/tcp_in.c 
lwip/src/core/tcp_out.c 
lwip/src/core/timeouts.c 
lwip/src/core/udp.c 
lwip/src/netif/bridgeif.c 
lwip/src/netif/bridgeif_fdb.c 
lwip/src/netif/ethernet.c 
lwip/src/netif/lowpan6.c 
lwip/src/netif/lowpan6_ble.c 
lwip/src/netif/lowpan6_common.c 
lwip/src/netif/ppp/auth.c 
lwip/src/netif/ppp/ccp.c 
lwip/src/netif/ppp/chap-md5.c 
lwip/src/netif/ppp/chap-new.c 
lwip/src/netif/ppp/chap_ms.c 
lwip/src/netif/ppp/demand.c 
lwip/src/netif/ppp/eap.c 
lwip/src/netif/ppp/eui64.c 
lwip/src/netif/ppp/fsm.c 
lwip/src/netif/ppp/ipcp.c 
lwip/src/netif/ppp/ipv6cp.c 
lwip/src/netif/ppp/lcp.c 
lwip/src/netif/ppp/lwip_ecp.c 
lwip/src/netif/ppp/magic.c 
lwip/src/netif/ppp/mppe.c 
lwip/src/netif/ppp/multilink.c 
lwip/src/netif/ppp/ppp.c 
lwip/src/netif/ppp/pppapi.c 
lwip/src/netif/ppp/pppcrypt.c 
lwip/src/netif/ppp/pppoe.c 
lwip/src/netif/ppp/pppol2tp.c 
lwip/src/netif/ppp/pppos.c 
lwip/src/netif/ppp/upap.c 
lwip/src/netif/ppp/utils.c 
lwip/src/netif/ppp/vj.c 
lwip/src/netif/slipif.c 
lwip/src/netif/zepif.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 
all:
$(CC) $(INCLUDES) $(SRCS) $(CFLAGS) -T $(LDSCRIPT) -o $(TARGET).elf
$(OBJCPY) $(TARGET).elf $(TARGET).bin -O binary
clean:
rm $(TARGET).elf $(TARGET).bin $(TARGET).d output.map 

为什么要用find替换那个漂亮的显式源列表?把名单拿回来!

特别是为什么find恰好是一个程序集源?当然,从C源文件中分离它可能是一个不错的举措,但我认为find使用它没有任何好处

这个。。。

ASM_DIRNAME := $(shell dirname $(ASM_SOURCES))

。。。没有用处(见下文)。

这个。。。

GCC_DIRNAME := $(shell dirname $(GCC_SOURCES))

。。。不仅没有用处,而且确实存在问题。因为您有多个C源,所以这个变量将获得一个完整的目录名列表,而不仅仅是一个。还有一堆重复的,尽管这部分在实践中不会给你带来问题。

这些。。。

ASM_OBJECTS := $(patsubst $(ASM_DIRNAME)/%.S, $(ASM_DIRNAME)/%.o, $(ASM_SOURCES))
GCC_OBJECTS := $(patsubst $(GCC_DIRNAME)/%.c, $(GCC_DIRNAME)/%.o, $(GCC_SOURCES))

。。。对CCD_ 4使用不当。稍有错误,因为逗号后面的空格是数据,而不是分隔符。不方便,因为普通的替换引用更清晰、更短、更传统,并且更便于移植,只需将一个文件扩展名转换为另一个。显式地表达目录名而不是仅仅将它们包含在%中也有一些轻浮之处。推荐:

ASM_OBJECTS := $(ASM_SOURCES:.S=.o)
GCC_OBJECTS := $(GCC_SOURCES:.c=.o)

你的all目标没有任何先决条件,它的配方构建了一切。我知道你从最初的makefile中继承了这一点,但显然你没有意识到这是为了实现你的目标而需要修改的第一件事。如果您想使用all目标(这是一种常见的约定,但不是必需的),那么它应该将所有顶级构建输出作为先决条件,而不是配方。在您的情况下,这似乎只是$(TARGET).bin

每个食谱都应该尽可能地建立食谱的目标,而不是其他重要的东西。根据这个原则,您应该有单独的规则来构建$(TARGET).bin$(TARGET).elf

每个规则都应该表达其目标的所有先决条件,因此$(TARGET).bin的规则应该以$(TARGET).elf为先决条件;$(TARGET).elf的规则应该将所有对象文件以及链接器脚本作为先决条件。

但是当我执行";制造坏的";我收到错误

这是因为该规则中的尾部反斜杠使其无效。可以通过在最后一个先决条件和第一个反斜杠之间放置分号(;)来解决这个问题,但应该通过删除反斜杠并确保配方缩进文本制表符(而不是空格)来解决它。

您也应该对您的两个模式规则应用相同的修复,因为如果您正确地进行了前面描述的一些更改,那么这些更改将实际使用。但你也用$(GCC_DIRNAME)和(稍微)$(ASM_DIRNAME)变量射中了自己的脚。您不需要这些,因为模式词干可以很好地匹配目录。你不想要前者,因为它使你的规则沿着以下几条线:

dir1 dir1 dir2 dir3/%.o: dir1 dir1 dir2 dir3/%.c
# ... recipe ...

这里面有很多问题,尤其是它只匹配您想要构建的一些.o文件。更简单的规则会做得更好,比如:

%.o: %.S
$(GCC) $(INCLUDES) $(CFLAGS) -c $< -o $@
%.o: %.c
$(GCC) $(INCLUDES) $(CFLAGS) -c $< -o $@

如果您将INCLUDES重命名为CPPFLAGS,那么您甚至可以完全转储后一条规则,以支持编译.c文件的内置规则。

此外,您的clean目标不会清理对象文件,如果目标的规则实际上没有使用目标名称构建文件,那么您应该声明目标是假的。

总的来说,那么,我的推荐将采用以下形式:

TARGET = analyser
CC = arm-none-eabi-gcc
OBJCPY = arm-none-eabi-objcopy
CFLAGS = # flags ...
LDSCRIPT = linker/MK64FN1M0xxx12_flash.ld
ASM_SOURCES = startup/startup_MK64F12.S
GCC_SOURCES = 
# long/list/of/sources.c ... 
# last/source.c
ASM_OBJECTS = $(ASM_SOURCES:.S=.o)
GCC_OBJECTS = $(GCC_SOURCES:.c=.o)
CPPFLAGS = 
# -Ithe/includes ... 
# -Ilast/include
all: $(TARGET).bin
$(TARGET).bin: $(TARGET).elf
$(OBJCPY) $< $@ -O binary
$(TARGET).elf: $(GCC_OBJECTS) $(ASM_OBJECTS)
$(CC) -o $@ $(CFLAGS) -T $(LDSCRIPT) $^
%.o: %.S
$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
clean:
rm -f $(TARGET).elf $(TARGET).bin $(TARGET).d output.map $(GCC_OBJECTS) $(ASM_OBJECTS)
.PHONY: all clean

您的all:规则说"每次编译所有内容":

all:
$(CC) $(INCLUDES) $(GCC_SOURCES) $(ASM_SOURCES) $(CFLAGS) -T $(LDSCRIPT) -o $(TARGET).elf
$(OBJCPY) $(TARGET).elf $(TARGET).bin -O binary

如果文件all不存在,则在所有源上运行C编译器并创建可执行文件(但不创建文件all)。如果文件all存在,则不会发生任何事情——all不依赖于任何内容。

如果您不想编译所有内容,则需要告诉make可执行文件依赖于对象文件并链接对象文件。

我想你需要更像的东西

PROGRAM = $(TARGET).elf
all: $(PROGRAM)
$(PROGRAM): $(GCC_OBJECTS) $(ASM_OBJECTS)
$(CC) $(INCLUDES) $(GCC_OBJECTS) $(ASM_OBJECTS) $(CFLAGS) -T $(LDSCRIPT) -o $(PROGRAM)
$(OBJCPY) $(PROGRAM) $(TARGET).bin -O binary

你可能需要做一些工作来构建对象文件,但这意味着";all依赖于程序,程序依赖于对象文件,当对象文件都是最新的时,您可以像这样构建程序"。您可能希望指定.PHONY: all,因为它不是"真正的"目标——它不是您创建的文件。

您应该使用宏来重复PROGRAM = $(TARGET).elf(可能还有$(TARGET).bin)这样的元素。如果你必须把它写出来不止一次,它可能应该是一个宏。

感谢大家参与的任务

主要的问题不仅是语法,而且是由";Sublime 3〃;软件

我已经将我的工作空间更改为";vscode";现在我对不需要的TAB 没有任何问题

Makefile正在中工作

TARGET=analyser
CC=arm-none-eabi-gcc
OBJCPY=arm-none-eabi-objcopy
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 -Wall -fno-common -ffunction-sections 
-fdata-sections -ffreestanding -fno-builtin -mthumb -mapcs -Xlinker --gc-sections 
-Xlinker -static -Xlinker -z -Xlinker muldefs -Xlinker -Map=output.map -mcpu=cortex-m4 
-mfloat-abi=hard -mfpu=fpv4-sp-d16 -Xlinker --defsym=__stack_size__=2048 -Xlinker 
--defsym=__heap_size__=25600 -Wall
LDSCRIPT=linker/MK64FN1M0xxx12_flash.ld
ASM_SOURCES = startup/startup_MK64F12.S
GCC_SOURCES = $(shell find . -name "*.c")
INCLUDES=
-Iapp 
-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 
GCC_OBJECTS = $(GCC_SOURCES:.c=.o)
DEP_OBJECTS = $(GCC_SOURCES:.c=.d)
all: $(TARGET).bin
$(TARGET).bin: $(TARGET).elf
$(OBJCPY) $< $@ -O binary
$(TARGET).elf: $(GCC_OBJECTS)
$(CC) -o $@ $(CFLAGS) $(ASM_SOURCES) -T $(LDSCRIPT) $^
%.o: %.c
$(CC) -I $(INCLUDES) $(CFLAGS) -c -o $@ $<
clean:
rm -f $(TARGET).elf $(TARGET).bin $(TARGET).d output.map $(GCC_OBJECTS) $(DEP_OBJECTS)
.PHONY: all clean

非常感谢你的帮助!

相关内容

  • 没有找到相关文章

最新更新