Skip to content

Commit 38b9113

Browse files
committed
Make injection of CMAKE_JS_* variables opt-in and provide our own explicit way of linking with Node-API
1 parent 6c98a22 commit 38b9113

File tree

4 files changed

+70
-14
lines changed

4 files changed

+70
-14
lines changed

.changeset/open-ducks-shop.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"cmake-rn": minor
3+
---
4+
5+
Breaking: CMAKE*JS*\* defines are no longer injected by default (use --cmake-js to opt-in)

packages/cmake-rn/README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,24 @@
33
A wrapper around Cmake making it easier to produce prebuilt binaries targeting iOS and Android matching [the prebuilt binary specification](https://github.com/callstackincubator/react-native-node-api/blob/main/docs/PREBUILDS.md).
44

55
Serves the same purpose as `cmake-js` does for the Node.js community and could potentially be upstreamed into `cmake-js` eventually.
6+
7+
## Linking against Node-API
8+
9+
Android's dynamic linker impose restrictions on the access to global symbols (such as the Node-API free functions): A dynamic library must explicitly declare any dependency bringing symbols it needs as `DT_NEEDED`.
10+
11+
The implementation of Node-API is split between Hermes and our host package and to avoid addons having to explicitly link against either, we've introduced a `weak-node-api` library (published in `react-native-node-api` package). This library expose only Node-API and will have it's implementation injected by the host.
12+
13+
To link against `weak-node-api` just include the CMake config exposed through `WEAK_NODE_API_CONFIG` and add `weak-node-api` to the `target_link_libraries` of the addon's library target.
14+
15+
```cmake
16+
cmake_minimum_required(VERSION 3.15...3.31)
17+
project(tests-buffers)
18+
19+
include(${WEAK_NODE_API_CONFIG})
20+
21+
add_library(addon SHARED addon.c)
22+
target_link_libraries(addon PRIVATE weak-node-api)
23+
target_compile_features(addon PRIVATE cxx_std_20)
24+
```
25+
26+
This is different from how `cmake-js` "injects" the Node-API for linking (via `${CMAKE_JS_INC}`, `${CMAKE_JS_SRC}` and `${CMAKE_JS_LIB}`). To allow for interoperability between these tools, we inject these when you pass `--cmake-js` to `cmake-rn`.

packages/cmake-rn/src/cli.ts

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ import {
1414
} from "@react-native-node-api/cli-utils";
1515
import { isSupportedTriplet } from "react-native-node-api";
1616

17-
import { getWeakNodeApiVariables } from "./weak-node-api.js";
17+
import {
18+
getCmakeJSVariables,
19+
getWeakNodeApiVariables,
20+
} from "./weak-node-api.js";
1821
import {
1922
platforms,
2023
allTriplets as allTriplets,
@@ -117,6 +120,11 @@ const noWeakNodeApiLinkageOption = new Option(
117120
"Don't pass the path of the weak-node-api library from react-native-node-api",
118121
);
119122

123+
const cmakeJsOption = new Option(
124+
"--cmake-js",
125+
"Define CMAKE_JS_* variables used for compatibility with cmake-js",
126+
).default(false);
127+
120128
let program = new Command("cmake-rn")
121129
.description("Build React Native Node API modules with CMake")
122130
.addOption(tripletOption)
@@ -129,7 +137,8 @@ let program = new Command("cmake-rn")
129137
.addOption(cleanOption)
130138
.addOption(targetOption)
131139
.addOption(noAutoLinkOption)
132-
.addOption(noWeakNodeApiLinkageOption);
140+
.addOption(noWeakNodeApiLinkageOption)
141+
.addOption(cmakeJsOption);
133142

134143
for (const platform of platforms) {
135144
const allOption = new Option(
@@ -296,16 +305,23 @@ async function configureProject<T extends string>(
296305
options: BaseOpts,
297306
) {
298307
const { triplet, buildPath, outputPath } = context;
299-
const { verbose, source, weakNodeApiLinkage } = options;
308+
const { verbose, source, weakNodeApiLinkage, cmakeJs } = options;
309+
310+
// TODO: Make the two following definitions a part of the platform definition
300311

301312
const nodeApiDefinitions =
302313
weakNodeApiLinkage && isSupportedTriplet(triplet)
303-
? getWeakNodeApiVariables(triplet)
304-
: // TODO: Make this a part of the platform definition
305-
[];
314+
? [getWeakNodeApiVariables(triplet)]
315+
: [];
316+
317+
const cmakeJsDefinitions =
318+
cmakeJs && isSupportedTriplet(triplet)
319+
? [getCmakeJSVariables(triplet)]
320+
: [];
306321

307322
const definitions = [
308323
...nodeApiDefinitions,
324+
...cmakeJsDefinitions,
309325
...options.define,
310326
{ CMAKE_LIBRARY_OUTPUT_DIRECTORY: outputPath },
311327
];

packages/cmake-rn/src/weak-node-api.ts

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,22 +41,36 @@ export function getWeakNodeApiPath(triplet: SupportedTriplet): string {
4141
}
4242
}
4343

44-
export function getWeakNodeApiVariables(triplet: SupportedTriplet) {
44+
function getNodeApiIncludePaths() {
4545
const includePaths = [getNodeApiHeadersPath(), getNodeAddonHeadersPath()];
4646
for (const includePath of includePaths) {
4747
assert(
4848
!includePath.includes(";"),
4949
`Include path with a ';' is not supported: ${includePath}`,
5050
);
5151
}
52-
const cmakeConfigPath = path.join(weakNodeApiPath, "weak-node-api.cmake");
53-
const libraryPath = getWeakNodeApiPath(triplet);
52+
return includePaths;
53+
}
54+
55+
export function getWeakNodeApiVariables(
56+
triplet: SupportedTriplet,
57+
): Record<string, string> {
5458
return {
5559
// Expose an includable CMake config file declaring the weak-node-api target
56-
WEAK_NODE_API_CONFIG: cmakeConfigPath,
57-
WEAK_NODE_API_LIB: libraryPath,
58-
// For compatibility with cmake-js
59-
CMAKE_JS_INC: includePaths.join(";"),
60-
CMAKE_JS_LIB: libraryPath,
60+
WEAK_NODE_API_CONFIG: path.join(weakNodeApiPath, "weak-node-api.cmake"),
61+
WEAK_NODE_API_INC: getNodeApiIncludePaths().join(";"),
62+
WEAK_NODE_API_LIB: getWeakNodeApiPath(triplet),
63+
};
64+
}
65+
66+
/**
67+
* For compatibility with cmake-js
68+
*/
69+
export function getCmakeJSVariables(
70+
triplet: SupportedTriplet,
71+
): Record<string, string> {
72+
return {
73+
CMAKE_JS_INC: getNodeApiIncludePaths().join(";"),
74+
CMAKE_JS_LIB: getWeakNodeApiPath(triplet),
6175
};
6276
}

0 commit comments

Comments
 (0)