Linux 环境下 gcc 链接库 编译、链接(概览) 以及 自动化工具Makefile的编写

个人博客首页(点击查看详情) -- https://blog.51cto.com/11495268
 
1、简介
    程序编译一般需要经预处理、编译、汇编和链接,在实际应用中,有些公共代码需要反复使用,就把这些代码编译成为 "库" 文件,本文 主要 描述 Linux 平台下 库文件的 创建 和 链接 相关操作(既然都看 这么底层的内容了,相信 也有一定的基础,所以本文 对相关命令 也不会进行详细解释)

    
备注:
    linux平台下,静态链接库是以 .a 的后缀文件,动态链接库是以 .so 的后缀文件
    widows平台下,静态链接库是以 .lib 的后缀文件,动态库文件是以 .dll 的后缀文件
    

2、库文件
    库是写好的 现有的、成熟的 一种可执行、可以复用代码的二进制形式(注,其本身不可执行),可以被操作系统载入内存执行;分为 静态链接库 和 动态链接库
    

2.1 静态库
2.1.1 简介
    静态链接库可以简单看成一组目标文件.o 的集合,即很多目标文件经过压缩打包后形成的一个文件
    

2.1.2 原理
    链接器将从 静态(链接)库 取得所需的代码,复制到生成的可执行文件

    

2.1.3 特点
    静态库对函数库的链接是放在程序编译时期完成
    程序在运行时对函数库再无瓜葛(因为所有相关的目标文件和牵涉到的函数库被链接合成一个可执行文件)
    浪费空间和资源(因为所有相关的目标文件和牵涉到的函数库被链接合成一个可执行文件)
    

2.1.4 创建流程

    

备注:
    linux下使用ar工具(windows下用lib.exe)将目标文件压缩到一起,并且对其进行编号和索引,以便于查找和索引
    

2.1.5 命令规则
    静态链接库的名称 和 库文件名称不同但有联系;例如,库名称为"static_library",那么起库文件名为"libstatic_library.a"
    

2.2 动态库
2.2.1 简介
    程序在开始运行后调用 动态(链接)库(Dynamic Link Library)中的函数 才被载入
    

2.2.2 原理
    程序编译是并不会被连接到目标代码中,而是在程序运行时才被载入

    

2.2.3 特点
    动态库把对一些库函数的链接载入推迟到程序运行时期
    进程之间的相同动态库实现共享
    

2.2.4 创建
    创建动态库与创建静态库不同,不需要打包工具,直接使用编译器创建动态库

# gcc -fPIC -shared -o libxxx.so xx1.c xx2.c xx3.c

    

2.2.5 命名规则
    动态链接库的名称 和 库文件名称不同但有联系;例如,库名称为"dynamic_library",那么起库文件名为"libdynamic_library.a"
    

3、库文件 编译、链接(实战操作)
3.1 静态库 编译、链接
3.1.1 静态库 源码

# cat gcc_lib_header.h
#ifndef __GCC_LIB_HEADER_H_
#define __GCC_LIB_HEADER_H_

#include <stdio.h>

void gcc_lib_one();
void gcc_lib_two();
void gcc_lib_three();

#endif

    

# cat gcc_lib_first.c
/*
    filename : gcc_lib_first.c
*/
#include "gcc_lib_header.h"

void gcc_lib_one(){
    printf("call gcc_lib_one() function\n");
}

    

# cat gcc_lib_sec.c
/*
    filename : gcc_lib_sec.c
*/
    #include "gcc_lib_header.h"

void gcc_lib_two(){
    printf("call gcc_lib_two() function\n");
}

    

# cat gcc_lib_third.c
/*
    filename : gcc_lib_third.c
*/
#include "gcc_lib_header.h"

void gcc_lib_three(){
    printf("call gcc_lib_three() function\n");
}

    

# cat gcc_lib_main.c
/*
    filename : gcc_lib_main.c
*/
#include "gcc_lib_header.h"

int main(int argc, char *argv[])
{
    gcc_lib_one();
    gcc_lib_two();
    gcc_lib_three();

    return 0;
}

    

3.1.2 静态库 编译

# gcc -c gcc_lib_first.c
# gcc -c gcc_lib_sec.c
# gcc -c gcc_lib_third.c

# ar  cqs  libstatic_gcc.a  gcc_lib_first.o gcc_lib_sec.o gcc_lib_third.o

    

3.1.3 静态库 链接

## -L ./ 等同于 -L.
# gcc -o gcc_lib_main_static gcc_lib_main.c -L. -static -l static_gcc

# ./gcc_lib_main_static
call gcc_lib_one() function
call gcc_lib_two() function
call gcc_lib_three() function

    

3.2 动态库 编译、链接
3.1.1 动态库 源码
    为了便于测试比较,使用 与 静态库编译相同的源码
    

3.1.2 动态库 编译

# gcc -fPIC -shared -o libdynamic_gcc.so  gcc_lib_first.c gcc_lib_sec.c gcc_lib_third.c

    

3.1.3 动态库 链接

# gcc -o gcc_lib_main_dynamic gcc_lib_main.c -L ./ -l dynamic_gcc

    

3.1.4 共享路径设置(不详细解释)

## 共享路径设置 :
##     [email protected]:LD_LIBRARY_PATH 修改 这个全局变量
##     [email protected]:修改 /etc/ld.so.conf 配置
## 本文 就 详细描述了,直接把 生成的共享库 cp 至 系统默认路径下
# cp libdynamic_gxx.so /usr/local/lib/

## 重新读取 库文件信息(需root用户执行)
# ldconfig

    

备注:
    如果 不设置 共享路径 或者 共享路径下 找不到 指定的 库文件,系统 就会 提示相关的错误信息:"./g++_lib_main_static: error while loading shared libraries: libstatic_gcc.so: cannot open shared object file: Error 40"
    

3.1.5 执行

## 查看 依赖库,没有问题 就执行
# ldd gcc_lib_main_dynamic
    linux-vdso.so.1 =>  (0x00007fff241e9000)
    libdynamic_gcc.so => /usr/local/lib/libdynamic_gcc.so (0x00007fe587990000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fe5875c6000)
    /lib64/ld-linux-x86-64.so.2 (0x000055b1d62ea000)

# ./gcc_lib_main_dynamic
call gcc_lib_one() function
call gcc_lib_two() function
call gcc_lib_three() function

    

4、自定义工具(Makefile)
4.1 安装 make

# apt-get install make

    

4.2 编写 Makefile

# cat Makef
default_target : help

help :
    @echo "usage : make [opt]"
    @echo "\topt arguement is one of \"static_gcc、dynamic_gcc\""

gcc_lib_first.o : gcc_lib_first.c gcc_lib_header.h
    gcc -c gcc_lib_first.c 

gcc_lib_sec.o : gcc_lib_sec.c gcc_lib_header.h
    gcc -c gcc_lib_sec.c

gcc_lib_third.o : gcc_lib_third.c gcc_lib_header.h
    gcc -c gcc_lib_third.c  

static_gcc : gcc_lib_first.o gcc_lib_sec.o gcc_lib_third.o
    ar  cqs  /tmp/libstatic_gcc.a  gcc_lib_first.o gcc_lib_sec.o gcc_lib_third.o
    gcc -o gcc_lib_main_static gcc_lib_main.c  -L /tmp -static -l static_gcc

dynamic_gcc :
    gcc -fPIC -shared -o /tmp/libdynamic_gcc.so  gcc_lib_first.c gcc_lib_sec.c gcc_lib_third.c
    gcc -o gcc_lib_main_dynamic gcc_lib_main.c -L /tmp -l dynamic_gcc
    cp /tmp/libdynamic_gcc.so /usr/local/lib/
    ldconfig

    

4.3 执行

## 创建 静态库 链接的 可执行文件
# make static_gcc
ar  cqs  /tmp/libstatic_gcc.a  gcc_lib_first.o gcc_lib_sec.o gcc_lib_third.o
gcc -o gcc_lib_main_static gcc_lib_main.c  -L /tmp -static -l static_gcc

## 创建 动态库 链接的 可执行文件
# make dynamic_gcc
gcc -fPIC -shared -o /tmp/libdynamic_gcc.so  gcc_lib_first.c gcc_lib_sec.c gcc_lib_third.c
gcc -o gcc_lib_main_dynamic gcc_lib_main.c -L /tmp -l dynamic_gcc
cp /tmp/libdynamic_gcc.so /usr/local/lib/
ldconfig

    

原文地址:https://blog.51cto.com/11495268/2391927

时间: 2024-10-29 21:35:09

Linux 环境下 gcc 链接库 编译、链接(概览) 以及 自动化工具Makefile的编写的相关文章

linux环境下tesseract4.1的编译安装

由于公司新的产品需要深度集成tesseract,所以需要在linux下和windows下源码编译安装tesseract,tesseract当前最新稳定版本是4.1.0,所以就从这个版本入手,编译的过程中碰到了不少困难,踩到了不少坑,所以特意分享出来,避免各位朋友再走弯路~~. 1.查看centos版本#cat /etc/redhat-releaseCentOS release 6.5 (Final) 2.查看gcc和g++版本#gcc --version#g++ --versiongcc至少应需

Linux环境下c程序的编译和执行

1 单个文件的编译和执行创建main.c文件,内容如下: #include <stdio.h> #include <stdlib.h> int main(void){ printf("Hello world!\n"); return 0; }; 编译: gcc -o main main.o 执行: [email protected]:/ybg/python# ./main Input an integer: 10 sum=55 2 多个文件的编译和执行创建sum

在linux环境下利用mmm命令编译android项目错误记录

此篇文章建立在之前的三篇文章的基础之上(本次内容主要参考老罗的<android源码情景分析一书>): 源码编译 内核编译 adb连接模拟器 ------------------------------------------------------------------------------------ 之后,在android源码环境中编写了一个简单的android程序HelloAndroid. 文件结构如下: ~/android/packages/experimental/HelloAn

【caffe】caffe在linux环境下的安装与编译

网上的caffe的安装教程繁杂而散乱,对初学者很不友好,尤其对该框架理解不深的童鞋.总的来说,caffe的安装不外乎几个固定的步骤,对每一步有了一定的理解,安装只是time-consuming的问题!关键是自己要理解每一步是做什么的,最起码要有思维惯性.对Ubuntu活Redhat等,都是大同小异. [一]安装相关依赖包 1.编译工具等,如gcc(对版本有要求),git.python-pip等: 2.编译依赖包,如cuda/cudnn/hdf5等,具体参考官网: ps:若有sudo权限,需要下载

linux环境下deb格式 转换成rpm格式

linux环境下deb格式 转换成rpm格式 使用alien工具转换deb格式到rpm格式 alien_8.87.tar.gz 下载alien_8.87.tar.gz [[email protected] ~]# wget http://ftp.de.debian.org/debian/pool/main/a/alien/alien_8.87.tar.gz [[email protected] ~]# tar zxvf alien_8.87.tar.gz[[email protected] ~]

Linux环境下GNU, GCC, G++编译器

一,GNU GNU是"GNU 's Not Unix"的递归缩写, Stallman宣布GNU应当发音为Guh-NOO(革奴)以避免与new这个单词混淆(注:Gnu在英文中原意为非洲牛羚,发音与new相同) 为保证GNU软件可以自由地"使用.复制.修改和发布",所有GNU软件都在一份在禁止其他人添加任何限制的情况下授权所有权利给任何人的协议条款,GNU通用公共许可证(GNU General Public License,GPL).这个就是被称为"反版权&q

在linux环境下编译运行OpenCV程序的两种方法

原来以为在Ubuntu下安装好了OpenCV之后,自己写个简单的程序应该很容易吧,但是呢,就是为了编译一个简单的显示图片的程序我都快被弄崩溃了. 在谷歌和上StackOverFlow查看相关问题解答之后,我下面就介绍Command Line和CMake两种方式. 首先我先粘上我测试的代码吧,文件名为Test.c 1 #include <highgui.h> 2 3 int main(int argc,char ** argv) { 4 5 IplImage* img = cvLoadImage

从零教你在Linux环境下(ubuntu)如何编译hadoop2.4

问题导读: 1.如果获取hadoop src  maven包?2.编译hadoop需要装哪些软件?3.如何编译hadoop2.4?扩展:编译hadoop为何安装这些软件? 本文链接 http://www.aboutyun.com/thread-8130-1-1.html 一.首先下载hadoop源码包下载的方式还是比较多的1.svn的方式svn下载首先需要安装SVN,如果想尝试使用svn,可以参考源码管理.获取网络源码工具:TortoiseSVN使用手册,hadoop的svn下载地址点此2.压缩

在虚拟机linux环境下编译windows版adb fastboot

原文出自:http://blog.chinaunix.net/uid-20546441-id-1746200.html 我根据虚拟机编译遇到的问题进行一些添加 [前提条件] Linux Android源码完整 虚拟机磁盘空间100G左右(60G用来存放代码和编译后的文件) swap 30G左右,若太小会导致在编译后提示缺失文件 [具体步骤] 理论上,只要下一个windows版本的SDK,里面就自带了fastboot和adb工具. 但我最近确实遇到了一个需要在linux下编译出windows版本的