我试着写了一个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
当我执行“make”命令时,编译过程
但当我执行“使坏”我收到错误
对于有经验的编码Maven来说,这可能很简单,但我在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
4条答案
按热度按时间xe55xuns1#
1.在原始Makefile中,对象文件列表是使用
patsubst
生成的。相反,您可以使用:=
赋值运算符直接将源文件扩展名替换为对象文件扩展名。1.对对象文件使用模式规则。不要使用
$(ASM_DIRNAME)/%.o:$(ASM_DIRNAME)/%.S
和$(GCC_DIRNAME)/%.o:$(GCC_DIRNAME)/%.c
规则,这会导致“混合隐式和普通规则”错误,而应该使用%.o: %.S
和%.o: %.c
等模式规则。这将匹配任何.S
或.c
文件,并生成相应的.o
文件。1.您应该为构建
TARGET.elf
和TARGET.bin
文件创建单独的规则。TARGET.elf
规则应该依赖于$(GCC_OBJECTS)
和$(ASM_OBJECTS)
,并使用$(CC)
命令编译和链接它们。TARGET.bin
规则应该依赖于TARGET.elf
文件,并使用$(OBJCPY)
命令生成二进制文件。1.此外,
clean
规则还应该删除生成的目标文件。使用rm -f
命令,然后使用目标文件列表$(ASM_OBJECTS)
和$(GCC_OBJECTS)
。mf98qq942#
为什么要用
find
来替换那个漂亮的源代码列表呢?把列表拿回来!特别是为什么
find
用于 * 确切的一个 * 汇编源代码?当然,将其从C源文件中分离出来可能是一个很好的举措,但我认为find
没有任何优势。这...
...没有用(见下文)。
这...
...不仅没有用,而且肯定会有问题。因为你有多个C源代码,这个变量将得到一个完整的目录名列表,而不仅仅是一个。还有一堆重复的目录名,尽管这部分在实践中不会给你带来问题。
这些
...使
$(patsubst)
的使用变得轻浮和轻微错误。轻微错误是因为逗号后的空格是数据,而不是分隔符。轻浮,因为普通的替换引用更清晰,更短,更常规,而且更便于移植,只需将一个文件扩展名转换为另一个。显式地表达目录名而不是只将它们包含在%
中也有些轻浮。推荐:您的
all
目标没有先决条件,它的配方构建了所有内容。我知道您从原始的makefile继承了这一点,但显然您没有意识到这是需要修改以实现目标的首要内容。如果您想使用all
目标,请单击此处。(这是一个常见的约定,但不是必需的),那么它应该将所有顶级构建输出作为先决条件,而不是配方。尽可能地,每个配方都应该构建配方的目标,而不是其他后果。根据这个原则,你应该有单独的规则来构建
$(TARGET).bin
和$(TARGET).elf
。每个规则都应该表达其目标的所有先决条件,因此
$(TARGET).bin
的规则应该将$(TARGET).elf
作为先决条件,而$(TARGET).elf
的规则应该将所有对象文件以及链接器脚本作为先决条件。但当我执行“使坏”我收到错误
这是因为该规则中的尾随反斜杠使其无效。您可以通过在最后一个先决条件和第一个反斜杠之间放置分号(
;
)来修复它,但您应该通过删除反斜杠并确保配方缩进文字制表符(而不是空格)来修复它。你也应该对你的两个模式规则应用同样的修正,因为如果你正确地进行了前面描述的一些修改,那么这些规则实际上就会被使用。
$(ASM_DIRNAME)
变量。您不需要这些,因为模式词干将很好地匹配目录。您不需要前者,因为它使你的规则沿着这些路线:这样做会有各种各样的问题,尤其是它只匹配你想要构建的一些
.o
文件。更简单的规则会做得更好,比如:如果您将
INCLUDES
重命名为CPPFLAGS
,那么您甚至可以完全丢弃后一个规则,而支持用于编译.c文件的内置规则。此外,
clean
目标并不清理目标文件,如果目标的规则实际上并不构建具有目标名称的文件,则应该将目标声明为phony。总的来说,我的建议是这样的:
4bbkushb3#
你的
all:
规则说“每次编译所有内容”:如果文件
all
不存在,那么在所有源代码上运行C编译器并创建可执行文件(但不包括文件all
)。如果文件all
存在,则什么也不会发生-all
不依赖于任何东西。如果你不想编译所有的东西,你需要告诉
make
可执行文件依赖于目标文件,并链接目标文件。我觉得你需要更像这样的东西:
你可能需要做一些工作来构建目标文件,但是这里说“
all
依赖于程序,程序依赖于目标文件,当目标文件都是最新的,你就像这样构建程序”。你可能想指定.PHONY: all
,因为它不是一个“真正的”目标-它不是你创建的文件。你应该使用宏来重复像
PROGRAM = $(TARGET).elf
这样的元素(可能还有$(TARGET).bin
)。如果你必须不止一次地写出它,它可能应该是一个宏。cczfrluj4#
感谢大家参与这项任务
主要的问题不仅是语法,还有“Sublime 3”软件生成的TAB符号
我已经将我的工作区更改为“vscode”,现在我没有任何不需要的TAB的问题
Makefile正在工作
非常感谢您的帮助!