1.编译过程

1.1 预处理(Pre-Processing)

  展开头文件, 宏替换(变量宏、函数宏)、替换空格等

gcc -E hello.c  -o hello.i     // -E 预处理选项, -o 重命名

1.2 编译(Compilation)

  逐行检查程序中出现的语法错误,简单的逻辑错误

gcc -S hello.i -o hello.s

1.3 汇编(Assemble)

  将 .s 汇编文件中所有的汇编指令翻译成二进制机器码(下面就是来了个截图,二进制显示了乱码)

gcc -c hello.s -o hello.o

1.4 链接(Linking)

  将 .o 的目标文件,链接库文件、数据段合并,地址回填(把汇编里相对地址替换成程序运行后真正可以运行的地址)。生成可执行文件 hello

gcc hello.o -o hello

1.5 gcc常用参数

-E // 展开头文件
-s // 生成汇编文件
-c // 编译生成2进制文件
-I // 指定头文件路径 大i
-L // 指定库文件路径
-l // 指定库名 小L
-g // 包含调试信息
-On // n取 0-3, n 越大优化级别越高
-Wall //warning all 显示所有警告
-D // 编译时动态注入一个宏, 编译的时候控制#define的具体数值

2.动态库和静态库

2.1 函数库

  本质:把具有相同功能的一组函数放到同一份文件中(源码或二进制的形式)

2.2 静态库

  对执行速度有要求

  • 机制:把引入的库文件通过编译直接复制到 .out 文件中
  • 优点:将函数库中的函数本地化,寻址方便,速度快(函数库执行效率 = 自定义函数的执行效率)
  • 缺点:每个程序都需要复制一份,会浪费内存

  制作静态库:

gcc -c add.c sub.c mul.c    // 制作 .o 文件
ar rs libmymath.a add.o sub.o mul.o // 制作静态库
gcc hello.c -L ./ -lmymath -o app // 指定头文件路径, 指定库名, 设置文件输出名app

2.3 动态库

  对执行速度不敏感,对系统资源敏感;更新比较频繁(可以避免完全重新编译)

  • 机制:代码共享
  • 优点:节省内存(共享)、易于更新(动态链接)
  • 缺点:相较于静态库函数调用速度慢,函数地址是延时绑定机制
gcc -c -fPIC add.c sub.c mul.c    // -fPIC生成与位置无关的目标文件
gcc -shared -o libmymath.so sub.o mul.o add.o // 生成一个动态库
gcc hello.c -o app -L ./lib -l mymath -I ./inc // 生成文件

 启动 ./app 报错,错误原因:”动态链接器“ ld-linux-x86-64.so.2 搜索动态库的路径没有指定

  链接器:工作于 gcc 编译过程中的链接阶段。工作结束后生成可执行文件

  动态链接器:工作于可执行程序运行之后,辅助加载器负责将动态库加载到内存

 解决办法

  环境变量法:export LD_LIBRARY_PATH=./lib 将当前动态库所在的目录加入到环境变量,终端退出后环境变量就会失效

  配置文件法:vi .bashrc 加入一行 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./lib,重启终端,每次启动终端自动生效

  拷贝法:把自己的动态库直接拷贝到 /lib 或 /usr/lib 中

  缓存文件法(推荐):修改配置文件,修改缓存文件,生成动态链接器需要搜索的新目录位置

sudo vim /etc/ld.so.conf    // 修改动态链接库的路径
// 将绝对路径增加到文件中
sudo ldconfig -v // 更新 ld.so.cache 该文件影响动态链接库搜索的位置

3.makefile

3.1 语法

 目标:依赖条件

 tab缩进,指令

hello:hello.o add.o sub.o mul.o
gcc hello.o add.o sub.o mul.o -o hello
hello.o:hello.c
gcc -c hello.c -o hello.o
sub.o:sub.c
gcc -c sub.c -o sub.o
add.o:add.c
gcc -c add.c -o add.o
mul.o:mul.c
gcc -c mul.c -o mul.o

 模式规则:在makefile中,具有有严格统一的规则,使用模式规则代替,模式规则中只能使用 $< 符号

%.o:%.c
gcc -c $< -o $@

 静态模式规则:将模式规则指定给某一个变量使用

$(obj):%.o:%.c
gcc -c $< -o $@

 伪目标:针对残缺的规则,使之生成目标(比如有一个clean.o文件已经是最新的,就不会执行clean清除命令

.PHONY:clean ALL

3.2 函数介绍

3.2.1 wildcard 函数

// 匹配当前工作目录下的所有 .c 文件,将文件名组成列表,赋值给 src 变量
// src = add.c sub.c mul.c hello.o
src = $(wildcard ./*.c)

3.2.2 patsubst 函数

// 用来替换参数, 将 参数3 中包含 参数1 的部分替换为 参数2
// obj = add.o sub.o mul.o hello.o
obj = $(patsubst %.c, %.o, $(src))

3.3 普通变量和自动变量

 普通变量

  • 定义变量语法:变量名 = 变量值     (foo = abc)
  • 取变量值语法:$(变量)           (bar = $abc ---> bar = abc)

 自动变量

  • $@: 在规则的命令中,表示规则中的目标
  • $^ : 在规则的命令中,表示所有依赖条件
  • $< : 在规则的命令中,表示第一个依赖条件。如果该变量应用在”模式规则“中,它可以将依赖条件列表中的每一个依赖,依次取出,套用模式规则

3.4 关键字

  ALL: 默认情况下第一组生成文件的目标就是终极目标,或者显示的写ALL:hello表示终极目标,完成后结束makefile

  clean: 借助makefile清除项目中的指定文件,例如(clean: -rm -rf $(obj) hello

  指令 make -n 模拟执行命令,不真正执行,可以先看一次避免出问题

3.5 修改后的 makefile

src = $(wildcard *.c)
obj = $(patsubst %.c, %.o, $(src)) CC = gcc
target = app ALL:$(target) $(target):$(obj)
$(CC) $^ -o $@ $(obj):%.o %.c
$(CC) -c $< -o $@ clean:
-rm -rf $(obj) $(target) .PHONY:clean ALL

4. gdb调试

4.1 基础指令

 基础的断点设置和继续运行等指令

  • -g:使用该指令编译可执行文件,否则没有调试表
  • gdb ./a.out
  • list:list 1 列出源码,根据源码指定行号设置断点,1表示从第一行开始显示源码
  • b:b 55 在第55行添加断点
  • run/r:运行程序,启动调试(可以直接找到停止位置就是出错位置)
  • next/n:下一条指令(越过函数)
  • step/s:下一条执行(进入函数内部)
  • print/p:打印变量值,如p var 查看 var 变量的值
  • continue:执行到下一个断点
  • finish:结束当前函数调用
  • quit:退出调试
  • start:不使用断点,直接开始单步调试

 设置一些条件和查看栈帧及变量

  • set args:启动gdb调试后,通过该指令可以设置main函数的参数,需要在start和run指令之前设置
  • info b:查看当前断点信息表
  • b 23 if i=5:设置断点在23行,如果 i=5 时断点才生效
  • ptybe:查看变量类型
  • display:设置跟踪变量,display i,跟踪变量 i
  • undisplay:取消跟踪变量
  • bt:列出当前程序存活的栈帧
  • frame:如果有多层调用,在内层想查看外层栈帧里的参数,使用 frame n (n 是栈帧编号)切换栈帧,再使用 p var 打印变量

Linux下gcc编译,动态库和静态库,makefile,gdb调试的更多相关文章

  1. Linux 下 GCC 编译共享库控制导出函数的方法

    通过一些实际项目的开发,发现这样一个现象,在 Windows 下可以通过指定 __declspec(dllexport) 定义来控制 DLL(动态链接库)中哪些函数可以导出,暴露给其他程序链接使用,哪 ...

  2. linux下 GCC编译链接静态库&动态库

    静态库 有时候需要把一组代码编译成一个库,这个库在很多项目中都要用到,例如libc就是这样一个库, 我们在不同的程序中都会用到libc中的库函数(例如printf),也会用到libc中的变量(例如以后 ...

  3. linux下的C语言开发(静态库/动态库)

    动态链接库不是Linux独有的特性,在windows下面也存在这样的特性.一般来说,windows下面的动态连接库是以*.dll作为结尾的,而linux下面的动态连接库是以*.so结尾的.和静态链接库 ...

  4. linux下gcc编译的参数详细说明

    参考网址:1 http://hi.baidu.com/zengzhaonong/item/f1f9383565fa5c302e0f8125 gcc使用方法 汇总 2 http://s99f.blog. ...

  5. linux下gcc编译多个源文件、gdb的使用方法

    一. gcc常用编译命令选项 假设源程序文件名为test.c. 1. 无选项编译链接 用法:#gcc test.c 作用:将test.c预处理.汇编.编译并链接形成可执行文件.这里未指定输出文件,默认 ...

  6. linux 下gcc 编译结构体问题

    最近在linux 学习c语言的编程,发现好多原来在vs 上的在linux 都编译不过去,今天就遇到了一个问题就是结构体的编译的问题, 结构体大概的定义是 struct Node{ int a; int ...

  7. Linux下gcc编译控制动态库导出函数小结

    根据说明文档“How To Write Shared Libraries"介绍, 有四种方法: 1. 在方法声明定义时,加修饰:__attribute__((visibility(" ...

  8. linux下gcc默认搜索头文件及库文件的路径

    一.头文件gcc 在编译时如何去寻找所需要的头文件:※所以header file的搜寻会从-I开始※然后找gcc的环境变量 C_INCLUDE_PATH,CPLUS_INCLUDE_PATH,OBJC ...

  9. linux下GCC编译文件

    Linux终端使用技巧: Ctrl+Alt+T打开终端 Ctrl+c死循环退出程序 Shift+Ctrl+T:新建标签页 Shift+Ctrl+N:新建窗口 Shift+Ctrl+Q:关闭终端 终端中 ...

  10. MacOSX64位机器上gcc编译32位x264静态库

    x264最新包地址:http://www.videolan.org/developers/x264.html 编译命令: ./configure --enable-static --host=i386 ...

随机推荐

  1. C# 相等比较

    C# 相等比较 有两种类型的相等: 值相等:即两个值是一样的 引用相等:即引用是一样的,也就是同一个对象 默认地,对于值类型来讲,相等指的就是值相等:对于引用类型,相等就是指的引用相等. int a ...

  2. 【语义分割专栏】:FCN原理篇

    目录 前言 语义分割 背景介绍 FCN核心剖析 全卷积(Fully Convolution) 反卷积(deconvolution) 最近邻插值法 双线性插值 反卷积 跳跃连接(Skip Connect ...

  3. RBMQ案例四:路由模式

    使仅订阅消息的子集成为可能.例如,我们将能够仅将关键错误消息定向到日志文件(以节省磁盘空间),同时仍然能够在控制台上打印所有日志消息.   通过路由来匹配对应的消息 一.消息发布端 #!/usr/bi ...

  4. odoo14忘记后台密码解决办法

    直接在数据库里面修改: # 更新密码(假设用为 id 为 1,可通过 SELECT 进行查询) UPDATE res_users SET password_crypt='your new passwo ...

  5. Fiddler破解钉钉禁止点赞 钉钉点赞一下转换1*10^7+个赞

    破解钉钉禁止点赞 点一下1*10^7+个赞 说明:本文未经授权禁止转载 紧急upd 3.14号之后无法点超过一个赞,所以修改数据包时(unlock.html)的数字无法设置那么大,只能设置为1.当然, ...

  6. Dispatch PDI v2.0.4即将发布,历经1000+用户装机验证,稳定版震撼来袭!

    Dispatch PDI V2.0.4版本,即将登场! 亲爱的用户们: 在数据调度领域的探索之路上,我们始终致力于为大家提供更强大.更高效的工具.今天,我们怀着激动的心情宣布,Dispatch PDI ...

  7. 在Avalonia中使用相对单位

    Avalonia目前不具备相对单位功能,要使用相对单位需要安装RelativeControl.Avalonia包 RelativeControl.Avalonia 开始使用 添加NuGet包: dot ...

  8. servlet 的生命周期

    1 //servlet 的生命周期 2 @WebServlet(value = "/life",name = "LifeServlet",loadOnStart ...

  9. Opencv学习:回到原点!关于一些基础的函数

    opencv简单的图片读取和显示 1.图像读取  Mat img = imread("C:/clip.png", 1); imshow("fang2", img ...

  10. HBase Sync功能导致HBase入库性能下降

    本文分享自天翼云开发者社区<HBase Sync功能导致HBase入库性能下降>,作者:5****m 问题背景与现象 HBase入库慢,regionserver日志中大量打印slow sy ...