crossbind
GitHub
GUIDE · CONCEPTS · LIBRARIES

Libraries

Native libraries travel through npm like any other dependency. 16 are already published prebuilt - GDAL, OpenSSL, SQLite, GEOS, PROJ, libTIFF and more - and the same mechanism packages your own C++, whether it ships as binaries, as sources, as a CMake project or as a Rust crate.

Using a prebuilt library

Install the variant for the platform you build, declare it as a dependency in crossbind.config.js, and import its header. Nothing is compiled on your machine - the binaries are in the package. A project that builds for several platforms lists one variant per platform, for example -android and -ios in a React Native app.

shell
npm install @crossbind/port-gdal-wasm@beta
crossbind.config.js
import gdal from '@crossbind/port-gdal-wasm/crossbind.config.js';
 
export default {
general: { name: 'my-geo-app' },
dependencies: [gdal],
paths: { config: import.meta.url },
};
src/main.js
import { initNative, GDALVersionInfo } from '@crossbind/port-gdal/gdal.h';
 
await initNative();
console.log(GDALVersionInfo('RELEASE_NAME'));

Headers live under the package's dist/prebuilt/<target>/include, and the import path is relative to that - @crossbind/port-gdal/gdal.h is GDAL's own gdal.h.

Meta package, platform variants

A package family is a thin meta package plus one package per platform, so you only download artifacts for the platforms you build. Every variant depends on @crossbind/port-gdal, which carries the family's shared build metadata and the @crossbind/port-gdal/<header>.h alias; you install -wasm, -android, -ios or -wasi for the platforms you build and list each one in dependencies. Importing the meta package pulls in the right variant for the target.

PackageCarries
@crossbind/port-gdalthe meta package: shared metadata and the header alias, pulled in by every variant
@crossbind/port-gdal-wasmthe WebAssembly prebuilt (browser, Node, edge)
@crossbind/port-gdal-android / -iosthe native mobile libraries
@crossbind/port-gdal-wasithe wasm32-wasip3 prebuilt
@crossbind/port-gdal-bin-wasithe upstream CLI tools as npm commands

Those -bin-wasi packages are prebuilt command-line tools - gdalinfo-wasi, ogr2ogr-wasi, sqlite3-wasi and friends. See WASI commands.

Auditable by construction
Every upstream source is sha256-pinned, and each published package ships its third-party notices, a CycloneDX SBOM and a provenance block naming the sources, toolchain and environment that produced the binaries.

The three package types

Typeexport.typeWhat consumers get
Prebuiltcmake (default)compiled libraries per platform - nothing to build
Sourcesourceraw C++ compiled during the consumer's build
CMakecmakesources plus a CMakeLists.txt for custom build systems
Cargocargoa Rust crate built per platform - see Rust

Prebuilt is the default and what almost every published package is. Source and CMake packages trade build time for control - the consumer compiles them, so platform-specific tweaks are possible.

Publishing your own

Point the config at your sources, name the library, and declare where the build output goes. That is the whole contract:

crossbind.config.js
export default {
general: { name: 'mylib' },
paths: {
config: import.meta.url,
native: ['src/native'],
output: 'dist',
},
export: {
type: 'cmake',
libName: ['mylib'],
},
};

Build once per platform and publish the result. The layout the CLI produces is what consumers rely on:

dist/
dist/
├── mylib-wasm-wasm32-st-release.browser.js
├── mylib-wasm-wasm32-st-release.browser.wasm
└── prebuilt/
├── wasm-wasm32-st-release/{include,lib}
├── android-arm64-v8a-mt-release/{include,lib}
└── ios-iphoneos-mt-release/{include,lib}

Wrapping an external project rather than your own sources? Add a crossbind.build.js next to the config: it fetches the upstream release, patches it if needed, and passes build parameters to cmake or configure. Every published library in the registry is built exactly that way.

Declare your C++ dependencies in package.json too
Build order is derived from the npm dependency graph. A library that links against another package must list it in dependencies, or the linker will run before that package has been built.
Type to search every guide page and section.
↑↓ navigate↵ openesc close