合并库
我在写自己的库的途中,为了读图片,又没有能力自己写,不得不用到了另外两个库(zlib和libpng), 编译出来以后给测试程序用. 麻烦的是,测试程序仍然需要添加上那两个库才能运行. 这大概是因为mingw在编译时没有自动合并库中的函数定义,而只是把函数名写进去了. 所以测试程序虽然包含了我的库,却无法找到内部用到的函数的实现.
然后我就尝试把zlib和libpng的源代码都加进来一块编译,虽然编译通过了,但测试程序根本读不出图片. 结果就又删了.
搜一了下:"合并静态库", 找到只言片语,说是用ar和nm这两个工具. 没想到真的可以! .a文件,也就是unix的库文件,大概来自archives这个词,是由各个模块的.o文件组成的. ar命令用来修改和创建库,nm用来查看库内部的.o模块. 没有一个直接的方法可以实现add x.a y.a, 来把y合并到x中的. 但这时... ar命令有一个参数-x, 用来把内部的.o模块都提取出来, 然后再用ar -r把提取出来的所有.o文件都加到主库就行了,实际操作如下:
ar -x y.a
这时目录中出现了y1.o, y2.o
ar -r x.a y1.o y2.o
没了
这时目录中出现了y1.o, y2.o
ar -r x.a y1.o y2.o
没了
最后达到了不加任何连接库就可以顺利运行的效果. 但是我那小小的库被合并胖了好几倍...
这招应该同样适用于合并动态库的导入库.
这样手动太累了,碰到libopengl32.a, 提取出来360多个模块! 这下非要做个自动合并工具才行了. that's it:
#include <stdio.h>
#include <stdlib.h>
int main(int argn, char **arg)
{
char str[256];
char command[20];
FILE *fp;
char *mainlib;
char *addlib;
if (argn != 3) {
printf ("should be not 2 file\n");
return 1;
}
mainlib = arg[1];
fp = fopen (mainlib, "r");
if (fp == NULL) {
printf ("error file\n");
return 1;
}
fclose (fp);
addlib = arg[2];
fp = fopen (addlib, "r");
if (fp == NULL) {
printf ("error file\n");
return 1;
}
fclose (fp);
printf ("start to expand addlib file\n");
sprintf (command, "ar -x %s", addlib);
system (command);
printf ("start to check the addlib out to a.txt \n");
// 用ar -t显示模块名列表,保存在a.txt文件里,如果能保存在内存里就快了
sprintf (command, "ar -t %s > a.txt", addlib);
system (command);
fp = fopen ("a.txt", "r");
if (fp == NULL) {
printf ("error\n");
return 1;
}
while (-1 != fscanf (fp, "%s", str)) {
sprintf (command, "ar -r %s %s", mainlib, str);
//sprintf (command, "ar -d %s %s", mainlib, str);
//printf ("%s\n", command);
system (command);
sprintf (command, "del %s", str);
system (command);
}
fclose (fp);
return 0;
}
后来试了一下通过管道来得到模块名, 速度并没有什么提高.#include <stdlib.h>
int main(int argn, char **arg)
{
char str[256];
char command[20];
FILE *fp;
char *mainlib;
char *addlib;
if (argn != 3) {
printf ("should be not 2 file\n");
return 1;
}
mainlib = arg[1];
fp = fopen (mainlib, "r");
if (fp == NULL) {
printf ("error file\n");
return 1;
}
fclose (fp);
addlib = arg[2];
fp = fopen (addlib, "r");
if (fp == NULL) {
printf ("error file\n");
return 1;
}
fclose (fp);
printf ("start to expand addlib file\n");
sprintf (command, "ar -x %s", addlib);
system (command);
printf ("start to check the addlib out to a.txt \n");
// 用ar -t显示模块名列表,保存在a.txt文件里,如果能保存在内存里就快了
sprintf (command, "ar -t %s > a.txt", addlib);
system (command);
fp = fopen ("a.txt", "r");
if (fp == NULL) {
printf ("error\n");
return 1;
}
while (-1 != fscanf (fp, "%s", str)) {
sprintf (command, "ar -r %s %s", mainlib, str);
//sprintf (command, "ar -d %s %s", mainlib, str);
//printf ("%s\n", command);
system (command);
sprintf (command, "del %s", str);
system (command);
}
fclose (fp);
return 0;
}