本文简单整理了GCC编译的命令项,可作为后续使用的参考。

编译

本文以GCC为主,默认编译*.c的c语言源代码。

源文件->可执行文件

gcc -Wall test.c -o test

gcc -Wall a.c b.c -o main

这里a.c、b.c一起编译生成一个可执行文件。

注意 -Wall选项表示打开所有最常用的编译警告,也是gcc最推荐使用的选项。

分段编译通常是先生成中间文件(*.o),然后通过链接器生成可执行文件。GCC也提供了类似机制。

源文件->中间文件(*.o)

gcc -Wall -c test.c

gcc -Wall -c a.c b.c main.c

多个*.c文件表示同时生成对应的中间目标文件。

中间文件(*.o)->可执行文件

gcc test.o -o test

gcc a.o b.o main.o -o test

依赖项设置

外部库文件依赖

对于需要引用库的情况,可以使用-l(小写字母L)指定依赖库,或者使用绝对路径引入。比如,:

import libm.a

gcc -Wall calc.c -lm -o calc

gcc -Wall calc.c /usr/lib/libm.a -o calc

默认情况下GCC会在/usr/local/include/usr/include目录中搜索头文件;在/usr/local/lib/usr/lib中搜索库。同时可以单独使用-I-L分别指定包含头文件、包含库文件的搜索路径。

比如下面命令:

gcc -Wall test.c -I/header -L/lib -o test

在Shell脚本中也可以通过环境变量指定默认搜索的头文件和库文件路径,分别使用C_INCLUDE_PATH和LIBRARY_PATH参数。

对于动态链接的情况,还有一个比较重要的环境变量,LD_LIBRARY_PATH,设置默认加载动态库的目录。

预处理和宏

GCC支持使用"-DNAME"的形式在编译时定义宏。

比如下面指令,会在test.c文件中定义TEST宏

gcc -Wall -DTEST test.c -o test

宏也可以带有参数,比如下面指令,

gcc -Wall -DNUM=100 val.c -o value

gcc -Wall -DNUM val.c -o value

在不指定的值的情况下,gcc会将宏默认赋值为1。也支持宏展开

gcc -Wall -DNUM="2+2" val.c -o value

下面是val.c的代码,感兴趣的可以验证下上面语句的实际输出情况

#include <stdio.h>
int main(void)
{
printf("Value of NUM is %d", NUM);
return 0;
}

生成预处理之后的文件(*.i)

gcc -E test.c -o test.i

或者使用-save-temps选项。

带有调试信息编译

GCC提供了“-g”调试选项在对象文件(*.o)和可执行文件中存储额外的调试信息。使用“-g”选项除了允许程序在调试器控制下运行外,还可以找到程序崩溃的环境。当程序异常退出时,操作系统会在当前目录生成“core”文件。程序员可以从core文件中查询到程序退出的位置和当时的变量值。

可以使用下面格式加载core文件。

gdb EXECUTABLE-FILE CORE-FILE

gdb backtrace 显示调用堆栈

编译优化

GCC提供了"-OLEVEL",用于选择哪一种优化,LEVEL可取值0、1、2、3、s。默认GCC使用“-O0”或者“-O”(大写字母o)。通常我们在实际开发调试时使用默认的“-O0”调试,发布或者部署时使用“-O2”。

至于具体含义建议参考GCC用户手册。优化的含义是在运行速度或者可执行程序大小上优化,当然优化级别越高,与源代码差距越大,可读性越差。

GNU 发行的软件包默认都打开了调试选项“-g”和优化选项“-O2”。

c++编译

c++编译需要使用g++,例如:

g++ -Wall test.cpp -o test

其他编译指令跟gcc类似

生成静态库

GCC提供了ar生成静态库,通常静态库是一系列对象文件(.o)的集合。

可以用下面指令将两个对象文件打包成linux下的静态库文件(
.a)。

gcc -Wall -c init.c uninit.c

ar cr libhello.a init.o uninit.o

查看*.a中的内容列表

ar t libhello.a

生成动态库

编译时使用“-fpic”选项,用于指定输出的目标文件是按照可重定位地址(relocatable addressing)方式生成的。pic表示position independent code。并在链接时使用“-shared”生成最终动态库。

以下指令将两个源代码生成一个*.so文件。

gcc -Wall -c -fpic first.c second.c

gcc -Wall -shared first.o second.o -o hello.so

生成文件查看及分析

查看可执行文件类型

使用file指令,可以查看可执行文件的类型。比如下面输出:

$ file a.out

a.out: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), not stripped

查看符号表

使用nm指令,比如:

nm test.o

查看动态库依赖项

使用ldd指令,可查看可执行模块的外部库依赖项

c程序中文件后缀说明

  • .a 静态对象库,是目标文件的封装格式。
  • .c c语言源代码
  • .h 源代码的头文件
  • .i 预处理之后的c语言源代码,是GCC编译中间产物
  • .o 目标文件,汇编之后的模块,是GCC编译中间产物
  • .s 汇编语言代码,是GCC中间产物。
  • .so 共享对象库

源代码(*.c)通过预处理,生成*.i文件;经过词法分析和语法分析之后生成伪代码形式的*.s文件;然后通过汇编之后生成依赖特定平台的目标文件(*.o);最后使用链接器将多个目标文件生成一个可执行文件。

备注

本文主要参考“An Introduction to GCC”整理。算是简单的GCC编译指令汇总。

GCC Reference的更多相关文章

  1. Summary on deep learning framework --- PyTorch

    Summary on deep learning framework --- PyTorch  Updated on 2018-07-22 21:25:42  import osos.environ[ ...

  2. gcc参数-l传递顺序错误导致`undefined reference'的一点小结

    刚才编译一个pthread的单文件程序, 使用的命令行是: gcc -o thread1 -lpthread thread1.c 结果报错: $ gcc -o thread1 -lpthread th ...

  3. variadic templates & pass by const reference & member operator [] in const map & gcc sucks

    /// bugs code with comments #include <iostream> #include <memory> #include <unordered ...

  4. GCC编译uboot出现(.ARM.exidx+0x0): undefined reference to `__aeabi_unwind_cpp_pr0&#39;错误的解决的方法

    /opt/arm-2010.09/bin/../lib/gcc/arm-none-linux-gnueabi/4.5.1/armv4t/libgcc.a(_bswapsi2.o):(.ARM.exid ...

  5. [Linux][C][gcc] Linux GCC 编译链接 报错ex: ./libxxx.so: undefined reference to `shm_open'

    本人原创文章,文章是在此代码github/note的基础上进行补充,转载请注明出处:https://github.com/dramalife/note. 以librt丶用户自定义动态库libxxx 和 ...

  6. ubuntu下 GCC编译程序出现 undefined reference to `std::ios_base::Init::Init()'问题

    网上的解释是:“ you need to add -lstdc++, or use 'g++' rather than 'gcc' as your driver program.”,也就是说如果想要使 ...

  7. gcc链接程序时出现undefined reference to""错误

    如:: undefined reference to ‘mq_unlink',意思是指函数mq_unlink没有定义. 可以使用如下步骤找到该函数所在的库: 1).查找哪些库包含了或使用了该函数:gr ...

  8. 在Linux下使用gcc编译mesa文件报undefined reference to symbol 'sin@@GLIBC_2.2.5和DSO missing from command line两个错误的解决方案

    一.概述 在Linux系统下使用gcc编译用C语言写的mesa的示例程序. 环境:Ubuntu Server 18.04.1 二.问题的出现 在Ubuntu下安装好mesa所需的库文件,将目标文件从g ...

  9. 利用gcc编译链接时出现 ‘undefined reference to `std::ios_base::Init::Init()’ 解决

    一般编译链接c++程序最好使用g++,若有如上的报错信息,需要在gcc后加上 -lstdc++ eg: gcc test.c -lstdc++ gcc和g++都是GNU的一个编译器. g++:后缀.c ...

随机推荐

  1. MATLAB R2018a 安装教程

    1.下载相应的 MATLAB  R2018a  版本如下:[matlab2018的百度云盘:链接:https://pan.baidu.com/s/1OV242y6EV6auvG3DvvqD8A 密码: ...

  2. Elasticsearch报警插件Watch安装以及使用

    参考:http://blog.csdn.net/ptmozhu/article/details/52296958 http://corejava2008.iteye.com/blog/2214279 ...

  3. JAVA删除文件及文件夹

    JAVA在删除文件或文件夹时,在java.io.File类下有个delete的方法,并且可以返回true or false, 用这个方法来删除单个文件时,很好使,但在删除文件夹时,如果文件夹下面有文件 ...

  4. 树莓派进阶之路 (009) - 树莓派ftp脚本(原创)

    FTP.sh #!/bin/sh cd echo "彻底卸载原有的ftp" sudo apt-get remove --purge vsftpd #(--purge 选项表示彻底删 ...

  5. 树莓派进阶之路 (005) - 树莓派Zsh安装脚本(原创)

    zsh.sh #!/bin/bash cd #安装zsh sudo apt-get install zsh #查看zsh cat /etc/shells #更改zsh chsh -s /bin/zsh ...

  6. 树莓派进阶之路 (006) - 树莓派安装wiringPi

    安装git-core sudo apt-get install git-core 下载winringPi库 git clone git://git.drogon.net/wiringPi 编译和安装库 ...

  7. io分析神器blktrace

    一.概述 [许久之前就用过blktrace,现整理如下] 从linux 一个完整的IO入手分析: 一个I/O请求进入block layer之后,可能会经历下面的过程: Remap: 可能被DM(Dev ...

  8. 一步一步掌握线程机制(三)---synchronized和volatile的使用

    现在开始进入线程编程中最重要的话题---数据同步,它是线程编程的核心,也是难点,就算我们理解了数据同步的基本原理,但是我们也无法保证能够写出正确的同步代码,但基本原理是必须掌握的. 要想理解数据同步的 ...

  9. Android Studio多Module开发需要注意的问题

    多module开发,其中的一个为入口module,其他module为独立的“应用”(library) 1.在原有的项目导入另外个项目的module为主项目的次module,即在A项目中添加一个启动B项 ...

  10. 第二篇:呈现内容_第二节:WebControl呈现

    一.WebControl的呈现过程 WebControl派生自Control类,所以WebControl的呈现功能基于Control的呈现逻辑之上,但有了比较大的扩展. 首先,WebControl重写 ...