Skip to content

Commit c287e88

Browse files
author
Muhammad Ahmad
committed
Read the native library out of the app bundle, not a stale APK
`react-native build-android` runs bundleDebug and writes outputs/bundle/debug/app-debug.aab. There is no outputs/apk/debug directory at all, so the alignment step's `find` failed before it reached any ELF, on both the original version and the rewrite. It passed locally only because an APK from an earlier `run-android` was still lying in the build directory — the check was reading an artifact that CI never produces. The step now takes whichever artifact exists, and the checker accepts a directory and fails when it contains no .so files, so "nothing was checked" can no longer read as "everything checked out". Verified against the real bundle, a multi-ABI APK, an empty directory, a library patched to 0x1000, and no arguments.
1 parent e7e7186 commit c287e88

2 files changed

Lines changed: 50 additions & 11 deletions

File tree

‎.github/workflows/ci.yml‎

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -114,16 +114,21 @@ jobs:
114114
run: pnpm build:android
115115

116116
# Google Play requires 16 KB page-size support for apps targeting Android
117-
# 15+. Our own native library is the one we can guarantee, so assert it
118-
# rather than trusting whichever NDK the runner happens to have.
117+
# 15+. `react-native build-android` produces an app bundle, so the library
118+
# is read out of the .aab — an .apk is accepted too, for when that command
119+
# changes or someone runs this against a locally assembled build.
119120
- name: Native library is 16 KB aligned
120121
run: |
121122
set -euo pipefail
122-
APK=$(find example/android/app/build/outputs/apk/debug -name '*.apk' -print -quit)
123-
echo "APK: $APK"
124-
rm -rf "${RUNNER_TEMP}/apkcheck"
125-
unzip -o -q "$APK" 'lib/*/librnsecuritytoolkit.so' -d "${RUNNER_TEMP}/apkcheck"
126-
node scripts/check-elf-alignment.mjs "${RUNNER_TEMP}"/apkcheck/lib/*/librnsecuritytoolkit.so
123+
ARTIFACT=$(find example/android/app/build/outputs \( -name '*.aab' -o -name '*.apk' \) -print -quit)
124+
if [ -z "$ARTIFACT" ]; then
125+
echo "no .aab or .apk under example/android/app/build/outputs"
126+
exit 1
127+
fi
128+
echo "artifact: $ARTIFACT"
129+
rm -rf "${RUNNER_TEMP}/nativecheck"
130+
unzip -o -q "$ARTIFACT" '*librnsecuritytoolkit.so' -d "${RUNNER_TEMP}/nativecheck"
131+
node scripts/check-elf-alignment.mjs "${RUNNER_TEMP}/nativecheck"
127132
128133
build-ios:
129134
name: Build iOS

‎scripts/check-elf-alignment.mjs‎

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,15 @@
1414
* 32-bit ABIs are reported but not enforced: the 16 KB page size applies to
1515
* 64-bit devices.
1616
*
17-
* Usage: node scripts/check-elf-alignment.mjs <file.so> [...]
17+
* A directory argument is walked for `.so` files, and finding none is a
18+
* failure rather than a silent pass — "nothing was checked" and "everything
19+
* checked out" must not look alike in a CI log.
20+
*
21+
* Usage: node scripts/check-elf-alignment.mjs <file.so | directory> [...]
1822
*/
1923

2024
import fs from 'node:fs/promises';
25+
import path from 'node:path';
2126
import process from 'node:process';
2227

2328
const REQUIRED_ALIGNMENT = 16 * 1024;
@@ -56,14 +61,43 @@ function loadSegmentAlignments(buffer) {
5661
return { is64Bit, alignments };
5762
}
5863

64+
/** Expands directory arguments into the `.so` files they contain. */
65+
async function collectLibraries(targets) {
66+
const files = [];
67+
68+
for (const target of targets) {
69+
const stats = await fs.stat(target);
70+
if (!stats.isDirectory()) {
71+
files.push(target);
72+
continue;
73+
}
74+
for (const entry of await fs.readdir(target, { recursive: true, withFileTypes: true })) {
75+
if (entry.isFile() && entry.name.endsWith('.so')) {
76+
files.push(path.join(entry.parentPath ?? entry.path, entry.name));
77+
}
78+
}
79+
}
80+
81+
return files.sort();
82+
}
83+
5984
async function main() {
60-
const files = process.argv.slice(2);
61-
if (files.length === 0) {
62-
process.stderr.write('usage: node scripts/check-elf-alignment.mjs <file.so> [...]\n');
85+
const targets = process.argv.slice(2);
86+
if (targets.length === 0) {
87+
process.stderr.write(
88+
'usage: node scripts/check-elf-alignment.mjs <file.so | directory> [...]\n'
89+
);
6390
process.exitCode = 2;
6491
return;
6592
}
6693

94+
const files = await collectLibraries(targets);
95+
if (files.length === 0) {
96+
process.stdout.write(` FAIL no .so files found in: ${targets.join(', ')}\n`);
97+
process.exitCode = 1;
98+
return;
99+
}
100+
67101
let failures = 0;
68102

69103
for (const file of files) {

0 commit comments

Comments
 (0)