c - 发现 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 的复杂性。我敢肯定,一旦弄清楚了这一点,我就会学到更多关于编写它们的知识。
我在这里先向您的帮助表示感谢!
解决方案
为了允许源文件驻留src
,您可以使用VPATH = $(SRCDIR)
与您一起定义的SRCDIR
. 要将目标文件放入其中obj
,您必须将目录添加到其中的文件名中OBJS
,例如使用OBJS := $(OBJS:%.o=$(OBJDIR)/%.o)
. 那么编译规则头是$(OBJDIR)/%.o: %.c
.
推荐阅读
- vue.js - 无法在 NativeScript 中的 GridLayout 内垂直对齐标签
- php - 将类自动加载到 PHP 交互式 Shell 中
- php - 即使在后端添加标头后也出现 CORS 错误。图像未移动到服务器上的目录
- java - Microsoft Graph:请求扩展返回 http 400 错误请求
- excel - 打开多个链接始终保持登录状态
- javascript - 如何从文本框中删除“选择文件”按钮?
- c# - 在foreach循环中调用多个存储过程时如何实现类似于事务的逻辑
- c# - 如何在另一个进程使用 Serilog 日志文件时查看它?
- sql - 从多列中查找最大值、第二个最大值和最小值
- javascript - 为什么使用 TypeScript 编译时从另一个节点模块导出为默认值会导致未定义的对象