{"id":26159663,"url":"https://github.com/tux3/armerge","last_synced_at":"2025-04-06T02:07:44.793Z","repository":{"id":41405983,"uuid":"292295140","full_name":"tux3/armerge","owner":"tux3","description":"Tool to merge static libraries and hide their private symbols","archived":false,"fork":false,"pushed_at":"2025-02-23T10:54:48.000Z","size":128,"stargazers_count":33,"open_issues_count":1,"forks_count":4,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-30T01:05:55.651Z","etag":null,"topics":["build-tool","cli","development"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tux3.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-09-02T13:45:26.000Z","updated_at":"2025-02-23T10:54:51.000Z","dependencies_parsed_at":"2024-08-10T16:29:11.545Z","dependency_job_id":"36febad8-100f-47a1-995e-6ab81b122b70","html_url":"https://github.com/tux3/armerge","commit_stats":{"total_commits":56,"total_committers":3,"mean_commits":"18.666666666666668","dds":0.0892857142857143,"last_synced_commit":"f99a8544035728c30f4fdaedf3591166f45074a3"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tux3%2Farmerge","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tux3%2Farmerge/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tux3%2Farmerge/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tux3%2Farmerge/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tux3","download_url":"https://codeload.github.com/tux3/armerge/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247423513,"owners_count":20936626,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["build-tool","cli","development"],"created_at":"2025-03-11T11:33:18.323Z","updated_at":"2025-04-06T02:07:44.767Z","avatar_url":"https://github.com/tux3.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# armerge\n\n[![crates.io](https://img.shields.io/crates/v/armerge.svg)](https://crates.io/crates/armerge)\n[![Apache 2 licensed](https://img.shields.io/badge/license-Apache%202-blue)](./LICENSE)\n![MSRV](https://img.shields.io/badge/MSRV-1.74-informational)\n[![CI](https://github.com/tux3/armerge/workflows/CI/badge.svg)](https://github.com/tux3/armerge/actions?query=workflow%3ACI)\n\nYou can use armerge to combine multiple static libraries into a single merged `ar` archive.  \nOptionally, armerge can take a list of symbols you want to keep exported, and localizes (hides) the rest.\n\nThis allows you to hide your private symbols and the symbols of your dependencies.  \nFor example, if your static library `libfoo.a` uses OpenSSL's `libcrypto.a`, armerge can create a single\n`libfoo_merged.a` that combines both, but where all the OpenSSL symbols are hidden\nand only public `libfoo` symbols of your choice are exported.\n\n## Usage\n\nExample command to merge `libfoo.a` and `libcrypto.a`, keeping only symbols starting with `libfoo_` public:\n\n`armerge --keep-symbols '^libfoo_' --output libfoo_merged.a libfoo.a libcrypto.a`\n\nOptions and usage:\n\n```\nUSAGE:\n    armerge [FLAGS] [OPTIONS] --output \u003coutput\u003e [--] [INPUTS]...\n\nFLAGS:\n    -h, --help       Prints help information\n    -V, --version    Prints version information\n    -v, --verbose    Print verbose information\n\nOPTIONS:\n    -k, --keep-symbols \u003ckeep-symbols\u003e...        Accepts regexes of the symbol names to keep global, and localizes the rest\n        --order-file \u003corder-file\u003e               Order file to control the sorting of merged objects\n    -o, --output \u003coutput\u003e                       Output static library\n    -r, --remove-symbols \u003cremove-symbols\u003e...    Accepts regexes of the symbol names to hide, and keep the rest global\n\nARGS:\n    \u003cINPUTS\u003e...    Static libraries to merge\n```\n\n## Platform support\n\nLinux/Android and macOS/iOS `ar` archives are supported, using their respective host toolchain.  \nWhen localizing symbols (`-k` option), only archives containing ELF or Mach-O objects are supported\n(and in this case the output archive will contain a single relocatable object `merged.o`).\n\nThis tool requires `ranlib`, `ld`, and `llvm-objcopy` to handle Linux static libraries.   \nFor macOS libraries, `libtool` and the Apple `ld` are used instead.\n\nYou may specify a different linker using the `LD` environment variable, and linker flags with `ARMERGE_LDFLAGS`.  \nYou may specify a different objcopy implementation with the `OBJCOPY` env var, and a different ranlib with `RANLIB`.\n\nYou can use armerge to handle Linux/Android archives on a macOS host if the right toolchain is installed.\n(i.e. you may need to set `LD`, `OBJCOPY`, and `RANLIB` to point to the Android NDK, or to some other toolchain).\n\n## Object merge order\n\nBy default, objects are passed to the linker in alphabetical order. Linkers typically lay out the output file's sections in the order the inputs are specified. Passing the objects in alphabetical order helps make the output deterministic.\n\nIf you want to control the order in which some of the object files are merged, you can use the `--order-file` option. With this option, you can specify an order file that controls the relative order in which armerge passes the listed object files to the linker, so you can precisely control the order in which certain sections will be laid out in the output.\n\nThe order file is a plain text file with one entry per line, in the format `{INPUT_LIB}@{OBJNAME}`, where `INPUT_LIB` is the name of the input library and `OBJNAME` is the name of the object file to select from that library. Blank lines or lines starting with the `#` sign are ignored. Any object files not listed are placed after all of the listed objects, in alphabetical order. For example:\n\n```\n# Place the custom malloc object file first\nlibmyallocator.a@mymalloc.o\n\n# Place the app's entry point next\nlibmyapp.a@entry.o\n\n# All other object files are placed after this in alphabetical order.\n```\n\n## Principle of operation\n\n### Merging static libraries\n\nWhen you're not interested in controlling which symbols are exported by your static libraries, merging them is surprisingly simple.\nOn all major platforms, a static library is really an archive (like a `.zip` file, but in `ar` format).  \n(In fact, some projects sometimes handle merging static libraries with ad-hoc shell scripts that call the `ar` tool.)\n\nEssentially all armerge has to do to combine multiple `.a` files into a single one is to extract the object files inside\n(being careful not to overwrite different files with the same name, which is allowed *even in a single archive*,\nsomething shell scripts often forget to handle), and add them all together in a new `ar` archive.\n\nFor performance reasons, `ar` archive usually also have an index, so we take care to recreate it when merging.\n\n### Controlling exported symbols\n\nWhen you create a dynamic library, you can choose which set of symbols you want to export and which you want to keep internal.  \nThis allows keeping dependencies and implementation details private, and prevents hard to debug symbol clashes.  \nFor example, a `libfoo.so` library could bundle a copy of OpenSSL without problem, but only as long as it doesn't export those symbols.\nHiding symbols is especially important on Android (which helpfully loads its own version of some popular dynamic libraries, like OpenSSL),\nalthough clashes can happen on any platform.\n\nUnfortunately the native C and C++ toolchains do not expose any options to hide symbols in static libraries.  \nThis is because — unlike dynamic libraries — static archives are not a coherent whole but just a bag of object files.\nThere is no concept of export control at the static library level, only at the object level.  \nSo if symbols are naively localized at the object level, the static library would simply fail to link when you use it,\nbecause each object would now fiercely keep its own symbols private from other objects, *even in the same library*.\n\nThe solution is to do the same thing that dynamic libraries do: have it consist of a single object file.\nSo in addition to merging multiple archive files into a single one, when you ask armerge to localize symbols it will\npass all the object files in input libraries to the linker and create a single pre-linked object file, called a relocatable object.\n\nThis results in a static library (for instance `libfoo.a`) that contains a single `merged.o` object.  \nSince all the input objects have already been pre-linked together, now there is a single symbol list for the whole library\n(like dynamic libraries have), and so we can ask the toolchain to localize symbols for us without any problems.\n\nIn this process, armerge really delegates most of the work to the linker and utilities like `objcopy`.  \nThe features required to control symbol export in static libraries is actually the same mechanism that is used for dynamic libraries\n(both are really just object files), so your system toolchain had the support for this all along.\n\nBut because linkers traditionally output static libraries containing multiple objects instead of a single pre-linked object,\nthey've created an historical asymmetry where hiding symbols in dynamic libraries has always been easy,\nwhile hiding symbols in static libraries has never been supported by the toolchain.\n\nSo, armerge first corrects the asymmetry by asking the linker to pre-link the objects, and only then asks it to hide symbols. \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftux3%2Farmerge","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftux3%2Farmerge","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftux3%2Farmerge/lists"}