Fix Termux/Android compatibility issues (DNS, locking, Android target support)#5
Fix Termux/Android compatibility issues (DNS, locking, Android target support)#5
Conversation
d61ca4b to
6c3d14b
Compare
|
Hi, do you know if this will continue to work with, and maybe improve, https://github.com/termux-user-repository/tur/blob/cf26feef42820d03b7061866ee5f456324657a7a/tur/codex/build.sh ? |
The current TUR provided codex is impacted by the issue that my PR resolves, so if I get an invite to PR upstream, this should fix at least the locking issues. I had some code change logic to handle the absence of /etc/resolve.conf on android, but found that simply adding an aarch64-linux-android target made all of that unnecessary.. but if this never gets merged upstream, I could provide a patch with that original conditional logic so that this can be fully solved via patches in the TUR. Are you a maintainer, @robertkirkman ? |
Yes, I have merge permission for TUR. If you want users of Codex on TUR to get this fix, you could also submit this to https://github.com/termux-user-repository/tur/pulls and I would be able to approve it there, and then whenever this version gets merged the patch could be removed from the TUR version when it gets updated. |
| #[cfg(target_os = "android")] | ||
| impl portable_pty::PtySystem for AndroidPtySystem { | ||
| fn openpty(&self, _size: PtySize) -> anyhow::Result<portable_pty::PtyPair> { | ||
| anyhow::bail!("PTY not supported on Android") |
There was a problem hiding this comment.
Could you describe what goes wrong if you do not disable PTY on Android? I was wondering about that.
There was a problem hiding this comment.
https://github.com/wallentx/codex/actions/runs/22244673318/job/64355979725#step:22:121
Compiling codex-cli v0.104.0-dev (/home/runner/work/codex/codex/codex-rs/cli)
error: linking with `/usr/local/lib/android/sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang` failed: exit status: 1
|
= note: "/usr/local/lib/android/sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang" "<1 object files omitted>" "-Wl,--as-needed" "-Wl,-Bstatic" "/tmp/rustc4CmmoS/{liblzma_sys-992b66fb89471db7,libbzip2_sys-ee2c4dea6113765e,liblibsqlite3_sys-74e3b2d982fb2832,libtree_sitter_bash-ba13aee0aa28265f,libtree_sitter-1ca4d45594f820fa,libzstd_sys-4dde45f3f9f13c1c,libaws_lc_sys-d9601faf5d845464,libring-7cc72dfc028a344e,libopenssl_sys-829833977529d351}.rlib" "<sysroot>/lib/rustlib/aarch64-linux-android/lib/libcompiler_builtins-*.rlib" "-Wl,-Bdynamic" "-lz" "-ldl" "-llog" "-lunwind" "-ldl" "-lm" "-lc" "-L" "/tmp/rustc4CmmoS/raw-dylibs" "-Wl,--eh-frame-hdr" "-Wl,-z,noexecstack" "-L" "/home/runner/work/codex/codex/codex-rs/target/aarch64-linux-android/release/build/tree-sitter-6f935e6c94cea3b9/out" "-L" "/home/runner/work/codex/codex/codex-rs/target/aarch64-linux-android/release/build/tree-sitter-bash-7043ce2866a501a9/out" "-L" "/home/runner/work/codex/codex/codex-rs/target/aarch64-linux-android/release/build/aws-lc-sys-f78b418f69a41d9e/out" "-L" "/home/runner/work/codex/codex/codex-rs/target/aarch64-linux-android/release/build/ring-478a869566eb754e/out" "-L" "/home/runner/work/codex/codex/codex-rs/target/aarch64-linux-android/release/build/openssl-sys-50d764c58005cb2d/out/openssl-build/install/lib" "-L" "/home/runner/work/codex/codex/codex-rs/target/aarch64-linux-android/release/build/zstd-sys-8fee5b13a7070f55/out" "-L" "/home/runner/work/codex/codex/codex-rs/target/aarch64-linux-android/release/build/libsqlite3-sys-0c9f47d8c58ecbb3/out" "-L" "/home/runner/work/codex/codex/codex-rs/target/aarch64-linux-android/release/build/bzip2-sys-18f29db9c9b4c5d5/out/lib" "-L" "/home/runner/work/codex/codex/codex-rs/target/aarch64-linux-android/release/build/lzma-sys-e22fad6537c17296/out" "-o" "/home/runner/work/codex/codex/codex-rs/target/aarch64-linux-android/release/deps/codex-94cb809459dd56d4" "-Wl,--gc-sections" "-pie" "-Wl,-z,relro,-z,now" "-Wl,-O1" "-Wl,--strip-all" "-nodefaultlibs"
= note: some arguments are omitted. use `--verbose` to show all linker arguments
= note: ld.lld: error: undefined symbol: openpty
>>> referenced by codex.5ecef7b0ac420300-cgu.0
>>> /home/runner/work/codex/codex/codex-rs/target/aarch64-linux-android/release/deps/codex-94cb809459dd56d4.codex.5ecef7b0ac420300-cgu.0.rcgu.o:(_$LT$portable_pty..unix..UnixPtySystem$u20$as$u20$portable_pty..PtySystem$GT$::openpty::hf566b6e5dd6631e1)
clang: error: linker command failed with exit code 1 (use -v to see invocation)
error: could not compile `codex-cli` (bin "codex") due to 1 previous error
There was a problem hiding this comment.
Ohh I see, thanks for showing that.
The cause of the error ld.lld: error: undefined symbol: openpty is because the openpty function does not exist in Android 5, and this PR code is targeting Android 5.
Termux only supports Android 7 and newer, and in Android 6 and newer the openpty function does exist, so this error will not affect Termux.
Therefore, it is appropriate to keep this code which disables PTY for an upstream Codex version that can be used with Android 5, but for the Termux version the code which disables PTY will be possible to disable.
There was a problem hiding this comment.
Ahh thanks for this! I'll bump the API level to 24 and remove the PTY exclusion. I don't suspect this will be useful to anyone outside of termux.
There was a problem hiding this comment.
@robertkirkman I bumped the API target level to 24 and it failed with the same error.
https://github.com/wallentx/codex/actions/runs/22280259015/job/64449939914
Copilot informs me:
There’s an important difference between Termux and native Android development with the NDK. Termux provides openpty via its own libraries (such as libutil), so code compiled and run in Termux has access to that function. However, when building native Android apps with the NDK, the openpty function is not available in Android’s system libraries (bionic libc)—regardless of Android version. This means native binaries targeting Android, including Android 6 and newer, will encounter linker errors if they rely on openpty, unless they provide their own implementation.
So, while Termux users can use openpty, native Android apps built with the NDK cannot depend on it. That’s why this linker error matters for the CI job and NDK-based builds, even though Termux itself is unaffected.
I'll still keep the target level to 24, since that's what termux-packages uses, but it looks like I need to reapply the pty exclusion for android
There was a problem hiding this comment.
#!/bin/bash
echo "Instalando ca-certificates..."
pkg install ca-certificates -y
echo "Configurando .bashrc..."
Evita duplicados
if ! grep -q "SSL_CERT_FILE" ~/.bashrc; then
echo '' >> ~/.bashrc
echo '# Codex Termux fix' >> ~/.bashrc
echo 'export SSL_CERT_FILE=$PREFIX/etc/tls/cert.pem' >> ~/.bashrc
echo 'export SSL_CERT_DIR=$PREFIX/etc/tls/certs' >> ~/.bashrc
echo 'export RESOLV_CONF=$PREFIX/etc/resolv.conf' >> ~/.bashrc
echo "Listo! Variables agregadas al .bashrc"
else
echo "Las variables ya existen en .bashrc, no se duplicaron."
fi
source ~/.bashrc
echo "Todo listo! Ya puedes usar codex"
There was a problem hiding this comment.
@Jose2021H I tried that excited that it might work, but I'm getting:
file:///data/data/com.termux/files/usr/lib/node_modules/@openai/codex/bin/codex.js:100 throw new Error( ^
Error: Missing optional dependency @openai/codex-linux-arm64. Reinstall Codex: npm install -g @openai/codex@latest at file:///data/data/com.termux/files/usr/lib/node_modules/@openai/codex/bin/codex.js:100:11 at ModuleJob.run (node:internal/modules/esm/module_job:430:25) at async onImport.tracePromise.__proto__ (node:internal/modules/esm/loader:639:26)
at async asyncRunEntryPointWithESMLoader (node:internal/modules/run_main:101:5)
Node.js v25.8.2
There was a problem hiding this comment.
@licy183 someone tried to use codex from TUR, but because it doesn't work, they opened an issue, and because of that I sent them a link to this thread which they linked in their issue,
i assume that if wallentx is continuing with this, they will eventually be able to solve that issue
There was a problem hiding this comment.
@robertkirkman @tomiia @mevanlc
Things got pretty messy and broken for a bit, but I've done a lot of cleanup and have a fully working build here that is roughly equivalent to 0.122.0-alpha.5:
https://github.com/wallentx/codex/actions/runs/24577406145
I'm working on CI now that will mirror upstream pre-releases/releases as much as possible, then apply the Termux patch layer and produce an Android artifact from that result.
At this point the PR is less "one small Android target patch" and more a collection of compatibility fixes that will need to be applied to upstream code as it changes. My goal with the mirrored releases are to make this automated and maintainable, because I don't have high hopes that I'll be getting an invite to PR to OpenAI, and I don't suspect that any of this work is a high priority for them.
The current landscape of changes is roughly:
Android/Termux Runtime Fixes
-
Advisory file locks: Android/Bionic/Termux can return
ErrorKind::Unsupportedfor RustFile::lock()/try_lock()style APIs.
This was the cause of errors like:Error: thread/start failed during TUI bootstrapand:
Failed to initialize session: lock() not supportedI added a small shared helper crate for optional advisory file locking so call sites can distinguish "lock acquired", "would block", and "locking unsupported". There is also an audit script to help find future upstream lock usage that may need the same treatment.
-
File watcher behavior: The live filesystem watcher is disabled/nooped on Android. This avoids platform behavior that is not reliable in the Termux environment while still allowing the rest of the app to start normally.
-
Shell path resolution: Codex normally assumes standard Unix absolute paths like
/bin/sh. On Termux those paths are not the real userland. I added Android-specific shell lookup that prefers$PREFIX/bin/..., falling back to Termux's usual/data/data/com.termux/files/usr/bin/...location when$PREFIXis unavailable. -
Clipboard/image paste: Android builds exclude unsupported desktop clipboard/image-paste paths so the crate compiles cleanly and reports unsupported clipboard behavior instead of pulling in incompatible assumptions.
Login/Auth Fixes
-
Device-code auth: The branch includes the fixes needed for device-code auth to work on Termux. This currently does not work in upstream for this Android/Termux build target.
-
ChatGPT browser login duplicate callback: Device-code login worked first, but "Sign in with ChatGPT" failed on Android/Chrome after the browser hit the localhost callback more than once. The first callback successfully redeemed the OAuth code; the duplicate callback then tried to redeem the same code again and got a 400 from the token endpoint. The visible error was:
Token exchange failed: token endpoint returned status 400 Bad Request: Invalid request. Please try again later.I added callback state tracking so duplicate callbacks for the same code either reuse the success redirect or wait briefly for the first callback to finish.
-
TUI originator compatibility: The app-server client name from the TUI is normalized back to the expected default originator for login/client behavior, while preserving the user-agent suffix.
Android Binary/Build Artifact Fixes
-
TLS alignment: The produced binary needed post-processing/alignment fixes for ARM64 Bionic. Before that, Termux reported:
executable's TLS segment is underaligned: alignment is 64 (skew 16), needs to be at least 64 for ARM64 BionicThe workflow now runs the cleanup/alignment steps needed for the Android artifact.
-
Custom Android V8 artifact: For now I had to fork
denoland/rusty_v8, make changes there to produce an Android artifact, and publish that artifact in a release so this Codex fork can fetch and use it:
https://github.com/wallentx/rusty_v8/releases/tag/v146.9.0That is an external dependency I still need to chase upstream, because this should ideally come from the upstream
rusty_v8artifact pipeline rather than my fork.
Maintenance / Future-Proofing
-
Lock audit helper: Since upstream can add new
lock()usage at any time, I addedscripts/termux-lock-audit.sh/just termux-lock-auditto flag candidate file-lock call sites that may need Android/Termux handling. -
Release automation: I'm setting up a release-train workflow so when upstream publishes a new
rust-v*pre-release/release, my fork can create arelease/<version-train>branch, apply the Termux patch layer, build the Android artifact in CI, let me manually test that exact artifact, and then promote that same artifact into a mirrored Termux release once the PR is merged.
Some of these feel like reasonable upstream candidates, especially the "unsupported file locks should be handled gracefully" pieces, device-code auth, and the duplicate OAuth callback handling. Others are probably downstream-only for now, especially Termux path assumptions, Android artifact post-processing, and the temporary dependency on my fork's V8 artifact.
This might seem like a lot of effort for a niche group of users, but it's something I want for myself, and I'm currently unemployed (holla if hiring for Staff/Principal DevOps), so this is also keeping me sane and busy.
There was a problem hiding this comment.
4cccbca to
89ee71b
Compare
Termux rust-v0.126.0-alpha.1
…ckpoint/wallentx_termux-target_from_release_0.126.0_d763bfd051ab # Conflicts: # codex-rs/Cargo.toml
…t_from_release_0.126.0_d763bfd051ab checkpoint: into wallentx/termux-target from release/0.126.0 @ d763bfd
Termux rust-v0.126.0-alpha.2
…ckpoint/wallentx_termux-target_from_release_0.126.0_c958229d879c # Conflicts: # codex-rs/Cargo.toml
…t_from_release_0.126.0_c958229d879c checkpoint: into wallentx/termux-target from release/0.126.0 @ c958229
….0-alpha.3 Release 0.126.0-alpha.3 # Conflicts: # .github/workflows/bazel.yml # .github/workflows/rust-release.yml # codex-rs/Cargo.toml # codex-rs/app-server/tests/suite/v2/thread_resume.rs
Termux rust-v0.126.0-alpha.3
…nt/wallentx_termux-target_from_release_0.126.0_eb70bfad6fb4 # Conflicts: # .github/termux-release.json # .github/workflows/termux-release-checkpoint.yml # .github/workflows/termux-release-deploy.yml
…t_from_release_0.126.0_eb70bfad6fb4 checkpoint: into wallentx/termux-target from release/0.126.0 @ eb70bfa
Termux rust-v0.129.0-alpha.7
…nt/wallentx_termux-target_from_release_0.129.0_1a78ed0ef81a # Conflicts: # .github/workflows/rust-release.yml # .github/workflows/shell-tool-mcp.yml # codex-rs/Cargo.toml # scripts/termux-create-checkpoint-pr.sh
…t_from_release_0.129.0_1a78ed0ef81a checkpoint: into wallentx/termux-target from release/0.129.0 @ 1a78ed0
## Why The core protocol still exposed a `ListModels` submission op even though no client sends it and the core submission loop treated it as an ignored unknown op. Keeping the dead variant made the protocol surface look supported while the active model listing API is the app-server `model/list` JSON-RPC request. ## What Changed - Removed the unused `Op::ListModels` variant from `codex-rs/protocol`. - Removed its `Op::kind()` mapping. The existing app-server `model/list` endpoint is unchanged. ## Verification - `cargo test -p codex-protocol`
## Why `skills/list` is already exposed through app-server v2 and covered by the app-server test suite. Keeping the separate core `Op::ListSkills` path leaves a duplicate legacy protocol surface that no longer needs to be maintained. ## What Changed - Removed `Op::ListSkills` and `EventMsg::ListSkillsResponse` from the core protocol. - Deleted the corresponding core session handler and stale core integration tests. - Removed rollout/MCP ignore branches and protocol v1 docs references for the deleted event/op. - Left app-server `skills/list` and its existing coverage intact. ## Validation - `cargo test -p codex-protocol` - `cargo test -p codex-core --test all suite::skills` - `cargo check -p codex-mcp-server -p codex-rollout -p codex-rollout-trace` - `just fix -p codex-core`
## Summary - Add plugin manifest keywords to core plugin marketplace/detail models - Expose keywords on app-server v2 PluginSummary and generated schema/types - Populate keywords in plugin/list and plugin/read responses for local plugins Depends on openai/openai#891087 ## Validation - just fmt - just write-app-server-schema - cargo test -p codex-app-server-protocol - cargo test -p codex-core-plugins - cargo test -p codex-app-server plugin_list_keeps_valid_marketplaces_when_another_marketplace_fails_to_load - cargo test -p codex-app-server plugin_read_returns_plugin_details_with_bundle_contents
…0949) ## Summary - make `thread_source` an explicit optional thread-level field on `thread/start`, `thread/fork`, and returned thread payloads - persist `thread_source` in rollout/session metadata so resumed live threads retain the original value - replace the old best-effort `session_source` -> `thread_source` mapping with an explicit caller-supplied analytics classification ## Why Before this change, analytics `thread_source` was populated by a best-effort mapping from `session_source`. `session_source` describes the runtime/client surface, not the actual thread-level origin, so that projection was not accurate enough to distinguish cases such as `user`, `subagent`, `memory_consolidation`, and future thread origins reliably. Making `thread_source` explicit keeps one thread-level analytics field while letting callers provide the real classification directly instead of recovering it indirectly from `session_source`. ## Impact For new analytics events, `thread_source` now reflects the explicit thread-level classification supplied by the caller rather than an inferred value derived from `session_source`. Existing protocol fields remain optional; callers that omit `threadSource` now produce `null` instead of a best-effort inferred value. ## Validation - `just write-app-server-schema` - `cargo test -p codex-analytics -p codex-core -p codex-app-server-protocol --no-run` - `cargo test -p codex-app-server-protocol generated_ts_optional_nullable_fields_only_in_params` - `cargo test -p codex-analytics thread_initialized_event_serializes_expected_shape` - `cargo test -p codex-core resume_stopped_thread_from_rollout_preserves_thread_source`
Extends `plugin/share/save` to accept optional discoverability and shareTargets while uploading plugin contents, and adds `plugin/share/updateTargets` for share-only target updates without re-uploading.
Termux rust-v0.129.0-alpha.8
…nt/wallentx_termux-target_from_release_0.129.0_bfb0621cfd50 # Conflicts: # .github/workflows/rust-release.yml # .github/workflows/shell-tool-mcp.yml # codex-rs/Cargo.toml # scripts/termux-create-checkpoint-pr.sh
…#20724) ## Why Codex currently accepts dynamic tool names and namespaces that the upstream Responses function-tool path does not actually support. In practice, that means app-server can register a dynamic tool successfully and only discover later that the LLM-facing tool contract will reject or mishandle it. This PR tightens the app-server-side dynamic tool contract to match the Responses API before we stack dynamic tool hook support on top of it. ## What changed - validate dynamic tool `name` against the Responses function-tool identifier contract: `^[a-zA-Z0-9_-]+$`, length `1..128` - validate dynamic tool `namespace` the same way, with the Responses namespace length limit `1..64` - reject namespaces that collide with the always-reserved Responses runtime namespaces such as `functions`, `multi_tool_use`, `file_search`, `web`, `browser`, `image_gen`, `computer`, `container`, `terminal`, `python`, `python_user_visible`, `api_tool`, `tool_search`, and `submodel_delegator` - escape invalid identifiers in error messages so control characters do not spill raw into logs or client-visible error text - document the tightened dynamic tool identifier contract in `codex-rs/app-server/README.md` - add both unit coverage for the validator and an app-server integration test that rejects a `thread/start` request with Responses-incompatible dynamic tool identifiers ## Verification - `cargo test -p codex-app-server validate_dynamic_tools_` - `cargo test -p codex-app-server --test all thread_start_rejects_dynamic_tools_not_supported_by_responses`
# Overview MCP refreshes were rebuilding active threads from fresh disk-backed config only, which dropped thread-start session overlays such as app-injected MCP servers. This keeps refreshes current with disk config while preserving the thread-local config that only the active thread knows about. # Changes - Rebuild refreshed config per active thread using that thread's current `cwd`, rather than fanning out one app-server config to every thread. - Preserve each thread's `SessionFlags` layer while replacing reloadable config layers with freshly loaded config, then derive the MCP refresh payload from the rebuilt result. - Move MCP refresh orchestration into app-server so manual refreshes fail loudly while background refreshes remain best-effort, and route plugin-triggered refreshes through the same per-thread reload path. - Add regression coverage for session overlays, fresh project config, plugin-derived MCP config, current requirements, and strict vs best-effort refresh behavior. # Verification - Passed focused Rust coverage for the thread-config rebuild behavior and deferred MCP refresh flow, plus `cargo test -p codex-app-server --lib`. - Verified end to end in the Codex dev app against the locally built CLI: registered an MCP via thread config, verified that it could be used successfully before refresh, manually triggered MCP refresh, and verified that it continued to be available afterward.
- [x] Return Accept early when auto_deny is enabled per feedback.
## Why openai#21255 added the standalone `codex-bwrap` binary. In the Cargo build, [`pkg_config::probe("libcap")`](https://github.com/openai/codex/blob/a736cb55a2bce57b4c8e5a4fe56f70c2b2ad892b/codex-rs/bwrap/build.rs#L37-L39) emits `-lcap` before [`cc::Build::compile("standalone_bwrap")`](https://github.com/openai/codex/blob/a736cb55a2bce57b4c8e5a4fe56f70c2b2ad892b/codex-rs/bwrap/build.rs#L50-L67) adds the static bwrap archive. The Linux musl link then sees `-lcap -lstandalone_bwrap`; because static archives are resolved left-to-right, `cap_from_name` is still undefined once `standalone_bwrap` introduces that reference. The musl setup already builds `libcap.a` and exposes it through [`libcap.pc`](https://github.com/openai/codex/blob/a736cb55a2bce57b4c8e5a4fe56f70c2b2ad892b/.github/scripts/install-musl-build-tools.sh#L78-L88), so the failure is link ordering rather than a missing dependency. ## What changed - probe `libcap` with `cargo_metadata(false)` so `pkg-config` does not emit its link flags early - emit the discovered `libcap` search paths and libraries after `standalone_bwrap` is compiled, preserving the needed static-link order ## Verification - `cargo test -p codex-bwrap` - `cargo clippy -p codex-bwrap --all-targets` The affected Linux musl release link is exercised by CI, which is the path this fix targets.
…t_from_release_0.129.0_bfb0621cfd50 checkpoint: into wallentx/termux-target from release/0.129.0 @ bfb0621
## Why openai#21255 changed the Linux sandbox fallback so Codex can use a bundled `codex-resources/bwrap` executable when no suitable system `bwrap` is available. That lookup is relative to the native Codex executable returned by `std::env::current_exe()`, as implemented in [`bundled_bwrap.rs`](https://github.com/openai/codex/blob/9766d3d51cec885114b6d6c53a02e9efbaf87171/codex-rs/linux-sandbox/src/bundled_bwrap.rs#L83-L93). The release already publishes a separate `bwrap` DotSlash output, but the Linux `codex` DotSlash output still pointed at a single-binary `.zst` payload. Running the `codex` DotSlash manifest only materializes the native `codex` executable; it does not also create sibling files from the separate `bwrap` manifest. The fallback path therefore needs the Linux `codex` DotSlash artifact itself to include the real `bwrap` executable at `codex-resources/bwrap`. ## What changed - stage a Linux primary `codex-<target>-bundle.tar.zst` release artifact containing `codex` and `codex-resources/bwrap` - point the Linux `codex` DotSlash outputs at that bundle tarball - leave the standalone `bwrap` DotSlash output in place for consumers that want to fetch `bwrap` directly ## Verification - `jq . .github/dotslash-config.json` - Ruby YAML parse of `.github/workflows/rust-release.yml`
Termux rust-v0.129.0-alpha.9
…nt/wallentx_termux-target_from_release_0.129.0_b187e52ce92d # Conflicts: # .github/workflows/rust-release.yml # .github/workflows/shell-tool-mcp.yml # codex-rs/Cargo.toml # scripts/termux-create-checkpoint-pr.sh
…t_from_release_0.129.0_b187e52ce92d checkpoint: into wallentx/termux-target from release/0.129.0 @ b187e52
Termux rust-v0.129.0-alpha.10
…nt/wallentx_termux-target_from_release_0.129.0_685f3524f4fe # Conflicts: # .github/workflows/rust-release.yml # .github/workflows/shell-tool-mcp.yml # codex-rs/Cargo.toml # scripts/termux-create-checkpoint-pr.sh
…t_from_release_0.129.0_685f3524f4fe checkpoint: into wallentx/termux-target from release/0.129.0 @ 685f352


Codex CLI currently fails on native Termux/Android due to DNS resolution and unsupported lock semantics in this environment. This PR adds compatibility adjustments that allow:
The changes preserve existing behavior on non-Android platforms.
Changes
DNS/Resolver fixes
$PREFIX/etc/resolv.conf,Graceful handling of unsupported locks
std::io::ErrorKind::Unsupportedfromtry_lock()without failing.Android build target support in CI
To produce and validate builds targeting Android (e.g. native Termux):
aarch64-linux-androidtarget in GitHub Actions.CC, andARfor the Android target.keyringtarget dependencies for Android.This enables CI to build Android artifacts that include the compatibility adjustments above, which aids testing and validation.
Validation
just fmtcargo test