Skip to content

Commit 9b3b264

Browse files
kraenhansenclaude
andcommitted
Add a cmake-rn init command (#488)
Scaffolds a package building a CMake Node-API module, or brings an existing one up to what `cmake-rn build` expects, mirroring `ferric init`. - The build moves into a default `build` subcommand, so existing `cmake-rn` invocations keep working. - `--weak-node-api <link|cmake-js|omit>` picks how a new CMakeLists.txt gets Node-API. An existing CMakeLists.txt is inspected against it rather than replaced. - Workspace handling, package.json updates and plan output move from ferric into @react-native-node-api/cli-utils, shared by both init commands. - packages/cmake-rn-example is generated by `pnpm run init-cmake-rn-example`, checked for drift in the Lint job, built by the native CI jobs and loaded by the test app. Closes #483 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U2xSE1YMYWQRnGpnbKVbne
1 parent 673d2c2 commit 9b3b264

51 files changed

Lines changed: 1976 additions & 544 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@react-native-node-api/cli-utils": minor
3+
---
4+
5+
Add the helpers shared by the `ferric init` and `cmake-rn init` commands: planning file changes, updating a `package.json` without overwriting what it declares, printing diffs, and adding a package to a pnpm, npm or yarn workspace.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
"cmake-rn": minor
3+
---
4+
5+
Add a `cmake-rn init [path]` command, scaffolding a package building a CMake Node-API module.
6+
7+
It writes the `package.json`, `CMakeLists.txt`, `src/addon.c`, a JavaScript entrypoint with its TypeScript declarations and `.gitignore` a package needs, and adds it to the workspace of the mono-repo it is initialized into. Run against a package that already exists, it bumps outdated dependencies, and inspects an existing `CMakeLists.txt` instead of replacing it, pointing out when it doesn't define or link the `weak-node-api` target. `--weak-node-api <link|cmake-js|omit>` picks how a new `CMakeLists.txt` gets Node-API: linking the `weak-node-api` target (the default), through the cmake-js variables so it also builds with cmake-js, or not at all. A differing entrypoint or source file is skipped with a diff to merge by hand, unless `--force` is passed. `--dry-run` prints all of this without writing anything.
8+
9+
The build is now the default `build` subcommand, so `cmake-rn` invocations keep working as before, and its options are listed by `cmake-rn build --help`.

‎.github/workflows/check.yml‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,12 @@ jobs:
8181
git status --porcelain packages/ferric-example
8282
git diff --exit-code packages/ferric-example
8383
test -z "$(git status --porcelain packages/ferric-example)"
84+
- run: pnpm run init-cmake-rn-example
85+
- name: Verify cmake-rn-example matches what cmake-rn init generates
86+
run: |
87+
git status --porcelain packages/cmake-rn-example
88+
git diff --exit-code packages/cmake-rn-example
89+
test -z "$(git status --porcelain packages/cmake-rn-example)"
8490
- run: pnpm run lint
8591
env:
8692
DEBUG: eslint:eslint

‎README.md‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,3 +75,7 @@ A test app using `react-native-test-app` to exercise the implementation of it al
7575
### [`@react-native-node-api/ferric-example`](packages/ferric-example)
7676

7777
A simple example of using the `ferric` CLI to build a Node-API module for React Native in Rust.
78+
79+
### [`@react-native-node-api/cmake-rn-example`](packages/cmake-rn-example)
80+
81+
A simple example of using the `cmake-rn` CLI to build a Node-API module for React Native in C, generated by `cmake-rn init`.

‎apps/test-app/App.tsx‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,15 @@ type Context = {
2424
nodeAddonExamples?: boolean;
2525
nodeTests?: boolean;
2626
ferricExample?: boolean;
27+
cmakeRnExample?: boolean;
2728
};
2829

2930
function loadTests({
3031
allTests = false,
3132
nodeAddonExamples = allTests,
3233
nodeTests = allTests,
3334
ferricExample = allTests,
35+
cmakeRnExample = allTests,
3436
}: Context) {
3537
describeIf(nodeAddonExamples, "Node Addon Examples", () => {
3638
for (const [suiteName, examples] of Object.entries(
@@ -85,6 +87,18 @@ function loadTests({
8587
}
8688
});
8789
});
90+
91+
describeIf(cmakeRnExample, "cmake-rn-example", () => {
92+
it("exports a callable sum function", () => {
93+
const exampleAddon =
94+
/* eslint-disable-next-line @typescript-eslint/no-require-imports -- TODO: Determine why a dynamic import doesn't work on Android */
95+
require("@react-native-node-api/cmake-rn-example") as typeof import("@react-native-node-api/cmake-rn-example");
96+
const result = exampleAddon.sum(1, 3);
97+
if (result !== 4) {
98+
throw new Error(`Expected 1 + 3 to equal 4, but got ${result}`);
99+
}
100+
});
101+
});
88102
}
89103

90104
export default function App() {

‎apps/test-app/package.json‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,13 @@
1515
"test:android:nodeAddonExamples": "MOCHA_REMOTE_CONTEXT=nodeAddonExamples node --run test:android -- ",
1616
"test:android:nodeTests": "MOCHA_REMOTE_CONTEXT=nodeTests node --run test:android -- ",
1717
"test:android:ferricExample": "MOCHA_REMOTE_CONTEXT=ferricExample node --run test:android -- ",
18+
"test:android:cmakeRnExample": "MOCHA_REMOTE_CONTEXT=cmakeRnExample node --run test:android -- ",
1819
"test:ios": "mocha-remote --exit-on-error -- concurrently --passthrough-arguments --kill-others-on-fail npm:metro 'npm:ios -- {@}' --",
1920
"test:ios:allTests": "MOCHA_REMOTE_CONTEXT=allTests node --run test:ios -- ",
2021
"test:ios:nodeAddonExamples": "MOCHA_REMOTE_CONTEXT=nodeAddonExamples node --run test:ios -- ",
2122
"test:ios:nodeTests": "MOCHA_REMOTE_CONTEXT=nodeTests node --run test:ios -- ",
22-
"test:ios:ferricExample": "MOCHA_REMOTE_CONTEXT=ferricExample node --run test:ios -- "
23+
"test:ios:ferricExample": "MOCHA_REMOTE_CONTEXT=ferricExample node --run test:ios -- ",
24+
"test:ios:cmakeRnExample": "MOCHA_REMOTE_CONTEXT=cmakeRnExample node --run test:ios -- "
2325
},
2426
"dependencies": {
2527
"@babel/core": "^7.26.10",
@@ -28,6 +30,7 @@
2830
"@react-native-community/cli": "^20.0.2",
2931
"@react-native-community/cli-platform-android": "^20.0.2",
3032
"@react-native-community/cli-platform-ios": "^20.0.2",
33+
"@react-native-node-api/cmake-rn-example": "workspace:*",
3134
"@react-native-node-api/ferric-example": "workspace:*",
3235
"@react-native-node-api/node-addon-examples": "workspace:*",
3336
"@react-native-node-api/node-tests": "workspace:*",

‎docs/USAGE.md‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ We will be implementing this `add` function.
3939

4040
## Steps needed for the author of the `calculator-lib` library
4141

42+
> [!TIP]
43+
> Run `npx cmake-rn init` (or `npx ferric init` for Rust) to scaffold a package with the steps below already taken care of, or to bring an existing package up to date.
44+
4245
### Install `react-native-node-api` as a dev-dependency and declare a peer dependency
4346

4447
```bash

‎eslint.config.js‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ export default tseslint.config(
1818
"packages/ferric-example/ferric_example.js",
1919
"packages/ferric-example/ferric_example.d.ts",
2020
"packages/ferric-example/target/**",
21+
"packages/cmake-rn-example/cmake-rn-example.js",
22+
"packages/cmake-rn-example/cmake-rn-example.d.ts",
2123
"packages/node-tests/node/**",
2224
"packages/node-tests/tests/**",
2325
"packages/node-tests/*.generated.js",

‎package.json‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,14 @@
1414
"publint": "node scripts/run-in-published.ts pnpm exec publint --strict",
1515
"prettier:check": "prettier --experimental-cli --check .",
1616
"prettier:write": "prettier --experimental-cli --write .",
17-
"test": "pnpm --filter react-native-node-api --filter cmake-rn --filter gyp-to-cmake --filter ferric-cli run test",
17+
"test": "pnpm --filter @react-native-node-api/cli-utils --filter react-native-node-api --filter cmake-rn --filter gyp-to-cmake --filter ferric-cli run test",
1818
"bootstrap": "node --run build && pnpm --recursive run bootstrap",
1919
"changeset": "changeset",
2020
"release": "node --run prerelease && changeset publish",
2121
"prerelease": "node --run build && pnpm --recursive run prerelease && node --run publint",
2222
"init-macos-test-app": "node scripts/init-macos-test-app.ts",
23-
"init-ferric-example": "node scripts/init-ferric-example.ts"
23+
"init-ferric-example": "node scripts/init-ferric-example.ts",
24+
"init-cmake-rn-example": "node scripts/init-cmake-rn-example.ts"
2425
},
2526
"author": {
2627
"name": "Callstack",

‎packages/cli-utils/package.json‎

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,29 @@
99
},
1010
"type": "module",
1111
"files": [
12-
"dist"
12+
"dist",
13+
"!dist/**/*.test.d.ts",
14+
"!dist/**/*.test.d.ts.map"
1315
],
1416
"exports": {
1517
".": "./dist/index.js"
1618
},
19+
"scripts": {
20+
"test": "tsx --test --test-reporter=@reporters/github --test-reporter-destination=stdout --test-reporter=spec --test-reporter-destination=stdout"
21+
},
1722
"dependencies": {
1823
"@commander-js/extra-typings": "^14.0.0",
1924
"bufout": "^1.0.0",
2025
"chalk": "^5.4.1",
2126
"commander": "^14.0.1",
27+
"diff": "^9.0.0",
2228
"ora": "^8.2.0",
23-
"p-limit": "^7.2.0"
29+
"p-limit": "^7.2.0",
30+
"picomatch": "^4.0.5",
31+
"semver": "^7.8.5"
32+
},
33+
"devDependencies": {
34+
"@types/picomatch": "^4.0.3",
35+
"@types/semver": "^7.8.0"
2436
}
2537
}

0 commit comments

Comments
 (0)