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

news2024/11/19 5:33:35

在这里插入图片描述
很多人在喧嚣声中登场,也有少数人在静默中退出。 --单独中的洞见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.coloradmin.cn/o/1199975.html

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

相关文章

移动硬盘和u盘的区别哪个好 移动硬盘和u盘有啥区别

在数字时代的今天,数据存储已经成为我们生活中的重要一环。当我们需要移动、备份或传输大量数据时,常常会不知道是选择移动硬盘还是U盘。其实,对于许多人来说,移动硬盘和U盘之间的区别并不清晰。下面我们就来看移动硬盘和u盘的区别…

【C语言:深入理解指针一】

文章目录 1.指针存在的意义2.指针变量和地址3.指针变量类型的意义3.1指针解引用3.2指针 - 整数3.3void* 4.关键字const4.1const修饰变量4.2 const修饰指针 5.指针运算5.1指针 -整数5.2指针-指针5.3指针比较大小 6. 野指针7.assert断言8. 数组名的理解9.一维数组传参的本质 1.指…

SpringBoot自动装配定义先后顺序失效原因极其解析

SpringBoot自动装配定义先后顺序失效原因极其解析 1、场景分析1.1、问题总结 2、使用AutoConfigureBefore、AutoConfigureAfter和AutoConfigureOrder注解指定加载顺序2.2、AutoConfigureXX注解失效原因总结 3、使用静态内部装配类提升加载顺序4、bean加载顺序规则 1、场景分析 …

腾讯云优惠券介绍、作用、领取方法及使用教程

随着云计算技术的发展,越来越多的企业和个人选择使用云服务进行数据存储、计算等业务。腾讯云作为国内知名的云服务商,提供了一整套完善的云解决方案,并不定期发放优惠券以吸引更多的客户。本文将为大家详细介绍腾讯云优惠券的作用、领取方法…

leetcode刷题日记:111. Minimum Depth of Binary Tree(二叉树的最小深度)

给我们一个二叉树,我们应该如何来求二叉树的最小深度呢? 二叉树的最小深度指的是叶子结点到所处的位置最小的,这就是二叉树的最小深度,也就是说我们要找的是离根结点最近的叶子结点。如果我们从根结点向下出发寻找叶子节点&#x…

【matlab】KMeans KMeans++实现手写数字聚类

目录 matlab代码kmeans matlab代码kmeans MNIST DATABASE下载网址: http://yann.lecun.com/exdb/mnist/ 聚类 将物理或抽象对象的集合分成由类似特征组成的多个类的过程称为聚类(clustering)。 对于给定N个n维向量x1,…,xN∈Rn,聚类的目标…

解决wrong fs type, bad option, bad superblock on /dev/sda1问题

1 背景 某天挂载硬盘的时候,系统提示了如下错误: 在此记录排查过程以及解决方案。 2 排查过程 出现这种问题应该先尝试从日志入手,输入: sudo dmesg | tail输出如下: 关键信息: [ 164.750178] ntfs3:…

【Mybatis小白从0到90%精讲】16: Mybatis like语句四种传参方式

文章目录 前言方式一:Java代码拼接方式二:MySQL CONCAT函数方式三:Mybatis bind标签方式四:SQL拼接前言 在实际开发中,SQL中使用 模糊查询like使用非常普遍,在MyBatis中,为了防止SQL注入攻击,可以使用#{}来传递参数,切记like语句不要使用${}的方式! 这里我总结了 四…

【离散数学必刷题】谓词逻辑(第二章 左孝凌版)刷完包过!

专栏:离散数学必刷题 本章需要掌握的重要知识: 1.利用谓词表达式表示命题 2.变元的约束 3.谓词公式的定义、谓词公式的赋值 4.谓词公式的翻译(注意在全总个体域时使用特性谓词) 5.有限论域上量词的消去 6.谓词公式中关于量词的等价…

【算法每日一练]-单调队列,滑动窗口(保姆级教程 篇1) #滑动窗口 #求m区间的最小值 #理想的正方形 #切蛋糕

今天讲单调队列 目录 题目:滑动窗口 思路: 题目:求m区间的最小值​ 思路: 题目:理想的正方形 思路: 题目:切蛋糕 思路: 一共两种类型:一种是区间中的最值&…

代码随想录算法训练营第四十九天|121. 买卖股票的最佳时机、122. 买卖股票的最佳时机 II

第九章 动态规划part10 121. 买卖股票的最佳时机 给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最…

C语言证明一个偶数总能表示为两个素数之和。输入一个偶数并将其分解为两个素数

完整代码&#xff1a; // 一个偶数总能表示为两个素数之和。输入一个偶数并将其分解为两个素数#include<stdio.h>//判断一个数n是否为素数 int isPrimeNumber(int n){//1不是素数if (n1){return 0;}for (int i 2; i <(n/2); i){//当有n能被整除时&#xff0c;不是素…

吃透 Spring 系列—IOC部分

目录 ◆ 传统Javaweb开发的困惑 -传统Javaweb开发代码分析-用户模块 -传统Javaweb开发困惑及解决方案 ◆ IoC、DI和AOP思想提出 - IoC 控制反转思想的提出 - DI 依赖注入思想的提出 - AOP 面向切面思想的提出 - 框架概念的出现 - 思想、框架和编码关系 ◆ Spring框架…

UML软件建模软件StarUML mac中文版软件介绍

StarUML for mac是一款UML建模器&#xff0c;StarUML for mac提供了几个模版&#xff0c;帮助用户建立使用新的图表&#xff0c;是目前最流行的UML建模工具&#xff0c;给开发工作带来大大的便利。 StarUML mac软件介绍 StarUML 是一个流行的软件建模工具&#xff0c;用于创建…

[vuex] unknown mutation type: SET_SOURCE

项目中使用了vuex&#xff0c;并且以模块的形式分好之后。在调用的时候出现了以上问题 /*当我们commit的时候要注意要加上模块的名字 user是模块名称&#xff0c;SET_SOURCE是user模块中定义的方法 正确写法&#xff1a;*/ this.$store.commit("user/SET_SOURCE", th…

Java14新增特性

前言 前面的文章&#xff0c;我们对Java9、Java10、Java11、Java12 、Java13的特性进行了介绍&#xff0c;对应的文章如下 Java9新增特性 Java10新增特性 Java11新增特性 Java12新增特性 Java13新增特性 今天我们来一起看一下Java14这个版本的一些重要信息 版本介绍 Java 14…

自动泊车轨迹规划学习

1.基于6次多项式的自动泊车轨迹算法研究 针对常见的自动泊车系统无法躲避障碍物&#xff0c;以及轨迹的曲率不连续等问题进行了泊车轨迹算法的研究以及跟踪算法的设计。 针对低速自动泊车场景进行分析&#xff0c;建立符合对应场景下的车辆运动学模型以及能够泊车的最小车位大…

JavaWeb Day10 案例 准备工作

目录​​​​​​​ 一、需求说明 二、环境搭建 &#xff08;一&#xff09;数据库 &#xff08;二&#xff09;后端 ①controller层 1.DeptController.java 2.EmpController.java ②mapper层 1.DeptMapper.java 2.EmpMapper.java ③pojo层 1.Dept.java 2.Emp.jav…

数据库加密的常用方法 安当加密

数据库加密的方法主要有以下几种&#xff1a; 前置代理及加密网关技术&#xff1a;在数据库之前增加一道安全代理服务&#xff0c;对数据库访问的用户都必须经过该安全代理服务&#xff0c;在此服务中实现如数据加解密、存取控制等安全策略。加密数据存储在安全代理服务中。但…

S32K3基础学习 linker链接器脚本ld文件的学习(一)

一、简介 最近学习NXP新推出的S32K3系列芯片&#xff0c;我在学习容易转牛角尖&#xff0c;非得要搞明白这个芯片的启动流程&#xff0c;所以花费了一些时间&#xff0c;进行查阅资料进行学习&#xff0c;这里做下详细的记录&#xff0c;希望有用&#xff0c;如果有错误欢迎指正…