GCC工具详解【Linux知识贩卖机】

在这里插入图片描述
很多人在喧嚣声中登场,也有少数人在静默中退出。 --单独中的洞见2

文章目录

  • 简介
  • 程序到可执行文件
    • 链接
    • 动态链接和静态链接
    • 动态库和静态库
    • 动态库和静态库的打包
      • 打包静态库
      • 打包动态库
      • 选项
    • -static
  • 总结

简介

在这里插入图片描述

GCC(GNU Compiler Collection) 是一个由GNU计划开发的编程语言编译器套装,用于支持多种编程语言。GCC最初是为GNU操作系统而开发的,但它现在也被广泛用于其他操作系统,包括各种版本的Linux、Unix、BSD和一些嵌入式系统。

GCC的一些主要特征和用途如下:

  1. 多语言支持:

    • GCC支持多种编程语言,包括C、C++、Fortran、Ada、Objective-C和其他一些语言。
    • 对于C++,有专门的g++命令,它是GCC套装中的C++编译器。
  2. 交叉编译:

    • GCC可以用于交叉编译,即在一种平台上生成另一种平台上运行的可执行文件。
  3. 优化:

    • 提供多个优化选项,允许程序员在编译时进行性能优化。
  4. 标准符合性:

    • GCC致力于遵循编程语言的标准,如ISO C、ISO C++等,以确保生成的代码在不同平台上的一致性。
  5. 开源:

    • GCC是自由软件,使用GNU通用公共许可证(GPL)发布,这意味着用户可以查看、修改和分发源代码。
  6. 支持多种平台:

    • GCC可以在多种硬件体系结构和操作系统上使用,包括x86、ARM、PowerPC等,并且可以在各种Linux发行版、Unix系统以及其他操作系统上运行。
  7. 插件支持:

    • GCC具有插件架构,允许开发者编写并使用插件来扩展编译器的功能。
  8. 生态系统:

    • GCC是一个庞大的生态系统的一部分,许多项目和库都依赖于GCC进行编译。

基本上,GCC是一个功能强大、灵活且广泛使用的编译器套装,为开发者提供了生成高质量可执行文件的工具。

程序到可执行文件

程序的整个编译过程可以分为多个阶段,这些阶段的主要任务是将高级源代码转换为可执行文件。典型的编译过程的阶段如下:

  1. 预处理(Preprocessing):

    • 任务:在实际编译之前对源代码进行预处理。
    • 工具:预处理器(通常是 cpp)。
    • 过程:包括宏展开、头文件包含、条件编译等。
  2. 编译(Compilation):

    • 任务:将预处理后的源代码翻译成汇编语言。
    • 工具:编译器(如 gccg++)。
    • 过程:将源代码翻译成汇编代码。
  3. 汇编(Assembly):

    • 任务:将汇编代码翻译成机器代码。
    • 工具:汇编器(通常是 as)。
    • 过程:将汇编代码翻译成二进制目标文件。
  4. 链接(Linking):

    • 任务:将多个目标文件和库文件组合成一个可执行文件。
    • 工具:链接器(通常是 ld)。
    • 过程:解析符号引用、地址重定位、符号解析,生成最终的可执行文件。
  5. 加载(Loading)(可选):

    • 任务:将可执行文件加载到内存中,准备执行。
    • 工具:操作系统的加载器。
    • 过程:将可执行文件从磁盘加载到内存,并将控制权转交给程序的入口点。

整个过程可以用以下命令表示(以C语言为例):

# 预处理
cpp source_code.c > intermediate_code.i# 编译
gcc -S intermediate_code.i -o assembly_code.s# 汇编
as assembly_code.s -o object_code.o# 链接
gcc object_code1.o object_code2.o -o executable_file

在实际项目中,这些步骤可能会合并或者包含其他步骤,例如优化(Optimization)阶段。在编译器的命令行选项中,你可以使用不同的标志来控制每个阶段的行为,以满足特定的需求。

tips:

cppgcc -E 的作用是相似的,它们都用于进行预处理。实际上,在大多数系统上,cpp 实际上就是 gcc -E 的一个符号链接。

  • cpp 命令:

  • cpp 是 C/C++ 的预处理器,它执行宏展开、条件编译等预处理任务。

  • 可以单独使用,如 cpp source_code.c -o output.i

  • 在一些系统上,cpp 可能是 gcc 中的一部分,而在另一些系统上,它可能是一个独立的工具。

  • gcc -E 命令:

  • gcc -Egcc 的一个选项,用于执行预处理操作。

  • 它实际上就是调用 cpp 进行预处理,但是通过 gcc 命令可以更方便地指定其他编译选项。

  • 使用方式为 gcc -E source_code.c -o output.i

在这里插入图片描述

所以,cppgcc -E 的效果基本相同,都是执行 C/C++ 源代码的预处理阶段。在实践中,你可以根据需要选择使用其中的一个。如果你只需要进行预处理而不需要其他编译阶段,cpp 可能更直接,而如果你希望通过 gcc 使用其他编译选项,那么就可以使用 gcc -E

类似于 cppgcc -E 的关系,asgcc -c 也有相似的关系。

  • as 命令:

  • as 是汇编器,用于将汇编代码转换为目标文件。

  • 可以单独使用,如 as assembly_code.s -o object_code.o

  • gcc -c 命令:

  • gcc -cgcc 的一个选项,用于执行编译操作并生成目标文件。

  • 使用方式为 gcc -c source_code.c -o object_code.o

  • 这实际上调用了 cc1(GCC 的前端)来进行编译,再使用 as 进行汇编。

在这里插入图片描述

因此,asgcc -c 在生成目标文件的过程中都会涉及到汇编阶段,只是 gcc -c 在执行时会将编译器的一些默认选项应用于源代码。在实践中,你可以根据需要选择使用其中的一个。如果只需进行汇编,as 可能更直接,而如果你想使用 gcc 的其他编译选项,那么可以使用 gcc -c

链接

粗略的说,链接是编程中的最后一个阶段,其主要任务是将多个目标文件和库文件组合成一个可执行文件。在链接阶段,各个目标文件之间的引用关系被解析,形成最终的可执行文件。

具体地说,链接的主要步骤包括:

步骤行为
1. 符号解析在编译过程中,各个源文件中可能存在引用其他文件中定义的函数或变量的情况。符号解析阶段会解决这些引用,确定它们的实际地址。
2. 地址重定位在编译过程中,生成的目标文件中包含相对地址(相对于文件开头的地址)。在链接阶段,这些相对地址需要被转换为绝对地址,以便最终的可执行文件能够正确地执行。
3. 库链接如果程序使用了外部库,链接器会将程序与这些库进行链接,将库的代码和数据合并到最终的可执行文件中。
4. 生成可执行文件:在解析符号、重定位地址、链接库之后,链接器将所有的目标文件和库文件组合在一起,生成最终的可执行文件。
5. 生成符号表链接过程生成一个符号表,其中包含了程序中所有函数和变量的地址信息。这对于动态链接、调试以及其他操作是很重要的。

链接过程的目标是产生一个可以直接在操作系统上运行的可执行文件。这个文件包含了程序的机器代码、数据、符号表等信息。

动态链接和静态链接

链接又可以分为静态链接和动态链接两种形式,他们是两种将程序组合成可执行文件的方式。

静态链接是在编译时进行。链接器将所有模块的代码和数据合并为一个单独的可执行文件。生成的可执行文件包含所有所需的代码和数据,形成一个完全独立的可执行文件。这样链接生成的可执行文件独立于系统上已安装的库,可以在不同的系统上运行。并且由于所有代码都被包含在可执行文件中,程序的启动和执行速度可能更快。

缺点是生成的可执行文件通常较大,因为包含了所有的代码和数据。且如果库发生变化,需要重新编译并重新链接整个程序。


动态链接是在运行时进行。链接器将程序模块与共享库的链接推迟到程序加载和运行时。生成的可执行文件包含程序的主要代码和动态链接器信息。共享库文件中包含共享的代码和数据,可以在多个程序之间共享。z这样链接生成的执行文件较小,因为只包含程序的主要代码和动态链接器信息。并且如果库发生变化,只需要更新库文件,而不需要重新编译整个程序,多个程序还可以共享同一个库,减少内存占用。

缺点是依赖于系统上已安装的共享库,可能导致兼容性和依赖性的问题。并且由于需要在运行时加载和链接共享库,可能导致一些性能开销。

因此在实践中,选择使用静态链接或动态链接取决于项目的特定需求和设计考虑。有时也可以采取混合的方式,即将一些核心的库静态链接,而其他的库动态链接。这样可以在某种程度上兼顾文件大小、独立性和更新的方便性。

动态库和静态库

动态库和静态库是两种不同的库文件类型,静态库和动态库通常是为静态链接和动态链接方式而设计的,在编译时,如果你使用静态链接,你会链接到静态库。如果你使用动态链接,你会链接到动态库。

动态库通常以 .so(在类Unix系统,如Linux上)或 .dll(在Windows上)为后缀,包含可执行代码和数据,但这些库的加载和链接是在运行时进行的。在编译时并不将库的代码和数据嵌入可执行文件中,而是在程序加载运行时由操作系统动态加载。

优点描述
共享性动态库可以多个程序可以共享同一个动态库,减少内存占用。
更新方便如果库发生变化,只需要更新库文件,而不需要重新编译整个程序。
热更新可以在程序运行时动态加载和卸载库,实现热更新的功能。
缺点描述
依赖性程序在运行时需要系统上已安装的相应动态库,可能导致兼容性和依赖性的问题。
性能开销加载和链接库的过程可能引入一些性能开销。

静态库通常以 .a(在类Unix系统上)或 .lib(在Windows上)为后缀,包含编译时需要的可执行代码和数据,它们会被静态地嵌入到可执行文件中。在编译时将库的代码和数据嵌入到可执行文件中,形成一个完全独立的可执行文件。

优点描述
独立性生成的可执行文件独立于系统上已安装的库,可以在不同的系统上运行。
性能由于所有代码都被包含在可执行文件中,程序的启动和执行速度可能更快。
缺点描述
文件大小生成的可执行文件通常较大,因为包含了所有的代码和数据。
更新困难如果库发生变化,需要重新编译并重新链接整个程序。

在实际项目中,开发者可以根据项目的需求和设计考虑选择使用动态库、静态库,或者两者混合使用。有时候,静态库和动态库的组合使用可以在一定程度上兼顾文件大小、独立性和更新的方便性。

动态库和静态库的打包

在软件开发中,打包(或者称为构建)静态库和动态库通常是通过编译器和一些构建工具完成。

打包静态库

  1. 编写源代码

    • 编写你的 C 或 C++ 源代码文件。
  2. 编译为目标文件

    • 使用编译器将源代码编译为目标文件(.o.obj)。
      gcc -c my_library.c -o my_library.o
      
  3. 打包为静态库

    • 使用 ar 工具将目标文件打包为静态库(.a.lib)。
      ar rcs libmy_library.a my_library.o
      
  4. 使用静态库

    • 在编译时,将静态库链接到可执行文件中。
      gcc my_program.c -o my_program -L. -lmy_library
      

在这里插入图片描述

打包动态库

  1. 编写源代码

    • 编写你的 C 或 C++ 源代码文件。
  2. 编译为目标文件

    • 使用编译器将源代码编译为目标文件。
      gcc -fPIC -c my_library.c -o my_library.o
      
  3. 生成动态库

    • 使用编译器将目标文件生成动态库(.so.dll)。
      gcc -shared -o libmy_library.so my_library.o
      
  4. 使用动态库

    • 在编译时,链接动态库;在运行时,系统会动态加载和链接动态库。
      gcc my_program.c -o my_program -L. -lmy_library
      

在这里插入图片描述

上述步骤中的关键点:

  • -fPIC(Position Independent Code)选项用于生成与地址无关的代码,是动态库的要求。
  • -shared选项用于生成共享库。

选项

这里的示例假设在同一目录下进行编译和链接。如果库文件位于不同目录,可能需要使用 -I-L 选项来指定头文件和库文件的搜索路径。

其中-L 选项用于指定库文件的搜索路径。编译器在链接时使用这个路径来查找库文件。-I 选项用于指定头文件的搜索路径。编译器在编译时使用这个路径来查找头文件。-l 选项用于指定链接时需要使用的库。通常与 -L 选项一起使用,指定库文件的名称。

例如:

gcc my_program.c -o my_program -L/path/to/library -lmy_library

-L/path/to/library 告诉编译器在 /path/to/library 目录下查找库文件,而 -lmy_library 则表示链接名为 libmy_library.so(或 libmy_library.a)的库文件。

gcc -I/path/to/include my_program.c -o my_program

-I/path/to/include 告诉编译器在 /path/to/include 目录下查找头文件。

-static

-static 是一个编译器选项,用于在编译时强制链接静态版本的库,而不是默认的动态版本。这个选项通常用于生成不依赖于系统上已安装的动态库的可执行文件。

当使用 -static 选项时,编译器将尽可能地链接静态库,而不是动态库。这意味着可执行文件中包含了所有所需的代码和数据,而不需要在运行时依赖于系统上已安装的动态库。这对于创建独立、可移植的可执行文件是有用的,因为它们不依赖于目标系统上已安装的共享库。

使用 -static 选项的例子:

gcc -static my_program.c -o my_program

这将编译 my_program.c 并链接到静态库,生成一个不依赖于动态库的可执行文件 my_program。请注意,使用 -static 选项可能会增加可执行文件的大小,因为它包含了所有的库代码和数据。

需要注意的是,有些库可能没有静态版本,因此在使用 -static 选项时,需要确保所需的库都有可用的静态版本。如果某个库没有静态版本,使用 -static 选项可能会导致链接错误。

总结

文章介绍了GCC工具的一些用法,包括程序到可执行文件过程中的一些细节,顺带将动静态库和动静态链接进行介绍,还介绍了一些常见的选项。希望文章内容对你有帮助。

在这里插入图片描述

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

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

相关文章

计算机中丢失mfc140u.dll怎么解决

mfc140u.dll是一个Microsoft Visual C库文件,主要用于MFC(Microsoft Foundation Class)应用程序的开发。它包含了MFC应用程序所需的一些常用功能,如对话框、窗口、菜单等。当mfc140u.dll丢失时,可能会导致MFC应用程序无…

思科9300交换机使用USB进行升级ISO

一、下载ISO 一、网址 Software Download - Cisco Systems 二、找到型号 四、选择XE 软件 五、进行下载 二、COPY 进 U盘 一、、请注意!如果你的U盘不是Fat32文件格式则交换机读取不了,请先格式化再复制文件。 二、下载后将 bin文件复制到U盘。 1.扩展…

idea Plugins 搜索不到插件

Settings — System Settings — HTTP Proxy,打开HTTP Proxy 页面,设置自动发现代理: 勾选Atuto-detect proxy settings,勾选Automatic proxy configuration URL,输入: https://plugins.jetbrains.com/id…

【Python】AppUI自动化—appium自动化元素定位、元素事件操作(17)下

文章目录 前言一.Appium 元素定位1.定位方式种类2.如何定位2.1 id定位2.2 className定位2.3 content-desc 定位2.4 Android Uiautomator定位4.1 text定位4.2 text模糊定位4.3 text正则匹配定位4.4 resourceId定位4.5 resourceId正则匹配定位4.6 className定位4.7 className正则…

No184.精选前端面试题,享受每天的挑战和学习

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云课上架的前后端实战课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入…

适用于初学者的 .NET MAUI

适用于初学者的 .NET MAUI | Microsoft Learn 记录微软Learn中用到的代码。文章比较粗糙,大部分是项目代码粘贴。想详细学习的可到上面的链接学习,代码可以从这里复制后直接运行。 练习中一共有两个页面: 1、MainPage.xaml 用于添加列表中的…

No182.精选前端面试题,享受每天的挑战和学习

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云课上架的前后端实战课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入…

【Unity实战】实现强大通用易扩展的对话系统(附项目源码)

文章目录 先看看实现的最终效果前言素材前期准备工作1. 简单绘制地形2. 绘制对话框3. 配置人物动画4. 实现简单的控制人物移动 控制对话框的显示隐藏定义对话内容实现简单的对话功能逐字打印效果按下按键快速显示文本实现多个NPC配置不同对话扩展TextAsset 读取文档文件实际应用…

No183.精选前端面试题,享受每天的挑战和学习

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云课上架的前后端实战课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入…

Mac电脑配置Flutter开发环境

1.进入官网下载页: Flutter SDK releases | Flutter 可以看到有 Windows、macOS、Linux三种系统的下载包 选择macOS,然后点击下载 Stable channel(稳定版)中的最新版本,下载完成后可以移动到资源库Library中。 2.下载…

TCP触发海康扫码相机S52CN-IC-JQR-NNN25

PC环境设置 为保证客户端正常运行以及数据传输的稳定性,在使用客户端软件前,需要对 PC 环境 进行设置 关闭防火墙 操作步骤如下: 1. 打开系统防火墙。 2. 在自定义设置界面中,选择关闭防火墙的对应选项,并单击…

74hc595模块参考

74hc595模块参考 8位串行并行输出(SIPO)移位寄存器 使用74HC595移位寄存器扩展微控制器上的输出引脚数量。如果你需要扩充输入引脚的数量那么你需要74HC165移位寄存器。 SER(串行输入)引脚用于一次一位地将数据发送到移位寄存器…

快速教程|如何在 AWS EC2上使用 Walrus 部署 GitLab

Walrus 是一款基于平台工程理念的开源应用管理平台,致力于解决应用交付领域的深切痛点。借助 Walrus 将云原生的能力和最佳实践扩展到非容器化环境,并支持任意应用形态统一编排部署,降低使用基础设施的复杂度,为研发和运维团队提供…

459. 重复的子字符串

459. 重复的子字符串 原题链接:完成情况:解题思路:参考代码:__459重复的子字符串_枚举__459重复的子字符串_字符串匹配__459重复的子字符串_KMP算法__459重复的子字符串_优化的KMP算法 错误经验吸取 原题链接: 459. …

酷开科技持续推动智能投影行业创新发展

近年来,投影仪逐渐成为年轻人追捧的家居时尚单品。据国际数据公司(IDC)报告显示,2022年中国投影机市场总出货量505万台,超80%为家用投影仪。相比于电视,投影仪外观小巧、屏幕大小可调节,无论是卧…

OpenCV:图像旋转与缩放

人工智能的学习之路非常漫长,不少人因为学习路线不对或者学习内容不够专业而举步难行。不过别担心,我为大家整理了一份600多G的学习资源,基本上涵盖了人工智能学习的所有内容。点击下方链接,0元进群领取学习资源,让你的学习之路更加顺畅!记得…

从白日梦到现实:推出 Elastic 的管道查询语言 ES|QL

作者:George Kobar, Bahubali Shetti, Mark Settle 今天,我们很高兴地宣布 Elastic 的新管道查询语言 ES|QL(Elasticsearch 查询语言)的技术预览版,它可以转换、丰富和简化数据调查。 ES|QL 由新的查询引擎提供支持&am…

vmware16.2内部win7联网

1、主机配置 前置条件:DHCP和NAT服务已启动 设置无线IP与虚拟机IP为自动获取 二者都是:右键-属性 选择IPv4 自动获取 2、虚拟机配置 设置虚拟机上网方式为NAT 菜单栏-虚拟机-设置 NMnet8改为NAT模式 菜单栏-编辑-虚拟网络编辑器 win7系统内部网…

13. 高精度延时

13. 高精度延时 GPT 定时器简介GPT 定时器结构GPT 定时器工作模式 GPT 定时器相关寄存器GPTx_CRGPTx_PRGPTx_SRGPTx_CNTGPTx_OCR GPT 配置步骤程序编写bsp_delay.hbsp_delay.cmain GPT 定时器简介 GPT 定时器是一个 32 位向上定时器,也就是从0x00000000 开始向上递…

【算法与数据结构】93、LeetCode复原 IP 地址

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引,可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析:参照【算法与数据结构】131、LeetCode分割回文串的思路,需要将IP字符串进行分割&#xff0…