首页 > 其他分享 >• 编译工具链

• 编译工具链

时间:2023-09-17 15:31:56浏览次数:35  
标签:可执行文件 文件 gcc LLVM 编译 编译器 工具

主要内容:

  • 编译工具链
  • Makefile Gcc Clang cmake
  • ELF

编译:编译过程就是把预处理完的文件进行一系列词法分析、语法分析、语义分析以及优化后生成相应的汇编代码文件。

编译工具链

简介

编译工具链是指用于将源代码编译成可执行文件的一组工具集合。它包括编译器、汇编器、链接器等工具,通常还包括调试器、性能分析器等辅助工具。

编译工具链的主要任务是将高级语言编写的源代码转换为目标机器上的机器码,以生成可执行文件或库。在这个过程中,编译器负责将源代码转换为汇编代码,汇编器将汇编代码转换为机器码,链接器将多个目标文件合并到一起,并解析符号依赖关系,最终生成最终的可执行文件或库。

常见的编译工具链包括GNU Compiler Collection (GCC)、LLVM/Clang、Microsoft Visual Studio、Intel C++ Compiler等。这些工具链可以在不同的操作系统和体系结构上使用,并提供了许多优化选项和调试功能,以方便软件开发人员进行程序开发和调试。


Gcc

简介

GCC(GNU Compiler Collection,GNU编译器套装),是一套由 GNU 开发的编程语言编译器。它是一套以 GPL 及 LGPL 许可证所发行的自由软件,也是 GNU计划的关键部分,亦是自由的类Unix及苹果电脑 Mac OS X 操作系统的标准编译器。

GCC 原名为 GNU C 语言编译器,因为它原本只能处理 C语言。GCC 很快地扩展,变得可处理 C++。之后也变得可处理 Fortran、Pascal、Objective-C、Java, 以及 Ada与其他语言。

GCC编译器已经被移植到比其他编译器更多的平台和指令集架构上,并被广泛部署在开发自由和专有软件的工具中。GCC还可用于许多嵌入式系统,包括基于ARM和Power ISA的芯片。

步骤

Gcc 编译的四个步骤:

  1. 预处理(E)
  2. 编译(S)
  3. 汇编(c)
  4. 链接(无)

暂时无法在飞书文档外展示此内容

Gcc 常用的参数:

在使用GCC编译器时候,必须给出一系列必要的调用参数和文件名称。

GCC最基本的用法是:

Gcc [options] [filenames]

其中options就是编译器所需要的参数(也称为编译选项),filename给出相关的文件名称。

.c 文件直接编译成可执行文件步骤:

  • gcc GccTest.c -o GccTest
  • ./GccTest 直接可以执行的指令
  • (gcc GccTest.c -o GccTest -v )可以看到过程


Makefile

简介

Makefile是一种文本文件,其中包含了编译源代码(如C、C++等)的规则和命令。它是GNU Make工具的输入文件,通过解析Makefile中的规则和依赖关系,自动化执行编译、链接、打包等操作,从而生成目标二进制文件或库文件。

Makefile通常由以下内容组成:

  • 变量定义:用于设置编译器、编译选项、目标文件名等参数的变量。
  • 规则定义:用于描述源文件和目标文件之间的依赖关系及其对应的编译命令。
  • 目标定义:用于指定最终生成的目标文件或库文件名称及其编译规则。

Makefile的规则:

  1. 依赖规则(Dependency Rules):用于描述每个目标文件所依赖的源文件和其他目标文件,以及如何将它们编译成中间文件。
  1.     例如:obj/main.o: src/main.c inc/common.h 表示main.o文件依赖于main.c和common.h文件,并通过gcc编译器将main.c编译成main.o文件。

  1. 编译规则(Compilation Rules):用于指定源文件的扩展名和编译命令,以及目标文件的扩展名和生成规则。
  1.     例如:.c.o: gcc -c $< -o $@ 表示使用gcc编译器将.c文件编译成.o文件,其中$<表示当前规则所依赖的源文件名,$@表示当前规则所生成的目标文件名。

Makefile是一种功能强大的自动化构建工具,它可以根据程序员定义的规则和依赖关系实现高效、灵活、可靠的代码构建过程。

Makefile的简单例子

文件a.c
```C
02        #include <stdio.h>
03
04        int main()
05        {
06        func_b();
07        return 0;
08}
```

文件b.c

```c
2        #include <stdio.h>
3
4        void func_b()
5        {
6                printf("This is B\n");
7        }
```

编译:

```bash
gcc -o test a.c b.c
```

运行:

```bash
./test
```

结果:

```bash
This is B
```

**gcc -o test a.c b.c**  这条命令虽然简单,但是它完成的功能不简单。

我们来看看它做了哪些事情,

我们知道.c程序 ==》 得到可执行程序它们之间要经过四个步骤:

* 1.预处理
* 2.编译
* 3.汇编
* 4.链接

我们经常把前三个步骤统称为编译了。我们具体分析:gcc -o test a.c b.c这条命令
它们要经过下面几个步骤:

* 1)对于**a.c**:执行:预处理 编译 汇编 的过程,**a.c ==>xxx.s ==>xxx.o** 文件。
* 2)对于**b.c**:执行:预处理 编译 汇编 的过程,**b.c ==>yyy.s ==>yyy.o** 文件。
* 3)最后:**xxx.o**和**yyy.o**链接在一起得到一个**test**应用程序。

提示:**gcc -o test a.c b.c -v** :加上一个**‘-v’**选项可以看到它们的处理过程
makefie最基本的语法是规则,规则:

```bash
目标 : 依赖1 依赖2 ...
[TAB]命令
```

当“依赖”比“目标”新,执行它们下面的命令。我们要把上面三个命令写成makefile规则,如下:

```bash
test :a.o b.o  //test是目标,它依赖于a.o b.o文件,一旦a.o或者b.o比test新的时候,
就需要执行下面的命令,重新生成test可执行程序。
gcc -o test a.o b.o
a.o : a.c  //a.o依赖于a.c,当a.c更加新的话,执行下面的命令来生成a.o
gcc -c -o a.o a.c
b.o : b.c  //b.o依赖于b.c,当b.c更加新的话,执行下面的命令,来生成b.o
gcc -c -o b.o b.c

makefile内容:

test :a.o b.o  
gcc -o test a.o b.o

a.o : a.c  
gcc -c -o a.o a.c

b.o : b.c  
gcc -c -o b.o b.c

Makefile语法

通配符

上节程序进行修改代码如下:

```bash
test: a.o b.o 
        gcc -o test $^
        
%.o : %.c
        gcc -c -o $@ $<
```

%.o:表示所用的.o文件

%.c:表示所有的.c文件

$@:表示目标

$<:表示第1个依赖文件

$^:表示所有依赖文件

gcc 生成.d 作为依赖文件

• 编译工具链_LLVM


Makefile常用函数


Clang

简介

Clang 是一个 C++ 编写、基于 LLVM、发布于 LLVM BSD 许可证下的 C/C++/Objective C编译器,其目标(之一)就是超越 GCC。

Low Level Virtual Machine (LLVM) 是一个开源的编译器架构

Clang是LLVM的一个子项目,基于LLVM架构的 C/C++/Objective C编译器前端

相比于GCC ,Clang具有如下优点:

  • 编译速度快:在某些平台上,Clang的编译速度显著的快过GCC(Debug模式下编译OC速度比GGC快3倍)
  • 占用内存小:Clang生成的AST所占用的内存是GCC的五分之一左右
  • 模块化设计:Clang采用基于库的模块化设计,易于 IDE 集成及其他用途的重用
  • 诊断信息可读性强:在编译过程中,Clang 创建并保留了大量详细的元数据 (metadata),有利于调试和错误报告
  • 设计清晰简单,容易理解,易于扩展增强

Clang 与LLVM关系

暂时无法在飞书文档外展示此内容

LLVM整体架构,前端用的是clang,广义的LLVM是指整个LLVM架构,一般狭义的LLVM指的是LLVM后端(包含代码优化和目标代码生成)。

源代码(c/c++)经过clang–> 中间代码(经过一系列的优化,优化用的是Pass) --> 机器码

LLVM

编译器LLVM(Low Level Virtual Machine)是一个开源的编译器基础设施。它提供模块化、可重用的编译器和工具链技术,可用于将高级编程语言代码转换为机器码。 编译器LLVM采用三阶段编译架构:前端、中间层和后端。前端负责将源代码解析为语法树,并进行语义分析、类型检查等操作。它支持多种编程语言,如C、C++、Rust、Swift等。中间层使用LLVM中间表示(IR)对源代码进行优化和转换。IR是一种低级、独立于特定语言和硬件的中间表示形式,它具有高度的可移植性和优化潜力。最后,后端将优化后的IR代码转换为特定硬件平台上的机器码。 LLVM编译器以其高度灵活和可扩展的特性而闻名。它提供了丰富的优化技术,如代码传播、循环优化、数据流分析等,以提高生成的机器码的性能和效率。此外,LLVM还支持Just-In-Time(JIT)编译技术,允许代码在运行时动态编译和优化。 值得一提的是,LLVM不仅仅是一个编译器,还是一个通用的编译基础设施。它提供了用于代码生成、静态分析、代码重整等多种工具和库。这使得LLVM成为许多编程语言(如Swift和Rust)的首选编译器。 总之,编译器LLVM是一个强大而灵活的开源编译器基础设施,它在学术界和工业界都得到了广泛的应用。它的模块化和可重用性使得它成为构建高性能编译器和工具链的理想选择。

Cmake

简介

CMake是一种跨平台的开源构建工具,它支持多种编译器、操作系统和目标平台,可以自动生成Makefile、Visual Studio项目文件等常见的构建脚本,并提供了丰富的模块化组件库和插件,方便程序员管理和构建复杂的软件项目。

CMake使用一种名为CMakeLists.txt的声明式语言来描述项目结构和编译规则,通过解析这个文件自动生成相应的构建文件。CMakeLists.txt文件由多个命令构成,用于定义变量、设置编译选项、指定源文件、链接库等操作,其中比较常用的命令包括:

  1. project:用于定义项目名称、版本号和语言类型。
  2. add_executable/add_library:用于定义可执行文件或库文件,并指定其对应的源文件列表。
  3. target_link_libraries:用于指定库文件之间的依赖关系,以及需要链接的第三方库。
  4. include_directories/link_directories:用于添加头文件搜索路径和库文件搜索路径。
  5. if/else/endif:用于根据条件判断是否需要编译某些源文件或链接某些库文件。

CMake还支持多种插件和扩展功能,如FindXXX模块用于查找特定的库文件、CTest模块用于测试代码、CPack模块用于打包发布等。

总之,CMake是一种非常灵活、易用、可扩展的构建工具,它为程序员提供了一种便捷的方式来管理和构建复杂的软件项目。

特点

  1. 开放源代码
  2. 跨平台
  3. 能够管理大型项目
  4. 简化编译构建过程和编译过程
  5. 高效率
  6. 可扩展


常用命令:

CmakeLists.txt 文件来描述文件过程。下面是常用命令:

project(xxx)                                          #项目的名称;必须

add_subdirectory(子文件夹名称)                         #父目录必须,子目录不必

add_library(库文件名称 STATIC 文件)                    #通常子目录(二选一)
add_executable(可执行文件名称 文件)                     #通常父目录(二选一)

include_directories(路径)                              #必须
link_directories(路径)                                 #必须

target_link_libraries(库文件名称/可执行文件名称 链接的库文件名称)       #必须

另:
add_executable(demo demo.cpp) # 生成可执行文件
add_library(common STATIC util.cpp) # 生成静态库
add_library(common SHARED util.cpp) # 生成动态库或共享库
详细的命令,仅供后期查询:
# 本CMakeLists.txt的project名称
# 会自动创建两个变量,PROJECT_SOURCE_DIR和PROJECT_NAME
# ${PROJECT_SOURCE_DIR}:本CMakeLists.txt所在的文件夹路径
# ${PROJECT_NAME}:本CMakeLists.txt的project名称
project(xxx)

# 获取路径下所有的.cpp/.c/.cc文件,并赋值给变量中
aux_source_directory(路径 变量)

# 给文件名/路径名或其他字符串起别名,用${变量}获取变量内容
set(变量 文件名/路径/...)

# 添加编译选项
add_definitions(编译选项)

# 打印消息
message(消息)

# 编译子文件夹的CMakeLists.txt
add_subdirectory(子文件夹名称)

# 将.cpp/.c/.cc文件生成.a静态库
# 注意,库文件名称通常为libxxx.so,在这里只要写xxx即可
add_library(库文件名称 STATIC 文件)

# 将.cpp/.c/.cc文件生成可执行文件
add_executable(可执行文件名称 文件)

# 规定.h头文件路径
include_directories(路径)

# 规定.so/.a库文件路径
link_directories(路径)

# 对add_library或add_executable生成的文件进行链接操作
# 注意,库文件名称通常为libxxx.so,在这里只要写xxx即可
target_link_libraries(库文件名称/可执行文件名称 链接的库文件名称)


ELF

现代PC平台流行的可执行文件格式(Executable)主要是Windows下的PE(Portable Executable)和Linux下的ELF(Executable and Linkable Format),它们都是COFF(Common file format)格式的变种。

ELF文件标准里面把系统中采用ELF格式的文件归为下表所列举的4类。

ELF 文件类型

说明

实例

可重定位文件(Relocatable File)

这类文件包含了代码和数据,可以被用来连接成可执行文件或共享目标文件,静态链接库也可以归为这一类。

Linux的.o

Winows的.obj

可执行文件(Executable File)

这类文明包含了可以直接执行的程序,它代表的就是ELF可执行文件,一般都没有扩展名。

比如/bin/bash 文件

Windows的.exe文件

共享目标文件(shared Object File)

这种文件包含了代码和数据,可以在以下两种情况下使用。一种是链接器可以使用这种文件跟其他的可重定位文件和共享目标文件链接,产生新的目标文件。第二种是动态链接器可以将几个这种1共享目标文件与可执行文件结合,作为进程映射映像的一部分来运行。

Linux 下的.so,如/lib/glibc-2.5.so

Windows的DLL

核心转储文件(Core Dump File)

当进程意外终止时,系统可以将该进程的地址空间内容及终止时的一些其他信息转储到核心转储文件。

Linux 下的core dump

简介

ELF(Executable and Linkable Format)是一种可执行文件和可链接目标文件的格式。ELF文件包含了程序代码、数据、符号表、调试信息和重定位信息等多种元素,可以直接被操作系统装载并执行。

ELF文件由多个节(Section)组成,每个节对应一个特定类型的数据,如.text节存储程序代码、.data节存储全局变量、.rodata节存储只读数据等。同一类型的节通常会按照地址排序,并被分组成段(Segment),比如.text和.rodata段就是典型的代码段和数据段。

ELF文件主要有三种类型:

  1. 可重定向文件,即通过汇编产生的文件,后缀是.o,该文件不能直接运行
  2. 可执行文件,将多个可重定向文件和共享库文件通过链接产生,可以直接运行
  3. 共享库,如libc的共享库libc.so,该文件同样不能直接运行,同可重定向文件相比,最大的区别在于该文件不需要经过重定向处理。

ELF文件的格式如下:

链接阶段

ELF header

Program Header Table(可选)

session

...

session n

...

...

Section Head Table

执行阶段

ELF header

Program Header Table(可选)

session 1


session 2


...

Section Head Table

  • ELF header: 描述整个文件的组织,包含ELF文件类型,硬件平台类型,程序执行入口, sections和segments的数量和起始偏移位置,大小等。
  • Program Header Table: 描述文件中的各种segments,通常一个segment包含若干个属性(如读写权限等)相同的section,将section合并成segment是为了减少内存空间浪费,方便内存管理,section的大小是任意的,但是segment的大小必须是所在操作系统的内存页(如4KB)大小的整数倍。操作系统加载可执行文件时会把LOAD类型的segment映射至虚拟地址空间。可重定向文件中没有此项,只有可执行文件中才有。
  • sections 或者 segments:具体的sections,sections是将汇编代码文件中的各种数据做归类保存,方便对其做内存分配与管理, 如.text section是可执行指令的集合,.data section包含初始化的全局变量,.bss section保存的是未初始化的全局变量和局部静态变量,.dynsym section记录了所有需要重定向处理的符号等。segments是从程序加载和运行的角度来描述elf文件,sections是从链接的角度来描述elf文件,也就是说,在链接阶段,我们可以忽略program header table来处理此文件,在运行阶段可以忽略section header table来处理此程序。
  • Section Header Table: 包含了文件各个section的属性信息,比如起始偏移位置,大小等。

ELF文件的优点在于其跨平台、灵活、可扩展的特性,可以方便地在不同架构、不同操作系统之间进行移植和交叉编译,同时也为动态链接等高级特性提供了良好的基础支持。

实例

obj-y                                += irqchip/
obj-y                                += bus/

# reset controllers early, since gpu drivers might rely on them to initialize
obj-$(CONFIG_RESET_CONTROLLER)        += reset/
obj-$(CONFIG_GENERIC_PHY)        += phy/

这段代码是一个Makefile规则,用于编译Linux内核中的驱动程序。

  • obj-y表示将目录下的所有文件都添加到目标列表中进行编译。
  • +=表示将指定目录添加到目标列表的末尾。
  • irqchip/bus/是两个目录名,它们包含了特定类型的驱动程序源代码。
  • obj-$(CONFIG_RESET_CONTROLLER)obj-$(CONFIG_GENERIC_PHY)是条件编译语句。如果配置选项CONFIG_RESET_CONTROLLERCONFIG_GENERIC_PHY被启用,那么相应的目录reset/phy/将会被添加到目标列表中进行编译。

总体来说,这段代码的作用是将irqchip/bus/reset/phy/目录下的驱动程序源代码添加到编译目标列表中,以便在编译过程中将它们编译为对象文件,并最终链接到可执行内核中。

参考文档:

cmake使用教程(实操版)_知愚的博客-CSDN博客

【CMake】CMakeLists.txt的超傻瓜手把手教程(附实例源码)_Yngz_Miao的博客-CSDN博客

GCC ,Clang 与 make,cmake 一览



标签:可执行文件,文件,gcc,LLVM,编译,编译器,工具
From: https://blog.51cto.com/u_15958702/7502330

相关文章

  • 超级好用绘图工具(Draw.io+Github)
    超级好用绘图工具(Draw.io+Github)方案简介绘图工具:Draw.io存储方式:Github1Draw.io1.2简介​ 是一款免费开源的在线流程图绘制软件,可以用于创建流程图、组织结构图、网络图、UML图等各种类型的图表。它提供了丰富的图形元素和编辑功能,使用户能够轻松地创建和编辑图......
  • 深入了解信号量:多线程同步的得力工具
    随着计算机科学和软件工程的不断发展,多线程编程变得越来越重要。多线程允许程序同时执行多个任务,提高了程序的效率和性能。然而,多线程编程也引入了新的问题,例如竞态条件和数据竞争。为了解决这些问题,同步工具变得至关重要,而信号量是其中一个强大的工具。什么是信号量?信号量是一......
  • 编译和解释的区别
    编译更偏向于翻译,也就是写好一个程序系统直接全部翻译好后,给计算机,计算机直接运行生成一个class来执行文件,好处是速度快,坏处是不便于更新,如果代码有什么变动就需要重新再编译一遍解释性:我理解为逐句翻译给电脑,逐句运行,逐句解释,坏处是速度比较慢,但是如果代码有什么更新,之前解释过......
  • 使用 Osql 工具管理 SQL Server 桌面引擎 (MSDE 2000)
    概要osql。可执行文件Sql.exe在MSDE2000的默认实例的MSSQL/Binn文件夹中。本文重点讨论如何通过使用osql工具管理MSDE2000。何为Osql?osql工具是一个MicrosoftWindows32命令提示符工具,您可以使用它运行Transact-SQL语句和脚本文件。osql工具使......
  • Go 项目的 MAKE 工具
    Go项目的MAKE工具MAKE工具是Linux和Unix系统中一种常见的自动化构建工具,通常用于管理和组织软件项目。在Go语言中,使用MAKE工具可以轻松地管理和构建项目,并自动执行诸如编译、测试、安装等复杂的操作。下面将介绍如何在Go项目中使用MAKE工具,并说明其主要优势......
  • 在CentOS上安装Redis-cli工具
    如果你想在CentOS上安装Redis-cli工具,可以按照以下步骤进行操作:1.安装Redis依赖包:在命令行中执行以下命令安装Redis依赖包:```sudoyuminstallgccmake```2.下载Redis源代码包:从Redis官网(https://redis.io/download)下载最新的Redis源代码包。3.解压源代码包:将下载的Redis......
  • Ubuntu16.04下C语言编译及makefile应用
    一、不同环境下C语言的编译在Ubuntu16.04下:step1:编写main1.c主程序用nano编好,下面为主程序展示注意:1、主程序中函数的声明step2:编写子程序 step3:用gcc命令编译采用多个文件一起编译,输出放在main1中 gcc的常见用法:-c只生成目标文件不进行连接,用于对目标文件的分别......
  • 构建工具Premake
    构建工具Premake经常用VisualStudio写一些小程序来验证OpenCASCADE的功能,每次创建项目后都配置头文件,库路径,程序运行时还要配置Debug的环境变量,比较麻烦。也尝试过CMake和QMake,都不太理想。CMake学习曲线陡峭一点,还会生成一堆文件。QMake简单些,但是有的选项不支持。直到看到一个......
  • 测试行业面临的问题及RunnerGo在工具层面如何解决的
    RunnerGo致力于打造成一款企业级全栈测试平台,旨在实现产品生命周期的闭环管理,帮助企业在整个产品生命周期中确保质量、降低风险,并提供卓越的用户体验。采用了较为宽松的Apache-2.0license开源协议,方便志同道合的朋友一起为开源贡献力量。 目前测试行业所面临的问题场景共享......
  • Kubernetes日志查看工具
    K8SFilebeat+ElasticSearch+Kibana虽然该组合可以满足我们对于服务监控的要求,但是如果只是部署一个内部单服务用的话,未免显得大材小用,而且部署服务还会带来大量的资源消耗。那么有没有简单查看 K8S 中多个 Pod 中的日志工具呢?咳咳咳,那么今天就介绍两款超好用的多容器实时......