Linux《底子开发工具(中)》

打印 上一主题 下一主题

主题 946|帖子 946|积分 2838

在之前的Linux《底子开发工具(上)》当中已经相识了Linux当中到的两大底子的开发工具yum与vim;相识了在Linux当中怎样进行软件的下载以及实现的基本原理、知道了编辑器vim的基本使用方式,那么接下来在本篇当中将接下去继续来相识另外的两大底子的开发工具gcc/g++和自动化构建make/makefile,相信通过本篇的学习会使得你会有大的劳绩,一起加油吧!!!





1.gcc/g++ 

在之前的C语言的学习时我们就相识了步伐由我们实现的代码到终极的可实验步伐是要颠末编译和链接两个大过程的,并且编译还可以细化分为预处理、编译、汇编三个过程。在之前的C语言的编译和链接以及深入理解预处理就相识了以上提到的过程基本的功能是什么,实现之后的结果是什么。但是之前我们在学习的过程当中只是将各个过程实现的功能大要的进行讲解,接下来我们就将在Linux当中验证之前我们相识的各个过程具体实现的结果是否和我们的预期是一样的。


1.1 编译链接

预处理

我们知道在预处理进行的是去注释、宏替换、条件编译、头文件展开等的工作,那么在Linux要得到一个文件只进行预处理之后的文件就必要用到gcc/g++编译选项的指令
注:gcc/g++都是编译器,其中gcc只能编译C语言,而g++既可以编译C语言也可以编译C++
  1. gcc -E [原文件名] -o [生成.i的文件]
复制代码
使用以上指令就可以将源目标的文件天生一份进行预处理之后的文件,在此一般会将该文件的后缀命名为.i,以上指令当中-E就表示在gcc/g++实验的过程当中只要预处理实验完就停止-o之后表明预处理之后要天生的文件的名称
比方以下示例:
以下实现了一个test1.c的文件,之后我们使用vim在内里编写了以下的代码

接下来就来使用以上我们学习的指令来使得gcc编译过程中只实验预处理之后就停止,天生的文件名为test1.i
 实验了指令之后接下来就打开天生的test1.i,这时定位到main就可以看到我们代码当中的头文件#include<stdio.h>已经被展开,并且宏M也进行了替换;原先代码当中的注释也去掉了

 

编译 

我们知道在编译过程当中主要就是将预处理之后的C/C++等的语言代码转换为汇编指令,在Linux当中要使得gcc/g++在实验过程当中到编译之后就停止必要使用以下的指令
  1. gcc -S [源文件] -o [目标生成的.s文件]
复制代码
以上指令的-S选项就可以使得实验完编译就停止,-o选项之后的文件名表明的是要天生的目标文件名,一般会将只实验到编译之后的文件名后缀命名为.s

比方以下示例:
以上我们已经将对应的test1.c使用gcc -E天生了对应的test1.i,那么接下来就继续将该test1.i使用gcc -S天生对应的test1.s

接下来查看天生的test1.s就可以看到此时该文件内已经将原来的C语言代码转化为了汇编代码



汇编

我们知道汇编主要实现的就是将编译之后天生的汇编代码天生呆板码,也就是原先的代码当中变成了只含0、1的二进制码。在Linux当中要使得在gcc/g++实验时到汇编这一步就停止就必要使用以下的指令
  1. gcc -c [源文件] -o [生成的目标.o文件]
复制代码
以上的指令就当中-c表示的是使用gcc/g++时到汇编这一步实验完就停止-o之后的文件表示的是要天生的目标文件名。一般将只实验到汇编的文件后缀命名为.o 

比方以下示例:
以上我们已经使用gcc -S指令天生了对应的实验完编译之后的文件test1.s,那么接下来就继续使用gcc -c指令天生实验完汇编的文件test1.o

使用vim打开天生的test1.o文件之后就可以看到现在该文件内是一堆乱码,这就是由于此时该文件已经是一个二进制文件,直接打开是无法查看该文件的内容的

 

链接

在链接过程主要是将对应的.o文件和库文件进行链接
要将对应的原文件天生对应的可实验步伐就必要使用以下的指令

以上我们就将之前在C语言相识的步伐的编译过程在Linux
  1. gcc [源文件名] -o [目标文件]
复制代码
比方以下示例:
以上我们已经使用gcc -c 天生了实验汇编之后的文件,那么接下来继续将该文件使用gcc 形成test.out
 运行产生的test.out


当中具体的演示了一遍,但实在以上的知识在之前我们就已经把握了,在此只不外是在复习加深。实在在Linux的学习当中我们更要相识的是编译链接当中的链接,之前我们只是知道在汇编之后进行链接时会将此时的.o文件和其他的文件进行链接天生对应的可实验步伐,但是在这个过程当中具体是怎样实现的在此我们还无法进行详细的讲解,这是由于在该过程当中牵扯到了进程和文件的相干知识,因此我们会在相识完进程和文件系统之后在动静态库和动静态链接再对链接进行详细的相识



1.2 几个小问题


在此你可能就会有迷惑了,为什么在将我们写的代码转化为可实验步伐的过程当中要履历过编译之后再进行链接?
在我们实现一个大的工程项目时,不可克制地要办理差别用户的使用,就比如在一个网页的开发软件内就可能会有免费版和专业版的区别,那么此时在这两个版本当中就必要使用两份差别的代码吗?这样确实是可以的,不外一般是不会这样做,这是由于专业版当中相比免费的版本只是添加了一些功能,这时如果使用差别的底层代码就必要维护两份代码。在这种情况下条件编译的作用不就显示出来了吗,此时在免费版当中就将对应的专业版功能的代码进行条件编译,只要当用户是以专业版进入时才会将这份代码开放,这时在底层就只必要维护一份代码即可。
因此编译的作用简单来说就是减少语言的开发资本


接下来我们来相识什么是编译器的自举 
我们知道gcc是用于编译C语言的代码,最后将其编译为呆板语言。实在gcc底层的代码也是由C语言实现的,但是问题就来了语言的编译器和C语言那个先诞生呢?
实在是先诞生对应的编译器编译器的之后才产语言的,实在一开始最早的是使用纸袋打孔的方式来实现编程的,此时对应有孔无孔就分别表示1,0。该语言就是呆板语言。



之后使用呆板语言编写出了了汇编语言的编译器,我们知道编译器的作用可以来
就比方在C语言诞生之前先使用汇编语言产生C语言的的编译器可以编写软件,那么编译器不也是软件,因此就使用汇编语言写出了底层代码为汇编语言的编译器。
在此之后使用汇编语言编写出了C语言的编译器,在使用之后再使用C语言编写出底层代码为C语言的的编译器。
以上形貌的过程当中有汇编写出汇编语言的编译器、由C语言写出C语言的编译器都是属于编译器自举。


在此还有问题就是为什么在C、C++当中都是要将将对应的步伐代码转化为汇编语言再由汇编语言转化为呆板语言?
这实在就是为了提高转化的服从,由于在C/C++诞生之前就已经形成了完善的汇编转化为呆板语言的体系,所以在实现出C/C++之后只必要建立C/C++和汇编之间的转化关系即可;这相比要建立C/C++和呆板语言之间的直接关系要容易的多,并且服从还更高。



1.3 动静态库和动静态链接

接下来在相识了gcc/g++的使用之后接下来来相识动静态库。
• 静态库是指编译链接时,把库文件的代码全部加入到可实验文件中,因此升成的文件比力大,但在运
行时也就不再必要库文件了。厥后缀名一般为“.a”
• 动态库与之相反,在编译链接时并没有把库文件的代码加入到可实验文件中,而是在步伐实验时由
运行时链接文件加载库,这样可以节省系统的开销。动态库⼀般后缀名为“.so”

在此在Linux当中动态库一般是libXXXX.so的格式,其中XXXX是库的名称,静态库一般是XXXX.a的格式。在Windows当中动态库一般是XXXX.dll的格式,静态库一般是XXXX.lib的格式。

因此动态链接就是指在链接过程当中链接动态库,静态链接就是指在链接过程当中在链接的是静态库。
接下来我们就来看看Linux当中的C尺度库,在此C尺度库一般是保存在/lib64/libc.so.6 路径当中,接下来就使用ls指令来看看

 这时就可以看到C尺度库名称为c-2.17

 在此要看一个可可实验步伐的链接情况可以使用以下的指令
  1. ldd [文件名]
复制代码
比方以上天生的test.out使用ldd就可以看出该步伐进行的动态链接 ,链接的动态库如下所示


在此也可以使用file来查看可实验步伐链接的方式 

这时我们要知道的是Linux当中默认的是接纳动态链接的方式。
 但是如果要让在链接时进行静态链接呢?
由于Linux当中默认是不存在动态库的,因此我们要使用静态链接之前要先实验以下的指令
  1. yum install glibc-static libstdc++ -static -y
复制代码

之后要进行静态链接只必要在使用gcc时最后带上-static选项即可
比方以下示例:
将test1.c按照静态链接的方式天生对应的可实验步伐test2.out,这时就会发现静态链接形成的可实验步伐相比原来动态链接的可实验步伐文件大小要大许多。



以上我们就相识了动静态链接的一系列操作,但是现在我们还是未相识动态链接和静态链接有什么区别,但是现在我们又无法理性的从原理具体的讲解,那么接下来就来感性的理解,来通过一个故事来理解动静态链接。

   在此你是XXX一中的一名门生,由于之前在初中时学习就比力好,你考上了市里的一中。从初中开始你就喜欢在学习之后玩玩电脑游戏来放松放松,但是到了高中问题就来了,在高中里要住在学校的宿舍里,这就没法玩电脑了,这就使你很苦恼了,你之后有电脑游戏的放松才能让学习的服从提高。此时你想到在你家附近的不是有一个表哥是一中高三的门生吗?去找这位学长来相识有什么办理的方法,到了表哥的家里之后,从表哥的口里得知了在学校的门口向东200米左右有一个网咖,许多的学长都是去这个网咖里打游戏的。因此在入学之前就把表哥说的网咖的地点记到脑子里了。不久之后你就进入到了一中当中,到了周末你感到身心疲惫,近来没了游戏的放松你感觉本身对学习都提不上尽了,此时你就想到之前表哥说的网咖,想着我们早上把数学和 英语作业写完去网咖玩两个小时的游戏,之后下战书再把其他的作业写完。想玩你就快速的把相应的作业写完了,出了学校去网咖了打了两个小时的游戏,到了下战书你写其他的作业的时间感觉本身的学习服从都提升了。之后的日子里,你都在周末的时间去网咖打几个小时的游戏,有了放松的时间你的学习快速的提高。
  

  
  
在以上的故事当中实在你就是可实验步伐,你找的表哥就是编译器以及链接器,此时从表哥的口里得知网咖的地点就是进行动态的链接,之后在周末的时间你就相当于可实验步伐加载到了内存当中,实验到了要去上网就想到网咖的地点,这就是调用之前进办法态链接的时间得到的库路径,之后通过网咖的地点找到网咖就相当于找到的对应的动态库,之后从网咖回到学校进行写作业就相当于动态库的调用完成继续进行步伐的实验

   接下来继续来看以上故事的续集。
  随着越来越多的人知道了学校的附近有这么一个网咖,在周末的时间许多的门生都去这个网咖上网了,不久之后就被你们一中的校长知道了,究竟不是所有人都是像你一样去网咖是为了放松,大多数去的人都着迷在了游戏当中这就使得大多数门生的成绩大幅度的降落,校长想着是时间办理这个问题了,不久之后校长就告知附近的公安这家网咖非法的给未成年人上网,不久之后帽子叔叔就把这家网咖给拿下了。之后的一个周末当中和之前一样想去网咖放松一下发现网咖已经被封了,你就只好回宿舍了。之后的一段时间由于你无法在周末的时间上网来放松就让你没了学习的动力;学习成绩开始了下滑,从之前的年段前十掉到了百名开外。你的爸爸知道了你的成绩下滑之后就找你谈话,你就把你下滑的原因告诉了你的爸爸,你爸爸说这事放心我和你校长是好哥么,我去找他想想办法。之后你的爸爸就找了校长和他说了你学习成绩的降落是由于在周末的时间没法上网放松,寻常的时间没法上网查一些资料,之后和校长说能不能开个特例让你在宿舍里安一台电脑,只要之后你再出现大的成绩下滑就把电脑撤了。这时你的爸爸就还找到了原来的学校附近被封的网咖,从这个网咖内购入了一台电脑,不久之后你的宿舍了就安上了。有了电脑的放松你的学习服从大大的提升,很快就回到了学校的年段前十。其他的门生看到你在宿舍里安了电脑,就和一样也纷纷在本身的宿舍了安装了电脑。
  
  在以上的故事续集当中当原来的网咖被封之后你在本身的宿舍安装了电脑,这样上网不消去网咖里的操作实在就是静态链接,其特点就是直接将对应的库拷贝到可实验步伐当中,这样在必要调用相应的库就不必要在调用的时间再去指定的路径当中调用对应的库,可以直接在可实验步伐的内部就可以调用。

   因此通过以上故事的讲述就可以看出动静态链接的优劣如下所示:
动态链接:步伐在调用相应的库的时间只必要通过路径即可找到,因此可实验步伐的内部不必要进行库的拷贝,可实验步伐的内存会比力小,但是动态库是共享的,所有库不能丢失否则就会出现所有依靠该动态库的步伐在运行的时间出现错误。
  静态链接:优点是不依靠库,纵然一个库出现丢失,原来进行过静态链接的可实验步伐内部也不会出现运行的错误。但是静态链接必要将库拷贝到对应的可实验步伐内,这就会使得空间的浪费,包括内存、磁盘、网络等。
  

2. 自动化构建-make/Makefile

2.1 配景

在相识make以及makefile之前先来相识make以及makefile的基本配景
   • 会不会写makefile,从⼀个侧面说明了⼀个人是否具备完成大型工程的能力
• ⼀个⼯程中的源⽂件不计数,其按范例、功能、模块分别放在若⼲个目次中,makefile定义了⼀系列的规则来指定,哪些文件必要先编译,哪些⽂件必要后编译,哪些文件必要重新编译,甚⾄于进⾏更复杂的功能操作
• makefile带来的好处就是⸺“自动化编译”,⼀旦写好,只必要⼀个make下令,整个工程完全⾃动编译,极⼤的提⾼了软件开发的服从。
• make是⼀个下令工具,是⼀个解释makefile中指令的下令工具,⼀般来说,大多数的IDE都有这个下令,⽐如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了⼀种在工程方面的编译⽅法。
make是⼀条下令,makefile是⼀个文件,两个搭配使⽤,完成项目自动化构建。
  
2.2 make和makefile的使用方法 

在以上我们相识了make以及makefile的重要性,那么接下来就来相识怎么使用make以及makefile内的文件内容该怎样创建。
首先要知道的是要使用make下令的条件是在当前的所处的目次下,含闻名为makefile或者Makefile的文件,因此在当中路径下我们就就先创建一个名为makefile的文件。
当前目次下创建了一个test1.c的文件,该文件内的内容如下所示:

之前我们使用将该文件编译为可实验步伐是直接使用 gcc test1.c -o test1.out 来实现,而接下来我要使用的是先创建对应的makefile,之后再使用make下令来实现可实验步伐的创建。
在此makefile内的内容就如下所示:

 
在此以上就是一个简单的makefile的内容,在此我们写的第一行就将要天生的文件依靠的源文件的依靠关系写出来,之后再写明了这两个依靠文件之间的依靠方法,实在也就是提供了源文件转化为目标文件的方式。
   在此了依靠关系和依靠方法在现实生存当中可以映射到你和父母要生存费这件事上,只有你和父母的关系才能让你能实验向你的父母要生存费这个动作上,你的舍友就无法向你的父母索要。在此你和父母的关系就是依靠关系,你要钱的活动就是依靠方法,能实验依靠方法的条件是你和父母有依靠关系。
  注:在此makefile当中编写依靠方法时要在依靠关系之后另起一行,并且之前还要空4个字符,若之前你已经将vim进行配置,那么在依靠关系之后按回车就会自动换行并且空对应的字符

编写了对应的makefile之后接下来回到之前的目次下,使用make下令就可以看到会将对应依靠关系的的依靠方法进行实验,并且还在当前的目次下天生了对应的目标文件test1.out
实验该文件就可以得到该可实验步伐的输出内容


但实在以上我们编写的makefile是不完备的,一般在编写makefile的时间还要将项目整理工作也在makefile进行实现。
以上的maekfile在添加上整理功能之后如下所示:

以上就是添加上了clean之后的makefile,在此实在clean是一个伪目标文件,为什么接下来会讲解。

    • 像clean这种,没有被第⼀个目标文件直接或间接关联,那么它后⾯所定义的下令将不会被自动实验,不外,我们可以显示要make实验。即下令⸺“make clean”,以此来清除所有的目标文件,以便重编译。
• 但是⼀般我们这种clean的目标文件,我们将它设置为伪目标,用 .PHONY 修饰,伪目标的特性是,总是被实验的。
   
  
在此使用make时是会自顶向下扫描makefile文件,默认形成的是第一个目标文件,因此以上的使用make下令时会直接实验gcc test1.c -o test1.out
如果要想指定形成绩必要使用 make targetname,就比方以上的make clean
接下来就回到原来的目次下,实验make clean下令
 
实验了之后再使用 ll 指令就会发现之前创建的test.out被删除了,并且一连多次使用make clean也可以实验

但是如果是多次使用make下令就只有当第一次是可以实验的,接下来的都会报错,这是为什么呢?


要办理该问题就必要相识到ACM时间,在此我们是使用stat来查看对应文件的ACM时间
  1. stat [文件名]
复制代码


以上使用了stat下令之后就可以看到三个时间的信息,在此Access表示的是之后一次访问文件的时间,Modify表示的是就是文件近来一次内容修改的时间,Change表示的就是文件的属性最后一次被修改的时间。

在此系统在判定是否要实验对应依靠关系的依靠方法时实在比力的就是对应源文件的Modify和目标文件的Modify时间,当目标文件的时间要比源文件的时间要靠后是才实验对应的依靠方法

那么为什么在操作系统当中要这样做,为什么不直接在用户每次使用对应的make下令时都将对应的依靠方法进行实验呢?
这实在是为了提高编译的服从,究竟真实的情况不是像我们当前这样只是有一个源文件,真正的项目当中都是存在成百上千个源文件的,每一次编译都是必要泯灭大量的时间的,因此当源文件的内容未出现修改时就不再进行编译,只有当原文件的M时间在目标文件之后才进行编译。

相识了以上的问题之后接下来就可以来解答之条件到的clean的伪目标文件是什么了,在此伪目标文件就是在目标该文件之后的依靠方法不依据源文件和目标文件的M时间前后来判定是否实验,只要用户使用make下令实验之后就会实验该依靠方法

 
在以上我们相识makefile的基本编写方式,那么接下来进一步来理解makefile的推导原则
在以上我们相识了在编译当中是可以将编译具体划分为预处理、编译、链接三步的,那么接下来就将原来makefile内的一个依靠关系和依靠方法具体的展开

注:在此在makefile当中使用#可以进行注释
以上就实现了细节更加完备的makefile,接下来就回到之前的目次当中使用make下令

通过make下令输出的结果就可以看出实在在使用make指令时是将makefile内的依靠方法因此入栈,推导完毕依次出栈。


以上只是让我们相识make是会进行依靠关系的推导的,直到依靠文件是存在的。但是一般我们不会将makefile写成以上的情势,接下来写更加具通用性的makefile。
实在在真正的项目当中可能是会有多个.c文件的,在此一般都是将这些.c文件编译为.o文件,之后再和其他的第三方库进行链接打包成为对应的可实验步伐。

因此一般在makefile当中一般都会将对应的.c文件编译为.o之后再进行编译。
比方以上的makefile按照以上的要求就变为以下的情势:


但是以上的makefile不具有广泛性,接下来来继续修改,在此当中我们可以像在C/C++当中原因创建变量,在此创建变量的方式是使用 变量名= 变量值 ,之后要访问该变量就使用 $(变量) 的方式,在此可以相识为在C/C++当中指针的解引用一样。
在此实现了以下情势的makefile当要改变对应的文件名时就只必要将对应变量定义的位置进行修改即可。
 

以上我们改变完成的makefile虽然相比我们之前的实现的makefile有了更好的通配性,但是问题是当要实现非常多文件的编译成为可实验步伐的工作时工作以上的makefile还是无法实现,因此接下来我们还要继续来对以上的makefile进行修改

   当要实现将多个文件编译链接成为一个可实验步伐时,就必要改变以上的SRC,在此在makefile提供了如下所示的两种语法来实现
  

  

    改变了SRC之后接下来OBJ也要进行改变,改变结果如下所示:
  

    接下来还必要将对应的依靠关系和依靠方法也进行修改
  

  以上的依靠方法也可以按照原来的方式进行,但是一般还是会修改为以上的情势 其中$^ 表示的是依靠文件, $@ 表示的是目标文件
    接下来的依靠关系和依靠方法修改为一以下情势,其中 $< 表示的就是将所有的.c文件编译为同名的.o文件 
  

  完备的makefile就如下所示:


 
完成了具有更加广泛性的makefile之后接下来我们来创建100个.c文件来测试实现的makefile是否能实现要求


接下来使用make下令就会出现刷屏的情况,这是由于默认是会将所有的依靠方法都会回显的
 
如果要在实验make时不进行任何的回显就必要在原来的依靠方法上之前加上@


使用完make指令之后就可以看到当前目次下多了一个make天生的可实验步伐mytest
 






以上就是本篇的全部内容了,接下来还会在以下的篇章中讲解剩下的两个Linux基本开发工具git和gdb,未完待续……

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

用户国营

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表