鱼C论坛

 找回密码
 立即注册
查看: 2533|回复: 1

[学习笔记] 004-gcc、静态库、共享库

[复制链接]
发表于 2018-10-24 21:47:52 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 moc 于 2018-10-24 22:03 编辑

1、gcc
gcc:
        gcc(GNU C Compiler)编译器的作者是Richard Stallman,也是GNU项目的奠基者。gcc是GNU Compiler Collection的缩写。最初是作为C语言的编译器(GNU C Compiler),现在已经支持多种语言了,如C、C++、Java、Pascal、Ada、COBOL语言等。
主要特征:
        1)gcc是一个可移植的编译器,支持多种硬件平台;
        2)gcc不仅仅是个本地编译器,它还能跨平台交叉编译;
        3)gcc有多种语言前端,用于解析不同的语言;
        4)gcc是按模块化设计的,可以加入新语言和新CPU架构的支持;
        5)gcc是自由软件。
gcc编译过程:
123.png

61.jpg

78.jpg

gcc常用编译选项:
选项作用
-o产生目标(.i、.s、.o、可执行文件等)
-c通知gcc取消链接步骤,即编译源码并在最后生成目标文件
-Onn为1~3,-O0表示没有优化,-O1为缺省值,-O3优化级别最高
-E只运行C预编译器
-S告诉编译器产生汇编语言文件后停止编译,产生的汇编语言文件扩展名为.s
-Wall        使gcc对源文件的代码有问题的地方发出警告
-Idir将dir目录加入搜索头文件的目录路径
-Ldir将dir目录加入搜索库的目录路径
-llib链接lib库
-g在目标文件中嵌入调试信息,以便gdb之类的调试程序调试

gcc使用说明:
        gcc -E hello.c -o hello.i(预处理)
        gcc -S hello.i -o hello.s(编译)
        gcc -c hello.s -o hello.o(汇编)
        gcc hello.o -o hello(链接)
        以上四个步骤,可合成一个步骤
        gcc hello.c -o hello(直接编译链接成可执行目标文件)
        gcc -c hello.c或gcc -c hello.c -o hello.o(编译生成可重定位目标文件)
gcc编译多个.c:
        hello_1.h
        hello_1.c
        main.c
        一次性编译:
        gcc  hello_1.c main.c –o newhello
        独立编译
        gcc -Wall -c main.c -o main.o
        gcc -Wall -c hello_1.c -o hello_fn.o
        gcc -Wall main.o hello_1.o -o newhello
gcc使用外部库编译:
        库文件是一些预先编译好的函数集合,那些函数都是按照可重用原则编写的。它们通常由一组互相关联的用来完成某项常见工作的函数构成。比如用来处理屏幕显示情况的函数(ncurses库)和数据库访问例程(dbm库)等。
        使用外部库时候用-l选项。
如:
//calc.c
#include <math.h>
#include <stdio.h>
int main(void)
{
        double x = pow(2.0, 3.0);
        printf("The cubed is %f\n", x);
        return 0;
}
gcc -Wall calc.c -o calc -lm
-lm表示要链接libm.so或者libm.a库文件
2、静态库
静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中,程序运行的时候将不再需要静态库。
1>. 命名规则
        lib + 库的名字 + .a
        如:libmytest.a
2>. 制作步骤
        ① 生成对应的.o文件 ==>  gcc -c -Wall myadd.c -o myadd.o    (-c取消最后的连接步骤)
        ② 将生成的.o文件打包为静态库。=>   ar rcs + 静态库的名字(libmyadd.a) + 生成的所有发的.o
                如: ar rcs libmyadd.a myadd.o
3>. 使用静态库生成可执行文件
-llib   ==> 连接静态库
        gcc  -Wall -g -I../inc -L../lib   main.c -o main -lmyadd
3、共享库
        共享库( .so或.sa ):即windows下的动态库dll,程序在运行的时候才去链接共享库的代码,多个程序共享使用库的代码。(主要的优点:便于升级)。
1>. 特点:
        1. 一个与共享库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码
        2. 在可执行文件开始运行以前,外部函数的机器码由操作系统从磁盘上的该共享库中复制到内存中,这个过程称为动态链接(dynamic linking)
        3. 共享库可以在多个程序间共享,所以动态链接使得可执行文件更小,节省了磁盘空间。操作系统采用虚拟内存机制允许物理内存中的一份共享库被要用到该库的所有进程共用,节省了内存和磁盘空间。
2>. 命名规则
        lib + 名字 + .so(.sa)
3>. 制作步骤
        -shared: 表示生成共享库格式
        -fPIC:产生位置无关码(position independent code),即按照环境变量寻找动态库
由.o生成共享库:
        gcc -shared -fPIC myadd.o -o libmyadd.so
由.c直接生成共享库
        gcc -shared -fPIC myadd.c –o libmyadd.so
4>. 使用共享库生成可执行文件
        gcc  -Wall -g -I../inc -L../lib   main.c -o main -lmyadd
5>. 动态库的搜索路径
        在生成于位置无关的可执行文件时,会动态链接的系统环境提供的共享库,所以需要配置环境变量文件。
》/etc/profile:
        用于设置系统级的环境变量和启动程序,在这个文件下配置会对所有用户生效。当用户登录(login)时,文件会被执行,并从/etc/profile.d目录的配置文件中查找shell设置。如果对/etc/profile修改的话必须重启才会生效.
》/etc/bash.bashrc
        每一个运行bash shell的用户执行此文件.当bash shell被打开时,该文件被读取。如果想对所有使用bash的用户修改某个配置并在以后打开的bash都生效的话可以修改这个文件,修改之后不用重启,重新打开一个bash即可生效。
》~/.profile
        每个用户都可使用该文件输入专用于自己使用的shell信息,当用户登录时,该文件仅仅执行一次!默认情况下,他设置一些环境变量,执行用户的.bashrc文件.
》~/.bashrc
        该文件包含专用于你的bash shell的bash信息,当登录时以及每次打开新的shell时,该该文件被读取.
执行顺序:
        登陆shell时,首先执行/etc/profile,之后执行用户目录下的~/.profile,~/.profile中会执行~/.bashrc。
动态库的搜索路径: LD_LIBRARY_PATH
查看该路径:   env | grep LD_*
        一般情况下,只需要修改本用户的配置,即修改 ~/.bashrc,vim打开后面添加如下即可。
PATH=$PATH:$HOME/bin
LD_LIBRARY_PATH=SHOME/lib:/usr/lib:.:./lib
export PATH LD_LIBRARY_PATH
4、常用工具
实用技巧: 把命令变为代码
                chmod u+x mygcc
                chmod 775 mygcc
1>  file filename
        查看文件属性。
2> Ldd utility
        list, dynamic, dependencies的缩写, 意思是列出动态库依赖关系。
3>  nm Utilitye
        列出特性文件中的符号信息.
4>  objdump Utilitye
        显示文件信息,  -f 仅显示头部信息  
5> Size utility
        显示对象文件中每个部分的大小
>> 主动加载共享库
        可以在自己的程序中使用 dlopen()。该函数将打开一个新库,并把它装入内存。
                   dlopen() 在 dlfcn.h 中定义,并在 dl 库中实现。
handle = dlopen( "/usr/lib/libalg.so", RTLD_LAZY );
dl_add = dlsym( handle, "add" );
dl_mod = dlsym( handle, "mod" );
printf ("x + y = %3d\n",  dl_add( x, y ) );
printf ("x % y = %3d\n",  dl_mod( x, y ) );
dlclose( handle );

本帖被以下淘专辑推荐:

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2018-10-24 23:47:32 | 显示全部楼层
不错不错,就是有些地方不实操的话还是不能确切的了解
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-9-21 11:23

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表