Skip to content

Commit 5c9321b

Browse files
authored
Add --strip option to strip debug symbols from outputs (#286)
* Refactored getting the NDK path and CMake toolchain into functions * Add strip option to cmake-rn * Locate and call NDK strip tool on Android libraries * Add stripping to Apple libraries * Add changeset
1 parent bb9a78c commit 5c9321b

File tree

4 files changed

+83
-26
lines changed

4 files changed

+83
-26
lines changed

.changeset/great-kings-clean.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"cmake-rn": patch
3+
---
4+
5+
Add `--strip` option to strip debug symbols from outputs

packages/cmake-rn/src/cli.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,11 @@ const targetOption = new Option(
106106
"CMake targets to build",
107107
).default([] as string[], "Build all targets of the CMake project");
108108

109+
const stripOption = new Option(
110+
"--strip",
111+
"Strip debug symbols from the final binaries",
112+
).default(false);
113+
109114
const noAutoLinkOption = new Option(
110115
"--no-auto-link",
111116
"Don't mark the output as auto-linkable by react-native-node-api",
@@ -132,6 +137,7 @@ let program = new Command("cmake-rn")
132137
.addOption(defineOption)
133138
.addOption(cleanOption)
134139
.addOption(targetOption)
140+
.addOption(stripOption)
135141
.addOption(noAutoLinkOption)
136142
.addOption(noWeakNodeApiLinkageOption)
137143
.addOption(cmakeJsOption);

packages/cmake-rn/src/platforms/android.ts

Lines changed: 58 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,44 @@ function getBuildPath(baseBuildPath: string, triplet: Triplet) {
4949
return path.join(baseBuildPath, triplet);
5050
}
5151

52+
function getNdkPath(ndkVersion: string) {
53+
const { ANDROID_HOME } = process.env;
54+
assert(typeof ANDROID_HOME === "string", "Missing env variable ANDROID_HOME");
55+
assert(
56+
fs.existsSync(ANDROID_HOME),
57+
`Expected the Android SDK at ${ANDROID_HOME}`,
58+
);
59+
const installNdkCommand = `sdkmanager --install "ndk;${ndkVersion}"`;
60+
const ndkPath = path.resolve(ANDROID_HOME, "ndk", ndkVersion);
61+
assert(
62+
fs.existsSync(ndkPath),
63+
`Missing Android NDK v${ndkVersion} (at ${ndkPath}) - run: ${installNdkCommand}`,
64+
);
65+
return ndkPath;
66+
}
67+
68+
function getNdkToolchainPath(ndkPath: string) {
69+
const toolchainPath = path.join(
70+
ndkPath,
71+
"build/cmake/android.toolchain.cmake",
72+
);
73+
assert(
74+
fs.existsSync(toolchainPath),
75+
`No CMake toolchain found in ${toolchainPath}`,
76+
);
77+
return toolchainPath;
78+
}
79+
80+
function getNdkLlvmBinPath(ndkPath: string) {
81+
const prebuiltPath = path.join(ndkPath, "toolchains/llvm/prebuilt");
82+
const platforms = fs.readdirSync(prebuiltPath);
83+
assert(
84+
platforms.length === 1,
85+
`Expected a single llvm prebuilt toolchain in ${prebuiltPath}`,
86+
);
87+
return path.join(prebuiltPath, platforms[0], "bin");
88+
}
89+
5290
export const platform: Platform<Triplet[], AndroidOpts> = {
5391
id: "android",
5492
name: "Android",
@@ -85,26 +123,8 @@ export const platform: Platform<Triplet[], AndroidOpts> = {
85123
cmakeJs,
86124
},
87125
) {
88-
const { ANDROID_HOME } = process.env;
89-
assert(
90-
typeof ANDROID_HOME === "string",
91-
"Missing env variable ANDROID_HOME",
92-
);
93-
assert(
94-
fs.existsSync(ANDROID_HOME),
95-
`Expected the Android SDK at ${ANDROID_HOME}`,
96-
);
97-
const installNdkCommand = `sdkmanager --install "ndk;${ndkVersion}"`;
98-
const ndkPath = path.resolve(ANDROID_HOME, "ndk", ndkVersion);
99-
assert(
100-
fs.existsSync(ndkPath),
101-
`Missing Android NDK v${ndkVersion} (at ${ndkPath}) - run: ${installNdkCommand}`,
102-
);
103-
104-
const toolchainPath = path.join(
105-
ndkPath,
106-
"build/cmake/android.toolchain.cmake",
107-
);
126+
const ndkPath = getNdkPath(ndkVersion);
127+
const toolchainPath = getNdkToolchainPath(ndkPath);
108128

109129
const commonDefinitions = [
110130
...define,
@@ -174,14 +194,14 @@ export const platform: Platform<Triplet[], AndroidOpts> = {
174194
async postBuild(
175195
outputPath,
176196
triplets,
177-
{ autoLink, configuration, target, build },
197+
{ autoLink, configuration, target, build, strip, ndkVersion },
178198
) {
179199
const prebuilds: Record<
180200
string,
181201
{ triplet: Triplet; libraryPath: string }[]
182202
> = {};
183203

184-
for (const { triplet } of triplets) {
204+
for (const { spawn, triplet } of triplets) {
185205
const buildPath = getBuildPath(build, triplet);
186206
assert(fs.existsSync(buildPath), `Expected a directory at ${buildPath}`);
187207
const targets = await cmakeFileApi.readCurrentTargetsDeep(
@@ -210,9 +230,24 @@ export const platform: Platform<Triplet[], AndroidOpts> = {
210230
if (!(sharedLibrary.name in prebuilds)) {
211231
prebuilds[sharedLibrary.name] = [];
212232
}
233+
const libraryPath = path.join(buildPath, artifact.path);
234+
assert(
235+
fs.existsSync(libraryPath),
236+
`Expected built library at ${libraryPath}`,
237+
);
238+
239+
if (strip) {
240+
const llvmBinPath = getNdkLlvmBinPath(getNdkPath(ndkVersion));
241+
const stripToolPath = path.join(llvmBinPath, `llvm-strip`);
242+
assert(
243+
fs.existsSync(stripToolPath),
244+
`Expected llvm-strip to exist at ${stripToolPath}`,
245+
);
246+
await spawn(stripToolPath, [libraryPath]);
247+
}
213248
prebuilds[sharedLibrary.name].push({
214249
triplet,
215-
libraryPath: path.join(buildPath, artifact.path),
250+
libraryPath,
216251
});
217252
}
218253

packages/cmake-rn/src/platforms/apple.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -330,11 +330,11 @@ export const platform: Platform<Triplet[], AppleOpts> = {
330330
async postBuild(
331331
outputPath,
332332
triplets,
333-
{ configuration, autoLink, xcframeworkExtension, target, build },
333+
{ configuration, autoLink, xcframeworkExtension, target, build, strip },
334334
) {
335335
const libraryNames = new Set<string>();
336336
const frameworkPaths: string[] = [];
337-
for (const { triplet } of triplets) {
337+
for (const { spawn, triplet } of triplets) {
338338
const buildPath = getBuildPath(build, triplet);
339339
assert(fs.existsSync(buildPath), `Expected a directory at ${buildPath}`);
340340
const sharedLibrary = await readCmakeSharedLibraryTarget(
@@ -348,10 +348,21 @@ export const platform: Platform<Triplet[], AppleOpts> = {
348348
"Expected exactly one artifact",
349349
);
350350
const [artifact] = artifacts;
351+
352+
const artifactPath = path.join(buildPath, artifact.path);
353+
354+
if (strip) {
355+
// -r: All relocation entries.
356+
// -S: All symbol table entries.
357+
// -T: All text relocation entries.
358+
// -x: All local symbols.
359+
await spawn("strip", ["-rSTx", artifactPath]);
360+
}
361+
351362
libraryNames.add(sharedLibrary.name);
352363
// Locate the path of the framework, if a free dynamic library was built
353364
if (artifact.path.includes(".framework/")) {
354-
frameworkPaths.push(path.dirname(path.join(buildPath, artifact.path)));
365+
frameworkPaths.push(path.dirname(artifactPath));
355366
} else {
356367
const libraryName = path.basename(
357368
artifact.path,

0 commit comments

Comments
 (0)