`
wanzhanzhuce
  • 浏览: 28275 次
社区版块
存档分类
最新评论

[转]静态库打包入动态库

阅读更多
from:http://bbs.chinaunix.net/thread-1321303-1-1.html

请问 linux下怎样把几个静态库(libabc.a...)编译成一个动态库(libtest.so)

我用 gcc -shared -fPIC libabc.a libdef.a -o libtest.so 
生成的 libtest.so 只有空架子, 没内容,
静态库都是用 ar cru 一批 .o 文件产生的。
谢谢
sorry, 先前帖子写错了。这是Makefile
LIBDIR = ./lib
SRCDIR = ./src
VPATH  = $(SRCDIR)

PROJ  = iccp
OPT   =
DEFS  =
LIST  = >> cc.lst 2>&1

CC = gcc

LIBRARY = $(LIBDIR)/$(PROJ).so

OBJECTS = $(LIBDIR)/mem.a \
        $(LIBDIR)/slog.a        \
        $(LIBDIR)/util.a        \
        $(LIBDIR)/mlogl.a        \
        $(LIBDIR)/asn1l.a        \
        $(LIBDIR)/mmsl.a        \
        $(LIBDIR)/mmsle.a        \
        $(LIBDIR)/mvl.a        \
        $(LIBDIR)/mi.a        \
        $(LIBDIR)/ositcpe.a       

all: $(LIBRARY)

$(LIBRARY): $(OBJECTS)
        rm -f $(LIBRARY)
        $(CC) -shared -fPIC $(OBJECTS) -Wl,-soname -Wl,$@ -o $@ -lc $(LIST)
        @echo "FINISHED CREATING $(LIBRARY) LIBRARY" $(LIST)
        @echo "-----------------------------------------------------" $(LIST)


$(LIBDIR)/mem.a:
        $(MAKE) $(AM_MAKEFLAGS) -f mem.mk
$(LIBDIR)/slog.a:
        $(MAKE) $(AM_MAKEFLAGS) -f slog.mk
$(LIBDIR)/util.a:
        $(MAKE) $(AM_MAKEFLAGS) -f util.mk
$(LIBDIR)/mlogl.a:
        $(MAKE) $(AM_MAKEFLAGS) -f mlogl.mk
$(LIBDIR)/asn1l.a:
        $(MAKE) $(AM_MAKEFLAGS) -f asn1l.mk
$(LIBDIR)/mmsl.a:
        $(MAKE) $(AM_MAKEFLAGS) -f mmsl.mk
$(LIBDIR)/mmsle.a:
        $(MAKE) $(AM_MAKEFLAGS) -f mmsle.mk
$(LIBDIR)/mvl.a:
        $(MAKE) $(AM_MAKEFLAGS) -f mvl.mk
$(LIBDIR)/mi.a:
        $(MAKE) $(AM_MAKEFLAGS) -f mi.mk
$(LIBDIR)/ositcpe.a:
        $(MAKE) $(AM_MAKEFLAGS) -f ositcpe.mk




ls -l lib 显示 :
total 1456
-rw-r--r-- 1 root root  43078 2008-11-27 17:36 asn1l.a
-rwxrwxr-x 1 root root   3928 2008-11-27 17:36 iccp.so
-rw-r--r-- 1 root root   4748 2008-11-27 17:31 mem.a
-rw-r--r-- 1 root root 211968 2008-11-27 17:36 mi.a
-rw-r--r-- 1 root root 137024 2008-11-27 17:36 mlogl.a
-rw-r--r-- 1 root root 314742 2008-11-27 17:36 mmsl.a
-rw-r--r-- 1 root root 310012 2008-11-27 17:36 mmsle.a
-rw-r--r-- 1 root root 144370 2008-11-27 17:36 mvl.a
-rw-r--r-- 1 root root 147536 2008-11-27 17:36 ositcpe.a
-rw-r--r-- 1 root root  26370 2008-11-27 17:35 slog.a
-rw-r--r-- 1 root root  94846 2008-11-27 17:36 util.a


还有, 编译库,makefile 中是不是需要显式的加前缀 lib ?
谢谢






都不愿意回答啊?
我自己观察别的lib 的编译流程, 找到了解决办法:
$(CC) -shared -fPIC $(OBJECTS) -Wl,-soname -Wl,$@ -o $@
改成:
$(CC) -shared -fPIC -Wl,--whole-archive   $(OBJECTS) -Wl,--no-whole-archive  -Wl,-soname -Wl,$@ -o $@
即可
网上有人说必须把 .a 解开 再 重新连接。其实不需要。



附:

g++和gcc的一些编译参数说明 zz

for(int var=0; var<5; var++){
    ...
}
var++; //使用for循环中定义的变量
cout << var << endl;加-fno-for-scope后可以通过编译:g++ main.cpp -fno-for-scope

int typeof; //与关键字重名
typeof = 1;
cout << typeof << endl;加-fno-gnu-keywords后可以通过编译:g++ main.cpp -fno-gnu-keywords

int and, xor; //使用了and, xor等操作符来作为变量名
and = 1;
xor = 2;
cout << "and = " << and << " xor = " << xor << endl;加-fno-operator-names后可以通过编译:g++ main.cpp -fno-operator-names

/usr/bin/cc -> /etc/alternatives/cc -> /usr/bin/gcc -> gcc-4.3cc与gcc是同一个程序

cc main.c -S编译成汇编文件main.s

cc main.s -o main可以直接编译汇编文件为可执行文件

cc main.c -o main -v加-v可以查看头文件及库文件的搜索路径及具体的编译参数

cc main.c -o main -L. -lfunc
cc main.c -o main ./libfunc.so可以以二种形式使用动态库

g++ main.cpp -o main
gcc main.cpp -o main -lstdc++使用g++及gcc来编译
以下为对参数--no-whole-archive及--whole-archive的尝试,先构造三个C文件://a.c
void afunc() { printf("inside a afunc()/n"); }
void samefunc() { printf("in samefunc of a.c/n"); }
  //b.c
void bfunc() { printf("inside a bfunc()/n"); }
void samefunc() { printf("in samefunc of b.c/n"); }   //test.c
extern void afunc();
extern void bfunc();
void testfunc()
{
    afunc();
    bfunc();
}

先用以下的命令来生成test.o, a.sa, b.sa文件:
gcc a.c -c -o a.o
ar -q a.o a.sa
gcc b.c -c -o b.o
ar -q b.o b.sa
gcc test.c -c -o test.o

gcc -shared -Wl,--no-whole-archive a.sa b.sa -Wl,--no-whole-archive -o m.so上面的命令运行通过, 但生成的文件中是不包含afunc, bfunc, samefunc的,不可用

gcc -shared test.o -Wl,--no-whole-archive a.sa b.sa -Wl,--no-whole-archive -o m.so上面的命令运行失败, 错误如下:
b.sa(b.o): In function `samefunc':
b.c:(.text+0x14): multiple definition of `samefunc'
a.sa(a.o):a.c:(.text+0x14): first defined here
collect2: ld returned 1 exit status

gcc -shared -Wl,--no-whole-archive a.sa b.sa -Wl,--no-whole-archive test.o -o m.so上面的命令运行通过,与再上面的命令相比,只是调换了test.o在命令行中的位置
但生成的文件中是不包含afunc, bfunc, samefunc的,不可用

如果以以下方式修改test.c
//test.c
#include <stdio.h>
#include <stdlib.h>
extern void afunc();
extern void bfunc();
void testfunc()
{
    afunc();
    //bfunc();   <---------------just comment following line
}

gcc -shared test.o -Wl,--no-whole-archive a.sa b.sa -Wl,--no-whole-archive -o m.so
链接成功,生成的m.so也是可用的,原因是: 当test.c中不使用bfunc时,也就不再加载b.sa(虽然b.sa是在命令行中的), 也就不会出现与a.sa中存在二个同名的samefunc函数了

当改成使用-Wl,--whole-archive后,只有当a.sa与b.sa中没有同名的函数时以下命令才可通过:
gcc -shared test.o -Wl,--whole-archive a.sa b.sa -Wl,--no-whole-archive -o m.so此m.so可以使用

总结:
1)当使用--whole-archive时,其会把所有的--whole-archive之后的.sa中的所有函数全部加入到生成的文件中来,这样的情况下,如果有同名函数,则链接就不会通过;
2)当使用--no-whole-archieve时,则此后的所有文件中的所有函数都不会加到生成的文件中,但下面的第3点情况例外;
3)如果命令行中有.o文件,如test.o, 并且.o文件后面有.sa文件,则会把.o文件中用到的函数的.sa文件加入到生成的结果文件中来(即使.sa前有--no-whole-archieve);所以这和.o及.sa的顺序有关系。

注:
--whole-archive, --no-whole-archive是ld的命令,gcc并不认识,所以要加-Wl,换成如下命令也是一样的:
ld -shared test.o --whole-archive a.sa b.sa --no-whole-archive -o m.so

ld的其它一些用法:
把多个.o加成.a:
ar -q result.a s1.o s2.o s3.o
在一个.a中去掉一个.o
ar -d result.a s1.o
居然可以在一个.a中加入多个相同的.o
ar -q result.a s1.o s1.o s1.o

g++ -v的输出为:
Using built-in specs.
Target: i486-linux-gnu
Configured with:
   ../src/configure -v --with-pkgversion='Ubuntu 4.3.3-5ubuntu4'
   --with-bugurl=file:///usr/share/doc/gcc-4.3/README.Bugs
   --enable-languages=c,c++,fortran,objc,obj-c++
   --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib
   --without-included-gettext --enable-threads=posix --enable-nls
   --with-gxx-include-dir=/usr/include/c++/4.3
   --program-suffix=-4.3 --enable-clocale=gnu --enable-libstdcxx-debug
   --enable-objc-gc --enable-mpfr --enable-targets=all
   --with-tune=generic --enable-checking=release --build=i486-linux-gnu
   --host=i486-linux-gnu --target=i486-linux-gnu
Thread model: posix
gcc version 4.3.3 (Ubuntu 4.3.3-5ubuntu4)

当gcc加-ansi参数编译时,有以下限制:
1)文件中不能以//来加注解


---------------------------------------------------------------------
首先 --whole-archive 和 --no-whole-archive 是ld专有的命令行参数,gcc 并不认识,要通gcc传递到 ld,需要在他们前面加 -Wl,字串。
--whole-archive 可以把 在其后面出现的静态库包含的函数和变量输出到动态库,--no-whole-archive 则关掉这个特性。
比如你要把 liba.a  libb.a libc.a 输出到 libabc.dll(或libabc.so)时应该这么写:
libabc.dll:liba.c libb.a libc.a
       gcc  -shared -o $@ -L. -Wl,--whole-archive -la -lb -lc -Wl,--no-whole-archive
在--whole-archive作用下的库里不能有函数同名。
分享到:
评论

相关推荐

    IOS 静态库打包流程简化详细介绍

    然而,传统的静态库打包过程繁琐,需要手动合并.a文件、拷贝头文件并打包。本文将详细介绍如何通过自动化脚本简化这一过程。 首先,创建一个新的静态库工程,例如名为`TestSDK`。然后,添加一个新的目标(Target)...

    动态库、静态库的创建与连接

    动态库、静态库的创建与连接 动态库和静态库是两种常见的库类型,它们在编译和链接过程中扮演着不同的角色。在这篇文章中,我们将详细介绍动态库和静态库的创建、连接方法及其优缺点。 一、静态库 静态库是一种...

    静态库和动态库:.doc

    1. 静态库的创建:静态库是由`ar`命令打包的对象文件(`.o`)集合,它在编译时会被直接合并到可执行程序中。例如,我们有多个`.c`文件,首先使用`gcc -c *.c`将它们编译为`.o`文件,然后使用`ar rcs lib*.a *.o`创建...

    制作静态库、动态库Framwork

    下面我们将详细探讨如何制作静态库和动态库Framework,以及打包Framework的脚本。 首先,我们来看静态库。静态库在编译时会被链接到目标应用中,成为应用程序的一部分。这意味着静态库中的所有代码和资源都会被包含...

    ffmpeg-4.3-arm64含静态库-动态库-调试信息-(内含三个压缩包).zip

    ffmpeg linux 下 arm64 环境使用的动态库和静态库打包, 内含三个压缩包: 《ffmpeg-4.3-arm64-动态库.zip》 《ffmpeg-4.3-arm64-含静态库-动态库.zip》 《ffmpeg-4.3-arm64-含静态库-动态库-带调试信息.zip》

    Android Studio 基于cmake 链接静态库,动态库

    在应用运行时,静态库会被编译进最终的APK,而动态库会作为单独的文件打包,并在运行时由Android系统加载。 总结,通过Android Studio和CMake,开发者可以方便地管理C/C++原生代码,链接静态库和动态库,实现跨平台...

    Linux静态库和动态库

    ### Linux静态库与动态库详解 #### 基本概念 **库的定义与作用**:库,实质上是预编译的代码集合,旨在提供重复使用的功能或服务,简化软件开发过程。无论是在Windows还是Linux平台,库的存在极大地提高了编程效率...

    jsoncpp 编译库VS2010,动态库,静态库

    使用静态库的优点是无需担心运行时库的缺失问题,因为所有依赖都在你的程序中打包了。但缺点是增加了程序的体积,同时可能导致版本升级困难。 2. **动态库(dll_compiled_vs2010)**: 动态库是以DLL(Dynamic ...

    gcc生成静态库和动态库

    ### gcc生成静态库和动态库 #### 一、概述 在Linux环境下,开发人员经常需要创建和使用静态库和动态库。这两种类型的库都用于封装一组功能或接口,以便其他程序能够重用这些代码,从而简化开发过程并提高代码复用...

    9.C++静态库和动态库1

    2. 使用`ar`工具将目标文件打包成静态库,例如`ar -crv libstaticmath.a StaticMath.o`,这将生成名为`libstaticmath.a`的静态库。 在Windows环境下,使用Visual Studio(VS)创建静态库(`.lib`): 1. 可以通过VS...

    zip 1.2.7 静态库 动态库

    "zip 1.2.7 静态库 动态库"指的是用于处理ZIP文件格式的库,具体为版本1.2.7,同时提供了静态库和动态库两种形式。 **ZLIB库和ZIP文件格式** ZLIB库是由Jean-loup Gailly和Mark Adler开发的一个开源库,主要用于...

    静态库和动态库的使用

    在计算机编程领域,静态库和动态库是两种不同的库文件类型,它们在程序开发和运行时扮演着重要的角色。理解并正确使用这两种库是每个软件开发者必须掌握的基础知识。 首先,我们来了解一下静态库。静态库(Static ...

    android编译的openssl静态库.a 动态库.so

    总结起来,`android编译的openssl静态库.a 动态库.so`涉及到的关键点包括:Android NDK的使用、OpenSSL源码的编译配置、静态库与动态库的区别以及如何在Android应用中集成这些本地库。正确理解和操作这些步骤对于在...

    Linux下Gcc生成和使用静态库和动态库详解

    ### Linux下Gcc生成和使用静态库和动态库详解 #### 一、基本概念 **1.1 什么是库** 库本质上是一种可执行代码的二进制形式,它可以被操作系统载入内存执行。无论是Windows还是Linux平台,都广泛地使用着库。然而...

    动态库与静态库的制作

    2. **创建静态库**:然后,使用`ar`工具将`.o`文件打包成静态库,如`libmessage.a`: ``` ar -rcs libmessage.a message.o ``` `-r`表示替换库中的成员,`c`表示创建新的库(如果不存在),`s`表示创建或更新...

    在Linux中创建静态库和动态库

    ### 在Linux中创建静态库和动态库 #### 静态库与动态库的基本概念 在Linux环境下,库是预编译代码的集合,用于在链接阶段被其他程序使用。库分为两种类型:静态库(static libraries)和动态库(dynamic libraries...

    Linux编译动态库和静态库

    在Linux系统中,开发软件时常会遇到需要创建和使用动态库(.so)与静态库(.a)的情况。动态库允许多个程序共享同一份代码,节省内存资源,而静态库则将库代码直接编译进目标程序,不依赖外部环境。本篇将详细介绍在...

    C++创建调用静态动态库

    3. 构建静态库:使用`ar rcs libstatic.a libfunc.o`命令将对象文件打包成静态库`libstatic.a`。 二、动态库 动态库在运行时被加载,可以节省磁盘空间和内存,因为多个程序可以共享同一份库。在Linux中,动态库的...

    libyuv动态库与静态库的使用,封装,测试demo

    libyuv动态库与静态库的使用,封装,测试demo.libyuv所处理的数据类型一般都是NV21 YUV420格式。需求端客户要对8位的灰度图像进行放缩处理,同时对外发布版本的时候不能直接告诉客户我们用的是libyuv,所以需要对...

Global site tag (gtag.js) - Google Analytics