GCC编译步骤

gcc -E t1.c -o t1.i 预处理

gcc -S t1.i -o t1.s 转成汇编语言

gcc -c t1.s -o t1.o 转成机器码

gcc t1.o -o t1.exe 链接

直接使用gcc t1.c将自动编译链接生成t1.out

或gcc t1.c -o t1.exe规定生成可执行文件的文件名

举例:

  1. #include <stdio.h>
  2. int main()
  3. {
  4. printf("hello world!");
  5. return 0;
  6. }

1.1预处理

预处理后生成1.i文件,打开如下:相当于把stdio.h文件包含进1.c文件了

  1. //.....
  2. # 1 "/usr/include/sys/cdefs.h" 1 3 4
  3. # 43 "/usr/include/sys/cdefs.h" 3 4
  4. # 1 "/usr/include/machine/_default_types.h" 1 3 4
  5. # 41 "/usr/include/machine/_default_types.h" 3 4
  6. # 41 "/usr/include/machine/_default_types.h" 3 4
  7. typedef signed char __int8_t;
  8. //......
  9. # 741 "/usr/include/stdio.h" 3 4
  10. static __inline int
  11. _getchar_unlocked(void)
  12. {
  13. struct _reent *_ptr;
  14. _ptr = (__getreent());
  15. return (__sgetc_r(_ptr, ((_ptr)->_stdin)));
  16. }
  17. static __inline int
  18. _putchar_unlocked(int _c)
  19. {
  20. struct _reent *_ptr;
  21. _ptr = (__getreent());
  22. return (__sputc_r(_ptr, _c, ((_ptr)->_stdout)));
  23. }
  24. # 797 "/usr/include/stdio.h" 3 4
  25. # 2 "1.c" 2
  26. # 3 "1.c"
  27. int main()
  28. {
  29. printf("hello world!");
  30. return 0;
  31. }

1.2转汇编

转汇编 后生成1.s文件,打开如下:

  1. .file "1.c"
  2. .text
  3. .def __main; .scl 2; .type 32; .endef
  4. .section .rdata,"dr"
  5. .LC0:
  6. .ascii "hello world!\0"
  7. .text
  8. .globl main
  9. .def main; .scl 2; .type 32; .endef
  10. .seh_proc main
  11. main:
  12. pushq %rbp
  13. .seh_pushreg %rbp
  14. movq %rsp, %rbp
  15. .seh_setframe %rbp, 0
  16. subq $32, %rsp
  17. .seh_stackalloc 32
  18. .seh_endprologue
  19. call __main
  20. leaq .LC0(%rip), %rcx
  21. call printf
  22. movl $0, %eax
  23. addq $32, %rsp
  24. popq %rbp
  25. ret
  26. .seh_endproc
  27. .ident "GCC: (GNU) 7.3.0"
  28. .def printf; .scl 2; .type 32; .endef

1.3转为机器码

转机器码(二进制)后生成1.o文件,打开如下:

1.4连接成可执行文件(我在win7上演示的)

生成exe可执行文件

详情点击

gcc/g++的编译参数,这里只介绍 -L 、-l、-include、-I、-shared、-fPIC

-L :表示要链接的库所在的目录。-L.  表示要链接的库在当前目录, -L/usr/lib 表示要连接的库在/usr/lib下。目录在/usr/lib时,系统会自动搜索这个目录,可以不用指明。

-l (L的小写):表示需要链接库的名称,注意不是库文件名称,比如库文件为 libtest.so,那么库名称为test

-include :包含头文件,这个很少用,因为一般情况下在源码中,都有指定头文件。

-I (i 的大写):指定头文件的所在的目录,可以使用相对路径。

-shared :指定生成动态链接库

-fPIC:  表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的所以动态载入时事通过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码共享的目的。

生成链接库

第1步,生成目标文件:g++ -c xxx.cpp

第2步,创建静态链接库:  ar  cqs  libxxxx.a  xx1.o xx2.o xx3.o (参数选项请看【5】)

第3步,程序中使用静态链接库

第4步,创建动态链接库 g++ -fPIC -shared -o libxxx.so xx1.cpp xx2.cpp xx3.cpp

第5步,动态链接库使用

 库的链接,上面简单演示了一遍库的生成过程,但是还有很多细节没有讲清楚。以下问题需要注意:

1. 链接过程中可能出现多种链接方式,需要使用一些参数来指定,下面只是一个演示,在测试时,自己填写具体的名称

[plain] view plain copy

  1. g++ testmain.o -o testmain -WI,-Bstatic -lstaticlib -WI,-Bdynamic -ldynamiclib

2. 链接过程中同一个库(名称相同)的静态和动态两种链接库,在链接过程中,系统优先选择动态链接库

3. 动态链接库路径,系统默认在/usr/lib 和/usr/local/lib两个库目录搜索,自己定义的库需要格外指定路径(设定变量LD_LIABRARY_PATH)或者将其拷贝到这两个目录下,在上面的例子的测试过程,已经有说明。当然也可以将当前路径添加到/etc/ld.so.conf文件中或者/etc/ld.so.conf.d目录下的一个文件中。

4. 查看动态链接库。有时候可能需要查看一个库中到底有哪些函数,nm命令可以打印出库中的涉及到的所有符号。库既可以是静态的也可以是动态的。nm列出的符号有很多,常见的有三种:

一种是在库中被调用,但并没有在库中定义(表明需要其他库支持),用U表示;

一种是在库中定义的函数,用T表示,这是最常见的;

另一种所谓的“弱态”符号,它们虽然在库中定义,但可能被其他库中的同名符号覆盖,用W表示。

使用ldd命令可以查看程序的库依赖:

gcc/g++ 链接库的编译与链接的更多相关文章

  1. gcc/g++实战之动态链接库与静态链接库编写

    函数库一般分为静态库和动态库两种. 静态库: 是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也就不再需要库文件了.其后缀名一般为”.a”. 动态库: 与之相反, ...

  2. GCC 预处理,汇编,编译,链接,连接静态库,动态库

    gcc Record gcc -E file1.c > output gcc -E file1.c -o file1.i gcc -S file1.i -o file1.s gcc -S fil ...

  3. 静态库动态库的编译、链接, binutils工具集, 代码段\数据段\bss段解释

    #1. 如何使用静态库 制作静态库 (1)gcc *.c -c -I../include得到o文件 (2) ar rcs libMyTest.a *.o 将所有.o文件打包为静态库,r将文件插入静态库 ...

  4. g++ 动态库的编译及使用

    #ifndef __HELLO_H_ #define __HELLO_H_ void print(); #endif #include "hello.h" #include < ...

  5. gcc/g++以c++11编译

    方法一: //在程序头加上预定义编译器命令 #pragma GCC diagnostic error "-std=c++11" //通过#pragma 指示 GCC编译器处理错误的 ...

  6. linux下C/C++编译时系统搜索 include 和 链接库 文件路径的指定

     C/C++程序在linux下被编译和连接时,GCC/G++会查找系统默认的include和link的路径,以及自己在编译命令中指定的路径.自己指定的路径就不说了,这里说明一下系统自动搜索的路径.   ...

  7. GCC 高版本7.4 编译链接 boost 报错 boost::thread::XXX’未定义的引用 解决方法

    背景:开发中的项目之前一直用GCC4.8,boost库1.48版本的开发环境.现在因业务需求,需要更换GCC7.4,boost库1.70. 问题:可以正常编译BOOST的链接库文件,但是链接时候报错. ...

  8. C/C++ 静态链接库(.a) 与 动态链接库(.so)

    平时我们写程序都必须 include 很多头文件,因为可以避免重复造轮子,软件大厦可不是单靠一个人就能完成的.但是你是否知道引用的那些头文件中的函数是怎么被执行的呢?这就要牵扯到链接库了! 库有两种, ...

  9. [转]Linux下用gcc/g++生成静态库和动态库(Z)

    Linux下用gcc/g++生成静态库和动态库(Z) 2012-07-24 16:45:10|  分类: linux |  标签:链接库  linux  g++  gcc  |举报|字号 订阅     ...

随机推荐

  1. Consul微服务的配置中心体验篇

    Spring Cloud Consul 项目是针对Consul的服务治理实现.Consul是一个分布式高可用的系统,具有分布式.高可用.高扩展性 Consul Consul 是 HashiCorp 公 ...

  2. 在论坛中出现的比较难的sql问题:33(递归 连续日期问题 )

    原文:在论坛中出现的比较难的sql问题:33(递归 连续日期问题 ) 最近,在论坛中,遇到了不少比较难的sql问题,虽然自己都能解决,但发现过几天后,就记不起来了,也忘记解决的方法了. 所以,觉得有必 ...

  3. C#,WinForm文本框录入内容判断

    || e.KeyChar > ) && (e.KeyChar != ) && (e.KeyChar != ) && (e.KeyChar != ) ...

  4. interface Part3(实现:显示和隐式)

    1. 接口的实现实际上和类之间的继承是一样的,也是重写了接口中的方法,让其有了具体的实现内容. 2. 但需要注意的是,在类中实现一个接口时必须将接口中的所有成员都实现,否则该类必须声明为抽象类,并将接 ...

  5. 多进程,多线程,使用sqlalchemy 创建引擎(单例模式),闭包装饰器承载数据库会话,装饰模型类的类方法

    python 多进程,多线程,使用 sqlalchemy 对数据库进行操作 创建引擎 & 获取数据库会话: 使用类的方式,然后在对象方法中去创建数据库引擎(使用单例,确保只创建一个对象,方法里 ...

  6. PC启动过程详解

    系统启动过程 1. 预引导(Pre-Boot)阶段 2. 引导阶段 3. 加载内核阶段 4. 初始化内核阶段 5. 用户登录阶段 基本概念: BIOS:即“Basic Input/Output Sys ...

  7. vscode左侧栏显示

    1.显示工具栏 点击文件,选择首选项,点击设置按钮 搜索workbench,勾选上Workbench> Activity Bar:Visble 勾选上后,工具栏就显示出来了 2.移动工具栏选中工 ...

  8. CentOS7安装CDH 第十一章:离线升级CDH版本

    相关文章链接 CentOS7安装CDH 第一章:CentOS7系统安装 CentOS7安装CDH 第二章:CentOS7各个软件安装和启动 CentOS7安装CDH 第三章:CDH中的问题和解决方法 ...

  9. LTS秘钥协商算法分析

    1.根据RCF文档说法 在1-RTT中有两种密钥协商算法(1-RTT ECDHE和 1-RTT PSK  )和4中0-RTT密钥协商方式(0-RTT PSK, 0-RTT ECDH ,0-RTT EC ...

  10. Django:CSRF(Cross-request forgery)跨站请求伪造

    一.CSRF是什么 二.CSRF攻击原理 三.CSRF攻击防范 一.CSRF是什么 CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Atta ...