树上小屋

这是一个将艺术和工程融为一体的活计.

导航

合并库

我在写自己的库的途中,为了读图片,又没有能力自己写,不得不用到了另外两个库(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
没了

最后达到了不加任何连接库就可以顺利运行的效果. 但是我那小小的库被合并胖了好几倍...
这招应该同样适用于合并动态库的导入库.

这样手动太累了,碰到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;
}
后来试了一下通过管道来得到模块名, 速度并没有什么提高.

posted on 2007-05-26 22:35  euclid  阅读(716)  评论(1编辑  收藏  举报