02.Ubuntu下开发STM32--我叫Makefile

16 篇文章 1 订阅

回忆我们在windows环境下使用IDE进行开发,只要一股脑的将多有的源文件添加到工程中,点一个按钮,IDE就会为我们生成可执行文件。但是期间发生了什么?我们无从得知。IDE让我们编程简单的同时,也让我们变得更加傻瓜。

在linux下编程,最常用的莫过于gcc了。比如我们编译main.c生成main.exe(在linux下,叫做main.out)或许更好些。只需要在控制台下敲下:

$ gcc -Wall main.c -o main.out

-Wall是允许提示所有的警告。更多参数解释请参考http://gcc.gnu.org/onlinedocs/gcc/Option-Index.html 。这仅仅是编译一个文件。如果是想编译多个文件呢?比如foo.c和main.c构成一个工程,我们可以这样:

$ gcc -Wall main.c foo.c -o main.out

可是问题来了。如果你的整个工程中有成百上千个源文件。如果其中任意一个文件发生了变化,在生成一个可执行文件的时候,不管其余的文件是不是已经变化了,都需要将每一个C文件重新编译,最后在一次链接。这无疑浪费了大量的时间。人们想到了一个方法,将每一个源文件单独编译,生成*.o文件。只要源文件没有发生变化,链接的时候就使用之前的*.o文件。这样就减去了编译的时间了。生成*.o文件很简单。只要在编译的时候加上-c就好了。

$gcc -Wall -c main.c -o main.o
$gcc -Wall -c foo.c -o foo.o

编译完两个文件之后,在统一进行链接:

$gcc main.o foo.o -o main.out

如果你的main.c更改过,foo.o没有更改。只要重新编译main.c并和未更改的foo.o进行链接就好了。

$gcc -Wall -c main.c -o main.o
$gcc main.o foo.o -o main.out

人总是比较懒的。不情愿在控制台中敲击一千次来编译一千个源文件,他们索性发明了一个叫Makefile的东西。Makefile是一个文件的名字,类似与我们使用IDE创建的工程。Makefile中包含了使用什么命令,参数编译程序,或者进行其他的处理。举一个简单的例子。比如在~/debug/foo下有一个文件叫做Makefile。里面的内容是这样的:([TAB]是你用键盘按一下TAB键。由于显示空格,所以我这里使用TAB来代替他).

all:
[TAB] echo Hello
[TAB] echo world!

使用Makefile很简单,只要在控制台进入Makefile的目录,输入make all命令回车即可。

$ cd ~/debug/foo
$ make all

在运行之后,屏幕会输出:

echo Hello
Hello
echo world!
world!

Makefile总会将他的命令和结果一同输出。如果你不想看到实际执行的命令,你可以在每行命令的前面加上@符号。这样命令就不会输出了。

all:
[tab] @echo Hello
[tab] @echo world!

上面的all叫做工作目标,与all在同一行的叫做依赖条件(如果没有依赖条件可以为空)。all下面的以TAB开头的若干行叫做执行命令。一个Makefile中可以有多个工作目标。如果你想执行Makefile中的特定的工作目标,可以在make后面加上工作目标的名字。像make all这样。如果你的make后面没有工作目标的名字。那么make会默认执行他在Makefile中找到的第一个工作目标。上面的make all其实等同于make。

来看一个实际的例子。

在~/debug/foo下有foo.c和main.c两个文件。两个文件共同链接成一个可执行文件。来为他写一个Makefile。

OBJS = foo.o main.o
DEFS = -DUSE_STDPERIPH_DRIVER
CFLAGS = -Wall  -g

all: main.out
clean:
[tab] @rm -f $(OBJS) main.out

main.out: $(OBJS)
[tab]gcc $^ -o $@

%.o:%.c
[tab]gcc $(DEFS) $(CFLAGS) -c $< -o $@

main.o foo.o : foo.h

在上面的例子中,

  • OBJS, DEFS, CFLAGS都是变量名。类似与C语言,区分大小写。不需要声明,直接使用就行。在使用的时候需要前面家$,并使用括号括起来。像这样$(DEFS) 。
  • 在gcc的参数中,以-Dxxx开头的是宏。比如gcc -DDebug … 在编译的时候定义了宏Debug
  • 在gcc的参数中,以-Ixxx开头的是头文件路径。如果想将Makefile的路径作为头文件路径,可以使用gcc -I./ 。
  • $<代表依赖条件中的地一个条件。$@代表工作目标的名字。$^代表依赖条件中所有的条件。
  • main.o :foo.h告诉make,当foo.h头文件变的时候,把main.c重新编译一次。
  • %.o : %.c的写法叫做隐含规则。意思是.c文件编译生成.o文件的时候,使用下面的命令。

在上面的例子中,条件是foo.c main.c Makefile这三个文件在同一个文件夹中。但是如果不在呢?这样Makefile就找不到main.c foo.c了。比如这样的情况:

.
├── inc
│   └── foo.h
└── src
    ├── foo.c
    └── main.c

这样的情况下,为了能够让Makefile找到源文件和头文件,需要在Makefile中添加这么两行:

vpath %.c ./src
vpath %.h ./inc

当然,添加vpath %.h ./inc只是为了让make找到foo.h。为了让gcc找到foo.h,不要忘记添加头文件路径(使用-I./inc添加)。

关于Makefile就简单的介绍这么多。更多的Makefile的知识请尽情Google。或者参考书籍(GNU make项目管理)。
附件1:GNU make的中文手册。仅供参考。
附件2:GNU make项目管理。
附件3: 跟我一起写Makefile

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
d:\stm32dev\stm32cubeide_1.12.1\stm32cubeide\plugins\com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.10.3-2021.10.win32_1.0.200.202301161003\tools\arm-none-eabi\bin\ld.exe: ./Core/Src/main.o: in function `main': main.c:(.text.startup.main+0x16): undefined reference to `TMC2660_DirectSet' d:\stm32dev\stm32cubeide_1.12.1\stm32cubeide\plugins\com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.10.3-2021.10.win32_1.0.200.202301161003\tools\arm-none-eabi\bin\ld.exe: main.c:(.text.startup.main+0x1e): undefined reference to `TMC2660Enable' d:\stm32dev\stm32cubeide_1.12.1\stm32cubeide\plugins\com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.10.3-2021.10.win32_1.0.200.202301161003\tools\arm-none-eabi\bin\ld.exe: main.c:(.text.startup.main+0x26): undefined reference to `TMC2660_MicrostepSet' d:\stm32dev\stm32cubeide_1.12.1\stm32cubeide\plugins\com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.10.3-2021.10.win32_1.0.200.202301161003\tools\arm-none-eabi\bin\ld.exe: main.c:(.text.startup.main+0x2e): undefined reference to `TMC2660_CurrentScaleSet' d:\stm32dev\stm32cubeide_1.12.1\stm32cubeide\plugins\com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.10.3-2021.10.win32_1.0.200.202301161003\tools\arm-none-eabi\bin\ld.exe: main.c:(.text.startup.main+0x34): undefined reference to `TMC2660_SPIMoveStep' collect2.exe: error: ld returned 1 exit status make: *** [makefile:64: TMC2660_tset.elf] Error 1 "make -j32 all" terminated with exit code 2. Build might be incomplete.
07-13

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值