Create, edit and compare ar, GNU thin and Microsoft COFF libraries in MoonBit
git clone https://github.com/xmyd0915/moonar.git
cd moonar
moon update
moon build --target native --deny-warncc -c first.c -o first.o
cc -c second.c -o second.o
moonar create libsample.a first.o second.o
moonar list libsample.a
cc main.c libsample.a -o democc -c second.c -o second.o
moonar replace libsample.a 1 second.o
moonar move libsample.a 1 0
moonar extract libsample.a 0 copied.omoonar create libthin.a first.o second.o --thin
moonar replace libthin.a 1 second.o
moonar convert libthin.a libpacked.a
moonar create libnested.a libpacked.a --thinmoonar check libthin.a --external
moonar diff before/libthin.a after/libthin.a --logical --json
moonar diff libthin.a libpacked.a --logical| 命令 | 功能 |
|---|---|
| list FILE / inspect FILE / check FILE | 普通成员列表、物理记录、结构校验 |
| create OUT [FILES...] | 创建普通归档;--thin 创建 GNU thin |
| add ARCHIVE FILES... [--at N] | 追加或从指定位置插入 |
| replace ARCHIVE INDEX FILE | 替换一个成员;普通归档保留其原名称 |
| delete ARCHIVE INDEX... | 删除指定成员 |
| move ARCHIVE FROM TO | 移到最终位置,保留其他成员的相对顺序 |
| rename ARCHIVE INDEX NAME | 修改名称;thin 中修改的是外部引用 |
| extract ARCHIVE INDEX OUT | 将指定成员写入明确的输出路径 |
| convert ARCHIVE OUT | 转换普通归档布局,或将 thin 物化 |
| index ARCHIVE | 从对象重新发现符号并建立索引 |
| diff BEFORE AFTER [--logical] | 普通归档物理比较;普通/thin 归档的直接逻辑比较 |
moon add xmyd0915/moonar@0.7.2let plan = @ar.ArchiveBuilder::from_members([
@ar.WriteMember::new(b"hello.txt", b"hello\n"),
]).unwrap()
let bytes = plan.write(format=@ar.Gnu).unwrap()
let archive = @ar.parse(bytes).unwrap()
let data = archive.member_bytes(0).unwrap()| 能力 | 支持范围 |
|---|---|
| 读取与写出 | GNU32/64、BSD32/64、Darwin32/64、Microsoft COFF 双索引;BSD/Darwin 支持大小端 |
| thin | GNU 直接文件与嵌套 archive-offset 引用,GNU32/64 索引,创建、编辑、加载、重定位与物化 |
| 自动符号发现 | ELF32/64、Mach-O32/64、标准 COFF、bigobj、短导入对象;带版本 3 摘要表的 LLVM bitcode |
| 成员 | 原始名称字节、长名称、重名、空内容、二进制数据和元数据 |
| 比较 | 物理字节、普通成员内容、元数据、顺序、符号映射与重名配对歧义 |
python tools/verify_toolchain.py
moon fmt --check
moon check --target all --deny-warn
moon test --target all --deny-warn
moon build --target native --deny-warn
python tools/verify_cli.py --moonar _build/native/debug/build/cmd/main/main.exe --require-llvm
python tools/verify_io.py --moonar _build/native/debug/build/cmd/main/main.exe
python tools/verify_zlib.py --moonar _build/native/debug/build/cmd/main/main.exe
python tools/verify_windows.py --moonar _build/native/debug/build/cmd/main/main.exe
python tools/verify_lto.py --moonar _build/native/debug/build/cmd/main/main.exe
python tools/verify_package.py
python tools/benchmark.pyfn ArchiveBuilder::append(self : ArchiveBuilder, entry : WriteMember) -> Result[ArchiveBuilder, WriteError]fn ArchiveBuilder::discover_symbols(self : ArchiveBuilder, max_symbols? : Int, max_symbol_name_bytes? : Int) -> Result[Array[WriteSymbol], WriteError]fn ArchiveBuilder::insert(self : ArchiveBuilder, index : Int, entry : WriteMember) -> Result[ArchiveBuilder, WriteError]fn ArchiveBuilder::move_member(self : ArchiveBuilder, from : Int, to : Int) -> Result[ArchiveBuilder, WriteError]fn ArchiveBuilder::replace(self : ArchiveBuilder, index : Int, entry : WriteMember) -> Result[ArchiveBuilder, WriteError]fn ArchiveBuilder::write(self : ArchiveBuilder, format? : WriteFormat, metadata? : WriteMetadata, symbols? : Array[WriteSymbol]?, index_little_endian? : Bool, max_bytes? : Int, max_members? : Int, max_name_bytes? : Int, max_symbols? : Int, max_symbol_name_bytes? : Int) -> Result[Bytes, WriteError]fn ArchiveSnapshot::compare_logical(self : ArchiveSnapshot, other : ArchiveSnapshot) -> LogicalComparisonpub(all) struct Comparison {
bytes_equal : Bool
order_changed : Bool
changes : Array[MemberChange]
ambiguities : Array[MatchAmbiguity]
} derive(Eq, Debug)pub(all) struct LogicalComparison {
bytes_equal : Bool
content_equal : Bool
metadata_changed : Bool
order_changed : Bool
symbols_equal : Bool
symbol_index_presence_changed : Bool
changes : Array[MemberChange]
ambiguities : Array[MatchAmbiguity]
} derive(Eq, Debug)pub(all) struct MatchAmbiguity {
name : Bytes
member_kind : MemberKind
before_indices : Array[Int]
after_indices : Array[Int]
} derive(Eq, Debug)pub(all) struct Member {
name : Bytes
kind : MemberKind
header_offset : Int
data_offset : Int
size : Int
stored_size : Int
metadata : Metadata
} derive(Eq, Debug)pub(all) struct MemberChange {
change : ChangeKind
name : Bytes
member_kind : MemberKind
occurrence : Int
before_index : Int?
after_index : Int?
payload_changed : Bool
metadata_changed : Bool
} derive(Eq, Debug)fn NestedLimits::new(max_bytes? : Int, max_members? : Int, max_name_bytes? : Int, max_symbols? : Int, max_symbol_name_bytes? : Int, max_depth? : Int) -> NestedLimitsfn ThinArchive::edit(self : ThinArchive, drop_symbol_indexes? : Bool) -> Result[ThinArchiveBuilder, WriteError]fn ThinArchive::load_member(self : ThinArchive, index : Int, loader : (Bytes, Int) -> Result[Bytes, String], max_bytes? : Int, allow_parent_paths? : Bool, nested_limits? : NestedLimits) -> Result[Bytes, ParseError]fn ThinArchive::materialize(self : ThinArchive, loader : (Bytes, Int) -> Result[Bytes, String], drop_symbol_indexes? : Bool, allow_parent_paths? : Bool, max_bytes? : Int, nested_limits? : NestedLimits) -> Result[ArchiveBuilder, ParseError]fn ThinArchive::member_path(self : ThinArchive, index : Int, allow_parent_paths? : Bool) -> Result[Bytes, ParseError]fn ThinArchive::member_sources(self : ThinArchive, loader : (Bytes, Int) -> Result[Bytes, String], allow_parent_paths? : Bool, nested_limits? : NestedLimits) -> Result[Array[Bytes], ParseError]fn ThinArchive::resolve_member(self : ThinArchive, index : Int, loader : (Bytes, Int) -> Result[Bytes, String], max_bytes? : Int, allow_parent_paths? : Bool, nested_limits? : NestedLimits) -> Result[WriteMember, ParseError]fn ThinArchive::snapshot(self : ThinArchive, loader : (Bytes, Int) -> Result[Bytes, String], max_bytes? : Int, allow_parent_paths? : Bool, nested_limits? : NestedLimits) -> Result[ArchiveSnapshot, ParseError]fn ThinArchive::validate_members(self : ThinArchive, loader : (Bytes, Int) -> Result[Bytes, String], max_bytes? : Int, allow_parent_paths? : Bool, nested_limits? : NestedLimits) -> Result[Int, ParseError]fn ThinArchiveBuilder::append(self : ThinArchiveBuilder, entry : ThinWriteMember) -> Result[ThinArchiveBuilder, WriteError]fn ThinArchiveBuilder::from_members(entries : Array[ThinWriteMember]) -> Result[ThinArchiveBuilder, WriteError]fn ThinArchiveBuilder::insert(self : ThinArchiveBuilder, index : Int, entry : ThinWriteMember) -> Result[ThinArchiveBuilder, WriteError]fn ThinArchiveBuilder::move_member(self : ThinArchiveBuilder, from : Int, to : Int) -> Result[ThinArchiveBuilder, WriteError]fn ThinArchiveBuilder::remove(self : ThinArchiveBuilder, index : Int) -> Result[ThinArchiveBuilder, WriteError]fn ThinArchiveBuilder::replace(self : ThinArchiveBuilder, index : Int, entry : ThinWriteMember) -> Result[ThinArchiveBuilder, WriteError]fn ThinArchiveBuilder::write(self : ThinArchiveBuilder, metadata? : WriteMetadata, symbols? : Array[WriteSymbol]?, symbol_width? : Int, max_bytes? : Int, max_members? : Int, max_name_bytes? : Int, max_symbols? : Int, max_symbol_name_bytes? : Int) -> Result[Bytes, WriteError]pub(all) struct ThinMember {
name : Bytes
kind : MemberKind
header_offset : Int
size : Int
metadata : Metadata
archive_member_offset : Int?
} derive(Eq, Debug)fn ThinWriteMember::new(name : Bytes, size : Int, metadata? : Metadata, archive_member_offset? : Int?) -> ThinWriteMemberfn parse(input : Bytes, max_members? : Int, max_bytes? : Int, max_name_bytes? : Int, max_symbols? : Int, max_symbol_name_bytes? : Int) -> Result[Archive, ParseError]fn parse_thin(input : Bytes, max_members? : Int, max_bytes? : Int, max_name_bytes? : Int, max_symbols? : Int, max_symbol_name_bytes? : Int) -> Result[ThinArchive, ParseError]fn symbols_from_object(data : Bytes, max_symbols? : Int, max_symbol_name_bytes? : Int) -> Result[Array[Bytes], ObjectError]Install
Download zipCreate, edit and compare ar, GNU thin and Microsoft COFF libraries in MoonBit