gcc 编译过程(图解)、编译参数、使用规则解析

22 篇文章 1 订阅
1 篇文章 0 订阅

 

0.gcc和g++是什么,有什么区别?

  • gcc 指令编译 C 语言程序,也可以用来编译 C++ 程序

       gcc 指令可以自行判断出当前程序所用编程语言的类别去编译

  • g++ 指令编译 C++ 代码,也可以用于编译 C 语言程序

       该指令都一律按照编译 C++ 代码的方式编译该文件

  • 如果想使用 gcc 指令来编译执行 C++ 程序

        需要在使用 gcc 指令时,手动为其添加 -lstdc++ -shared-libgcc 选项,表示 gcc 在编译 C++ 程序时可以链接必要的 C++ 标准库

        g++ 指令就等同于gcc -xc++ -lstdc++ -shared-libgcc指令

1.gcc 工作流程

    一个hello.c文件编译过程

            

2.gcc常用参数

gcc最基本的用法是:gcc [options] [filenames]
其中,options就是编译器所需要的参数,filenames给出相关的文件名称

gcc/g++指令选项功 能
-E(大写)预处理指定的源文件,不进行编译。
-S(大写)编译指定的源文件,但是不进行汇编。
-C  (大写)阻止 GCC 删除源文件和头文件中的注释
-c编译、汇编指定的源文件,但是不进行链接。
-o指定生成文件的文件名。如果不使用 -o 选项,那么将采用默认的输出文件。例如默认情况下,生成的可执行文件的名字默认为 a.out
-l手动添加链接库,选项用于指明所需静态链接库的名称
-L为 GCC 增加另一个搜索链接库的目录,选项用于向 GCC 编译器指明静态链接库的存储位置
-ansi对于 C 语言程序来说,其等价于 -std=c90;对于 C++ 程序来说,其等价于 -std=c++98。
-std=手动指令编程语言所遵循的标准,例如 c89、c90、c++98、c++11 等。
-rdynamic它将指示连接器把所有符号(而不仅仅只是程序已使用到的外部符号)都添加到动态符号表(即.dynsym表)里,以便那些通过 dlopen() 或 backtrace() (这一系列函数使用.dynsym表内符号)这样的函数使用
-static选项强制 GCC 编译器使用静态链接库
-shared生成动态链接库
-fpic/-fPIC生成位置无关代码,令 GCC 编译器生成动态链接库(多个目标文件的压缩包)时,表示各目标文件中函数、类等功能模块的地址使用相对地址,而非绝对地址。这样,无论将来链接库被加载到内存的什么位置,都可以正常使用
-Wall使用它能够使GCC产生尽可能多的警告信息
-Werror将警告信息当成编码错误来对待,GCC会在所有产生警告的地方停止编译,迫使程序员对自己的代码进行修改
-Wl,option表示后面的参数将传给link程序ld(链接器)(例如:-Wl,rpath=     优先到rpath指定的目录去寻找依赖库)
-std

指定GCC 编译程序时所使用的编译标准,例如 -std=c89、-std=c11、-std=gnu90 等

注意:对于在 for 循环中声明变量 i 的做法,是违反 C89 标准的

 另一篇博客:详细介绍了静态链接和动态链接、以及如何创建和使用

3.GCC生成可执行文件时找不到库文件

程序链接阶段指明所用库文件的方式有 2 种。假设当前 mian.c 文件需要借助 libmymath.a 才能完成链接,则完成链接操作的 gcc 指令有以下 2 种写法:

[root@bogon demo]# gcc -static main.c libmymath.a -o main.exe     GCC 编译器只会在当前目录中(这里为 demo 目录)查找 libmymath.a 静态链接库
[root@bogon demo]# gcc -static main.c -lmymath -o main.exe


如果使用 -l(小写的 L)选项指明了要查找的静态库的文件名 -lmymath,则 GCC 编译器会按照如下顺序,依次到指定目录中查找所需库文件:
  1. 如果 gcc 指令使用 -L 选项指定了查找路径,则 GCC 编译器会优先选择去该路径下查找所需要的库文件;
  2. 再到 Linux 系统中 LIBRARY_PATH 环境变量指定的路径中搜索需要的库文件;
  3. 最后到 GCC 编译器默认的搜索路径(比如 /lib、/lib64、/usr/lib、/usr/lib64、/usr/local/lib、/usr/local/lib64 等,不同系统环境略有差异)中查找。

1.如果读者使用第一种方法完成链接操作,但 GCC 编译器提示找不到所需库文件,表明所用库文件并未存储在当前路径下,解决方案就是手动找到库文件并将其移至当前路径,然后重新执行链接操作。

2.第二种方法, GCC 编译器提示未找到所需库文件,表明库文件的存储路径不对,解决方案有以下 3 种:
  • 手动找到该库文件,并在 gcc 指令中用 -L 选项明确指明其存储路径。比如 libmymath.a 静态库文件存储在 /usr 目录下,则完成链接操作的 gcc 指令应为gcc -static main.c -L/usr -lmymath -o main.exe
  • 将库文件的存储路径添加到 LIBRARY_PATH 环境变量中。仍以库文件存储在 /usr 目录下,则通过执行export LIBRARY_PATH=$LIBRARY_PATH:/usr指令,即可将 /usr 目录添加到该环境变量中(此方式仅在当前命令行窗口中有效);
  • 将库文件移动到 GCC 编译器默认的搜索路径中

4.GCC运行可执行文件时找不到动态库文件

执行已生成的可执行文件时,如果 GCC 编译器提示找不到所需的库文件,这意味着 GCC 编译器无法找到支持可执行文件运行的某些动态库文件。

事实上,当 GCC 编译器运行可执行文件时,会按照如下的路径顺序搜索所需的动态库文件:

  1. 如果在生成可执行文件时,用户使用了-Wl,-rpath=dir(其中 dir 表示要查找的具体路径,如果查找路径有多个,中间用 : 冒号分隔)选项指定动态库的搜索路径,则运行该文件时 GCC 会首先到指定的路径中查找所需的库文件;
  2. GCC 编译器会前往 LD_LIBRARY_PATH 环境变量指明的路径中查找所需的动态库文件;
  3. GCC 编译器会前往 /ect/ld.so.conf 文件中指定的搜索路径查找动态库文件;
  4. GCC 编译器会前往默认的搜索路径中(例如 /lib、/lib64、/usr/lib、/usr/lib64 等)中查找所需的动态库文件。

注意,可执行文件的当前存储路径,并不在默认的搜索路径范围内,因此即便将动态库文件和可执行文件放在同一目录下,GCC 编译器也可能提示“找不到动态库”。


因此,对于 GCC 运行可执行文件时提示找不到动态库文件的问题,常用的解决方法是:
  • 将动态库文件的存储路径,添加到 LD_LIBRARY_PATH 环境变量中。假设动态库文件存储在 /usr 目录中,通知执行export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr指令,即可实现此目的(此方式仅在当前命令行窗口中有效);
  • 修改动态库文件的存储路径,即将其移动至 GCC 编译器默认的搜索路径中。
  • 修改~/.bashrc 或 ~/.bash_profile 文件,即在文件最后一行添加export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:xxx(xxx 为动态库文件的绝对存储路径)。保存之后,执行 source .bashrc 指令(此方式仅对当前登陆用户有效)。


注意:值得一提的是,GCC 编译器提供有 ldd 指令,借助该指令,我们可以明确知道某个可执行文件需要哪些动态库文件做支撑、这些动态库文件是否已经找到、各个动态库文件的具体存储路径等信息。

 

未完待续...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值