【AI系统】GCC 主要特征

简介: GCC(GNU Compiler Collection)是由理查德·斯托曼于1987年创建,最初作为GNU项目的一部分,旨在为GNU/Linux系统提供高效C语言编译器。随着时间发展,GCC不仅支持多种编程语言如C++、Java、Swift等,还具备强大的可移植性、模块化设计及跨平台交叉编译能力,成为全球广泛使用的开源编译器之一。其编译过程分为预处理、编译、汇编和链接四个阶段,支持静态和动态链接方式,适用于本地编译和交叉编译场景。

GCC(GNU Compiler Collection,GNU 编译器集合)最初是作为 GNU 操作系统的编译器编写的,旨在为 GNU/Linux 系统开发一个高效的 C 编译器。其历史可以追溯到 1987 年,当时由理查德·斯托曼(Richard Stallman)创建,作为 GNU 课程的一部分。

最初,GCC 仅是一个用于编译 C 语言的编译器,但很快扩展以支持其他编程语言,其设计强调可移植性和模块化,使其能够适应多种硬件和操作系统环境。

在 1990 年代和 2000 年代,GCC 经历了几次重要的重构和扩展。改进包括引入新的优化技术、提升代码生成和分析能力,以及增强对新兴编程语言和硬件架构的支持。这些改进使得 GCC 成为编程社区中的重要工具,广泛应用于学术研究、商业开发和开源课程中。随着 GNU/Linux 系统的快速发展,GCC 逐渐扩展其支持范围,涵盖了包括 Microsoft Windows、BSD 系列、Solaris 和 Mac OS 在内的多种操作系统平台。

同时,GCC 的指导委员会根据其使命宣言做出重要决策,致力于持续发布高质量的版本。通过 Git 版本控制系统和每周的源代码快照,GCC 的最新源代码随时可供获取。任何人都被鼓励参与贡献或协助测试,以推动 GCC 的持续发展。

编译器

此外,GCC 还引入了与现代编程语言如 Swift 和 Java 相关的前端,使其成为一个全面而多功能的编译器。作为一个模块化设计的软件,GCC 提供了丰富的功能和灵活性,既能在本地平台上进行编译,也支持跨平台的交叉编译。作为自由软件的一部分,用户可以免费获取并自由使用 GCC,并且得到了自由软件基金会(Free Software Foundation,FSF)的强力支持。

GCC 具有以下主要特征:

  • 可移植性:支持多种硬件平台,使得用户可以在不同的硬件架构上进行编译。
  • 跨平台交叉编译:支持在一个平台上为另一个平台生成可执行文件,这对嵌入式开发尤为重要。
  • 多语言前端:除了 C 语言,还支持 C++、Objective-C、Fortran、Ada、Go 和 D 等多种编程语言。
  • 模块化设计:允许轻松添加新语言和 CPU 架构的支持,增强了扩展性。
  • 开源自由软件:源代码公开,用户可以自由使用、修改和分发。

GCC 编译流程

GCC 的编译过程可以大致分为预处理、编译、汇编和链接四个阶段。

编译器

源程序(文本)

当编写源程序时,通常会使用以 .c 或 .cpp 为扩展名的文件。下面以打印宏定义 HELLOWORD 为例,我们使用 C 语言编写 hello.c 源文件:

#include <stdio.h>

#define HELLOWORD ("hello world\n")

int main(void){
   
    printf(HELLOWORD);
    return 0;
}

预处理(cpp)

生成文件 hello.i

gcc -E hello.c -o hello.i

在预处理过程中,源代码会被读入,并检查其中包含的预处理指令和宏定义,然后进行相应的替换操作。此外,预处理过程还会删除程序中的注释和多余空白字符。最终生成的.i 文件包含了经过预处理后的代码内容。

当高级语言代码经过预处理生成.i 文件时,预处理过程会涉及宏替换、条件编译等操作。以下是对这些预处理操作的解释:

  • 头文件展开:

在预处理阶段,编译器会将源文件中包含的头文件内容插入到源文件中对应的位置,以便在编译时能够访问头文件中定义的函数、变量、宏等内容。

  • 宏替换:

在预处理阶段,编译器会将源文件中定义的宏在使用时进行替换,即将宏名称替换为其定义的内容。这样可以简化代码编写,提高代码的可读性和可维护性。

  • 条件编译:

通过预处理指令如 #if、#else、#ifdef 等,在编译前确定某些代码片段是否应被包含在最终的编译过程中。这样可以根据条件编译选择性地包含代码,实现不同平台、环境下的代码控制。

  • 删除注释:

在预处理阶段,编译器会删除源文件中的注释,包括单行注释(//)和多行注释(/.../),这样可以提高编译速度并减少编译后代码的大小。

  • 添加行号和文件名标识:

通过预处理指令如 #line,在预处理阶段添加行号和文件名标识到源文件中,便于在编译过程中定位错误信息和调试。

  • 保留 #pragma 命令:

在预处理阶段,编译器会保留以#pragma 开头的预处理指令,如#pragma once、#pragma pack 等,这些指令可以用来指导编译器进行特定的处理,如控制编译器的行为或优化代码。

hello.i 文件部分内容如下,详细可见../code/gcc/hello.i 文件。

int main(void){
   
    printf(("hello world\n"));
    return 0;
}

在该文件中,已经将头文件包含进来,宏定义 HELLOWORD 替换为字符串"hello world\n",并删除了注释和多余空白字符。

编译(ccl)

在这里,编译并不仅仅指将程序从源文件转换为二进制文件的整个过程,而是特指将经过预处理的文件(hello.i)转换为特定汇编代码文件(hello.s)的过程。

在这个过程中,经过预处理后的 .i 文件作为输入,通过编译器(ccl)生成相应的汇编代码.s 文件。编译器(ccl)是 GCC 的前端,其主要功能是将经过预处理的代码转换为汇编代码。编译阶段会对预处理后的.i 文件进行语法分析、词法分析以及各种优化,最终生成对应的汇编代码。

汇编代码是以文本形式存在的程序代码,接着经过编译生成.s 文件,是连接程序员编写的高级语言代码与计算机硬件之间的桥梁。

生成文件 hello.s:

gcc -S hello.i -o hello.s

打开 hello.s 后输出如下:

    .section    __TEXT,__text,regular,pure_instructions
    .build_version macos, 10, 15    sdk_version 10, 15, 6
    .globl    _main                   # -- Begin function main
    .p2align    4, 0x90
_main:                                  # @main
    .cfi_startproc
# %bb.0:
    pushq    %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset %rbp, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register %rbp
    subq    $16, %rsp
    movl    $0, -4(%rbp)
    leaq    L_.str(%rip), %rdi
    movb    $0, %al
    callq    _printf
    xorl    %ecx, %ecx
    movl    %eax, -8(%rbp)          # 4-byte Spill
    movl    %ecx, %eax
    addq    $16, %rsp
    popq    %rbp
    retq
    .cfi_endproc
                                        # -- End function
    .section    __TEXT,__cstring,cstring_literals
L_.str:                                 # @.str
    .asciz    "hello world\n"

.subsections_via_symbols

现在 hello.s 文件中包含了完全是汇编指令的内容,表明 hello.c 文件已经被成功编译成了汇编语言。

汇编(as)

在这一步中,我们将汇编代码转换成机器指令。这一步是通过汇编器(as)完成的。汇编器是 GCC 的后端,其主要功能是将汇编代码转换成机器指令。

汇编器的工作是将人类可读的汇编代码转换为机器指令或二进制码,生成一个可重定位的目标程序,通常以 .o 作为文件扩展名。这个目标文件包含了逐行转换后的机器码,以二进制形式存储。这种可重定位的目标程序为后续的链接和执行提供了基础,使得汇编代码能够被计算机直接执行。

生成文件 hello.o

gcc -c hello.s -o hello.o

链接(ld)

链接过程中,链接器的作用是将目标文件与其他目标文件、库文件以及启动文件等进行链接,从而生成一个可执行文件。在链接的过程中,链接器会对符号进行解析、执行重定位、进行代码优化、确定空间布局,进行装载,并进行动态链接等操作。通过链接器的处理,将所有需要的依赖项打包成一个在特定平台可执行的目标程序,用户可以直接执行这个程序。

gcc -o hello.o -o hello

添加-v 参数,可以查看详细的编译过程:

gcc -v hello.c -o hello
  • 静态链接

静态链接是指在链接程序时,需要使用的每个库函数的一份拷贝被加入到可执行文件中。通过静态链接使用静态库进行链接,生成的程序包含程序运行所需要的全部库,可以直接运行。然而,静态链接生成的程序体积较大。

  • 动态链接

动态链接是指可执行文件只包含文件名,让载入器在运行时能够寻找程序所需的函数库。通过动态链接使用动态链接库进行链接,生成的程序在执行时需要加载所需的动态库才能运行。相比静态链接,动态链接生成的程序体积较小,但是必须依赖所需的动态库,否则无法执行。

GCC 编译方法

本地编译

所谓"本地编译",是指编译源代码的平台和执行源代码编译后程序的平台是同一个平台。这里的平台,可以理解为 CPU 架构+操作系统。比如,在 Intel x86 架构或者 Windows 平台下、使用 Visual C++ 编译生成的可执行文件,在同样的 Intel x86 架构/Windows 10 下运行。

交叉编译

所谓"交叉编译(Cross_Compile)",是指编译源代码的平台和执行源代码编译后程序的平台是两个不同的平台。比如,在 Intel x86 架构/Linux(Ubuntu)平台下、使用交叉编译工具链生成的可执行文件,在 ARM 架构/Linux 下运行。

与传统编译区别

传统的三段式划分是指将编译过程分为前端、优化、后端三个阶段,每个阶段都有专门的工具负责。

编译器

而在 GCC 中,编译过程被分成了预处理、编译、汇编、链接四个阶段 。其中 GCC 的预处理、编译阶段属于三段式划分的前端部分,汇编阶段属于三段式划分的后端部分。

GCC 的链接阶段是三段式划分后端部分的优化阶段合并,但其与端部分的目的一致,都是为了生成可执行文件。

GCC 编译过程的四个阶段与传统的三段式划分的前端、优化、后端三个阶段有一定的重合和对应关系,但 GCC 更为详细和全面地划分了编译过程,使得每个阶段的功能更加明确和独立。

如果您想了解更多AI知识,与AI专业人士交流,请立即访问昇腾社区官方网站https://www.hiascend.com/ 或者深入研读《AI系统:原理与架构》一书,这里汇聚了海量的AI学习资源和实践课程,为您的AI技术成长提供强劲动力。不仅如此,您还有机会投身于全国昇腾AI创新大赛和昇腾AI开发者创享日等盛事,发现AI世界的无限奥秘~

目录
相关文章
|
19天前
|
机器学习/深度学习 自然语言处理 Linux
Linux 中的机器学习:Whisper——自动语音识别系统
本文介绍了先进的自动语音识别系统 Whisper 在 Linux 环境中的应用。Whisper 基于深度学习和神经网络技术,支持多语言识别,具有高准确性和实时处理能力。文章详细讲解了在 Linux 中安装、配置和使用 Whisper 的步骤,以及其在语音助手、语音识别软件等领域的应用场景。
52 5
|
15天前
|
机器学习/深度学习 人工智能 算法
基于深度学习的【蔬菜识别】系统实现~Python+人工智能+TensorFlow+算法模型
蔬菜识别系统,本系统使用Python作为主要编程语言,通过收集了8种常见的蔬菜图像数据集('土豆', '大白菜', '大葱', '莲藕', '菠菜', '西红柿', '韭菜', '黄瓜'),然后基于TensorFlow搭建卷积神经网络算法模型,通过多轮迭代训练最后得到一个识别精度较高的模型文件。在使用Django开发web网页端操作界面,实现用户上传一张蔬菜图片识别其名称。
59 0
基于深度学习的【蔬菜识别】系统实现~Python+人工智能+TensorFlow+算法模型
|
25天前
|
机器学习/深度学习 算法 TensorFlow
基于深度学习的【野生动物识别】系统设计与实现~Python
动物识别系统,使用Python作为主要开发语言,基于深度学习TensorFlow框架,搭建卷积神经网络算法。并通过对18种动物数据集进行训练,最后得到一个识别精度较高的模型。并基于Django框架,开发网页端操作平台,实现用户上传一张动物图片识别其名称。目前可识别的动物有:'乌龟', '云豹', '变色龙', '壁虎', '狞猫', '狮子', '猎豹', '美洲狮', '美洲虎', '老虎', '蜥蜴', '蝾螈', '蟾蜍', '豹猫', '钝吻鳄', '雪豹','非洲豹', '鬣蜥'。本系统是一个完整的人工智能,机器学习,深度学习项目,包含训练预测代码,训练好的模型,WEB网页端界面,数
60 2
|
4月前
|
机器学习/深度学习 人工智能 自然语言处理
【深度学习】python之人工智能应用篇--跨模态生成技术
跨模态生成技术是一种将不同模态的数据(如文本、图像、音频、视频等)进行融合和转换的技术。其目标是通过将一个模态的数据作为输入,生成与之对应的另一个模态的输出。这种技术对于突破单一模态的局限性,提高信息处理的准确性和丰富性具有重要意义。跨模态生成技术主要依赖于深度学习和生成模型,通过学习和模拟不同模态之间的映射关系来实现模态间的转换。
53 1
|
4月前
|
机器学习/深度学习 人工智能 PyTorch
【Deepin 20深度探索】一键解锁Linux深度学习潜能:从零开始安装Pytorch,驾驭AI未来从Deepin出发!
【8月更文挑战第2天】随着人工智能的迅猛发展,深度学习框架Pytorch已成为科研与工业界的必备工具。Deepin 20作为优秀的国产Linux发行版,凭借其流畅的用户体验和丰富的软件生态,为深度学习爱好者提供理想开发平台。本文引导您在Deepin 20上安装Pytorch,享受Linux下的深度学习之旅。
91 12
|
4月前
|
机器学习/深度学习 人工智能 数据可视化
10个用于可解释AI的Python库
10个用于可解释AI的Python库
|
4月前
|
机器学习/深度学习 数据采集 自然语言处理
深度学习之可解释的决策系统
深度学习的可解释决策系统是一种集成深度学习模型和解释技术的系统,旨在提高决策过程的透明度和可理解性。这种系统能够在保持深度学习模型强大预测能力的同时,让用户和开发者了解其决策背后的逻辑和依据。
39 0
|
7月前
|
人工智能
MIT等首次深度研究集成LLM预测能力:可媲美人类群体准确率
【4月更文挑战第16天】研究人员集成12个大型语言模型(LLM)组成“硅基群体”,在预测比赛中与925名人类预测者对比。研究发现,LLM群体的预测准确性与人类群体无显著差异,且通过集成可抵消个体模型的偏差,提高预测准确。GPT-4和Claude 2等模型结合人类预测后,准确度提升17%至28%。然而,个别LLM预测精度不一,模型选择和校准度是提升预测性能的关键,同时LLM在时间跨度和现实场景适应性方面仍有挑战。
98 6
MIT等首次深度研究集成LLM预测能力:可媲美人类群体准确率
|
7月前
|
机器学习/深度学习 存储 人工智能
Mamba深度解析:AI模型的新突破
Mamba深度解析:AI模型的新突破
301 2
|
机器学习/深度学习 安全 Java
【网安AIGC专题10.19】论文6(顶会ISSTA 2023):提出新Java漏洞自动修复数据集:数据集 VJBench+大语言模型、APR技术+代码转换方法+LLM和DL-APR模型的挑战与机会
【网安AIGC专题10.19】论文6(顶会ISSTA 2023):提出新Java漏洞自动修复数据集:数据集 VJBench+大语言模型、APR技术+代码转换方法+LLM和DL-APR模型的挑战与机会
518 0