700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > Linux命令【三】gcc编译+静态库+动态库+makefile+gdb调试

Linux命令【三】gcc编译+静态库+动态库+makefile+gdb调试

时间:2020-12-24 16:06:22

相关推荐

Linux命令【三】gcc编译+静态库+动态库+makefile+gdb调试

用C编译器编译源文件:gcc 源文件 -o 可执行文件名

详细步骤:

gcc -E a.c -o a.i预处理器将头文件展开,宏替换,去掉注释gcc -S a.i -o a.s编译器将C文件变成汇编文件gcc -c a.s -o a.o汇编器将会变文件变成二进制文件gcc a.o -o a链接器进行链接

ESc+链接

如果不使用参数-o则自动生成a.out

制定头文件的路径gcc a.c -I 头文件的目录 -o 生成可执行文件的名字在比较旧的版本上-I和头文件目录之间不能有空格,现版本无所谓

指定宏-D 宏名

优化-O1/O2/O3O3优化速度最高

输出警告信息-Wall

生成调试信息-g

静态库

命名规则

lib+库的名字+.a制作步骤

生成对应的.o文件,直接使用参数-c得到.o文件,记得不要使用-o参数,否则将会直接生成可执行文件

将生成的.o文件进行打包,需要使用软件ar.o打包为.a

ar rcs 静态库名称 所有的.o

发布和使用静态库

打包静态库和头文件,将所有的静态库放到lib文件夹中,将所有的头文件放到include文件夹中,制作好静态库以后可以发送这两个文件夹。

用户通过头文件知道有哪些函数接口。通过直接和源文件编译静态库使用。

gcc 源文件 静态库 -o 可执行文件 -Iincludegcc 源文件 -Iinclude -L lib -l 静态库文件名(去掉头部lib和尾部.a) -o 可执行文件

静态库的优缺点

nm 静态库文件 //查看静态库

打包的最小单元为.o

优点:

库已经打包在程序中,不需要再提供库的加载速度比较快

缺点:可执行文件会比较大如果库发生了改变需要重新编译

动态库/共享库

命名规则

lib+名字+.so制作步骤

(1) 生成与位置无关的代码(.o)

gcc -fPIC -c *.c -Iinlcude

(2) 将.o打包成共享库

Linux每一个运行的程序操作系统都会为其分配一个0-4G的地址空间。Linux下可执行文件格式:ELF

gcc -shared -o libname.so *.o -Iinclude

再讲lib中的.so文件和include中的头文件发送给用户

用户使用

gcc main.c lib/libname.so -o main -Iincludegcc main.c -Iinclude -L lib -l name -o main//需要注意的是这里的name是不包含lib和后缀.so的

使用ldd查看可执行文件所依赖的所有的共享库的名字

动态库的使用需要动态链接器帮助。我们需要让动态链接器找到我们自己的动态链接库

正常情况下使用会出现动态库无法找到的问题。然后就需要我们去解决。

可是我自己尝试的时候没有遇到这个情况。。。我也不清楚为什么,可能是现在版本的gcc已经智能地解决这个问题了。

(1)将动态库放到系统的lib文件夹中

(2) 配置环境变量LD_LIBRARY_PATH(如果你的动态库没有在默认的环境变量中,会先在这个环境变量中查找)

用于临时测试

echo $LD_LIBRARY_PATH //$从环境变量中取值 查看环境变量export LD_LIBRARY_PATH=./lib //将当前目录下的lib文件夹导入到环境变量中

关掉终端后失效

(3)

ls -avi .bashrc在里面加上export LD_LIBRARY_PATH=动态库目录重启终端

永久

(4)工作中更加常用的方法

找到动态链接器的配置文件

/etc/ld.so.conf

需要使用管理员权限

将动态库的路径写到配置文件中

更新sudo ldconfig -v-v是提示信息

动态库没有加载到源文件中,而是在需要使用的位置加上了一个标记,在使用的时候才进行访问。

优点:

执行程序很小动态库更新方便

缺点:需要将动态库发布给用户加载库的时候速度较慢

gdb 调试

l默认展示包含main()的文件l 文件名:行号展示以行号为中心上下文件的内容l 文件名:函数名展示文件中的函数,输入l继续展示后面的内容,然后后面再直接按回车,会继续向下展示文件,一次展示10行break 行号在某一行打断点b 行号b 行号 if 条件条件断点,条件断点只能设置在循环内部,如果设置在边界不会停止b filename:行号在某个文件的某一行设置断点info breaki b查看断点信息startgdb开始运行程序,每次运行一行,n单步调试,c继续执行到断点s下一步,会进入函数体内部(step)n下一步,不会进入函数内部run直接运行到断点,如果没有断点直接运行结束p 变量展示某个变量的值ptype 变量展示变量的类型display 变量追踪某个变量的值undisplay 变量编号取消追踪某个变量info display打印所有追踪变量的信息u将循环运行结束,结束循环finish跳出当前函数,需要将函数中的断点消除d 断点编号删除断点(del)set var 变量=x直接运行到变量为x的时候quit退出gdb

makefile

makefile项目管理工具,用于管理源代码

简单makefile文件

命名规则

(1)makefile

(2)Makefile

编写规则

makefile 一般情况下要和.c文件在一个文件夹中,如果不在需要绝对路径

三要素:

目标:依赖 //目标就是想要生成文件的名字 依赖:`.c`文件命令(必须要有Tab缩进):gcc a.c b.c c.c -o 目标

使用

make

进阶makefile文件

当一些文件修改以后需要重新编译,为了解决这个问题:

例如:

app:main.o add.o sub.o mul.o//终极目标,默认第一条语句是终极目标gcc main.o add.o sub.o mul.o -o app//如果依赖中的文件没有发现,就去下面的子目标中查找有没有相关的规则用于生成文件main.o:main.c gcc main.c -cadd.o:add.cgcc add.c -csub.o:sub.cgcc sub.c -cmul.o:mul.cgcc mul.c -c

上面的写法会自动查找文件是否修改,如果没有修改就不会编译,从而提高效率

工作原理:通过比较修改时间,目标应该比依赖的修改时间迟,如果发现目标比依赖的修改时间早则重新生成目标。

进进阶makefile文件

上面的写法有些冗余,通过变量来将写法变得简洁

obj=main.o add.o sub.o mul.otarget=app$(target):$(obj)//$取obj变量中的值gcc $^ -o $@//模式规则%.o:%.cgcc -c $< -o &@

makefile中的自动变量:

$<规则中的第一个依赖$@规则中的目标$^规则中的所有依赖只能够在规则中的命令来使用

makefile自己维护的变量:都是大写,例如CC,CPPFLAGS,CFLAGS,LDFLAGS

进进进阶makefile文件

在makefile中的函数都是有返回值的

获取指定目录下所有的.c文件

src=$(wildcard 所需要查找的目录/*.c)

获取指定目录下所有的.o文件

obj=$(patsubst ./%.c , ./%.o , $(src))#模式匹配

自动删除以前生成的目标文件

clean:rm $(target) -f#如果不存在也会强制删除,不会弹出提示信息

生成文件 时候:

make clean #会删除目标文件,只会执行生成clean的语句

如果目录中真的存在clean目标,则会提示目标是最新的而不会运行。

.PHONY:clean #声明clean为伪目标,不会与目录中的目标进行比较

在命令前面加上-,则命令执行失败以后也不会停下来,继续向后执行

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。