IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 嵌入式Linux学习笔记(三)Linux C编译/Makefile基础 -> 正文阅读

[嵌入式]嵌入式Linux学习笔记(三)Linux C编译/Makefile基础

一、代码编译

  • 没有使用VIM编辑器,使用VSCode编辑代码,简易容易上手,且支持Linux。

1、 编译代码

(1)安装编译需要的软件包

  • 安装 gcc、g++、make 等工具,build-essential提供了编译程序所需的所有软件包。
sudo apt-get install build-essential
  • 查看GCC版本号,“Target: x86_64-linux-gnu”一行,这说明这个 GCC 编译器是针对 X86 架构的,因此只能编译在 X86 架构 CPU 上运行的程序。如果想要编译在 ARM 上运行的程序就需要针对 ARM 的 GCC 编译器,也就是交叉编译器! ARM 开发,因此后期肯定要安装针对 ARM 架构的 GCC 交叉编译器。目标架构不同,需要的GCC编译器就不同。
gcc -v

在这里插入图片描述

(2)编译代码命令

  • GCC 编译器和其它编译器一样,不仅能够检测出错误类型,而且标记除了错误
    发生在哪个文件,哪一行。
gcc [选项] [文件名字]

-c:只编译不链接为可执行文件,编译器将输入的.c 文件编译为.o 的目标文件。
-o:<输出文件名>用来指定编译结束以后的输出文件名,如果使用这个选项的话 GCC 默认编译出来的可执行文件名字为 a.out。 -g:添加调试信息,如果要使用调试工具(如 GDB)的话就必须加入此选项,此选项指示编
译的时候生成调试所需的符号信息。
-O:对程序进行优化编译,如果使用此选项的话整个源代码在编译、链接的的时候都会进行优化,这样产生的可执行文件执行效率就高。
-O2:比-O 更幅度更大的优化,生成的可执行效率更高,但是整个编译过程会很慢。
  • VScode编辑代码
    在这里插入图片描述
  • 终端编译代码指令gcc,./a.out运行代码
//默认编译后输出a.out
gcc main.c

在这里插入图片描述

//指定输出文件名称,输出main
gcc main.c –o main

在这里插入图片描述

(3)编译流程

  • GCC 编译器的编译流程是:预处理、编译、汇编和链接。
  • 预处理就是展开所有的头文件、替换程序中的宏、解析条件编译并添加到文件中。
  • 编译是将经过预编译处理的代码编译成汇编代码,也就是我们常说的程序编译。
  • 汇编就是将汇编语言文件编译成二进制目标文件。
  • 链接就是将汇编出来的多个二进制目标文件链接在一起,形成最终的可执行文件,链接的时候还会涉及到静态库和动态库等问题。

二、Makefile基础

1、简介

  • 像脚本文件一样,一键编译多个文件。在工程目录下创建名为“Makefile”的文件,
    文件名一定要叫做“Makefile”!!!
作用:

1、如果工程没有编译过,那么工程中的所有.c 文件都要被编译并且链接成可执行程序。
2、如果工程中只有个别 C 文件被修改了,那么只编译这些被修改的 C 文件即可。
3、如果工程的头文件被修改了,那么我们需要编译所有引用这个头文件的 C 文件,并且
链接成可执行文件。
  • 编辑Makefile,所有行首需要空出来的地方一定要使用“TAB”键!不要使用空格键!
    在这里插入图片描述
gcc -o main main.o input.o calcu.o //将编译出来的所有.o 文件链接成可执行文件 main

//分别是将 main.c、input.c 和 calcu.c 编译成对应的.o 文件,使用了“- c”选项,只编译不链接
gcc -c main.c			
gcc -c input.c
gcc -c calcu.c
  • Makefile 编写好以后我们就可以使用 make 命令来编译我们的工程了,直接在命令行中输入“make”即可,make 命令会在当前目录下查找是否存在“Makefile”这个文件,如果存在的话就会按照 Makefile 里面定义的编译方式进行编译。
    在这里插入图片描述
  • Makefile 中命令缩进没有使用 TAB 键,会导致一下错误。
    在这里插入图片描述

2、Makefile 语法

(1)Makefile 规则格式

目标…... : 依赖文件集合……
	命令 1
	命令 2
	……
  • 举例,这条规则的目标是 main,main.o、input.o 和 calcu.o 是生成 main 的依赖文件,如果要更新目标 main,就必须先更新它的所有依赖文件,如果依赖文件中的任何一个有更新,那么目标也必须更新,“更新”就是执行一遍规则中的命令列表。规则的命令是用来创建或者更新目标的。规则除第一条,没有先后顺序。
//这是一条规则
main : main.o input.o calcu.o					//目标:依赖文件集合
	 gcc -o main main.o input.o calcu.o			//命令1

(2)Make 的执行过程

1、make 命令会在当前目录下查找以 Makefile(makefile 其实也可以)命名的文件。
2、当找到 Makefile 文件以后就会按照 Makefile 中定义的规则去编译生成最终的目标文件。
3、当发现目标文件不存在,或者目标所依赖的文件比目标文件新(也就是最后修改时间比目标文件晚)的话就会执行后面的命令来更新目标。

(3)Makefile 变量

  • Makefile 中的变量都是字符串!类似 C 语言中的宏。
  • 举例,main.o input.o 和 calcue.o输入了两遍
main: main.o input.o calcu.o
	 gcc -o main main.o input.o calcu.o

可替换为:

#Makefile 变量的使用					//注释			
objects = main.o input.o calcu.o
main: $(objects)
	gcc -o main $(objects) 

- ① 赋值符“=”

  • 在 Makefile 要输出一串字符的话使用“echo”,就和 C 语言中的“printf”一样。
  • 赋值符“=”,变量的真实值取决于它所引用的变量的最后一次有效值。
name = zzk
curname = $(name) 
name = david

print: 
	@echo curname: $(curname)

结果:curname:david

- ② 赋值符“:=”

  • 赋值符“:=”,变量的真实值取决于它所引用的变量的第一次定义值。

- ③ 赋值符“?=”

  • 如果前面curname没有被赋值,就使用?=这个变量值。
curname ?= david

- ④变量追加“+=”

  • main.o input.o calcu.o
objects = main.o inpiut.o
objects += calcu.o

(4)Makefile 模式规则

  • “%”表示长度任意的非空字符串,比如“%.c”就是所有的以.c 结尾的文件,类似与通配符,a.%.c 就表示以 a.开头,以.c 结束的所有文件。
  • 当“%”出现在目标中的时候,目标中“%”所代表的值决定了依赖中的“%”值,使用方
    法如下:
%.o : %.c
	命令
main: main.o input.o calcu.o 
	gcc -o main main.o input.o calcu.o 
main.o: main.c
	gcc -c main.c 
input.o: input.c 
	gcc -c input.c 
calcu.o: calcu.c 
	gcc -c calcu.c 
 
clean:
	rm *.o
	rm main

使用模式规则改为:

objects = main.o input.o calcu.o 
main: $(objects)
	gcc -o main $(objects)

%.o : %.c 
	  #命令

clean: 
	rm *.o
	rm main

(5)Makefile自动化变量 ?

  • 常用的三种:
$@:规则中的目标集合,在模式规则中,如果有多个目标的话,“$@”表示匹配模式中定义的目标集合。
$<:依赖文件集合中的第一个文件,如果依赖文件是以模式(即“%)定义的,那么“$<”就是符合模式的一系列的文件集合。
$^:所有依赖文件的集合,使用空格分开,如果在依赖文件中有多个重复的文件,“$^”会去除重复的依赖文件,值保留一份。
  • $@
  • $<
  • $^
objects = main.o input.o calcu.o 
main: $(objects) 
	gcc -o main $(objects)
 
%.o : %.c 						#使用了模式规则
	gcc -c $< 					#使用了自动化变量
	
clean:
	rm *.o
	rm main

(5)Makefile 伪目标

  • 使用伪目标的主要是为了避免 Makefile 中定义的只执行命令的目标和工作目录下的实际文
    件出现名字冲突,也可以编写一个规则用来执行一些命令。
.PHONY : clean
  • 声明 clean 为伪目标以后不管当前目录下是否存在名为“clean”的文件,输入“make clean”的话规则后面的 rm 命令都会执行。
objects = main.o input.o calcu.o 
main: $(objects) 
	gcc -o main $(objects)
 
.PHONY : clean					#伪目标

%.o : %.c 						#使用了模式规则
	gcc -c $< 					#使用了自动化变量
	
clean:
	rm *.o
	rm main

(6)Makefile 条件判断

  • 关键字:ifeq、ifneq、ifdef 和 ifndef

  • 语法一:

<条件关键字> 
	<条件为真时执行的语句>
endif
  • 语法二:
<条件关键字> 
	<条件为真时执行的语句>
else
	<条件为假时执行的语句>
endif

- ① ifeq、ifneq 判断是否相等

ifeq (<参数 1>, <参数 2>)
ifeq ‘<参数 1 >,<参数 2>’
ifeq “<参数 1>,<参数 2>”
ifeq “<参数 1>,<参数 2>’
ifeq ‘<参数 1>,<参数 2>

- ② ifdef、ifndef 判断是否非空

  • 如果“变量名”的值非空,那么表示表达式为真,否则表达式为假。“变量名”同样可以是一个函数的返回值。
ifdef <变量名>

(7)Makefile 函数使用(不支持自定义函数)

$(函数名 参数集合)
或者
${函数名 参数集合}

- ① 函数 subst

  • 把字符串“my name is zzk”中的“zzk”替换为“ZZK”
$(subst zzk,ZZK,my name is zzk)

- ②函数 patsubst

  • 将字符串“a.c b.c c.c”中的所有符合“%.c”的字符串,替换为“%.o”,替换完成以后的字
    符串为“a.o b.o c.o”。
$(patsubst %.c,%.o,a.c b.c c.c)

- ③函数 dir

  • 提取文件“/src/a.c”的目录部分,也就是“/src”
$(dir </src/a.c>)

- ④函数 notdir

  • 提取文件“/src/a.c”中的非目录部分,也就是文件名“a.c”。
$(notdir </src/a.c>)

- ⑤函数 foreach

  • 此函数的意思就是把参数中的单词逐一取出来放到参数中,然后再执行 所包含的表达式。每次 都会返回一个字符串,循环的过程中, 中所包含的每个字符串会以空格隔开,最后当整个循环结束时, 所返回的每个字符串所组成的整个字符串将会是函数 foreach 函数的返回值。

- ⑥函数 wildcard

  • 获取当前目录下所有的.c 文件,类似“%”。
$(wildcard *.c)

  • 参照【正点原子】文档学习。
  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-08-20 15:17:19  更:2021-08-20 15:17:53 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 22:26:24-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码