Skip to content

Commit 2d4648e

Browse files
committed
Build every binding against the repository's core; drop cxx_impl
The Flutter, Rust and C# bindings each embedded core as a cxx_impl submodule, so a core change meant moving three extra pointers. They now build the repository's core/ directly: the Rust build.rs, the Flutter plugin's CMake (resolving Flutter's .plugin_symlinks first) and the C# native CMake point at it, and the Apple source wrappers, umbrella headers and ffigen.yaml are regenerated with core-relative paths. codegen sync no longer has anything to move per binding. Published packages still need core's sources inside them. The release workflows copy core into cxx_impl/ (never committed); build.rs and the plugin CMake prefer that copy when present, and the Flutter workflow points the Apple wrappers at it with `codegen.py --core-dir ... --sources-only` in a local commit that is not pushed, since `dart pub publish` warns about modified checked-in files. CI checks out only core and also runs when the core pointer moves.
1 parent da9d941 commit 2d4648e

200 files changed

Lines changed: 617 additions & 659 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.agents/skills/core-api-change/SKILL.md‎

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@ description: Carry a change to the C++ public API in core/ all the way downstrea
55

66
# core-api-change
77

8-
`./codegen sync` does the mechanical half: regenerate, bump each binding's embedded core,
9-
rerun bindgen / ffigen, commit core and the workspace. This skill is the other half — the decisions
8+
`./codegen sync` does the mechanical half: regenerate, rerun bindgen / ffigen, commit core and the workspace. This skill is the other half — the decisions
109
and checks the script cannot make. Work through the phases in order; each one ends in
1110
something you can verify before moving on.
1211

@@ -140,18 +139,16 @@ skill rather than trusting the compile.
140139
```
141140

142141
It commits core with your message, then the workspace as `Sync with core <sha9>`: the
143-
core pointer plus everything regenerated under `bindings/` and each binding's `cxx_impl`
144-
gitlink. It does not push.
142+
core pointer plus everything regenerated under `bindings/`. The bindings build against
143+
`core/` directly, so there is no per-binding copy of core to move. It does not push.
145144

146145
**A binding has unrelated work — manual path.** Same steps, staged narrowly:
147146

148147
1. Commit core yourself (`git -C core add <paths> && git -C core commit -m ...`).
149-
2. In each binding: update the embedded core submodule (`cxx_impl`) to that sha,
150-
fetching from the local `core/`; rust → rerun bindgen (command in
151-
`tools/codegen/README.md`); flutter → `python3 codegen.py --no-submodule-update` in
152-
`bindings/flutter/cnativeapi`.
153-
3. Workspace: `git add core` plus only the generated paths and the `cxx_impl` gitlinks
154-
under `bindings/`; commit as `Sync with core <sha9>`.
148+
2. `./codegen`; rust → rerun bindgen (command in `tools/codegen/README.md`); flutter →
149+
`python3 codegen.py` in `bindings/flutter/cnativeapi`.
150+
3. Workspace: `git add core` plus only the generated paths under `bindings/`; commit as
151+
`Sync with core <sha9>`.
155152

156153
Either way: no Co-Authored-By trailers; after staging, read `git status --short` and
157154
`git diff --cached --stat` in each repo **before** committing — a file you did not write

‎.agents/skills/record-demo/SKILL.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ saved video or an `ERROR`.
8585
optional: the test laptop's scoop was broken (self-update fails, the 7zip dependency
8686
would not install), and winget asks to accept agreements.
8787
- The apps must already be built there in debug (see `remote-hosts`), from the checkout
88-
you mean to show — check that submodules such as the Flutter binding's `cxx_impl` are
88+
you mean to show — check that the `core` submodule is
8989
actually checked out at the recorded commit (`git submodule update`), not just
9090
pointed at it.
9191
- **The whole screen is in the picture.** Before recording, look at the desktop

‎.agents/skills/remote-hosts/references/windows.md‎

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,8 @@ $ErrorActionPreference = "Stop"
4545

4646
- Same layout as here (`core/`, `bindings/*` on `main`). Get changes there with
4747
`git pull` in each repo — but **GitHub over HTTPS is flaky from that network**.
48-
For unpushed or unreachable commits, fetch between local checkouts instead (for the
49-
Flutter binding's nested core: `git -C …\cxx_impl fetch $RemoteWorkspace\core main`),
50-
or `scp` a patch / the changed files.
48+
For unpushed or unreachable commits, fetch between local checkouts instead
49+
(`git -C …\core fetch <another checkout> main`), or `scp` a patch / the changed files.
5150
- Tooling: VS 2022 (generator `"Visual Studio 17 2022" -A x64`; there is no ninja),
5251
CMake, Python 3, Flutter via fvm. The `fvm\default` junction does not resolve over
5352
SSH — point `HOST_PATH_PREPEND` at a concrete `fvm\versions\<channel>\bin`. The
@@ -63,8 +62,8 @@ $ErrorActionPreference = "Stop"
6362
- `core.autocrlf` makes `git status` noisy and `flutter pub get` rewrites
6463
`analysis_options.yaml` files. Judge real changes with
6564
`git diff --ignore-cr-at-eol --stat`.
66-
- **Leave it as you found it.** Record `git status --short` for the workspace,
67-
`core` and `bindings/flutter/cnativeapi/cxx_impl` *before* you start; at the end
65+
- **Leave it as you found it.** Record `git status --short` for the workspace
66+
and `core` *before* you start; at the end
6867
`git checkout --` only the files you touched and compare. Pre-existing local
6968
changes on that machine are the user's — do not revert them.
7069

‎.github/workflows/csharp-ci.yml‎

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@ on:
55
branches: [main]
66
paths:
77
- "bindings/csharp/**"
8+
- "core"
89
- "examples/csharp_*/**"
910
- ".github/workflows/csharp-ci.yml"
1011
pull_request:
1112
branches: [main]
1213
paths:
1314
- "bindings/csharp/**"
15+
- "core"
1416
- "examples/csharp_*/**"
1517
- ".github/workflows/csharp-ci.yml"
1618
workflow_dispatch:
@@ -37,9 +39,9 @@ jobs:
3739
timeout-minutes: 15
3840
steps:
3941
- uses: actions/checkout@v4
40-
- name: Checkout C# binding submodules
42+
- name: Checkout core
4143
working-directory: .
42-
run: git submodule update --init --recursive -- bindings/csharp
44+
run: git submodule update --init core
4345
- uses: actions/setup-dotnet@v4
4446
with:
4547
dotnet-version: |
@@ -67,9 +69,9 @@ jobs:
6769
library: build/native/Release/nativeapi.dll
6870
steps:
6971
- uses: actions/checkout@v4
70-
- name: Checkout C# binding submodules
72+
- name: Checkout core
7173
working-directory: .
72-
run: git submodule update --init --recursive -- bindings/csharp
74+
run: git submodule update --init core
7375
- uses: actions/setup-dotnet@v4
7476
with:
7577
dotnet-version: |

‎.github/workflows/flutter-ci.yml‎

Lines changed: 16 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@ on:
55
branches: [ main, ohos-main ]
66
paths:
77
- "bindings/flutter/**"
8+
- "core"
89
- "examples/flutter_*/**"
910
- "pubspec.yaml"
1011
- ".github/workflows/flutter-ci.yml"
1112
pull_request:
1213
branches: [ main, ohos-main ]
1314
paths:
1415
- "bindings/flutter/**"
16+
- "core"
1517
- "examples/flutter_*/**"
1618
- "pubspec.yaml"
1719
- ".github/workflows/flutter-ci.yml"
@@ -25,10 +27,8 @@ jobs:
2527
- name: Checkout repository
2628
uses: actions/checkout@v4
2729

28-
# Only the Flutter binding's submodules: the root ones (core, other
29-
# bindings) are not needed here and some use SSH URLs.
30-
- name: Checkout Flutter submodules
31-
run: git submodule update --init --recursive -- bindings/flutter
30+
- name: Checkout core
31+
run: git submodule update --init core
3232

3333
- name: Setup Flutter
3434
uses: subosito/flutter-action@v2
@@ -67,10 +67,8 @@ jobs:
6767
- name: Checkout repository
6868
uses: actions/checkout@v4
6969

70-
# Only the Flutter binding's submodules: the root ones (core, other
71-
# bindings) are not needed here and some use SSH URLs.
72-
- name: Checkout Flutter submodules
73-
run: git submodule update --init --recursive -- bindings/flutter
70+
- name: Checkout core
71+
run: git submodule update --init core
7472

7573
- name: Setup Flutter
7674
uses: subosito/flutter-action@v2
@@ -110,10 +108,8 @@ jobs:
110108
- name: Checkout repository
111109
uses: actions/checkout@v4
112110

113-
# Only the Flutter binding's submodules: the root ones (core, other
114-
# bindings) are not needed here and some use SSH URLs.
115-
- name: Checkout Flutter submodules
116-
run: git submodule update --init --recursive -- bindings/flutter
111+
- name: Checkout core
112+
run: git submodule update --init core
117113

118114
- name: Setup Flutter
119115
uses: subosito/flutter-action@v2
@@ -157,10 +153,8 @@ jobs:
157153
- name: Checkout repository
158154
uses: actions/checkout@v4
159155

160-
# Only the Flutter binding's submodules: the root ones (core, other
161-
# bindings) are not needed here and some use SSH URLs.
162-
- name: Checkout Flutter submodules
163-
run: git submodule update --init --recursive -- bindings/flutter
156+
- name: Checkout core
157+
run: git submodule update --init core
164158

165159
- name: Setup Flutter
166160
uses: subosito/flutter-action@v2
@@ -198,10 +192,8 @@ jobs:
198192
- name: Checkout repository
199193
uses: actions/checkout@v4
200194

201-
# Only the Flutter binding's submodules: the root ones (core, other
202-
# bindings) are not needed here and some use SSH URLs.
203-
- name: Checkout Flutter submodules
204-
run: git submodule update --init --recursive -- bindings/flutter
195+
- name: Checkout core
196+
run: git submodule update --init core
205197

206198
- name: Setup Flutter
207199
uses: subosito/flutter-action@v2
@@ -253,10 +245,8 @@ jobs:
253245
- name: Checkout repository
254246
uses: actions/checkout@v4
255247

256-
# Only the Flutter binding's submodules: the root ones (core, other
257-
# bindings) are not needed here and some use SSH URLs.
258-
- name: Checkout Flutter submodules
259-
run: git submodule update --init --recursive -- bindings/flutter
248+
- name: Checkout core
249+
run: git submodule update --init core
260250

261251
- name: Setup Flutter
262252
uses: subosito/flutter-action@v2
@@ -294,10 +284,8 @@ jobs:
294284
- name: Checkout repository
295285
uses: actions/checkout@v4
296286

297-
# Only the Flutter binding's submodules: the root ones (core, other
298-
# bindings) are not needed here and some use SSH URLs.
299-
- name: Checkout Flutter submodules
300-
run: git submodule update --init --recursive -- bindings/flutter
287+
- name: Checkout core
288+
run: git submodule update --init core
301289

302290
- name: Setup Flutter
303291
uses: subosito/flutter-action@v2

‎.github/workflows/flutter-publish.yml‎

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ jobs:
1616
steps:
1717
- uses: actions/checkout@v4
1818

19-
- name: Checkout Flutter submodules
20-
run: git submodule update --init --recursive -- bindings/flutter
19+
- name: Checkout core
20+
run: git submodule update --init core
2121

2222
# Set up the Dart SDK and provision the OIDC token used for publishing.
2323
- uses: dart-lang/setup-dart@65eb853c7ba17dde3be364c3d2858773e7144260
@@ -29,6 +29,18 @@ jobs:
2929
channel: stable
3030
version: 3.47.5
3131

32+
# The cnativeapi package must carry core's sources: copy them into
33+
# cxx_impl/ (untracked; the CMake build prefers it when present) and point
34+
# the Apple source wrappers there. The rewritten wrappers go into a local
35+
# commit that is never pushed, because `dart pub publish` warns about
36+
# modified checked-in files.
37+
- name: Vendor core into cnativeapi
38+
run: |
39+
mkdir bindings/flutter/cnativeapi/cxx_impl
40+
git -C core archive HEAD | tar -x -C bindings/flutter/cnativeapi/cxx_impl
41+
python3 bindings/flutter/cnativeapi/codegen.py --core-dir bindings/flutter/cnativeapi/cxx_impl --sources-only
42+
git -c user.name=release -c user.email=release@localhost commit -qam "Point cnativeapi at its vendored core (not pushed)"
43+
3244
# Publish cnativeapi
3345
- name: Install dependencies (cnativeapi)
3446
run: dart pub get

‎.github/workflows/rust-ci.yml‎

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ on:
55
branches: [main]
66
paths:
77
- "bindings/rust/**"
8+
- "core"
89
- "examples/rust_*/**"
910
- "Cargo.toml"
1011
- "Cargo.lock"
@@ -13,6 +14,7 @@ on:
1314
branches: [main]
1415
paths:
1516
- "bindings/rust/**"
17+
- "core"
1618
- "examples/rust_*/**"
1719
- "Cargo.toml"
1820
- "Cargo.lock"
@@ -36,8 +38,8 @@ jobs:
3638
timeout-minutes: 20
3739
steps:
3840
- uses: actions/checkout@v4
39-
- name: Checkout Rust binding submodules
40-
run: git submodule update --init --recursive -- bindings/rust
41+
- name: Checkout core
42+
run: git submodule update --init core
4143
- uses: dtolnay/rust-toolchain@stable
4244
with:
4345
components: rustfmt, clippy
@@ -59,8 +61,8 @@ jobs:
5961
os: [ubuntu-latest, macos-latest, windows-latest]
6062
steps:
6163
- uses: actions/checkout@v4
62-
- name: Checkout Rust binding submodules
63-
run: git submodule update --init --recursive -- bindings/rust
64+
- name: Checkout core
65+
run: git submodule update --init core
6466
- uses: dtolnay/rust-toolchain@stable
6567
- name: Install Linux dependencies
6668
if: runner.os == 'Linux'

‎.github/workflows/rust-release.yml‎

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ jobs:
2222
contents: write
2323
steps:
2424
- uses: actions/checkout@v4
25-
- name: Checkout Rust binding submodules
26-
run: git submodule update --init --recursive -- bindings/rust
25+
- name: Checkout core
26+
run: git submodule update --init core
2727
- uses: dtolnay/rust-toolchain@stable
2828
- uses: actions/setup-python@v5
2929
with:
@@ -47,15 +47,22 @@ jobs:
4747
- uses: Swatinem/rust-cache@v2
4848
- name: Test release sources
4949
run: cargo test --workspace --release --locked
50+
# A published crate cannot reach the repository's core/, so cnativeapi
51+
# carries a copy in cxx_impl/ (build.rs prefers it when present). It is
52+
# untracked, hence --allow-dirty for that crate.
53+
- name: Vendor core into cnativeapi
54+
run: |
55+
mkdir bindings/rust/cnativeapi/cxx_impl
56+
git -C core archive HEAD | tar -x -C bindings/rust/cnativeapi/cxx_impl
5057
- name: Verify packaged native sources build outside the checkout
51-
run: cargo package -p cnativeapi --locked
58+
run: cargo package -p cnativeapi --locked --allow-dirty
5259
- name: Publish crates in dependency order
5360
if: github.event_name == 'push' && github.ref_type == 'tag'
5461
env:
5562
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
5663
run: |
5764
test -n "$CARGO_REGISTRY_TOKEN"
58-
cargo publish -p cnativeapi --locked
65+
cargo publish -p cnativeapi --locked --allow-dirty
5966
cargo publish -p nativeapi --locked
6067
- uses: actions/upload-artifact@v4
6168
with:

‎.gitmodules‎

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,3 @@
22
path = core
33
url = ../nativeapi-core.git
44
branch = main
5-
[submodule "packages/cnativeapi/cxx_impl"]
6-
path = bindings/flutter/cnativeapi/cxx_impl
7-
url = https://github.com/libnativeapi/nativeapi-core.git
8-
[submodule "crates/cnativeapi/cxx_impl"]
9-
path = bindings/rust/cnativeapi/cxx_impl
10-
url = https://github.com/libnativeapi/nativeapi-core.git
11-
[submodule "cxx_impl"]
12-
path = bindings/csharp/src/CNativeAPI/cxx_impl
13-
url = https://github.com/libnativeapi/nativeapi-core.git

‎AGENTS.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ codegen # Python entry point orchestrating the generators
2424

2525
- `core` — the C++ core library (repo: `nativeapi-core`). The source of truth for the native API surface (windows, tray icons, menus, displays, keyboard, dialogs, storage, etc.) with per-platform implementations (macOS/Windows/Linux).
2626
- `tools/codegen` — three crates: `shared` (libclang parser, IR, naming), `capi` (C ABI + umbrella header), `bindings` (Rust/Dart/C# generators, consuming the IR JSON emitted by `capi`). Only `capi` depends on libclang. See tools/codegen/README.md.
27-
- `bindings/*` — language bindings wrapping the core library. All live in this repo. Each embeds the core repo as a submodule (`cxx_impl`) so its packages build standalone. The Rust binding layers `crates/nativeapi` (safe API) over `crates/cnativeapi` (FFI).
27+
- `bindings/*` — language bindings wrapping the core library. All live in this repo and build against the `core/` submodule directly (Rust `build.rs`, the Flutter plugin's CMake and generated Apple source wrappers, the C# native CMake). Only a published package carries its own copy of core, in `cxx_impl/`, which the release workflows vendor and never commit. The Rust binding layers `nativeapi` (safe API) over `cnativeapi` (FFI).
2828

2929
## Design specs
3030

@@ -63,7 +63,7 @@ A core change ripples to every binding. After editing headers in `core`, run:
6363
./codegen sync -m "<core commit message>"
6464
```
6565

66-
It regenerates everything, updates each binding's embedded core submodule (fetched from the local `core/`, so no push is required first), reruns `bindgen` (Rust raw FFI) and the flutter binding's `codegen.py` (umbrella headers + ffigen), then commits core and this repo (`Sync with core <sha>`: the core pointer plus everything regenerated under `bindings/`). Add `--push` to publish in dangling-safe order (core → workspace).
66+
It regenerates everything, reruns `bindgen` (Rust raw FFI) and the flutter binding's `codegen.py` (umbrella headers + ffigen), then commits core and this repo (`Sync with core <sha>`: the core pointer plus everything regenerated under `bindings/`). Add `--push` to publish in dangling-safe order (core → workspace).
6767

6868
Manual follow-ups sync cannot do (details in tools/codegen/README.md):
6969

@@ -90,7 +90,7 @@ scenarios for *this project's* examples live in [tools/gui/](tools/gui/README.md
9090

9191
## Conventions
9292

93-
- `core` tracks `branch = main`. Use `make sync` to fast-forward it; `make status` to see dirty state everywhere; `make bump` to stage its pointer. Each binding's embedded core (`cxx_impl`) is moved by `./codegen sync` or by hand, never by `make`.
93+
- `core` tracks `branch = main`. Use `make sync` to fast-forward it; `make status` to see dirty state everywhere; `make bump` to stage its pointer.
9494
- The leanflutter packages built on nativeapi (`tray_manager`, `window_manager`, `launch_at_startup`, …) live in their own repos under github.com/leanflutter and depend on the published `nativeapi`; they are not part of this repo. To try one against local changes, point a `dependency_overrides` entry in that package at `bindings/flutter/nativeapi` (and `cnativeapi`) and never commit the override.
9595
- Commit workspace submodule pointer updates only when the combination is compatible (a known-good snapshot).
9696
- Examples live in `examples/<binding>_<name>_example` (`flutter_`, `rust_`, `csharp_`), not inside the bindings; a new Flutter or Rust example must also be listed in the root `pubspec.yaml` / `Cargo.toml`, a C# one in `bindings/csharp/NativeAPI.slnx`. Only the pub.dev package examples (`bindings/flutter/*/example`) stay inside their package.

0 commit comments

Comments
 (0)