GCC编译过程及基本命令总结

2023-05-16

一、GCC简介

GCC即GNU Compiler Collection,原本只是针对C语言的编译工具,现在已经变成了一个工具集,包含了C、C++、JAVA等语言的集合体。

管理和维护:由GNU项目负责。

二、GCC对C、C++的编译流程

(1) 预处理(Preprocessing) 

--宏替换;

--删除注释;

--处理预处理指令,如#include,#ifdef,头文件都被展开,拼接所有头文件到一个文件中。

(2) 编译(Compilation)        

--词法分析,识别单词,确认词类;比如 int i;知道 int 是一个类型,i是一个关键字以及判断i的名字是否合法

--语法分析,识别短语和句型的语法属性;

--语义分析,确认单词、短语和句型的语义特征;

--代码优化,修辞、文本编辑;

--代码生成,生成译文(.s文件,统一代码在不同系统中的.s文件不一致)。

(3)汇编(Assemby)             

--把汇编语言代码翻译成目标机器指令(生成目标文件,.o文件)。

编译器把一个cpp编译为目标文件的时候,除了要在目标文件里写入cpp里包含的数据和代码,还要至少提供3个表:未解决符号表,导出符号表和地址重定向表。

未解决符号表,提供了所有在该编译单元里引用但是定义并不在本编译单元里的符号及其出现的地址。

导出符号表,提供了本编译单元具有定义,并且愿意提供给其他编译单元使用的符号及其地址。

地址重定向表,提供了本编译单元所有对自身地址的引用的记录。

(4) 链接(Linking)                 

--将所有.o文件及引用到的动态链接库文件中的函数链接到一起,生成可执行文件(.out文件)。

三、GCC的基本使用(以下选项在g++中同样试用,一般c程序就用gcc编译,c++程序就用g++编译

基本使用格式 :    $ gcc  [选项]  <文件名>

(1) -o 设置gcc处理结果的文件名为<文件名>

如 gcc main.c -o main  ,即为将编译结果的文件名设置为main,如果不使用-o命令,则编译结果是默认的文件名(假如被处理的源文件为source.suffix,若省略了-o选项,则生成的可执行文件默认为a.out,目标文件默认名为source.o,汇编文件默认为source.s)。

例如对于这个main.c

-- 执行 gcc main.c (输出默认文件名)

-- 执行 gcc main.c -o main (指定gcc处理结果的文件名为main)

(2) -c 只编译,不链接

执行 gcc -o main.c (结果为.o文件) 

一般对于包含对个.c文件的大工程,首先把每个.c文件编译成独立的.o文件,然后把所有.o文件进行链接生成可执行文件。 

(3) -E 预编译 (将所有的头文件和宏都拼接到一个.c文件中)

 执行 gcc -E main.c (可见在main()函数之前,所有的头文件和宏定义都被包含进来(先把头文件copy过来,然后对宏进行替换))

 也就是说对于一个程序,预编译会把所有的头文件和宏定义都拼接到一个文件中,因为其实一个程序就算其包含了很多子文,但是最终都是编译一个文件。

(4) -S 只编译不汇编

执行 gcc -S main.c (生成.s文件,同意程序在不同体系下的计算机中生成的汇编文件是不一致的)

(5) -g 生成调试信息(debug版本)

执行 gcc -g main.c -o main_d ,生成带调试信息的版本,并令生成的文件名为“main_d”。可见加了-g的版本比普通版本所占空间更大,因为debug版本加入了调试信息,会把代码编进去,后面可以使用GDB工具进行调试跟进


【多目录编译】

(6) -I 添加头文件路径(多文件目录下)

例如有如下目录:

--person

        --person/person.h

        --person/person.cpp

--test

         --test/main.cpp

main.cpp如下

person.h如下 

person.cpp如下

 编译过程如下:

(a). 执行 g++ -c person.cpp ,首先单独编译person.cpp生成目标文件person.o 。

(b). 执行 g++ main.cpp ../person/person.o -o main -I ../person,编译person.o和main.cpp,-I添加头文件目录。


【静态编译】

(7)  -static 静态编译(若指定为静态编译,则会把所有引用到的系统文件都指定成静态库,全部编译到这个可执行文件中)

使用ldd可以查看程序所引用到的动态库。

执行 ldd main ,可见一个简单的程序都引用了很多库。

执行  g++ main.cpp ../person/person.o -o main_static -I ../person -static ,将程序进行静态编译(使用个g++是因为gcc编译c++找不到库文件)。

然后再使用ldd main_static查看调用的动态库,可以发现它不调用任何动态库。

 而且可执行文件的大小变得非常大。

注:大部分情况下不建议使用静态方式进行编译,因为其最大的问题就是编译时间太长,稍微大点的项目编译要几分钟,但是它在其他环境下运行比较简单,不需要配置环境依赖。


【动态编译】

(8) -fpic -shared  前者指定函数和代码位置不相关,设置之后可以使用-shared将其设置为动态链接库动态链接库在linux中的命名规则为 lib+name+.so,引用的时候只要使用name就行了)。

执行 gcc person.cpp -fpic -shared -o libperson.so ,将person.cpp编译成动态链接库 libperson.so。

(9) -L -l(小写的L) 前者指定动态链接库的所在目录,后者指定需要链接的动态链接库(不加lib 和.so)

执行 g++ main.cpp -o main -I../person -L../person -lperson ,在编译main时使用-I(大写的i)指定头文件目录,使用-L指定董涛链接库目录,使用-lperson指定需要在编译时链接libperson.so这个动态链接库文件。

 注意:执行通过动态链接而编译生成的可执行文件main时,需要指定动态链接库文件libperson.so的路径,否则运行数失败。

解决方法有两种:

(a) 将需要链接的动态链接库文件libperson.so拷贝到系统的path路径下。

(b) 写执行脚本export LD_LIBRARY_PATH=../person,添加临时路径。

 使用ldd命令查看main依赖,可见确实在../person目录下找到的。

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

GCC编译过程及基本命令总结 的相关文章

随机推荐

  • Linux平台设备和驱动

    一 platform总线 一个现实的linux设备驱动通常需要挂接在一种总线上 xff0c 对于本身依附于PCI xff0c USB xff0c IIC xff0c SPI等的设备而言 xff0c 这自然不是问题 xff0c 但是在嵌入式系
  • 2019年终总结&小半年流媒体服务器开发经验总结

    2019年终总结 amp 小半年流媒体服务器开发经验总结 文章目录 2019年终总结 amp 小半年流媒体服务器开发经验总结19年开发小结流媒体服务框架设计登录服开发ffmpeg音视频合成服务开发 流媒体服务开发小结rtp处理视频的合成 a
  • 设备接入ONENET(3)STM32 + ESP8266(MQTT协议)接入云 :官方例程移植笔记(HAL+LL库)

    重要提示 xff1a 由于OneNET版本迭代 xff0c 导致鉴权方式可能变更 xff0c 若程序无法连接 xff0c 请参考官方手册或再OneNET论坛搜索相关内容 移植本意应该是指通过修改 使得运行原先在另一个平台可运行的程序 STM
  • pygame 学习笔记(4)推荐一本python入门游戏书籍《PYTHON游戏编程入门》

    简介 PYTHON游戏编程入门 xff08 More Python Programming for the Absolute Beginner xff09 是 S Harbour写的一本入门书籍 xff0c 基于pygame库 本书每一个章
  • VLC加载插件失败原因及解决

    最近做视频播放的程序 xff0c 找到了VLC开源库 在windows 43 vs2013 43 QT5 3环境下进行调试 出现了在调用libvlc new时提示不能找到插件 加载libvlc失败的问题 原因及解决方法如下 xff1a 1
  • logcat的使用

    参考链接 log信息级别 以下优先级从上往下排序 xff1a V xff1a verbose 显示全部信息 最低优先级 xff0c 对应Log v String tag String msg D xff1a debug 显示调试信息 xff
  • 物联网架构实例—解决Linux(Ubuntu)服务器最大TCP连接数限制

    1 前言 xff1a 在对物联网网关进行压测的时候 xff0c 发现在腾讯云部署网关程序 xff0c 设备接入数量只能达到4000多个长连接 xff0c 之后就再也无法接入终端了 之前在阿里云部署的时候明明可以到达2万左右 xff0c 而且
  • Prometheus从入门到跑路

    1 prometheus框架结构 2 prometheus组件介绍 2 1 Prometheus Server 这是Prometheus的服务端 xff0c 也就是核心 Prometheus本身是一个以进程方式启动 xff0c 之后以多进程
  • ucos-ii学习笔记1 创建任务&&任务调度

    span style font family none font size 12px background color rgb 255 255 255 span span 最近在学习嵌入式系统 xff0c 听说ucos ii是使用最广 xf
  • ucos ii学习笔记2 邮箱&&信息量

    上一篇说了ucos ii的大致运行原理 xff0c 这一篇主要用来说明不同任务之间的数据传递的 有人会说 xff1a 不同任务间的数据传递直接用全局变量不就好了 xff0c 我一开始也有这种疑惑 xff0c 也在简单程序中实验过没什么问题
  • ucos ii学习笔记4 软件定时器

    span span p span style font size 18px span span ucos ii从V2 83版本以后加入了软件定时器 xff0c 软件定时器的最快时钟节拍就等于ucos ii的系统时钟节拍 xff0c 由一个单
  • 时钟源关系初解

    最近发现自己对时钟的各种关系不是很清晰 xff0c 所以在这里初步的顺一下 以STM32F4为例 xff0c 大概都差不多 STM32F4有5个时钟源 xff0c 分别是HSI HSE LSI LSE PLL 从名字上看出HSI和HSE是高
  • up-board

    安装ubuntu16 04 安装board内核 http www eeboard com bbs thread 59222 1 1 html 对管脚的控制 http www eeboard com bbs thread 59257 1 1
  • 【嵌入式软件实习】找实习和电话面试记录与总结

    前言 前一段时间就是非常想找实习 xff0c 这次是接到了一家还算是比较大的公司的面试通知和实习offer 做一下简单的记录给在找实习的大家一个参考吧 主要内容为 xff1a 三连即可提高学习效率0 0 x1f9d1 x1f3fb 作者简介
  • Ubuntu更换apt镜像源

    原文 xff1a Ubuntu更换apt镜像源 在ubuntu中 xff0c 默认使用 ubuntu 的官方源http archive ubuntu com xff0c 但是这个官方源在国内下载的速度太慢 xff0c 甚至只有几十k 于是考
  • JS 闭包 详细说明(教程)

    首先 xff0c 闭包是一个高阶函数 xff0c 高阶函数除了可以接受函数作为参数外 xff0c 还可以把函数作为结果值返回 xff08 不知道高阶函数是啥 xff0c 点击链接 xff09 先通过一个例子来了解一下如何把函数作为结果值返回
  • STVP烧录程序

    STVP介绍 STVD xff1a ST Visual Develop xff0c 可视化开发工具STVP xff1a ST Visual Programmer xff0c 可视化编程工具 xff0c stvp主要打开一些固件 hex s1
  • 传感器标定系列——Kalibr工具

    文章目录 Kalibr介绍安装资源 Kalibr介绍 Kalibr is a toolbox that solves the following calibration problems 多相机标定 Multi Camera Calibra
  • TCP传输图片及多线程

    最终效果图 xff1a 注意 xff1a 图片发送大体流程同 Qt网络编程 TCP IP 一 只是在发送时这里采用 的 数据流QDataStream形式 因为使用摄像进行监控时也是对一帧一帧的图片进 行处理 xff0c 因此掌握了如何用Qt
  • GCC编译过程及基本命令总结

    一 GCC简介 GCC即GNU Compiler Collection xff0c 原本只是针对C语言的编译工具 xff0c 现在已经变成了一个工具集 xff0c 包含了C C 43 43 JAVA等语言的集合体 管理和维护 xff1a 由