欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-03-16 20:19:23
...
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作用下的库里不能有函数同名。
相关标签: gcc c