Migrating from cpp.js 1.x
crossbind is cpp.js under a new name, with the same header-import model. Every rename below was checked against the last cpp.js release, 1.0.4, and the current tree. Work through the steps in order; most projects need the first five. The cpp.js 1.x documentation stays online.
What was renamed
| cpp.js 1.x | crossbind 2.x |
|---|---|
cpp.js, the CLI and core | crossbind |
create-cpp.js | create-crossbind |
@cpp.js/plugin-vite, -rollup, -webpack, -webpack-loader, -metro, -react-native, -react-native-ios-helper | @crossbind/plugin-*, the same seven names |
@cpp.js/core-embind-jsi | @crossbind/core-embind-jsi |
@cpp.js/package-<name>, one package with every platform inside | @crossbind/port-<name> plus one package per platform: -wasm, -android, -ios, -wasi; see Libraries |
cppjs.config.js | crossbind.config.js |
cppjs.build.js, package authors only | crossbind.build.js |
.cppjs/ cache directory | .crossbind/ |
~/.cppjs.json system config | ~/.crossbind.json |
initCppJs() | initNative() |
_CPPJS_DATA_PATH_ placeholder in env | _CROSSBIND_DATA_PATH_ |
org.js.cpp.<name> iOS bundle and framework identifiers | dev.crossbind.<name> |
bugra9/cpp.js Docker image | ghcr.io/crossbind/web and ghcr.io/crossbind/android, pinned by digest inside the CLI |
beta tag; the changelog covers both lines.1. Requirements
Node.js 18 was enough for cpp.js; crossbind needs Node.js 24 or newer. Docker, CMake 3.28+ for mobile, and Xcode with CocoaPods for iOS are unchanged. Until the first stable train every crossbind package is on the npm beta tag, so install commands carry @beta.
2. Replace the packages
A 1.x prebuilt package carried the Web, Android and iOS binaries in one tarball. A 2.x family is split per platform: -wasm for the browser, Node.js and edge, -android and -ios for React Native, -wasi for WASI builds. Install one variant per platform you build. The meta package @crossbind/port-gdal arrives as a dependency of each variant and is not installed on its own.
The eleven 1.x libraries - expat, GDAL, GEOS, GeoTIFF, iconv, PROJ, SpatiaLite, SQLite3, libTIFF, WebP and zlib - are all published as families, with new ones beside them; Libraries lists what is on npm.
3. Rename and update the config
Rename cppjs.config.js to crossbind.config.js. general, paths, ext, dependencies and export keep their shape; two things change inside.
- Dependency imports point at a platform variant.
@cpp.js/package-proj/cppjs.config.jsbecomes@crossbind/port-proj-wasm/crossbind.config.js, one import per platform you build. - `platform` becomes `targetSpecs`. The 1.x keys
Emscripten-x86_64,Android-arm64-v8aandiOS-iphoneosare now filters -platform: 'wasm' | 'android' | 'ios' | 'wasi'with optionalarch,runtime,buildTypeandruntimeEnv- anddata,envandignoreLibNamemove underspecs, next to the newcmakeandemccFlagslists.
Everything else in the file is new and optional: target.runtime for multithreaded wasm, cargoDependencies and export.type: 'cargo' for Rust, dts for generated types, extensions and functions for build hooks. The full list is in Configuration.
4. Swap the bundler plugin
Rollup, Webpack, Rspack, Metro and the React Native plugin follow the same rename; how each one is registered is unchanged. See Bundlers.
5. Update the JavaScript
Header import paths are unchanged, for your own headers and for library headers such as @crossbind/port-gdal/gdal.h. initNative() takes options where initCppJs() took none - worker mode, persistent storage, environment variables - all listed in the API reference.
The helpers on the returned module keep their names: toArray, toVector, getFileBytes, getFileList and autoMountFiles. Two things moved:
generateVirtualPath()is nowgetRandomPath().- Browser files no longer live under
/virtual/. They mount under/memfs/<app>/, or/opfs/<app>/once you opt into persistent storage withuseWorker: true.autoMountFilesreturns the new paths, so code that only uses what it returns keeps working; hard-coded/virtual/...paths do not. See Filesystem.
6. CLI and output names
| cpp.js 1.x | crossbind 2.x |
|---|---|
cppjs build -p WebAssembly|Android|iOS|All | crossbind build -p wasm|android|ios|wasi, with -a arch, -r runtime (st, mt), -e runtime env (browser, node, edge) and -b build type |
cppjs config get|set|delete|list|keys | crossbind config ..., the same subcommands |
cppjs docker run|create|start|stop|delete | crossbind docker ..., the same subcommands |
| - | crossbind licenses and crossbind clean-deps are new |
dist/mylib.browser.js, mylib.node.js, mylib.wasm | dist/<name>-wasm-wasm32-st-release.browser.js, .node.js, .edge.js: the target is part of the file name |
dist/prebuilt/Emscripten-x86_64/, Android-arm64-v8a/, iOS-iphoneos/ | dist/prebuilt/<platform>-<arch>-<runtime>-<buildType>/, for example wasm-wasm32-mt-release or android-arm64-v8a-mt-release |
A script or a Cloudflare Worker that imports the built module by file name needs the new path; Runtimes shows the current names per environment.
7. Rebuild native apps
iOS frameworks are identified as dev.crossbind.<name> instead of org.js.cpp.<name>. In a React Native project run pod install again and rebuild both platforms; the JavaScript side needs nothing beyond step 5.
What you gain, optional
- Rust:
export.type: 'cargo'andcargoDependencies. - WASI:
platform: 'wasi'builds and the-bin-wasicommand tools. - Threading:
target.runtime: 'mt'and worker mode. - Filesystem: persistent OPFS storage in the browser.
- Generated TypeScript types through
dts, see Configuration.
Checklist
- Node.js 24 or newer.
- Packages swapped; one library variant per platform.
crossbind.config.jsrenamed, dependency imports andtargetSpecsupdated.- Bundler plugin import renamed.
initCppJsisinitNative; no hard-coded/virtual/paths.- Build scripts use the new CLI flags and output names.
- Mobile: pods reinstalled, both apps rebuilt.