GCC编译器

        我们编写的的源文件需要编译才能生成可执行文件。在Windows平台开发,我们只需要借助集成开发环境点几个按钮就可生成可执行文件;在Linux下也可以使用集成开发工具,但是更多的是直接使用编译工具;即使使用集成开发工具,也需了解基本的编译选项;

1. GCC简介

        在Linux中,使用最多的编译工具无疑是GCC(GNU Compiler Collection,GNU编译器套件)。GCC之所以成为Linux中最常用的编译工具,主要基于以下几个原因:

        1. 开源与自由

        GCC是GNU项目的一部分,遵循GNU通用公共许可证(GPL),这意味着它是完全开源和免费的。这种开放性吸引了大量的开发者和用户,促进了GCC的普及和发展。

       2.  跨平台支持

        GCC支持多种操作系统和硬件架构,包括Linux、Windows、macOS等,以及从x86到ARM等多种处理器架构。这种广泛的兼容性使得GCC成为跨平台开发的首选编译器。

        3. 语言支持丰富

        GCC不仅仅是一个C语言编译器,它还支持C++、Objective-C、Fortran、Ada、Go等多种编程语言。这种多语言支持能力使得GCC能够满足不同项目和团队的需求。

        4. 性能优化

        GCC提供了多种优化选项,允许开发者根据需要对代码进行优化,以提高程序的运行速度和效率。这些优化选项包括针对速度的优化、针对大小的优化等,可以满足不同场景下的需求。

        5. 集成与自动化

        GCC可以与多种构建系统和自动化工具(如Make、CMake等)集成,实现编译过程的自动化。这种集成能力使得大型项目的编译和构建变得更加简单和高效。

        6. 社区支持强大

        GCC拥有庞大的开发者社区和用户群体,这为GCC的发展提供了强大的支持。开发者可以通过社区获取帮助、分享经验、参与开发等,共同推动GCC的进步和完善。

2. GCC主要功能

  1.         编译:将源代码(如 .c 或 .cpp 文件)转换成汇编语言或中间代码(如对象文件 .o 或 .obj),这是编译过程的主要步骤。
  2.         汇编:将汇编语言代码转换成机器码,但这一步在 GCC 中通常是隐式的,因为 GCC 的前端和后端通常一起工作,直接生成对象文件。
  3.         链接:将多个对象文件、库文件和其他资源合并成一个可执行文件或库文件。虽然 GCC 主要关注编译阶段,但它也提供了链接器(如 ld),并且可以通过命令行选项控制链接过程。
  4.         优化:在编译过程中,GCC 提供了多种优化选项,可以帮助开发者生成更快、更小或更节能的代码。这些优化可以是针对速度的、针对大小的,或者是针对其他特定目标的。
  5.         调试支持:GCC 支持生成调试信息,这些信息可以被调试器(如 GDB)使用来跟踪和调试程序。

3.  GCC编译过程

        一个C文件要经过预处理、编译、汇编、链接这四步才能变成可执行文件;

预处理:包含(#include)头文件插入源文件、宏展开、条件命令编译;

编译:将源文件翻译成汇编语言;

汇编:将会汇编代码翻译成机器代码,生成可执行文件(如.o或.obj文件)。;

链接:将多个目标文件及所需要的库文件链接成一个可执行文件(如.exe或.elf文件);

        通过gcc选项可以控制这些过程;常用编译选项

4.  编译多个文件

        一起编译加链接

gcc  -o test  main.c  sub.c 

        逐个编译、统一链接

gcc -c -o main.o  main.c 
gcc -c -o sub.o   sub.c 
gcc -o test main.o sub.o 

使用库编译

        首先,你需要有库的源代码,并编译它们以生成静态库(.a)或动态库(.so)。这通常通过gcc的-fPIC(用于生成位置无关代码,仅对动态库必需)和-shared(生成共享库,即动态库)选项来完成。

        动态库:程序运行时被加载到内存中,并由操作系统管理。可执行文件仅包含对动态库中函数的引用,而不是实际的函数代码。

        静态库:程序编译时被链接到可执行文件中。这意味着最终生成的可执行文件包含了静态库中的代码和数据。

        使用动态库编译

        步骤 1: 编译源文件到对象文件

gcc -c -o main.o main.c  
gcc -c -o sub.o sub.c  
gcc -c -o sub2.o sub2.c  
gcc -c -o sub3.o sub3.c

        步骤 2: 创建动态库

      在创建动态库时,需要使用 -fPIC 选项来生成位置无关的代码(Position Independent Code),这是共享库所必需的。此外,应该使用 -shared 选项来告诉 gcc 想要创建一个共享库。

gcc -fPIC -c -o sub.o sub.c  
gcc -fPIC -c -o sub2.o sub2.c  
gcc -fPIC -c -o sub3.o sub3.c  
gcc -shared -o libsub.so sub.o sub2.o sub3.o

        注意,这里我重新编译了 sub.csub2.c 和 sub3.c,以确保它们是以 -fPIC 选项编译的 ;

        步骤 3: 链接动态库到可执行文件

        在链接主程序到动态库时,需要使用 -l 选项来指定库名(不包括前缀 lib 和后缀 .so),并使用 -L 选项来指定库文件所在的目录。但是,请注意 -L 选项后面应该跟的是目录名,而不是库文件的完整路径。

gcc -o test main.o -lsub -L/path/to/libsub.so/所在目录
        使用静态库编译

       步骤 1: 编译源文件到对象文件

gcc -c -o main.o main.c  
gcc -c -o sub.o sub.c  
gcc -c -o sub2.o sub2.c  # 假设你还有一个sub2.c文件  
gcc -c -o sub3.o sub3.c  # 假设你还有一个sub3.c文件

         步骤 2: 创建静态库

        接下来,使用 ar 命令和 crs 选项来创建一个静态库(.a 文件)。这里,c 表示创建一个新的存档文件,r 表示将文件插入到存档中(替换已存在的同名文件),s 表示在存档中创建索引。

ar crs libsub.a sub.o sub2.o sub3.o

这个命令会创建一个名为 libsub.a 的静态库,它包含了 sub.osub2.o 和 sub3.o 这三个对象文件。

        步骤 3: 链接静态库到可执行文件

        最后,使用 gcc 来链接你的主对象文件(main.o)和静态库(libsub.a),以生成可执行文件。如果静态库不在当前目录下,你需要使用 -L 选项来指定库文件的搜索路径。但是,在这个例子中,我们假设库文件就在当前目录下。

gcc -o test main.o libsub.a

        由于库文件就在当前目录下,gcc 会自动找到它并链接到可执行文件中。如果库文件不在当前目录下,你需要使用 -L 选项来指定库文件的路径,比如 -L/path/to/libs,并且如果库名不是以 lib 开头或者没有 .a 后缀,你还需要使用 -l 选项来指定库名(去掉 lib 前缀和 .a 后缀)。但在这个例子中,由于库名已经是 libsub.a,所以我们不需要 -L 或 -l 选项(除非库文件不在当前目录)。

  • 8
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值