Makefile学习过程中遇到的一些疑惑点,
Makefile的规则和使用
直接看这个视频链接
(https://www.bilibili.com/video/BV1tyWWeeEpp/?spm_id_from=333.788&vd_source=1ef8dd7d3b9716a677c49316caa40add)
两件事:
1.文件的依赖是什么?
2.如何生成这个依赖?
伪目标就是一个不生成文件的目标,它只是一个标签,用来执行一些操作。
有时候我们需要执行一些不生成文件的操作,比如清理临时文件、生成文档、打包等等,这时候就用伪目标来定义这些规则。
最常用的伪目标就是clean,用来清理编译过程中生成的临时文件或者可执行文件。
当我们想要生成的目标文件不止一个的话,就可以使用all这个伪目标。如图:
直接用make all就可以生成 hello 和 world 两个目标文件,
就不需要make hello,make world这样一个一个来执行了。
假如本来就存在一个名为clean的文件,此时,可以把伪目标clean使用.phony显示的告诉make这是个伪目标,这样make就不会把clean当作文件名来处理了。
赋值完后,可以通过 $ 引用变量去引用;
$引用变量,在正式工程的makefile中,通常也会把目标文件、源文件、中间文件等等定义为变量,然后使用 $ 符号去引用。
预定义变量顾名思义就是Make程序预先自动创建好的变量,
预定义变量一般是以 美元符号+特殊字符 来表示,比如:
等等…
语法格式是:
$(var:a=b)或${var:a=b}
表示把变量var的值中的a后缀替换成b后缀
例如:
src := a.c b.c c.c
obj := $(src:c=o)
把变量src的值中的.c后缀替换成.o后缀,赋值给变量obj,结果是:
obj := a.o b.o c.o
看全志开发学习文档
很多情况下不需要手动去编写makefile,因为还有个更好用更方便的构建makefile的工具CMake。
CMake是一个跨平台的构建工具,它可以根据不同的平台和编译器,生成对应的构建文件。
比如在Unix或者Linux平台可以生成makefile,
在Window平台就可以生成Visual Studio的项目文件。
CMake的配置文件是一个叫做CMakeLists.txt的文件,它的语法比makefile要简单一些
brew install cmake protobuf rust python@3.10 git wget
1.在工程的根目录下新建一个CMakeLists.txt的文件
2.首先来加上一行CMake的最小版本要求
3.然后再来加上一个PROJECT命令,括号里写上【工程的名字】,随便取
4.然后设置源文件列表(把需要用到的源文件列出来的意思)
用SET命令来定义一个SOURCES变量,括号里写上【main.c和message.c这两个源文件】,源文件两个之间用空格隔开。
5.最后再加上一个生成可执行文件的命令,括号里写上【生成的可执行文件的名字hello】,再加上SOURCES这个变量,表示这个可执行文件是由这个变量中的源文件生成的。
——————————————————————————
这样一个最简单的cmake配置文件就写好了。——————————————————————————
6.为了同一开始的makefile的例子区分开,在工程的根目录下新建一个build目录。
7.然后进入到build目录里面。
8.8.执行 cmake…命令
通过配置文件CMakeLists文件在当前目录下生成构建文件makefile (所以用cmake);
但是CMakeLists文件不在当前目录下,而是在上一级目录里面(所以用…);
执行完成之后就会发现,build目录下生成了一个makefile文件;
makefile文件里面的规则就是CMake根据我们的配置文件CMakeLists.txt里的配置自动帮我们生成的。
9.然后再执行make命令,就可以看到build目录里面生成了一个可执行文件hello。
10.再执行这个./hello,可以得到运行的结果
11.再执行clean,hello文件就被正常清0了。
用户设置环境以便能够在一种类型的计算机系统(x86架构,比如常见的个人电脑)上编译程序(交叉编译),并让这个程序能够在另一种不同类型的计算机系统(ARM架构,如许多移动设备或树莓派等单板机)上运行。
想要在x86平台上进行交叉编译,并在ARM平台上运行这个程序。
用户如何配置他们的开发环境,使其能够支持跨平台编译。要实现这一点,你需要在你的电脑上安装一个叫做“交叉编译工具链”的软件包,这个工具链包含了编译器和其他工具,可以用来创建适用于ARM架构的可执行文件。
为了使用这个交叉编译工具链,你需要在你的.bashrc文件中设置环境变量PATH。.bashrc是一个位于你的主目录下的隐藏文件,它包含了一些当你的bash shell启动时会读取并执行的命令。在这个例子中,你需要用文本编辑器(这里是vi编辑器)打开这个文件,并在文件末尾添加一行新的环境变量定义:
export PATH=$PATH:/home/$(whoami)/orangepi-build/toolchains/gcc-arm-9.2-2019.12-x86_64-aarch64-none-linux-gnu/bin
这行命令做的事情是将交叉编译工具链的位置添加到系统的PATH变量中,这样当你在命令行输入编译命令时,系统就能够找到这些工具了。
/home/$(whoami)/orangepi-build/toolchains/gcc-arm-9.2-2019.12-x86_64-aarch64-none-linux-gnu/bin
这行是工具链的路径,$(whoami) 是一个命令替换,它会被当前用户的用户名所替代。
$(whoami) 是一个命令替换,它会被当前用户的用户名所替代。
完成这一步后,每次你打开一个新的终端窗口或者重新加载.bashrc文件(通过运行 source .bashrc),环境变量就会生效,你就可以开始进行交叉编译工作了。
总结一下,
.bashrc 文件就像是你给终端设定的个人偏好设置文件,而
source .bashrc 命令则是在告诉终端“刷新”这些设置,以便立即应用任何更改。
当你打开一个终端时,Bash shell 会查找这个文件来了解你希望它怎样配置自己的行为。你可以在这个文件里设置各种各样的东西,比如:
有时候,你可能修改了 .bashrc 文件,添加了新的设置或别名,但是当你在当前的终端窗口里尝试使用它们时,却发现不起作用。这是因为已经打开的终端窗口或标签页在启动时就已经读取了一次 .bashrc 文件的内容,并且不会自动去检查这个文件是否已经被更新。
这时候,你可以通过运行 source .bashrc(或者 . ~/.bashrc)命令来让当前的终端窗口重新读取 .bashrc 文件中的设置。这相当于告诉 shell:“请重新加载这个文件中的命令。”
C/C++编译过程。
预处理,展开头文件,宏定义,条件编译处理等。通过gcc -E source.c -o source.i或者cpp source.c生成。
编译。这里是一个狭义的编译意义,指的是将预处理后的文件翻译成汇编代码的过程。通过gcc -S source.i生成。默认生成source.s文件。
汇编。汇编即将上一步生成的汇编代码翻译成对应的二进制机器码的过程。通过gcc -c source.s来生成source.o文件。
链接。链接是将生成目标文件和其引用的各种符号等生成一个完整的可执行程序的过程。链接的时候会进行虚拟内存的重定向操作。
上面四个步骤就是C/C++程序编译的几个基本步骤。.o文件就是C/C++源码编译的结果。即上面所说的C/C++编译过程中的前三步。一般开发中很少将这三步分开来做,通常的做法是一步生成;只有第四个步骤链接是复杂一点的。很多时候我们编译比较大的项目,报错的往往是在链接的时候缺少某些库,或者某些符号找不到定义,重定义等。