首页 > 解决方案 > 发现 STM32:编写 makefile 来创建 src inc (etc) 目录

问题描述

我是一名电气工程师,在初级/中级阶段进入了嵌入式 C。在阅读了 Steve Oualline 的 Practical C Programming 之后,我发现 Geoffery Brown 的“发现 STM32 微控制器”是一个优秀的初学者嵌入式资源。我非常向任何想要学习嵌入式 C 的人推荐这条道路。

对于我的问题:Discovering STM32 的作者提供了一个 Makefile 方案,其中包括一个项目特定的 Makefile 以及一个 Makefile common (Makefile.common) 到所有包含的项目目录。我真的很想将我的代码组织到 src、inc、obj 和 bin 目录中,但作者没有在 makefile 模板中提供此功能。在阅读了 Makefiles 并尝试了一些事情之后,我不知道如何使用作者提供的结构来做到这一点。我的目标是保留相同的 Makefile/Makefile.common 方案,同时在构建 .elf 后将我的代码组织到项目子文件夹中的单独 bin、src、inc 和 obj 目录中。

更简单地说,我希望我的目录结构/文件夹看起来像:

DiscoveringSTM32
    Makefile.common
    ProjectA
        src
            main.c
            stuff.c
            whateverelse.c
            Makefile
        inc
            stuff.h
            whateverelse.h
        bin
            ProjectA.elf
        obj
            stuff.o
            whateverelse.o

上下文/我正在使用的内容: FWIW,我的完整 DiscoveringSTM32 存储库在这里。项目特定(例如“ProjectA”)作者提供的 Makefile 如下所示:

TEMPLATEROOT = ..

# compilation flags for gdb

CFLAGS  = -O1 -g 
ASFLAGS = -g 
LDLIBS += -lm

# object files

OBJS =  $(STARTUP) main.o
OBJS += foo.o bar.o
OBJS += baz.o fee.o 
OBJS += fo.o fum.o

# include common make file
include $(TEMPLATEROOT)/Makefile.common

虽然作者提供 Makefile.common 看起来像

# name of executable

ELF=$(notdir $(CURDIR)).elf                    

# Tool path

TOOLROOT="C:\Users\Robert\OneDrive\Documents\GNU_ARM_TOOLS\9-2020-q2-update\bin"

# Library path

LIBROOT="C:\Users\Robert\OneDrive\Documents\DiscoveringSTM32\STM32F10x_StdPeriph_Lib_V3.5.0"

# Tools

CC=$(TOOLROOT)/arm-none-eabi-gcc
LD=$(TOOLROOT)/arm-none-eabi-gcc
AR=$(TOOLROOT)/arm-none-eabi-ar
AS=$(TOOLROOT)/arm-none-eabi-as

# Code Paths

DEVICE=$(LIBROOT)/Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x
CORE=$(LIBROOT)/Libraries/CMSIS/CM3/CoreSupport
PERIPH=$(LIBROOT)/Libraries/STM32F10x_StdPeriph_Driver

# Search path for standard files

vpath %.c $(TEMPLATEROOT)

# Search path for perpheral library

vpath %.c $(CORE)
vpath %.c $(PERIPH)/src
vpath %.c $(DEVICE)

# Search path for Library

vpath %.c $(TEMPLATEROOT)/Library/ff9/src
vpath %.c $(TEMPLATEROOT)/Library/ff9/src/option
vpath %.c $(TEMPLATEROOT)/Library

#  Processor specific

#PTYPE = STM32F10X_MD_VL 
PTYPE = STM32F10X_MD #try this for blue pill
LDSCRIPT = $(TEMPLATEROOT)/stm32f100.ld
STARTUP= startup_stm32f10x.o system_stm32f10x.o 

# Compilation Flags

FULLASSERT = -DUSE_FULL_ASSERT 

LDFLAGS+= -T$(LDSCRIPT) -mthumb -mcpu=cortex-m3 
CFLAGS+= -mcpu=cortex-m3 -mthumb 
CFLAGS+= -I$(TEMPLATEROOT) -I$(DEVICE) -I$(CORE) -I$(PERIPH)/inc -I.
CFLAGS+= -D$(PTYPE) -DUSE_STDPERIPH_DRIVER $(FULLASSERT)
CFLAGS+= -I$(TEMPLATEROOT)/Library/ff9/src -I$(TEMPLATEROOT)/Library

# Build executable 

$(ELF) : $(OBJS)
    $(LD) $(LDFLAGS) -o $@ $(OBJS) $(LDLIBS)

# compile and generate dependency info

%.o: %.c
    $(CC) -c $(CFLAGS) $< -o $@
    $(CC) -MM $(CFLAGS) $< > $*.d

%.o: %.s
    $(CC) -c $(CFLAGS) $< -o $@

clean:
    rm -f $(OBJS) $(OBJS:.o=.d) $(ELF) startup_stm32f* $(CLEANOTHER)

debug: $(ELF)
    arm-none-eabi-gdb $(ELF)


# pull in dependencies

-include $(OBJS:.o=.d)

我理解这里发生的事情,我们定义我们的目标文件(即 main.o 来自 main.c,foo.o 来自 foo.c)并且我们有规则从它们的依赖项创建目标文件,最终构建我的可闪存 ELF 文件。

我尝试过的事情

经过一些谷歌搜索和阅读一些在线教程后,我尝试像这样定义我的目录:

BINDIR = bin
SRCDIR = src
OBJDIR = obj
INCDIR = inc

然后通配我所有的 .c 和 .o

# name of executable

ELF:= $(BINDIR)/$(notdir $(CURDIR)).elf
SRC := $(wildcard $(SRCDIR)/*.c)
OBJ = $(SRC:$(SRCDIR)/%.c=$(OBJDIR)/%.o)
OBJ += $(STARTUP)

我在 $(STARTUP) 中 +='d 以及因此由 STARTUP 定义的关联文件,因为我遇到了“错误:没有规则来制作目标 startup_stm32f10x.o”。

我所做的最远的努力是在我的特定项目目录(例如 Documents/DiscoveringStm32/projectA)中成功创建了一个包含 .elf 文件的 bin 目录。到达那里涉及保留作者提供的 += 目标文件方案并将 makefile.common 中的 ELF 定义修改为:

ELF:= $(BINDIR)/$(notdir $(CURDIR)).elf

我试着做:

$(ELF) : $(OBJDIR)/$(OBJS)
    $(LD) $(LDFLAGS) -o $@ $(OBJS) $(LDLIBS)

# compile and generate dependency info

$(OBJDIR)/%.o: $(SRCDIR)/%.c
    $(CC) -c $(CFLAGS) $< -o $@
    $(CC) -MM $(CFLAGS) $< > $*.d

%.o: %.s
    $(CC) -c $(CFLAGS) $< -o $@

但这引发了错误。

通过这一切,我开始欣赏 Makefile 的复杂性。我敢肯定,一旦弄清楚了这一点,我就会学到更多关于编写它们的知识。

我在这里先向您的帮助表示感谢!

标签: cgccmakefileembeddedstm32

解决方案


为了允许源文件驻留src,您可以使用VPATH = $(SRCDIR)与您一起定义的SRCDIR. 要将目标文件放入其中obj,您必须将目录添加到其中的文件名中OBJS,例如使用OBJS := $(OBJS:%.o=$(OBJDIR)/%.o). 那么编译规则头是$(OBJDIR)/%.o: %.c.


推荐阅读