{"id":19269320,"url":"https://github.com/atsushieno/libcxx-provider","last_synced_at":"2025-08-02T08:06:28.661Z","repository":{"id":65508006,"uuid":"503374962","full_name":"atsushieno/libcxx-provider","owner":"atsushieno","description":"A utility Android package that just provides libc++_shared.so for apps with complex STL dependencies","archived":false,"fork":false,"pushed_at":"2025-02-28T02:01:23.000Z","size":133,"stargazers_count":5,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-01T15:56:24.721Z","etag":null,"topics":["android","android-ndk","prefab"],"latest_commit_sha":null,"homepage":"","language":"CMake","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/atsushieno.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":"2022-06-14T13:36:58.000Z","updated_at":"2025-03-19T09:42:09.000Z","dependencies_parsed_at":"2023-01-26T16:25:15.108Z","dependency_job_id":"b35c5c45-2936-4780-81ff-5ea42d1cc7e7","html_url":"https://github.com/atsushieno/libcxx-provider","commit_stats":null,"previous_names":[],"tags_count":22,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atsushieno%2Flibcxx-provider","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atsushieno%2Flibcxx-provider/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atsushieno%2Flibcxx-provider/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atsushieno%2Flibcxx-provider/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/atsushieno","download_url":"https://codeload.github.com/atsushieno/libcxx-provider/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250128349,"owners_count":21379493,"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":["android","android-ndk","prefab"],"created_at":"2024-11-09T20:19:30.969Z","updated_at":"2025-04-21T20:32:34.840Z","avatar_url":"https://github.com/atsushieno.png","language":"CMake","funding_links":[],"categories":[],"sub_categories":[],"readme":"# libcxx-provider README\n\n## What is this?\n\nlibcxx-provider is almost a stub project that only provides libc++_shared.so to apps.\n\nIf you build somewhat complex Android native application using Android NDK and are suffered from:\n\n\u003e java.lang.UnsatisfiedLinkError: dlopen failed: library \"libc++_shared.so\" not found: needed by ...\n\n...then this libcxx-provider is your savior.\n\nlibcxx-provider is a [Prefab](https://google.github.io/prefab/) package, and published via [Maven Central](https://repo1.maven.org/maven2/dev/atsushieno/).\n\n\n## Usage\n\nIn your app project, add the following lines to your `build.gradle.kts` (or `build.gradle`):\n\n```\ndependencies {\n    runtimeOnly(\"dev.atsushieno:libcxx-provider:21.4.7075529\")\n}\n```\n\n`runtimeOnly` would look unfamiliar to most of you - it indicates that the package contents are thrown into the outputs without building anything. You can use `implementation` instead of `runtimeOnly`, and optionally use the String value of the NDK version the `libc++_shared.so` comes from, but it involves extra compilcation steps from C++ and Kotlin sources.\n\nThe package version number actually indicates the NDK version that provides `libc++_shared.so_`. Version `21.4.7075529` is built with NDK r21e (`21.4.7075529`).\n\nFor the packaged versions, see https://search.maven.org/artifact/dev.atsushieno/libcxx-provider\n\n(Using NDK versions directly is kind of reckless but it would be better than `0.21.4` etc. because we cannot ship beta/RC versions. Hopefully I make no mistake on them. In the worst case we will come up with further dotted revisions.)\n\n\n## Rationale\n\n### ODR\n\nAndroid NDK comes with LLVM C++ standard library i.e. libc++ (which is comparable to GCC libstdc++). Whenever we write and compile C++ code, we most definitely need the STL.\n\nOne important rule you have to follow is [ODR - One Definition Rule](https://developer.android.com/ndk/guides/cpp-support#one_stl_per_app). We cannot use multiple C++ runtimes.\n\nUnlike C standard library i.e. libc (bionic), libc++ is not shipped as part of Android platform system libraries, so we cannot reference libc.so to load at run-time from the system (where ODR would not matter) but package libc++ in our apps instead.\n\nlibc++ can be linked either statically or dynamically, and for simple apps that only link every native code bits into one application library (.so) statically, things are simple. But if you have two or more shared libraries that linked libc++ statically, [that goes problematic](https://developer.android.com/ndk/guides/cpp-support#static_runtimes). You can easily break the ODR.\n\nTherefore we are mostly supposed to use the shared version i.e. `libc++_shared.so` in our libraries.\n\nODR should not be specific to C++. For example, there should be only one `kotlin-stdlib-*.jar` throughout the apk, but Gradle Kotlin plugin would resolve those conflicts to only the latest version. That does not happen to C++/NDK build systems (CMake or ndk-build).\n\n### Excluding libc++_shared.so from every AAR\n\nThe ODR is simple in principle, but we are suffered from various pitfalls.\n\nA popular problem is \"More than one file was found with OS independent path 'lib/x86/libc++_shared.so'\" etc. It happens when more than one AARs package the same library (even if they are identical).\n\nWhenever we build an AAR that contains a native library that depends on another (base) library (by adding its container AAR dependency), it is also packaged into the AAR.\n\nRegarding `libc++_shared.so`, almost everything in C++ uses it and therefore it is even easier to get inflated everywhere, and causes conflicts:\n\n\u003cimg src=\"images/package-states1.drawio.svg\" /\u003e\n\n\nHow to avoid this? We can exclude those dependency `*.so` files from AARs by e.g.:\n\n```\n    packagingOptions {\n        jniLibs.excludes.add(\"**/libc++_shared.so\")\n    }\n```\n\nThis way, we don't have to worry about `libc++_shared.so` duplicates.\n\nWhen your application project that references such AARs is being built using NDK, it will resolve `libc++_shared.so` and package into the apk/aab.\n\n\u003cimg src=\"images/package-states2.drawio.svg\" /\u003e\n\n### Problem on using native-bound libraries without C++ compilation\n\nI (@atsushieno) build [an audio plugin framework](https://github.com/atsushieno/android-audio-plugin-framework/) that comes with a couple of framework library AARs and they are used by various plugin apps. Some of those AARs come with the native libraries, and they build up a dependency tree.\n\nThose library AARs are in general designed for apps to be usable without compiling native code. JVM native binding (interop, FFI) projects would be also good example use cases.\n\nThis however uncovers an interesting problem. Those apps often don't have to involve `externalNativeBuild`, then no native compilation happens. In such case, only those native libraries from AARs are packaged into the apk/aab. Now you may have noticed - `libc++_shared.so` is not in any of the AARs, and there is no further native compilation involved.\n\n\u003cimg src=\"images/package-states3.drawio.svg\" /\u003e\n\nWhat happens then? The answer is -\n\n\u003e java.lang.UnsatisfiedLinkError: dlopen failed: library \"libc++_shared.so\" not found (...)\n\nIt is [what I experienced](https://github.com/atsushieno/android-audio-plugin-framework/issues/109) and what I wanted to resolve with this package. By adding this simplest AAR package, the missing `libc++_shared.so` piece is filled in my apps.\n\n\u003cimg src=\"images/package-states4.drawio.svg\" /\u003e\n\nIMHO The Android NDK team should distribute a package like this, just like how Kotlin team does for `kotlin-stdlib` (or the .NET team for CoreCLR/CoreFX artifacts), but so far anyone could do this, hence I am on it now.\n\n\n## Hacking\n\n### How to build for newer NDK version\n\nFind and replace those lines that specifies the version:\n\n```\n/sources/libcxx-provider$ git grep -n 21.4 | grep -v README.md\nlibcxx-provider/build.gradle:18:        versionName \"21.4.7075529\" // It has to align with ndkVersion\nlibcxx-provider/build.gradle:26:    ndkVersion \"21.4.7075529\"\nlibcxx-provider/src/main/cpp/package-info.cpp:7:            const char *ndk_version = \"21.4.7075529\";\nlibcxx-provider/src/main/java/dev/atsushieno/libcxx/LibCXX.java:4:    String ndkVersion = \"21.4.7075529\";\n```\n\nThen run `./gradlew build publishToMavenLocal` to build and install to your local Maven repository, or `./gradle build publish` to publish to the registered Maven server (note that only the package maintainers can perform it).\n\n\n## License\n\nlibcxx-provider sources are distributed under the MIT license.\n\nThe corresponding Maven packages are distributed under the Apache V2 licanse.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fatsushieno%2Flibcxx-provider","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fatsushieno%2Flibcxx-provider","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fatsushieno%2Flibcxx-provider/lists"}