Python 解压静态库 .a 和 .lib 文件

Python 解压静态库 .a 和 .lib 文件

2023-11-05 19:31:36
ChrisZZ

1.目的

解压 Windows 上的静态库文件 xxx.lib, 解压 linux aarch64 上的静态库文件 xxx.a。

使用 Python 是为了跨平台:

  • 不管 host 是什么系统, 都能执行解压
  • 不管被解压的静态库是 .a 还是 .lib, 在当前系统上都能解压

2. 方案调研

如果不限定为 Python, 那么用 7z 解压是最佳选择: 支持超多格式, 跨平台支持良好。

但目前没找到 7z 的 Python 封装, 找到的基本功能不全。希望用 7zz 这个命令行解压 .a/.lib 的意思是, 解压一个 archive, 而不是解压一个 .7z 类型的压缩包。因此:

  • pylzma: API 提供的过于 lowlevel, 文档里例子并不实用
  • py7zr: 只能处理 .7z 文件
  • zipfile: 这是 Python 内置模块,但只能处理 .zip 文件
  • patool (https://github.com/wummel/patool): 功能挺全的,一般用也够的,但它仅仅是命令行套壳,因此如果要在 Windows 系统上解压 Linux/macOSX 上生成的 .a 文件, 应该是做不到的
  • https://github.com/s3rvac/ar-cpp 这是用 CPP 实现的 ar 格式解析,但是作者弃坑了,说支持可能不太全不太对
  • https://en.wikipedia.org/wiki/Ar_(Unix) 这是 AR 格式的维基百科,按照上面说的,理论上可以自行实现 AR 格式解析

https://github.com/vidstige/ar 这个实现是纯 Python 的因此是跨平台的。不过没有支持 macOSX 上的 .a 文件, 我提交了 PR (https://github.com/vidstige/ar/pull/2),能否被 merge 就随缘了, 至少目前我的实际使用场景不需要支持 mac。

3. 使用 ar 模块

安装

pip install ar

准备静态库

libhello_d.a: 略。基于 CMake 自行生成即可。

使用 ar 模块

列出里面的 .o 文件(有时候还有 txt 文件), 保存所有entry为文件:

import ar
with open('file.a', "rb") as f:
    archive = ar.Archive(f)
    for entry in archive:
        fout = open(entry.name, "wb")
        fin = open(filepath, "rb")
        fin.seek(entry.offset)
        buffer = fin.read(entry.size)
        fout.write(buffer)
        fout.close()

验证一致性

使用 7zz x xxx.a 解压, 和 python 解压结果比对二进制:

# test locally

import sys
sys.path.insert(0, "/Users/chris/work/github/ar")
import ar
import os


filepath = "libhello_d.a"

save_dir = "by_py"
def extract_by_py():
    os.makedirs(save_dir, exist_ok=True)
    with open(filepath, "rb") as f:
        archive = ar.Archive(f)
        for entry in archive:
            print(entry.name, entry.offset, entry.size)
            fout = open(save_dir + "/" + entry.name, "wb")
            fin = open(filepath, "rb")
            fin.seek(entry.offset)
            buffer = fin.read(entry.size)
            fout.write(buffer)
            fout.close()

save_dir2 = "by_7zz"
def extract_by_7zz():
    cmd = "7zz x " + filepath + " -o" + save_dir2
    os.system(cmd)

def compare_binary():
    for item in os.listdir(save_dir):
        if item == "__.SYMDEF SORTED":
            continue
        cmd = "diff " + save_dir + "/" + item + " " + save_dir2 + "/" + item
        print(cmd)
        os.system(cmd)

if __name__ == "__main__":
    #extract_by_py()
    #extract_by_7zz()
    compare_binary()

4. 总结

  • 使用 pip install ar 提供的 API,可以完成跨平台的 .a/.lib 静态库的解压
  • ar 模块的官方文档很简略,也没有支持 BSD(macOSX)上的静态库的支持, 结合 Wikipedia 尝试了修复,提交了 PR
  • 如果有人封装了 7z 命令行的完整功能, 那么事情就无比简单了, 这位好心人还没出现
  • 后续使用, 根据解压的速度, 考虑是否基于 C/C++ 重新实现

你可能感兴趣的:(python,开发语言)