宝剑锋从磨砺出——编译器gcc的使用



剑,是一种武器,古龙先生很喜欢论剑,对剑也有不一样的理解;对于剑,使用它的是剑客,而如果要升级则是人的升级,从而推动剑术的提高与用剑的境界的提升。

 好的剑都是铸剑师倾入自己的心血浇灌而成的;而对于剑客,要想能够使用它,不仅仅是挥动它,而是用能够与之沟通,能够“心灵相通”,不断地与之磨合,达到收发自如的境界。

编译器就是程序员的“剑”,而且GCC就是“剑中利器”;但是它对于所有人都是一样的,其关键在于使用它的人,如何去“磨”,如何去“练”,“磨”出自己的“形状”,“练”出自己的感觉,让自己得心应手的去使用它。


一)gcc的基本介绍,详细的使用情况,请查看附件或者gcc的官网手册——https://gcc.gnu.org/onlinedocs/gcc-4.9.2/gcc/

gcc GNU Compiler Collection的缩写,即GNU编译器工具集。在c语言的编译流程中主要扮演两个角色预处理器与编译器,另外,它也能够调用了binutils中的汇编器(as)与链接器(ld)生成对应的elf文件。它主要支持编译的语言有:c/c++/java/object-c/object-c++/fortran/ada.

gcc作为一个编译器,为了能够更好的整理各种工具,它被设计为一个由specs文件驱动的程序。specs文件描述了gcc的所有行为。默认的spec文件可以用gcc -dumpspecs,详细描述见https://gcc.gnu.org/onlinedocs/gcc-4.9.2/gcc/Spec-Files.html#Spec-Files。通过spec文件可以理解gcc的执行流程与相关参数的设置,通过修改它可以配置它的执行流程。当然也可以定制spec文件,通过gcc -specs=<file>实现。

为什么要学习与熟悉gcc呢?不仅仅是因为它是完备的编译器,更因为GNU开源的强大力量,已经将它推广到各种处理器构架与各种应用平台。但是因为它的适用性很广,从而导致了它很多的命令项,让人头晕目眩,但是常用的确只有一些,被反复使用,值得总结一下。

gcc被编译出来,主要的可执行文件(LFS7.6:6.17.2):

c++/g++:c++编译器

gcc/cc:c编译器

cpp:c语言预处理器

gcov:程序覆盖测试工具,用于统计程序运行代码执行的频率,从而为程序优化做参考


 二)gcc的基本用法

 1.演绎c语言编译的流程(以hello.c为例):

 a)预处理:gcc -E hello.c,将c语言定义的宏展开,输出到终端界面

     b)编译:gcc -S hello.c,解析c语言语法生成对应的汇编语言(AT&T语法)文件,hello.s

     c)汇编:gcc -c hello.s ,调用as将编译生成的hello.s生成模板文件(elf文件),即hello.o

     d)链接:gcc -o hello hello.o,调用ld将生成的hello.o链接成可执行文件,即hello


         2.编译c语言源码的主要命令行参数: 

    在编译c语言过程中,需要注意两个方面:其一为头文件(*.h)的寻找,其二为函数库的链接。c语言中头文件的使用是一般是用相对路径,#include <*.h>指定包含的文件内容,但是从哪个路径下去寻找对应的头文件。需要用-I path的参数来指定对应的路径。当在链接时,如果碰到如下出错,“hello.c:(.text+0xf): undefined reference to `add'”表示无法找到对应的符号引用,则为链接出错。解决这样的问题是用“-L path”指定链接库的路径,“-l so-name”指定链接库的名(比如:libcurl.so,名称为curl)。

如上所诉,gcc指定编译路径与链接库的方式为:

gcc -I inc-path -L lib-path -l lib-name.

C语言中使用宏来帮助程序编写,为了提高程序兼容性,在许多软件项目用宏来分隔不同平台与使用环境的代码,从而当在实际编译过程中指定相应的宏来控制程序的编译过程。可以用“-D MACRONAME=VALUE”来将MACRONAME传递给程序,编译。

将调试信息添加到elf文件中,方便程序调试,建议是每次编译都把它打开,方便程序调试.用参数“-g”来指定。

优化程序指令“-O 2,指定编译时的优化等级。

为了提前发现各种语法错误与逻辑错误,可以将“- Wall”所有的警告信息打印出来,然后对代码进行优化与纠正。

    链接所有的目标文件,生成动态链接库:gcc -shared -fPIC -o lib$fn.so $fn.c


    3.gcc的默认路径与行为:

    a)如何获取gcc的默认链接路径与头文件路径(LFS7.65.4):

    (1)编译测试的c语言源代码:echo 'main(){}' > dummy.c

   (2)获取编译信息:gcc dummy.c -v -Wl,--verbose &> dummy.log

   (3)查询默认头文件路径:grep -B4 '^ /usr/include' dummy.log

   (4)查询默认的链接路径:grep 'SEARCH.*/usr/lib' dummy.log |sed 's|; |\n|g'

   (5)查询标准c的库路径(glibc):grep "/lib.*/libc.so.6 " dummy.log

   (6)获取默认链接库的路径的方法:gcc -print-search-dirs |sed -n '/libraries:/p'

    b)影响gcc行为的环境变量,格式跟PATH一样用:分割:

    CPATH/C_INCLUDE_PATH增加头文件搜索路径

 LIBRARY_PATH增加链接库的搜索路径


4.交叉编译工具,主要有三部分(binutils/gcc/glibc)介绍:

在开发主机上生成目标主机的编译工具,比如:在x86开发平台上生成arm板上运行的gcc——arm-none-linux-gnueabi-gcc;在gcc之前添加交叉编译前缀。对于交叉编译工具,形式上在编译器工具集之前添加了交叉编译前缀,使用方式和gcc是一致的,只是有一些针对目标机器的特定参数,实际效果是生成了能够在目标主机上运行的可执行文件,可以通过binutils进行分析。获取交叉编译工具的方法有三种:1.到网上下载现成的工具集;2,自己一步一步编译;3.用现成的编译脚本一次编译。

三)Makefile的基本介绍,详细见附件makefile文档

    软件工程都是由很多模块化的源文件构成,当软件规模不断扩大,同时软件bug不断修改,也是为了简化与减少重复的软件劳动,需要有序地将所有软件源文件管理起来,从而诞生了Makefile

   了解Makefile对理解程序如何生成的与软件模块的构成有很大的帮助,而且往往一开始接触软件项目时,都有一套软件系统或者由自己构建软件系统,此时makefile就是第一个需要去熟悉的步骤。

   首先makefilemake命令给读取,然后执行;make命令的常用参数:

   基本格式:make [选项] [目标](如果目标不为空,则去执行makefile定义的目标)

-j N :同时允许 个任务;可以加快make的执行。

-C dir:进入dir目录,执行make命令

Makefile的基本书写格式:

目标:依赖

[Tab]命令

所有的makefile可以看作是定义的目标的集合。

    当系统越来越复杂时,构建makefile也是很复杂的事,同时也考虑到软件系统编译时,也依赖于系统编译环境,所以就有了自动构建makefile的相关工具与命令:gnu发布软件的autotools(通过configure配置来生成相关的makefile),cmake来自动构建makefile,qt编译时使用的qmake等。在Android系统开发构成也引入了Android.mkmm命令来编译系统。


 




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值