Linux基础开发工具二(gcc/g++,自动化构建makefile)

3. 编译器gcc/g++

3.1 背景知识


1. 预处理(进行宏替换/去注释/条件编译/头文件展开等)

2. 编译(生成汇编)

3. 汇编(生成机器可识别代码)

4. 连接(生成可执行文件或库文件)

3.2 gcc编译选项

格式 : gcc 【选项】 要编译的文件 【选项】【目标文件】

1.预处理(进行宏替换)

预处理功能主要包括宏定义,⽂件包含,条件编译,去注释等。

预处理指令是以#号开头的代码行。

实例: gcc –E hello.c –o hello.i

选项“-E”,该选项的作⽤是让 gcc 在预处理结束后停⽌编译过程。

选项“-o”是指⽬标⽂件,“.i”⽂件为已经过预处理的C原始程序。

2. 编译(生成汇编)

在这个阶段中,gcc ⾸先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的⼯作,在检查⽆误后,gcc 把代码翻译成汇编语⾔。

用户可以使⽤“-S”选项来进⾏查看,该选项只进⾏编译⽽不进⾏汇编,⽣成汇编代码。

实例: gcc –S hello.i –o hello.s
 

3. 汇编(生成机器可识别代码)

汇编阶段是把编译阶段⽣成的“.s”⽂件转成⽬标⽂件

读者在此可使⽤选项“-c”就可看到汇编代码已转化为“.o”的⼆进制⽬标代码了

实例: gcc –c hello.s –o hello.o

4. 连接(生成可执行文件或库文件)


3.3 动态链接和静态链接

在我们的实际开发中,不可能将所有代码放在⼀个源⽂件中,所以会出现多个源⽂件,⽽且多个源⽂件之间不是独⽴的,⽽会存在多种依赖关系,如⼀个源⽂件可能要调⽤另⼀个源⽂件中定义的函数,但是每个源⽂件都是独⽴编译的,即每个*.c⽂件会形成⼀个*.o⽂件,为了满⾜前⾯说的依赖关系,则需要将这些源⽂件产⽣的⽬标⽂件进⾏链接,从⽽形成⼀个可以执⾏的程序。这个链接的过程就是静态链接。静态链接的缺点很明显:

  1. 浪费空间:因为每个可执⾏程序中对所有需要的⽬标⽂件都要有⼀份副本,所以如果多个程序对同⼀个⽬标⽂件都有依赖,如多个程序中都调⽤了printf()函数,则这多个程序中都含有

    printf.o,所以同⼀个⽬标⽂件都在内存存在多个副本;

  2. 更新⽐较困难:因为每当库函数的代码修改了,这个时候就需要重新进⾏编译链接形成可执⾏程序。但是静态链接的优点就是,在可执⾏程序中已经具备了所有执⾏程序所需要的任何东西,在执⾏的时候运⾏速度快

动态链接的出现解决了静态链接中提到问题。动态链接的基本思想是把程序按照模块拆分成各个相对独⽴部分,在程序运⾏时才将它们链接在⼀起形成⼀个完整的程序,⽽不是像静态链接⼀样把所有程序模块都链接成⼀个单独的可执⾏⽂件。

动态链接其实远⽐静态链接要常⽤得多。⽐如我们查看下 hello 这个可执⾏程序依赖的动态库,会发现它就⽤到了⼀个c动态链接库:

$ ldd hello
linux-vdso.so.1 => (0x00007fffeb1ab000)
libc.so.6 => /lib64/libc.so.6 (0x00007ff776af5000)
/lib64/ld-linux-x86-64.so.2 (0x00007ff776ec3000)# ldd命令⽤于打印程序或者库⽂件所依赖的共享库列表。

在这里涉及到⼀个重要的概念: 库!!!

我们的C程序中,并没有定义“printf”的函数实现,且在预编译中包含的“stdio.h”中也只有该函数的声明,⽽没有定义函数的实现,那么,是在哪⾥实“printf”函数的呢?

答案是:系统把这些函数实现都被做到名为 libc.so.6 的库文件中去了,在没有特别指定时,gcc 会到系统默认的搜索路径“/usr/lib”下进行查找,也就是链接到 libc.so.6 库函数中去,这样就能实现函数“printf”了,而这也就是链接的作用。

如何理解库?
为什么要有库?让程序员直接使用,提高开发效率,语言上的库更多的时提供公共的方法集合(c语言提供的printf需要stdio.h, c++提供STL容器 需要iostream),printf(“hello world” )是打印到了显示器硬件上,是c语言工程师把printf往显示器上打印的功能写好了把他放在库里面你直接调用;使你不用外部的东西直接在语言当中就能编程使用语言提供的方法能在语言层面调用printf,STL容器之类)把搭建上层应用所需要的所有底层功能全部按技术角度提前写好放入库,让程序员直接使用,提高开发效率。

动态库/共享库最终也是会加载到内存中的,只有一份,把公共的方法抽取出来,在系统中只有一份节省内存资源,磁盘里面不存速度慢一点。


 动态链接就是程序还没加载到内存中时,就已经和动态库建立了连接;

动态链接:

程序通过连接器获取了连接信息,要进行链接!!

进行链接就是去动态库获取写入方法的地址;

优点:节省资源;

缺点:动态库一旦丢失所有程序无法直接运行、速度慢;


静态链接:  把你要的方法直接拷贝到可执行程序中

动态库把方法直接给了连接器,连接器进行链接时,直接给程序,和动态库取消联系,不依赖任何库

优点:不依赖任何库,自己独立就能运行;

缺点:体积大,占据资源多(占据磁盘空间,内存空间)无法充分利用资源,加载速度受影响

我们的系统中一般默认没有安装c/c++的静态库,我们可以用命令行安装c/c++的静态库:

使用yum(适用于CentOS,RHEL,Fedora)centos:

sudo yum install glibc-static

sudo yum install libstdc++-static

如果需要完整的的开发工具链(如gcc、g++等),可以安装一下包:

sudo yum install gcc gcc-c++ make

使用apt(适用于Ubuntu,Debian等):

sudo apt install libc6-dev

sudo apt install libstdc++-static-dev

如果需要完整的的开发工具链(如gcc、g++等),可以安装一下包:

sudo apt install build-essential

3.4 静态库和动态库


静态库是指编译链接时,把库⽂件的代码全部加⼊到可执⾏⽂件中,因此⽣成的⽂件⽐较⼤,但在运⾏时也就不再需要库⽂件了。其后缀名⼀般为".a"

动态库与之相反,在编译链接时并没有把库⽂件的代码加⼊到可执⾏⽂件中,⽽是在程序执⾏时由运⾏时链接⽂件加载库,这样可以节省系统的开销。动态库⼀般后缀名为“.so”,如前⾯所述的libc.so.6 就是动态库。gcc 在编译时默认使⽤动态库。完成了链接之后,gcc 就可以⽣成可执⾏⽂件,如下所⽰。 gcc hello.o –o hello

gcc默认生成的⼆进制程序,是动态链接的,这点可以通过 file 命令验证。
 

Linux下,动态库XXX.so, 静态库XXX.a

Windows下,动态库XXX.dll, 静态库XXX.lib

如何查看是否已经安装epel-release源:

EPEL 仓库的配置文件通常位于 /etc/yum.repos.d/ 目录下。你可以列出该目录下的文件,看看是否有与 EPEL 相关的 repo 文件:

ls -l /etc/yum.repos.d/ | grep epel

也可以安装一个广泛使用的C++库集合,提供了大量的功能,从智能指针到正则表达式支持等

# 安装 Boost 静态库
sudo yum install boost-devel

二. 自动化构建 -make/Makefile

2.1 背景

会不会写makefile,从⼀个侧⾯说明了⼀个人是否具备完成⼤型工程的能力。

⼀个⼯程中的源⽂件不计数,其按类型、功能、模块分别放在若⼲个⽬录中,makefile定义了⼀系列的规则来指定,哪些⽂件需要先编译,哪些⽂件需要后编译,哪些⽂件需要重新编译,甚⾄于进⾏更复杂的功能操作

makefile带来的好处就是⸺“⾃动化编译”,⼀旦写好,只需要⼀个make命令,整个⼯程完全⾃动编译,极⼤的提⾼了软件开发的效率。

make是⼀个命令⼯具,是⼀个解释makefile中指令的命令⼯具,⼀般来说,⼤多数的IDE都有这个命令,⽐如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可⻅,makefile都成为了⼀种在⼯程⽅⾯的编译⽅法。

make是⼀条命令,makefile是⼀个文件,两个搭配使⽤,完成项目自动化构建

2.2 基本使用 

实例代码
 

#include <stdio.h>
int main()
{
printf("hello Makefile!\n");
return 0;
}

Makefile文件

myproc:myproc.c
gcc -o myproc myproc.c
.PHONY:clean
clean:
rm -f myproc

依赖关系

上⾯的⽂件myproc,它依赖myproc.c

依赖方法

gcc -o myproc myproc.c ,就是与之对应的依赖关系

项⽬清理

⼯程是需要被清理的

像clean这种,没有被第⼀个⽬标⽂件直接或间接关联,那么它后⾯所定义的命令将不会被⾃动执⾏,不过,我们可以显⽰要make执⾏。即命令⸺“make clean”,以此来清除所有的⽬标⽂件,以便重编译。

但是⼀般我们这种clean的⽬标⽂件,我们将它设置为伪⽬标,⽤ .PHONY 修饰,伪⽬标的特性是,总是被执⾏的。

这里就涉及到了总是被执行和不被执行两个概念。

这里直接看图详解:

 

输入make命令,make命令会自动在当前目录下 找Makefile,然后用make去解释Makefile里面的内容, 从上往下执行Makefile中的编译方法,帮我们形成可执行程序。

有了.PHONY,make clean 就可以重复执行 rm -f code。     

.PHONY:让make忽略源文件和可执行标文件的M时间对比
 

2.3 推导过程 

 

myproc:myproc.o
gcc myproc.o -o myprocmyproc.o:myproc.s
gcc -c myproc.s -o myproc.omyproc.s:myproc.i
gcc -S myproc.i -o myproc.smyproc.i:myproc.c
gcc -E myproc.c -o myproc.i.PHONY:clean
clean:
rm -f *.i *.s *.o myproc

编译过程 

$ make
gcc -E myproc.c -o myproc.i
gcc -S myproc.i -o myproc.s
gcc -c myproc.s -o myproc.o
gcc myproc.o -o myproc

 

make是如何工作的,在默认的方式下,也就是我们只输入make命令。那么:

  1. make会在当前⽬录下找名字叫“Makefile”或“makefile”的⽂件。
  2. 如果找到,它会找⽂件中的第⼀个⽬标⽂件(target),在上⾯的例⼦中,他会找到 myproc 这个⽂件,并把这个⽂件作为最终的⽬标⽂件。
  3. 如果 myproc ⽂件不存在,或是 myproc 所依赖的后⾯的 myproc.o ⽂件的⽂件修改时间要⽐ myproc 这个⽂件新(可以⽤ touch 测试),那么,他就会执⾏后⾯所定义的命令来⽣成myproc 这个⽂件。
  4. 如果 myproc 所依赖的 myproc.o ⽂件不存在,那么 make 会在当前⽂件中找⽬标为myproc.o ⽂件的依赖性,如果找到则再根据那⼀个规则⽣成 myproc.o ⽂件。(这有点像⼀个堆栈的过程)
  5.  当然,你的C⽂件和H⽂件是存在的啦,于是 make 会⽣成 myproc.o ⽂件,然后再⽤ myproc.o ⽂件声明 make 的终极任务,也就是执⾏⽂件 hello 了。
  6. 这就是整个make的依赖性,make会⼀层⼜⼀层地去找⽂件的依赖关系,直到最终编译出第⼀个⽬标⽂件。
  7.  在找寻的过程中,如果出现错误,⽐如最后被依赖的⽂件找不到,那么make就会直接退出,并报错,⽽对于所定义的命令的错误,或是编译不成功,make根本不理。
  8. make只管文件的依赖性,即,如果在我找了依赖关系之后,冒号后⾯的⽂件还是不存在,那么就停止工作


 

输入make命令时,会读取当前目录下的Makefile文件,自顶向下对文件进行扫描,首先会发现code依赖的code.o不存在,因为code.o也有依赖关系,所以make进而找code.o的依赖关系,依次往下。到最后找到code.i依赖的code.c,依赖文件列表code.c本身在当前目录下是已经存在的,所以code.c已经具备了能够进行形成code.i的条件了,所以make就会执行code.i的依赖方法gcc -E code.c -o code.c这条命令,一旦code.i形成那么code.s,code.s所对应的依赖关系也有了,就会执行他的依赖方法。依次往上。---这就是make自动推导的过程。

当识别到code.o不存在会向下找,因为code.o也有依赖关系,所以make除了找code.o的依赖关系,还会把上一组code.o形成code的这组依赖方法入栈,然后依次往下,等到识别到code.c已经具备了能够进行形成code.i的条件时,然后依次出栈执行依赖方法。

不想看这个命令执行的过程,只看结果,前面加@,关闭回显

 

2.4 扩展语法

有了变量的定义,我们要定义的目标文件叫Bin,

源文件SRC

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             # 引⼊命令

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/83485.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PostGIS实现栅格数据入库-raster2pgsql

raster2pgsql使用与最佳实践 一、工具概述 raster2pgsql是PostGIS提供的命令行工具,用于将GDAL支持的栅格格式(如GeoTIFF、JPEG、PNG等)导入PostgreSQL数据库,支持批量加载、分块切片、创建空间索引及金字塔概览,是栅格数据入库的核心工具。 二、核心功能与典型用法 1…

精益数据分析(64/126):移情阶段的用户触达策略——从社交平台到精准访谈

精益数据分析&#xff08;64/126&#xff09;&#xff1a;移情阶段的用户触达策略——从社交平台到精准访谈 在创业的移情阶段&#xff0c;精准找到目标用户并开展深度访谈是验证需求的关键。今天&#xff0c;我们结合《精益数据分析》中的方法论&#xff0c;探讨如何利用Twit…

ORACLE RAC环境REDO日志量突然增加的分析

服务概述 CRM系统在7/11日出现REDO日志产生量突增&#xff0c;达到平时产生量的20倍以上&#xff0c;对数据同步已经造成了较大的影响。工程师接到故障申报后&#xff0c;及时进行响应&#xff0c;通过对相关日志等信息的深入分析&#xff0c;整理汇总此文档。 二、数据库REDO…

注册表设置windows背景护眼色

方法一&#xff1a; CtrlR&#xff0c;输入regedit打开注册表 HKEY_CURRENT_USER\Control Panel\Colors 右侧窗口Windows键值由255 255 255改为202 234 206。 方法二&#xff1a; 还是注册表 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\DefaultColo…

回溯法理论基础 LeetCode 77. 组合 LeetCode 216.组合总和III LeetCode 17.电话号码的字母组合

目录 回溯法理论基础 回溯法 回溯法的效率 用回溯法解决的问题 如何理解回溯法 回溯法模板 LeetCode 77. 组合 回溯算法的剪枝操作 LeetCode 216.组合总和III LeetCode 17.电话号码的字母组合 回溯法理论基础 回溯法 回溯法也可以叫做回溯搜索法&#xff0c;它是一…

自己手写tomcat项目

一&#xff1a;Servlet的原理 在Servlet(接口中)有&#xff1a; 1.init():初始化servlet 2.getServletConfig()&#xff1a;获取当前servlet的配置信息 3.service():服务器&#xff08;在HttpServlet中实现&#xff0c;目的是为了更好的匹配http的请求方式&#xff09; 4.g…

兰亭妙微:用系统化思维重构智能座舱 UI 体验

兰亭妙微设计专注于以产品逻辑驱动的界面体验优化&#xff0c;服务领域覆盖AI交互、智能穿戴、IoT设备、智慧出行等多个技术密集型产业。我们倡导以“系统性设计”为方法论&#xff0c;在用户需求与技术边界之间找到最优解。 此次智能驾驶项目&#xff0c;我们为某车载平台提供…

ubuntu安装google chrome

更新系统 sudo apt update安装依赖 sudo apt install curl software-properties-common apt-transport-https ca-certificates -y导入 GPG key curl -fSsL https://dl.google.com/linux/linux_signing_key.pub | gpg --dearmor | sudo tee /usr/share/keyrings/google-chrom…

技术测评:小型单文件加密工具的功能解析

最近在测试一款名为OEMexe的文件加密工具&#xff0c;发现它确实有一些独特之处值得分享。这款软件体积非常小巧&#xff0c;仅209KB&#xff0c;属于绿色单文件版程序&#xff0c;无需安装即可直接运行。 主要特点 多格式支持&#xff1a;能够处理多种常见文件格式&#xff0…

Java-Objects类高效应用的全面指南

Java_Objects类高效应用的全面指南 前言一、Objects 类概述二、Objects 类的核心方法解析2.1 requireNonNull系列方法&#xff1a;空指针检查的利器2.2 equals方法&#xff1a;安全的对象比较2.3 hashCode方法&#xff1a;统一的哈希值生成2.4 toString方法&#xff1a;灵活的对…

计网| 网际控制报文协议(ICMP)

目录 网际控制报文协议&#xff08;ICMP&#xff09; 一、ICMP 基础特性 二、ICMP 报文分类及作用 差错报告报文 询问报文 网际控制报文协议&#xff08;ICMP&#xff09; ICMP&#xff08;Internet Control Message Protocol&#xff0c;网际控制报文协议&#xff09;是 …

微服务初步学习

系统架构演变过程 一、单体架构 前后端都在一个项目中&#xff0c;包括我们现在的前后端分离开发&#xff0c;都可以看作是一个单体项目。 二、集群架构 把一个服务部署多次&#xff0c;可以解决服务不够的问题&#xff0c;但是有些不必要的功能也跟着部署多次。 三、垂直架…

Web安全基础:深度解析与实战指南

一、Web安全体系架构的全面剖析 1.1 分层防御模型(Defense in Depth) 1.1.1 网络层防护 ​​防火墙技术​​: 状态检测防火墙(SPI):基于连接状态跟踪,阻断非法会话(如SYN Flood攻击)下一代防火墙(NGFW):集成IPS、AV、URL过滤(如Palo Alto PA-5400系列)配置示例…

使用大语言模型从零构建知识图谱(上)

从零到一&#xff1a;大语言模型在知识图谱构建中的实操指南 ©作者|Ninja Geek 来源|神州问学 将你的 Pandas data frame 利用大语言模型转换为知识图谱。从零开始构建自己的基于大语言模型的图谱构建器&#xff0c;实际使用 Langchain 的 LLMGraphTransformer &#xff…

18.自动化生成知识图谱的多维度质量评估方法论

文章目录 一、结构维度评估1.1 拓扑结构评估1.1.1 基础图论指标1.1.2 层级结构指标 1.2 逻辑一致性评估1.2.1 形式逻辑验证1.2.2 约束满足度 二、语义维度评估2.1 语义一致性评估2.1.1 标签语义分析2.1.2 关系语义评估 2.2 语义表示质量2.2.1 嵌入质量2.2.2 上下文语义评估 三、…

go 集成base64Captcha 支持多种验证码

base64Captcha 是一个基于 Go 语言开发的验证码生成库&#xff0c;主要用于在 Web 应用中集成验证码功能&#xff0c;以增强系统的安全性。以下是其主要特点和简介&#xff1a; base64Captcha主要功能 验证码类型丰富&#xff1a;支持生成多种类型的验证码&#xff0c;包括纯…

制作大风车动画

这个案例的风车旋转应用了图形变换来实现&#xff0c;速度和缩放比例应用slider来实现&#xff0c;其中图片的速度&#xff0c;图片大小的信息通过State来定义变量管理&#xff0c;速度和和缩放比例的即时的值通过Prop来管理。 1. 案例效果截图 2. 案例运用到的知识点 2.1. 核…

代码随想录算法训练营第四十二四十三天

LeetCode/卡码网题目: 42. 接雨水84. 柱状图中最大的矩形98. 所有可达路径 其他: 今日总结 往期打卡 42. 接雨水 跳转: 42. 接雨水 学习: 代码随想录公开讲解 问题: 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能…

SEO 优化实战:ZKmall模板商城的 B2C商城的 URL 重构与结构化数据

在搜索引擎算法日益复杂的今天&#xff0c;B2C商城想要在海量信息中脱颖而出&#xff0c;仅靠优质商品和营销活动远远不够。ZKmall模板商城以实战为导向&#xff0c;通过URL 重构与结构化数据优化两大核心策略&#xff0c;帮助 B2C 商城实现从底层架构到搜索展示的全面升级&…

Linux自有服务

自有服务概述 概述 自有服务&#xff0c;即不需要用户独立去安装的软件的服务&#xff0c;而是当系统安装好之后就可以直接使用的服务&#xff08;内置&#xff09; 显示服务 显示服务 命令&#xff1a;systemctl \[选项] 选项参数 list-units --type service --all&#x…