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

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

阅读更多
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作用下的库里不能有函数同名。
分享到:
评论

相关推荐

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

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

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

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

    制作静态库、动态库Framwork

    包内包含两个文件: 1制作静态库、动态库Framwork方法 2 打包Framwork脚本

    静态库和动态库:.doc

    源码经过编译生成对象文件,对象文件进一步处理可以生成可执行程序或者库文件。 对于可执行程序和动态库,此“进一步处理”指的是“链接”,使用gcc命令。...对于静态库,此“进一步处理”指的是“打包”,使用ar命令。

    在linux下面生成动态库静态库

    亲测可用,非常详细的打包静态库和动态库的方法,不骗人

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

    IOS 静态库打包流程简化 在iOS开发中,我们经常会遇到开发SDK的需求。开发好的静态库后需要手动的合并.a文件,然后再拷贝相关的头文件,接着把静态库和头文件放在同一个文件里面打包发送给SDK的使用者。本文将介绍...

    glutstatic.lib静态库 附带对应的.h.zip

    一直以为“静态库”就是拿来静态链接的库,对应动态库。 但是,为啥不管哪里下载的glut静态库都是把自己链接到glut32.dll动态库上? 哇,我真的搞不懂,我要静态库是因为什么原因?不就是想把库和exe链接到一起吗?...

    CLion+mingw打包和调用C++动态静态库

    CLion+mingw打包和调用C++动态静态库

    JNI文档资料源码_2020_02_14_3

    【Android NDK 开发】Android.mk 配置静态库 ( Android Studio 配置静态库 | 配置动态库与静态库区别 | 动态库与静态库打包对比 ) 博客地址 : https://hanshuliang.blog.csdn.net/article/details/104322381 I...

    C++静态库与动态库深入研究

    库有两种:静态库(.a、.lib)和动态库(.so、.dll)。所谓静态、动态是指链接。回顾一下,将一个程序编译成可执行程序的步骤:之所以成为【静态库】,是因为在链接阶段,会将汇编生成的目标文件.o与引用到的库一起...

    Abseil在vs2019下编译的静态库(c++17)

    Abseil在vs2019下编译的静态库,指定的C++版本为C++17。 Abseil 目前开放的 C++ 标准库的扩充库,是从 Google 内部 C ++ 代码库抽取出来的基础库的合集。这些库在 Google 内部经过广泛的测试和生产使用,是 Google ...

    OpenSSL-1.0.2m静态库

    OpenSSL静态库,省去摸索过程,可以将OpenSSL打包进源码,不再依赖外部dll

    qt5.12.0静态资源包/Visual Studio 2022 静态编译qt项目/静态与动态编译

    qt5.12.0静态资源包,不支持directx 12版本....就是静态编译出来会将相关用到的qt核心依赖库随编译一起打包出来一个exe文件,无需引入qt core等dll。动态编译要手东windeoloy ,体积几百M,静态编译只需要10M不到

    x264源代码+编译脚本+动态库+静态库+头文件.zip

    x264源代码+编译脚本+动态库+静态库+头文件,打包下载,包括armv7a和x86两种架构 想自己编译的可以参考博客:https://hellogoogle.blog.csdn.net/article/details/119561028

    iOS创建与使用静态库

    (一)iOS静态库、动态库与Framework静态库与动态库的区别 (1)什么是库? 库(Library)直白一点说就是一段编译好的二进制代码,加上头文件就可以供别人使用;(例如: iOS中Objective-C编译下的.h和.m文件,打包静态库后会...

    QNX系统中添加自己编译的.so库.zip_QNX .so文件_SO打包_qnx文件_qnx系统g++编译_so库

    将自己编译生成的动态链接库文件打包到QNX系统中,主要修改的是打包所依赖的build配置文件

    Linux下的StanfordCPPLib(含动态库和静态库)

    斯坦福大学的C++开源类库,已打包成Linux下的链接库。适用于教材《C++程序设计 基础、编程抽象与算法策略》,内附使用说明。

    QT 5.15.10/windows msvc X64静态编译好的目录打包

    QT静态库,可以将Qt程序编译成独立运行的.exe文件,2013/8/26 vs2017 x64编译。 Q:为什么要使用QT静态库? A:用QtCreator编译程序时,使用的是动态编译。编译好的程序在运行时需要另外加上相应的Qt库文件,一大堆...

    cmake多级目录编译实现

    1、压缩包中打包文件为一个商用项目,由Makefile...3、MSLayer为一个静态库,iMM_Cache也为一个静态库,均为动态库,CMakelist的具体实现,清参考源码,include和src中放的源码是示例,你编译时可以放入你自己源码。

    【Android FFMPEG 开发】博客资源_2020_02_20_1

    FFMPEG 静态库打包动态库 ( 仅做参考 ) III . 创建 Android Studio 工程 IV . FFMPEG 头文件与静态库拷贝 V . CMakeList.txt 配置 FFMPEG 头文件 与 函数库 VI . C++ 代码 VII . 博客资源 ————————...

Global site tag (gtag.js) - Google Analytics