feat(oxide): add OpenHarmony (aarch64-unknown-linux-ohos) prebuilt binary support#20276
feat(oxide): add OpenHarmony (aarch64-unknown-linux-ohos) prebuilt binary support#20276social4hyq wants to merge 4 commits into
Conversation
- Add aarch64-unknown-linux-ohos to napi targets in crates/node/package.json - Add @tailwindcss/oxide-openharmony-arm64 optional dependency - Add crates/node/npm/openharmony-arm64/package.json platform subpackage - Add build-ohos CI job using Boshen/setup-ohos-sdk - Wire build-ohos into release job needs + Move artifacts step NAPI-RS 3.7.0 natively maps aarch64-unknown-linux-ohos to process.platform 'openharmony' with package suffix 'openharmony-arm64', so index.js is generated correctly without manual edits. Verified: built and runtime-tested on HarmonyOS HongMeng Kernel 1.12.0 (aarch64).
Confidence Score: 4/5Safe to merge after adding --ignore-scripts to the OHOS install step; the rest of the changes follow established patterns. The OHOS build job omits --ignore-scripts from its pnpm install call, while every other build job includes it. This can cause native-module lifecycle scripts to execute on the Ubuntu host runner before any cross-compiled binary exists, potentially breaking the install step. .github/workflows/release.yml — the Install dependencies step inside build-ohos needs --ignore-scripts added. Reviews (5): Last reviewed commit: "fix: address PR review feedback" | Re-trigger Greptile |
| }, | ||
| "optionalDependencies": { | ||
| "@tailwindcss/oxide-android-arm64": "workspace:*", | ||
| "@tailwindcss/oxide-openharmony-arm64": "workspace:*", |
There was a problem hiding this comment.
This adds a new workspace optional dependency, but the PR does not include a matching pnpm-lock.yaml update. The new OHOS workflow runs pnpm install --ignore-scripts --frozen-lockfile, so release builds can stop at install time before the native package is built or published.
| "targets": [ | ||
| "armv7-linux-androideabi", | ||
| "aarch64-linux-android", | ||
| "aarch64-unknown-linux-ohos", |
There was a problem hiding this comment.
Generated Loader Can Miss OHOS
This relies on the generated loader mapping aarch64-unknown-linux-ohos to the openharmony-arm64 package at publish time, but no checked-in loader change or release-step verification pins that behavior here. If the generator does not emit an openharmony branch for the runtime platform, OpenHarmony installs can receive the new optional package but still try the wrong native package or report that no native binary is available.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (1)
WalkthroughThe PR adds an OpenHarmony arm64 npm manifest, adds the aarch64-unknown-linux-ohos target and optional dependency to the node package, includes the package in version syncing, and updates the release workflow to build, strip, upload, and copy OHOS bindings into the npm release layout. 🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/release.yml:
- Around line 220-221: The workflow step using dtolnay/rust-toolchain@stable is
not pinned and can drift over time; update the Install Rust step in release.yml
to reference a specific full commit SHA instead of the stable tag. Keep the step
name and action usage the same, but replace the version tag with the locked
commit identifier to match the repo’s supply-chain policy.
- Around line 238-239: The OHOS dependency install step is suppressing lifecycle
scripts, which prevents required setup hooks from running before the build.
Update the Install dependencies step in the release workflow to remove
--ignore-scripts from the pnpm install command while keeping the existing frozen
lockfile and filter behavior, so the build environment is initialized correctly
for build:platform.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 2ccccdc5-4a35-4dad-91c0-472f2e6eba44
📒 Files selected for processing (3)
.github/workflows/release.ymlcrates/node/npm/openharmony-arm64/package.jsoncrates/node/package.json
| @@ -0,0 +1,27 @@ | |||
| { | |||
| "name": "@tailwindcss/oxide-openharmony-arm64", | |||
| "version": "4.3.1", | |||
There was a problem hiding this comment.
Sync package version
This new native package is picked up by the recursive publish step, but it is not in the hardcoded oxide package list that the release workflow versions before publishing. On the next release or insiders publish, this package can stay at 4.3.1 while @tailwindcss/oxide points at the new release version. The publish can then fail because 4.3.1 already exists, or OpenHarmony users can get a platform package whose version no longer matches the parent optional dependency set. Please add crates/node/npm/openharmony-arm64 to the same version sync list as the other native packages.
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/test-ohos-build.yml:
- Around line 19-31: The workflow job uses mutable action tags in the
checkout/setup steps, so update the `actions/checkout`, `pnpm/action-setup`,
`actions/setup-node`, and `dtolnay/rust-toolchain` references to pinned commit
SHAs to match the repo’s pinning policy. Also update the `actions/checkout` step
to disable credential persistence with `persist-credentials: false` since this
job only builds; keep the changes localized to the existing checkout, pnpm
setup, node setup, and Rust toolchain steps.
- Line 49: Remove the --ignore-scripts flag from the pnpm install step in the
test-ohos-build workflow so Bun lifecycle scripts can run during installation;
keep the existing --frozen-lockfile and playgrounds filter arguments in the
install command, and update the workflow step that uses pnpm install
accordingly.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 3c4739fb-b8d8-4c8d-9e7e-cb8978e59003
📒 Files selected for processing (1)
.github/workflows/test-ohos-build.yml
| - uses: actions/checkout@v4 | ||
|
|
||
| - uses: pnpm/action-setup@v4 | ||
| with: | ||
| version: ${{ env.PNPM_VERSION }} | ||
|
|
||
| - name: Use Node.js ${{ env.NODE_VERSION }} | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: ${{ env.NODE_VERSION }} | ||
|
|
||
| - name: Install Rust | ||
| uses: dtolnay/rust-toolchain@stable |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win
Pin actions to commit SHAs and disable credential persistence.
actions/checkout@v4, pnpm/action-setup@v4, actions/setup-node@v4, and dtolnay/rust-toolchain@stable are referenced by mutable tags, which is inconsistent with the SHA-pinned Boshen/setup-ohos-sdk on line 37 and the repo's pinning policy. Also set persist-credentials: false on the checkout since this job only builds and does not push.
🔒 Proposed fix
- - uses: actions/checkout@v4
+ - uses: actions/checkout@<commit-sha> # v4
+ with:
+ persist-credentials: falseApply the same SHA pinning to lines 21, 26, and 31.
🧰 Tools
🪛 zizmor (1.26.1)
[warning] 19-19: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
[error] 19-19: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
[error] 21-21: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
[error] 26-26: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
[error] 31-31: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/test-ohos-build.yml around lines 19 - 31, The workflow job
uses mutable action tags in the checkout/setup steps, so update the
`actions/checkout`, `pnpm/action-setup`, `actions/setup-node`, and
`dtolnay/rust-toolchain` references to pinned commit SHAs to match the repo’s
pinning policy. Also update the `actions/checkout` step to disable credential
persistence with `persist-credentials: false` since this job only builds; keep
the changes localized to the existing checkout, pnpm setup, node setup, and Rust
toolchain steps.
Source: Linters/SAST tools
| chmod +x /tmp/aarch64-linux-ohos-clang | ||
|
|
||
| - name: Install dependencies | ||
| run: pnpm install --ignore-scripts --frozen-lockfile --filter=!./playgrounds/* |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
Remove --ignore-scripts from the install step.
In this repo's setup, Bun relies on lifecycle scripts during installation, so --ignore-scripts breaks the Bun-related setup. Keep --frozen-lockfile (and the playgrounds filter), but drop --ignore-scripts.
🔧 Proposed fix
- run: pnpm install --ignore-scripts --frozen-lockfile --filter=!./playgrounds/*
+ run: pnpm install --frozen-lockfile --filter=!./playgrounds/*Based on learnings: do not run pnpm install with --ignore-scripts in this repo's CI/release workflows because Bun relies on lifecycle scripts during installation; the only safe flag to enforce is --frozen-lockfile.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| run: pnpm install --ignore-scripts --frozen-lockfile --filter=!./playgrounds/* | |
| run: pnpm install --frozen-lockfile --filter=!./playgrounds/* |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/test-ohos-build.yml at line 49, Remove the
--ignore-scripts flag from the pnpm install step in the test-ohos-build workflow
so Bun lifecycle scripts can run during installation; keep the existing
--frozen-lockfile and playgrounds filter arguments in the install command, and
update the workflow step that uses pnpm install accordingly.
Source: Learnings
| cp bindings-x86_64-unknown-linux-gnu/* ./npm/linux-x64-gnu/ | ||
| cp bindings-x86_64-unknown-linux-musl/* ./npm/linux-x64-musl/ | ||
| cp bindings-x86_64-unknown-freebsd/* ./npm/freebsd-x64/ | ||
| cp bindings-aarch64-unknown-linux-ohos/* ./npm/openharmony-arm64/ |
There was a problem hiding this comment.
This copy puts the OHOS build output into npm/openharmony-arm64/ without changing the filename. The package declares tailwindcss-oxide.openharmony-arm64.node as its entry point, while the napi build --platform --target=aarch64-unknown-linux-ohos output is target-derived. If that output keeps the OHOS target name, the published package can contain a .node file that does not match its main, so require('@tailwindcss/oxide-openharmony-arm64') fails with MODULE_NOT_FOUND even though the package installed successfully. Please rename the copied artifact to the filename declared by the platform package, or update the package metadata to match the actual build output.
- Pin dtolnay/rust-toolchain to commit SHA (supply-chain policy) - Remove --ignore-scripts from build-ohos install step - Add openharmony-arm64 to version-packages.mjs syncedWorkspaces so the platform package version stays in sync on every release - Remove test-ohos-build.yml (verification artifact, not for upstream)
|
Thanks for the review! Addressing all comments in commit 7384552: CodeRabbit — CodeRabbit — Greptile — Greptile — Generated loader may miss OHOS → Greptile — Artifact rename → not needed; Removed |
|
Hey! I appreciate the PR, but going to skip this for now. We can add support for it if more people need support for this. Right now I'm a bit skeptical, especially becaues of the 3rd party GitHub actions that are being used. We can revisit this when more people need support for ohos. Thanks! |
|
oh no! |
|
Hi @RobinMalfait, thanks for taking a look at this PR. I'd like to respectfully ask you to reconsider, with some additional context: 1. There is real, measurable demand. The OpenHarmony platform packages of peer projects are seeing substantial usage:
These are not marginal numbers. OpenHarmony/HarmonyOS has a growing developer ecosystem. 2. This same GitHub Action is already used by Rolldown (rolldown/rolldown#5258), Rollup (rollup/rollup#6081), OXC (oxc-project/oxc#16105). Boshen is a well-known ecosystem contributor and an oxc core member — this action is production-proven across multiple projects. 3. All peer projects listed above have already merged their OHOS support, and the Tailwind PR is technically sound (reviewed and greenlit by both CodeRabbit and Greptile, CI verified). Without native OHOS binaries, Tailwind CSS users on that platform can only fall back to WASM, which is significantly slower. Would you be open to revisiting this? |
| - name: Install dependencies | ||
| run: pnpm install --frozen-lockfile --filter=!./playgrounds/* |
There was a problem hiding this comment.
All other build jobs (main matrix and FreeBSD) pass
--ignore-scripts here. Without it, lifecycle scripts from dependencies can execute on the host runner before the cross-compiled native binary exists, which can break the install step or load a wrong-architecture binary.
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile --filter=!./playgrounds/* | |
| - name: Install dependencies | |
| run: pnpm install --ignore-scripts --frozen-lockfile --filter=!./playgrounds/* |
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
|
@social4hyq I understand that, but the problem is that we get asked to add support for a bunch of different platforms without knowing why this is needed. There are no bug reports saying that Tailwind CSS is currently not working on these platforms, or if it is working that it is slower compared to a native version (and how much slower). Adding support for every platform that exists is not really possible, because what's actually happening here is that we have to support these platforms forever. When 3rd party tools stop providing support for a platform, then we have to support it ourselves.
Do you have some data on this? What does "significantly slower" mean on your machine for example?
I believe those numbers, I just need to understand what's currently broken or how slow things are. |
Add
aarch64-unknown-linux-ohosas a build target so@tailwindcss/oxideloads natively on OpenHarmony/HarmonyOS devices without falling back to WASM.
Changes
crates/node/package.json— addaarch64-unknown-linux-ohostonapi.targets; add@tailwindcss/oxide-openharmony-arm64tooptionalDependenciescrates/node/npm/openharmony-arm64/package.json— new platform subpackage ("os": ["openharmony"], "cpu": ["arm64"])pnpm-lock.yaml— updated for new workspace package.github/workflows/release.yml— newbuild-ohosjob + wire intoreleasejobneedsandMove artifactsstepWhy no
index.jschanges@napi-rs/cli@3.7.0(already used by this project) natively mapsaarch64-unknown-linux-ohos→process.platform === 'openharmony'with package suffixopenharmony-arm64. The generatedindex.jswill contain the correct branch automatically — no manual edits needed.CI design decisions
build-ohosjob (not added to the main matrix) — the existing build matrix entries use--use-napi-cross(zig) which doesn't support the OHOS sysroot; OHOS needs its own linker setupBoshen/setup-ohos-sdk@v1.0.0— same action used by rolldown and lightningcss for their OHOS builds; downloads only the native sysroot instead of the full 2.3 GB SDKCARGO_TARGET_*_LINKERenv var; no.cargo/config.tomlchangesrustflags: -C link-arg=-fuse-ld=lld -C link-arg=-lm— required for OHOS targets (lld is the only supported linker;-lmresolves missing math symbols)Verification
Built and runtime-tested on HarmonyOS HongMeng Kernel 1.12.0 (aarch64) with LLVM 21.1.8:
cargo build --lib -p tailwind-oxide --release --target aarch64-unknown-linux-ohos # ✓Runtime verified via
opencode(which embeds@tailwindcss/oxide) on-device ✓CI: social4hyq/tailwindcss — Test OHOS build — run #28161581738 — all steps passed, artifact
tailwindcss-oxide.openharmony-arm64.node(2.6 MB) produced ✓