基础开发工具

什么是软件包管理器?

  • 在linux 下安装软件,一个通用的办法就是下载源代码。然后编译,形成可执行程序,但是这样太麻烦了
  • 所以就有软件包管理器出现。别人吧软件写好打包放在服务器上,我们要安装,通过软件包管理器从服务器上下载到本地。
  • 软件就是app,软件包管理器就像应用商店。
  • linux下软件包管理器yum/apt就像一个客户端,从服务器上下载软件。
  • yum(Yellow dog Updater, Modified)是Linux下⾮常常⽤的⼀种包管理器. 主要应⽤在Fedora, RedHat, Centos等发⾏版上.
  • Ubuntu:主要使⽤apt(Advanced Package Tool)作为其包管理器。apt同样提供了⾃动解决依 赖关系、下载和安装软件包的功能。

linux软件的生态

一个操作系统为什么要有完整的生态

怎么样评估一个操作系统好?

首先,光有一个强大的操作系统不够,还必须要完整的生态,因为这样才会有更多人使用。一个操作系统是否完整,要看它的生态是否完善。

操作系统生态必须有社区论坛,强大的官网文档,丰富的软件体系。维护更新速度快。对客户要有针对性。

当一个开源的操作系统,别人为了使用它,不让他黄,肯定会有程序员去写丰富的软件,还有unbantu,等系统。这样社区论坛也热闹,官网文档也强。

所以我们下载软件,就可以通过软件包管理器,yum/apt,去查找软件,下载,再直接安装。yum/apt是怎么直接在几亿台服务器找到软件的了,因为软件服务器的路径会写在软件包管理器下文件里面。

但是有防火墙不能直接访问外网,或者下载速度慢。所以,有很多公司搞了镜像软件包服务器。

他们把软件下载国内的服务器。yum/apt文件下的路径也会被修改成国内的服务器。

.conf是文件的后缀,存放配置文件的。

软件依赖是什么?

就是我们下载安装一个软件,还会依赖其他软件来运行。比如vs2022,来需要在vs环境下安装c++等的编译环境。但是yum/apt在服务器下载,安装软件,解决这个问题。

yum/apt的具体操作

yum/apt是软件包管理器。它的作用是在服务器下载软件并安装。

他们怎么获取软件的服务器的。在配置文件下存放许多软件的镜像地址。叫做软件源。

软件源又分为稳定软件源和扩展软件源。

稳定软件源是放软件测试稳定,可靠的软件放在服务器上,存放的是服务器的地址。

扩展软件源是还没有成熟,或者稳定的软件。当软件完善之后也会放在稳定软件的服务器上。

像linux系统配置的软件源的服务器地址一般都是指向国外的。所以我们要更新配置软件源,将一个新的文件替换原来的软件源。

首先我们先备份原来的标准源

复制代码
sudo cp /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup//把.repo备份一份,原文件也在

再拷贝一个新的一份文件做备份。

wget:获取网址。

cpp 复制代码
# 使用 wget 下载阿里云的 CentOS-7.repo 文件,
# 并用 -O 把它直接保存并覆盖到 /etc/yum.repos.d/CentOS-Base.repo
sudo wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo

但是清除旧缓存,不然yum,找不到国内服务器地址,还有旧的缓存。

cpp 复制代码
yum clean all

最后更新缓存

cpp 复制代码
yum makecache

上面就是更新软件源的方法。就是用新文件替换了旧的文件存放软件包服务器的地址。

apt的查看软件包的指令

cpp 复制代码
root@iZwz9c6v6ajdocnv9xkh8rZ:~# apt search lrzsz
Sorting... Done
Full Text Search... Done
cutecom/jammy 0.30.3-1build1 amd64
  Graphical serial terminal, like minicom

lrzsz/jammy,now 0.12.21-10 amd64 [installed]
  Tools for zmodem/xmodem/ymodem file transfer

更详细的看软件包(show)

cpp 复制代码
root@iZwz9c6v6ajdocnv9xkh8rZ:~# apt show lrzsz
Package: lrzsz
Version: 0.12.21-10
Priority: optional
Section: universe/comm
Origin: Ubuntu
Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
Original-Maintainer: Martin A. Godisch <godisch@debian.org>
Bugs: https://bugs.launchpad.net/ubuntu/+filebug
Installed-Size: 531 kB
Depends: libc6 (>= 2.15)
Suggests: minicom
Homepage: https://ohse.de/uwe/software/lrzsz.html
Download-Size: 74.8 kB
APT-Manual-Installed: yes
APT-Sources: http://mirrors.cloud.aliyuncs.com/ubuntu jammy/universe amd64 Packages
Description: Tools for zmodem/xmodem/ymodem file transfer
 Lrzsz is a cosmetically modified zmodem/ymodem/xmodem package built
 from the public-domain version of Chuck Forsberg's rzsz package.
 .
 These programs use error correcting protocols ({z,x,y}modem) to send
 (sz, sx, sb) and receive (rz, rx, rb) files over a dial-in serial port
 from a variety of programs running under various operating systems.

yum查看软件包的指令

cpp 复制代码
yum list | grep lrzsz
lrzsz.x86_64 0.12.20-36.el7 @base 

也可以search

cpp 复制代码
yum search lrzsz

yum和apt安装软件的指令

cpp 复制代码
sudo yum install 软件
sudo apt install 软件
cpp 复制代码
sudo yum install -y 软件
sudo apt install -y 软件


yum/apt 会⾃动找到都有哪些软件包需要下载, 这时候敲 "y" 确认安装.

出现 "complete" 字样或者中间未出现报错, 说明安装完成.
注意事项:

安装软件时由于需要向系统⽬录中写⼊内容, ⼀般需要 sudo 或者切到 root 账⼾下才能完成.

yum/apt安装软件只能⼀个装完了再装另⼀个. 正在yum/apt安装⼀个软件的过程中, 如果再尝试⽤
yum/apt安装另外⼀个软件, yum/apt会报错.

如果 yum / apt报错, 请⾃⾏百度

卸载软件

cpp 复制代码
sudo  yum remove -y 软件
sudo apt remove -y 软件 

y跟上面一样

vim编辑器

三种模式

1.命令模式

输入许多命令,可以编写文件。进入默认是命令模式。

【yy】复制这一行.

p\]粘贴,前面可以加数字多少行复制。 【gg】回到文本开头。 【G】回到文本末尾 \[\^\]回到行开头 【$】回到行尾 【h】向左 【j】向下 【k】向上 【l】向右 \[dd\]删除行 \[x\]删除单个字符 【u】撤销 【crtl+r】对撤销取消 【行号+shift+g】跑到对应的行上 【w】单词为单位,向前查找 【b】单词为单位,向后查找。 批量化注释,批量化去注释crtl+v进入视图。然后j下移选择多少行。再shift+i进入插入模式。再在开头输入//最后esc退出,就批量注释了。删除注释就是crtl+v,选择要取消注释的,然后按d就可以了。 shift+\~大小写转换 \[r\]替换光标那的字符。 \[shift+r\]光标后面的都可以替换。 \[u\]撤销 ctrl+r:对撤销动作取消。 shift+zz:保存并退出。 ### 底行模式 set nu:对每行都写上行号。 w:保存,wq:保存并退出。q!:强制退出。wq!保存强制退出 ```cpp jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ gcc t.c jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ ls -l total 24 -rwxrwxr-x 1 jcm jcm 15960 Mar 11 19:54 a.out drwxrwxr-x 2 jcm jcm 4096 Mar 8 21:07 dir -rw-rw-r-- 1 jcm jcm 283 Mar 11 19:54 t.c -rw-rw-r-- 1 jcm jcm 0 Mar 8 20:53 tess.c -rw-rw-r-- 1 jcm jcm 0 Mar 10 20:34 test.c -rw------- 1 jcm jcm 0 Mar 8 20:59 txt10.c -rw------- 1 jcm jcm 0 Mar 8 20:59 txt1.c -rw------- 1 jcm jcm 0 Mar 8 20:59 txt2.c -rw------- 1 jcm jcm 0 Mar 8 20:59 txt3.c -rw------- 1 jcm jcm 0 Mar 8 20:59 txt4.c -rw------- 1 jcm jcm 0 Mar 8 20:59 txt5.c -rw------- 1 jcm jcm 0 Mar 8 20:59 txt6.c -rw------- 1 jcm jcm 0 Mar 8 20:59 txt7.c -rw------- 1 jcm jcm 0 Mar 8 20:59 txt8.c -rw------- 1 jcm jcm 0 Mar 8 20:59 txt9.c ``` 编译之后,生成了a.out文件。在执行文件的时候,就算文件在当前路径下。我们也并不能只给文件名,linux找不到。 ```cpp a.out//找不到 ./a.out//应该这样给。 或者给绝对路径,从根目录开始 ``` ```bash jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ ./a.out hello world hello world hello world hello world hello world hello world hello world hello world hello world ``` 一般都要退出文件编译,再运行gcc t.c 然后执行./a.out文件,这样太慢了。 我们可以在底行模式加个!加gcc t.c 然后!./a.out就可以同样执行代码,还不会退出。 > 当我们需要几个文件的时候.h .c我们编译完.c,再退出编译.h。太慢了。我们底行输入vs 文件就可以进行分屏操作 ![](https://i-blog.csdnimg.cn/direct/210b6ebf78fc4a2887e5bf862d447ca6.png) ![](https://i-blog.csdnimg.cn/direct/9a9a82a1c5b544abbd5eee55338fd07e.png) 不仅可以分两屏,还可以分三屏更多。 底行模式还有常用的就是/,在文本查找内容进行高亮。 %s/被替换/新文件/g,可以替换文本中的内容。 ![](https://i-blog.csdnimg.cn/direct/8d31fc6d170149eabefa021461b33b09.png) ### 补充的指令 ## vim配置 为了使vim更好用,我们可以在.vimrc文件里面配置一些命令,然后当我们vim的时候,就会打开.vimrc,生效我们的配置命令。推荐每个用户配置在自己的家目录下,不配置在root下 ![](https://i-blog.csdnimg.cn/direct/518796e13a73403aa3fd67822749323e.png) ## gcc/g++编译器 gcc:编译c语言的 g++:编译c++的 编译器:就是把源文件编译成可执行的二进制文件。 ##### 1 预处理 gcc -E code.c -o code.i。进行预处理。 预处理又分为:头文件展开。宏替换。去掉注释。条件编译。(头文件展开就是把头文件里面的内容拷贝到源文件。去掉注释,就是把注释的内容去掉。)使语言变成干净的语言。 jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ gcc -E jcm.c -o jcm.i ###### 条件编译 为什么要条件编译? 条件编译的主要用途 1. 根据不同平台或环境编译代码:可以针对不同的操作系统或硬件架构编写特定的代码。 2. 调试和发布版本的区分:在调试版本中可以包含调试信息,而在发布版本中则可以排除这些信息。 3. 多版本控制:根据不同的需求或功能选择性地编译某些模块或功能。 ![](https://i-blog.csdnimg.cn/direct/fbe8fe75c77f442fa3dc461cfd079622.png) 多版本控制,就是有些商业化软件会有基础版和专业版。基础版和专业版的公共代码一样。 利用条件编译就可以只实现一套代码。条件编译控制输出哪部分的代码。这样代码维护起来方便 ![](https://i-blog.csdnimg.cn/direct/001e3032a83a462aa8d45eec7f3493fe.png) ##### 2 翻译 将c语言翻译成汇编语言 ```bash jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ gcc -S jcm.i -o jcm.s ``` ##### 3 汇编 将汇编-》obj目标文件(可重定位的二进制文件) ```bash jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ gcc -c jcm.s -o jcm.o ``` ##### 4链接 将目标文件与c语言的标准库里面的内容链接 ```bash jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ gcc jcm.o -o jcm.exe jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ ./jcm.exe hellojcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ ls -l ``` ##### 解释的命令 -o就是把文件变成其他名称。-E就是预处理 -S就是翻译 -c就是汇编 ##### 最后建议 > ```bash > > jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ touch hello{1..20}.c > jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ gcc -c hello{1..20}.c > jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ ls -l > total 164 > -rw-rw-r-- 1 jcm jcm 17956 Mar 13 17:04 code.i > -rw-rw-r-- 1 jcm jcm 1560 Mar 13 17:05 code.o > -rw-rw-r-- 1 jcm jcm 738 Mar 13 17:04 code.s > drwxrwxr-x 2 jcm jcm 4096 Mar 8 21:07 dir > -rw-rw-r-- 1 jcm jcm 0 Mar 13 17:33 hello10.c > -rw-rw-r-- 1 jcm jcm 936 Mar 13 17:33 hello10.o > -rw-rw-r-- 1 jcm jcm 0 Mar 13 17:33 hello11.c > -rw-rw-r-- 1 jcm jcm 936 Mar 13 17:33 hello11.o > -rw-rw-r-- 1 jcm jcm 0 Mar 13 17:33 hello12.c > -rw-rw-r-- 1 jcm jcm 936 Mar 13 17:33 hello12.o > -rw-rw-r-- 1 jcm jcm 0 Mar 13 17:33 hello13.c > -rw-rw-r-- 1 jcm jcm 936 Mar 13 17:33 hello13.o > -rw-rw-r-- 1 jcm jcm 0 Mar 13 17:33 hello14.c > -rw-rw-r-- 1 jcm jcm 936 Mar 13 17:33 hello14.o > -rw-rw-r-- 1 jcm jcm 0 Mar 13 17:33 hello15.c > -rw-rw-r-- 1 jcm jcm 936 Mar 13 17:33 hello15.o > -rw-rw-r-- 1 jcm jcm 0 Mar 13 17:33 hello16.c > -rw-rw-r-- 1 jcm jcm 936 Mar 13 17:33 hello16.o > -rw-rw-r-- 1 jcm jcm 0 Mar 13 17:33 hello17.c > -rw-rw-r-- 1 jcm jcm 936 Mar 13 17:33 hello17.o > -rw-rw-r-- 1 jcm jcm 0 Mar 13 17:33 hello18.c > -rw-rw-r-- 1 jcm jcm 936 Mar 13 17:33 hello18.o > -rw-rw-r-- 1 jcm jcm 0 Mar 13 17:33 hello19.c > -rw-rw-r-- 1 jcm jcm 936 Mar 13 17:33 hello19.o > -rw-rw-r-- 1 jcm jcm 0 Mar 13 17:33 hello1.c > -rw-rw-r-- 1 jcm jcm 936 Mar 13 17:33 hello1.o > -rw-rw-r-- 1 jcm jcm 0 Mar 13 17:33 hello20.c > -rw-rw-r-- 1 jcm jcm 936 Mar 13 17:33 hello20.o > -rw-rw-r-- 1 jcm jcm 0 Mar 13 17:33 hello2.c > -rw-rw-r-- 1 jcm jcm 936 Mar 13 17:33 hello2.o > -rw-rw-r-- 1 jcm jcm 0 Mar 13 17:33 hello3.c > -rw-rw-r-- 1 jcm jcm 936 Mar 13 17:33 hello3.o > -rw-rw-r-- 1 jcm jcm 0 Mar 13 17:33 hello4.c > -rw-rw-r-- 1 jcm jcm 936 Mar 13 17:33 hello4.o > -rw-rw-r-- 1 jcm jcm 0 Mar 13 17:33 hello5.c > -rw-rw-r-- 1 jcm jcm 936 Mar 13 17:33 hello5.o > -rw-rw-r-- 1 jcm jcm 0 Mar 13 17:33 hello6.c > -rw-rw-r-- 1 jcm jcm 936 Mar 13 17:33 hello6.o > -rw-rw-r-- 1 jcm jcm 0 Mar 13 17:33 hello7.c > -rw-rw-r-- 1 jcm jcm 936 Mar 13 17:33 hello7.o > -rw-rw-r-- 1 jcm jcm 0 Mar 13 17:33 hello8.c > -rw-rw-r-- 1 jcm jcm 936 Mar 13 17:33 hello8.o > -rw-rw-r-- 1 jcm jcm 0 Mar 13 17:33 hello9.c > -rw-rw-r-- 1 jcm jcm 936 Mar 13 17:33 hello9.o > ``` > > gcc -c会把.c文件形成同名的.o文件。最后我们再把.o文件链接。这样提高了编译效率 ![](https://i-blog.csdnimg.cn/direct/229f64e321d84e46b8010b263c315978.png) ## 链接为什么要有库?库是什么? 在链接的时候为什么要用库?因为这样提高了效率,不然每个程序员要用的时候都要自己去实现,浪费。 库是什么?库是别人写好的代码集合。 库在哪里了?linux下centos和unbantu的路径不同。![](https://i-blog.csdnimg.cn/direct/83e6bf4661da47098f958b8de6173b0c.png) ![](https://i-blog.csdnimg.cn/direct/1911fb864b65496fb0a57dddc4890cbc.png) *** ** * ** *** ![](https://i-blog.csdnimg.cn/direct/ab8c39571a31440db2336f9e0f2b3d18.png) 编译出来的文件,默认是动态库。我们可以把它修改成静态库 ```bash jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ gcc yu.c -o yu -statically ``` ```bash jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ file yu yu: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, BuildID[sha1]=758cbf26757fe7b843d260ddb19e9cb26157182a, for GNU/Linux 3.2.0, not stripped ``` 这样就是一个静态链接了。 ### 动态库和静态库的优缺点 ![](https://i-blog.csdnimg.cn/direct/b0c24dc316d24582bdacf410cda6847d.png) ![](https://i-blog.csdnimg.cn/direct/c2765333ffce437aa1adb501a9cf1218.png) ![](https://i-blog.csdnimg.cn/direct/472985f4dec543499d4231b3d6945f37.png) ## 自动化构建-make/makefile * 会不会写makefile,从⼀个侧⾯说明了⼀个⼈是否具备完成⼤型⼯程的能⼒ * ⼀个⼯程中的源⽂件不计数,其按类型、功能、模块分别放在若⼲个⽬录中,makefile定义了⼀ 系列的规则来指定,哪些⽂件需要先编译,哪些⽂件需要后编译,哪些⽂件需要重新编译,甚⾄ 于进⾏更复杂的功能操作makefile带来的好处就是⸺"⾃动化编译",⼀旦写好,只需要⼀个make命令,整个⼯程完全 ⾃动编译,极⼤的提⾼了软件开发的效率。 * make是⼀个命令⼯具,是⼀个解释makefile中指令的命令⼯具,⼀般来说,⼤多数的IDE都有这 个命令,⽐如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可⻅,makefile 都成为了⼀种在⼯程⽅⾯的编译⽅法 ![](https://i-blog.csdnimg.cn/direct/b87f5908dd1f45f785b784f64dd4c1cf.png) ```cpp jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ make gcc -E code.c -o code.i gcc -S code.i -o code.s gcc -c code.s -o code.o gcc code.o -o code jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ ls -l total 1000 -rwxrwxr-x 1 jcm jcm 15960 Mar 15 21:05 code -rw-rw-r-- 1 jcm jcm 68 Mar 15 21:05 code.c -rw-rw-r-- 1 jcm jcm 17950 Mar 15 21:05 code.i -rw-rw-r-- 1 jcm jcm 1496 Mar 15 21:05 code.o -rw-rw-r-- 1 jcm jcm 659 Mar 15 21:05 code.s drwxrwxr-x 2 jcm jcm 4096 Mar 8 21:07 dir -rw-rw-r-- 1 jcm jcm 56 Mar 13 17:07 jcm.c -rwxrwxr-x 1 jcm jcm 15960 Mar 13 17:09 jcm.exe -rw-rw-r-- 1 jcm jcm 17934 Mar 13 17:08 jcm.i -rw-rw-r-- 1 jcm jcm 1496 Mar 13 17:09 jcm.o -rw-rw-r-- 1 jcm jcm 675 Mar 13 17:08 jcm.s -rw-rw-r-- 1 jcm jcm 203 Mar 15 21:03 makefile -rw-rw-r-- 1 jcm jcm 60 Mar 13 21:16 test.c -rw-rw-r-- 1 jcm jcm 1504 Mar 13 21:16 test.o -rw-rw-r-- 1 jcm jcm 102 Mar 11 21:04 t.h -rwxrwxr-x 1 jcm jcm 900344 Mar 14 19:09 yu -rw-rw-r-- 1 jcm jcm 165 Mar 14 17:52 yu.c jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ vim makefile jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ make clean rm -f code code.o code.s code.i jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ ls -l total 956 -rw-rw-r-- 1 jcm jcm 68 Mar 15 21:05 code.c drwxrwxr-x 2 jcm jcm 4096 Mar 8 21:07 dir -rw-rw-r-- 1 jcm jcm 56 Mar 13 17:07 jcm.c -rwxrwxr-x 1 jcm jcm 15960 Mar 13 17:09 jcm.exe -rw-rw-r-- 1 jcm jcm 17934 Mar 13 17:08 jcm.i -rw-rw-r-- 1 jcm jcm 1496 Mar 13 17:09 jcm.o -rw-rw-r-- 1 jcm jcm 675 Mar 13 17:08 jcm.s -rw-rw-r-- 1 jcm jcm 203 Mar 15 21:03 makefile -rw-rw-r-- 1 jcm jcm 60 Mar 13 21:16 test.c -rw-rw-r-- 1 jcm jcm 1504 Mar 13 21:16 test.o -rw-rw-r-- 1 jcm jcm 102 Mar 11 21:04 t.h -rwxrwxr-x 1 jcm jcm 900344 Mar 14 19:09 yu -rw-rw-r-- 1 jcm jcm 165 Mar 14 17:52 yu.c ``` make自动执行,make clean执行下面删除方法。 看了上面的代码,肯定不知道.PHONY是干什么的,它是伪目标,修饰的目标文件和依赖方法总是被执行。什么是总是被执行,那我们先谈谈什么是不总是被执行。 jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ make gcc -E code.c -o code.i gcc -S code.i -o code.s gcc -c code.s -o code.o gcc code.o -o code jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ ls -l total 1000 -rwxrwxr-x 1 jcm jcm 15960 Mar 15 23:55 code -rw-rw-r-- 1 jcm jcm 68 Mar 15 21:05 code.c -rw-rw-r-- 1 jcm jcm 17950 Mar 15 23:55 code.i -rw-rw-r-- 1 jcm jcm 1496 Mar 15 23:55 code.o -rw-rw-r-- 1 jcm jcm 659 Mar 15 23:55 code.s drwxrwxr-x 2 jcm jcm 4096 Mar 8 21:07 dir -rw-rw-r-- 1 jcm jcm 56 Mar 13 17:07 jcm.c -rwxrwxr-x 1 jcm jcm 15960 Mar 13 17:09 jcm.exe -rw-rw-r-- 1 jcm jcm 17934 Mar 13 17:08 jcm.i -rw-rw-r-- 1 jcm jcm 1496 Mar 13 17:09 jcm.o -rw-rw-r-- 1 jcm jcm 675 Mar 13 17:08 jcm.s -rw-rw-r-- 1 jcm jcm 203 Mar 15 21:03 makefile -rw-rw-r-- 1 jcm jcm 60 Mar 13 21:16 test.c -rw-rw-r-- 1 jcm jcm 1504 Mar 13 21:16 test.o -rw-rw-r-- 1 jcm jcm 102 Mar 11 21:04 t.h -rwxrwxr-x 1 jcm jcm 900344 Mar 14 19:09 yu -rw-rw-r-- 1 jcm jcm 165 Mar 14 17:52 yu.c jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ make make: 'code' is up to date. jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ make make: 'code' is up to date. jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ make make: 'code' is up to date. 先编译了code.c,然后继续make编译code.c,他不会执行,它提示code是新的。那他怎么知道code是最新的 它是通过看modify时间来看的,如果源文件的时间比可执行程序旧,就不会继续执行编译,因为编译也需要时间。 jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ stat code.c File: code.c Size: 68 Blocks: 8 IO Block: 4096 regular file Device: fc03h/64515d Inode: 398067 Links: 1 Access: (0664/-rw-rw-r--) Uid: ( 1001/ jcm) Gid: ( 1001/ jcm) Access: 2026-03-15 21:05:22.544538587 +0800 Modify: 2026-03-15 21:05:18.828394051 +0800 Change: 2026-03-15 21:05:18.828394051 +0800 Birth: 2026-03-15 21:05:18.828394051 +0800 jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ stat code File: code Size: 15960 Blocks: 32 IO Block: 4096 regular file Device: fc03h/64515d Inode: 398059 Links: 1 Access: (0775/-rwxrwxr-x) Uid: ( 1001/ jcm) Gid: ( 1001/ jcm) Access: 2026-03-15 23:55:05.384575948 +0800 Modify: 2026-03-15 23:55:05.384575948 +0800 Change: 2026-03-15 23:55:05.384575948 +0800 Birth: 2026-03-15 23:55:05.364575170 +0800 modify时间的改变是通过修改文件的内容。 access是通过访问文件。 change是修改文件的属性。 但是access虽然cat也是访问,但是修改access是有规律的,不可能你访问一次就修改时间,修改时间,要缓存在磁盘上,io操作。修改文件内容access会改变。如果每次读取(例如用 cat 查看)都立即将更新后的 atime 写回磁盘,会导致大量的磁盘 I/O,极大地降低系统性能。因为 atime 的修改和文件内容修改不同,它非常频繁且通常不那么关键。 当我们工程目标文件也用PHONY修饰,总是可以执行。 ![](https://i-blog.csdnimg.cn/direct/e4295ad92b5f4a93a4533ca6e8831581.png) ```cpp jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ make gcc -E code.c -o code.i gcc -S code.i -o code.s gcc -c code.s -o code.o gcc code.o -o code jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ make gcc code.o -o code jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ make gcc code.o -o code jcm@iZwz9c6v6ajdocnv9xkh8rZ:~$ make gcc code.o -o code ``` 那么code就会一直被链接,如果写出gcc code.c -o code。那么会一直编译,编译时间长,效率降低。 > *.PHONY:让make忽略源⽂件和可执⾏⽬标⽂件的M时间对⽐* 小结:最佳实践:clean可以被PHONY修饰,但是形成工程可执行文件不能被修饰。 gcc是通过比较源文件和可执行目标文件modify来对比,通过这个来查看是否执行,提升编译效率。 #### 更适用的makefile 假如我们有许多文件.c都要编译成可执行程序,如果按上面一个一个编译太麻烦了。 ![](https://i-blog.csdnimg.cn/direct/3555383b063a4361844706c58b609a9b.png) 我们使用变量替换,我们就可以编译很多文件, ```cpp jcm@iZwz9c6v6ajdocnv9xkh8rZ:~/lesson1$ make code10.c -> code10.o code1.c -> code1.o code2.c -> code2.o code3.c -> code3.o code4.c -> code4.o code5.c -> code5.o code6.c -> code6.o code7.c -> code7.o code8.c -> code8.o code9.c -> code9.o code.c -> code.o code10.o code1.o code2.o code3.o code4.o code5.o code6.o code7.o code8.o code9.o code.o-> code ``` 上面中的$是变量引用,在定义变量的时候,后面不是字符串,都要加$,比如makefile的函数或者变量。$\^代表所有的依赖文件,$@代表目标文件。$\<代表每一个依赖文件。所以在编译形成.o的时候是每一个文件编译一个.o。 ```cpp BIN=proc.exe # 定义变量 CC=gcc #SRC=$(shell ls *.c) # 采⽤shell命令⾏⽅式,获取当前所有.c⽂件名 SRC=$(wildcard *.c) # 或者使⽤ wildcard 函数,获取当前所有.c⽂件名 OBJ=$(SRC:.c=.o) # 将SRC的所有同名.c 替换 成为.o 形成⽬标⽂件列表 LFLAGS=-o # 链接选项 FLAGS=-c # 编译选项 RM=rm -f # 引⼊命令 $(BIN):$(OBJ) @$(CC) $(LFLAGS) $@ $^ # $@:代表⽬标⽂件名。 $^: 代表依赖⽂件列表 @echo "linking ... $^ to $@" %.o:%.c # %.c 展开当前⽬录下所有的.c。 %.o: 同时展开同 名.o @$(CC) $(FLAGS) $< # %<: 对展开的依赖.c⽂件,⼀个⼀个的交给gcc。 @echo "compling ... $< to $@" # @:不回显命令 .PHONY:clean clean: $(RM) $(OBJ) $(BIN) # $(RM): 替换,⽤变量内容替换它 .PHONY:test test: @echo $(SRC) @echo $(OBJ) ``` *** ** * ** *** *** ** * ** *** 我们在修改其中一个文件了![](https://i-blog.csdnimg.cn/direct/f4c066eb931c4e0c99c2f53ce42c4dbe.png) ```cpp jcm@iZwz9c6v6ajdocnv9xkh8rZ:~/lesson1$ make code10.c -> code10.o code1.c -> code1.o code2.c -> code2.o code3.c -> code3.o code4.c -> code4.o code5.c -> code5.o code6.c -> code6.o code7.c -> code7.o code8.c -> code8.o code9.c -> code9.o code.c -> code.o code10.o code1.o code2.o code3.o code4.o code5.o code6.o code7.o code8.o code9.o code.o-> code jcm@iZwz9c6v6ajdocnv9xkh8rZ:~/lesson1$ vim code.c jcm@iZwz9c6v6ajdocnv9xkh8rZ:~/lesson1$ make code.c -> code.o code10.o code1.o code2.o code3.o code4.o code5.o code6.o code7.o code8.o code9.o code.o-> code ``` 当我们再次编译的时候。只有code.c编译成code.o。因为其他的code1..2.c都已经编译过一次了。 ![](https://i-blog.csdnimg.cn/direct/0fcc3650191348b59654bbf6f42b9f1d.png)这就是为什么在设计自动化工程的时候要先编译在链接,而不是直接ggc code.c -o code。因为这样都要编译一次,编译也需要时间。

相关推荐
AuroBreeze2 小时前
RISC-V: Minimal U-mode implementation
linux·c语言·c++·risc-v
阿常呓语2 小时前
Linux命令 echo详解
linux·服务器·linux命令·echo
梦想的初衷~2 小时前
Python驱动的WRF模式自动化:业务化预报系统搭建实战
linux·python·自动化·大气科学·气候环境·风能太阳能
YQ_012 小时前
Windows + Ubuntu 双系统安装:不使用 GRUB,直接在开机时选择系统
linux·windows·ubuntu
橙子也要努力变强2 小时前
Linux I/O 缓冲区、inode、软硬链接与磁盘结构全解析
linux·c++·操作系统
子有内涵2 小时前
【Linux】程序地址空间(是什么?为什么?)
linux·运维·算法
异步的告白3 小时前
嵌入式Linux学习-默认规则
linux
wangjialelele3 小时前
详解Redis终端操作和Redis-plus-plus接口使用
linux·数据库·c++·redis·分布式·缓存·中间件
timi先生3 小时前
安装 GitLab
linux·运维