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规定生成可执行文件的文件名

举例:

#include <stdio.h>

int main()
{
printf("hello world!");
return 0;
}

1.1预处理

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

//.....
# 1 "/usr/include/sys/cdefs.h" 1 3 4
# 43 "/usr/include/sys/cdefs.h" 3 4
# 1 "/usr/include/machine/_default_types.h" 1 3 4
# 41 "/usr/include/machine/_default_types.h" 3 4 # 41 "/usr/include/machine/_default_types.h" 3 4
typedef signed char __int8_t; //......
# 741 "/usr/include/stdio.h" 3 4
static __inline int
_getchar_unlocked(void)
{
struct _reent *_ptr; _ptr = (__getreent());
return (__sgetc_r(_ptr, ((_ptr)->_stdin)));
} static __inline int
_putchar_unlocked(int _c)
{
struct _reent *_ptr; _ptr = (__getreent());
return (__sputc_r(_ptr, _c, ((_ptr)->_stdout)));
}
# 797 "/usr/include/stdio.h" 3 4 # 2 "1.c" 2 # 3 "1.c"
int main()
{
printf("hello world!");
return 0;
}

1.2转汇编

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

	.file	"1.c"
.text
.def __main; .scl 2; .type 32; .endef
.section .rdata,"dr"
.LC0:
.ascii "hello world!\0"
.text
.globl main
.def main; .scl 2; .type 32; .endef
.seh_proc main
main:
pushq %rbp
.seh_pushreg %rbp
movq %rsp, %rbp
.seh_setframe %rbp, 0
subq $32, %rsp
.seh_stackalloc 32
.seh_endprologue
call __main
leaq .LC0(%rip), %rcx
call printf
movl $0, %eax
addq $32, %rsp
popq %rbp
ret
.seh_endproc
.ident "GCC: (GNU) 7.3.0"
.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. 【转】equals和==的区别

    ==: == 用于比较两个对象的内存地址值(引用值)是否相等,也就是比较的是变量(栈)内存中存放的对象的(堆)内存地址,用来判断两个对象的地址是否相同,即是否是指相同一个对象.比较的是真正意义上的指针 ...

  2. 解决github提示安全漏洞的问题

    今天在提交代码的时候发现github提示了这样的错误: We found potential security vulnerabilities in your dependencies. Only t ...

  3. PLSQL登录的时候Warning提示:Using a filter for all users can lead to poor performance!

    转自: https://blog.csdn.net/athena2015/article/details/81811908

  4. 前端框架开始学习Vue(一)

    MVVM开发思想图(图片可能会被缩小,请右键另存查看,图片来源于网络)   定义基本Vue代码结构   1 v-text,v-cloak,v-html命令 默认 v-text没有闪烁问题,但是会覆盖元 ...

  5. 用python代码编写象棋界面,棋盘覆盖问题

    编写象棋界面 import turtle t=turtle.Pen() t.speed(100) def angle(x,y): t.penup() t.goto(x+3,y+3) t.pendown ...

  6. Django中过滤的实现

    过滤模块 安装 >: pip install django-filter 注册应用:settings/dev.py INSTALLED_APPS = [ # 列表过滤模块 'django_fil ...

  7. 剑指Offer(三十一):整数中1出现的次数(从1到n整数中1出现的次数)

    剑指Offer(三十一):整数中1出现的次数(从1到n整数中1出现的次数) 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https:// ...

  8. Linux基础之终端、控制台、tty、pty等概念简介

    基本概念: 1>tty(终端设备的统称): tty一词源于teletypes,或者teletypewriters,原来指的是电传打字机,是通过串行线用打印机键盘阅读和发送信息的东西,后来这东西被 ...

  9. 《AlwaysRun!团队》第四次作业:项目需求调研与分析

     项目  内容  这个作业属于哪个课程 http://www.cnblogs.com/nwnu-daizh/  这个作业的要求在哪里 https://www.cnblogs.com/nwnu-daiz ...

  10. 网站入侵工具 SQL注入神器

    0x 00 前言 SQLMAP 0x 01 注入原理              不说了 *****************************************结束分割线********** ...