[转]静态库打包入动态库
程序员文章站
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作用下的库里不能有函数同名。
请问 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作用下的库里不能有函数同名。