Skip to content

Commit

Permalink
Reference sections
Browse files Browse the repository at this point in the history
  • Loading branch information
jhugman committed Aug 17, 2024
1 parent e3493ff commit 48a01ca
Show file tree
Hide file tree
Showing 8 changed files with 540 additions and 0 deletions.
9 changes: 9 additions & 0 deletions docs/src/SUMMARY.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
# Summary

[Introduction](README.md)

* [Getting Started](getting-started/README.md)
- [Before you start](getting-started/pre-installation.md)

* [Reference](api/README.md)
- [Command Line](api/commandline.md)
- [Configuring your project](api/config-yaml.md)
- [Tweaking code generation](api/uniffi-toml.md)
- [Generating a Turbo Module](api/turbo-module-files.md)
Empty file added docs/src/api/README.md
Empty file.
221 changes: 221 additions & 0 deletions docs/src/api/commandline.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
`uniffi-bindgen-react-native` the command line utility that ties together much of the building of Rust, and the generating the bindings and turbo-modules.

Most commands take a `--config FILE` option. This is a YAML file which collects commonly used options together, and is [documented here](config-yaml.md).

The command can be invoked with `./node_modules/.bin/uniffi-bindgen-react-native`.

Running the following command from within your project:

```sh
alias ubrn=$(pwd)/node_modules/.bin/uniffi-bindgen-react-native
```
allows you to run the command as `ubrn`, which is simpler to type. From hereon, commands will be given as `ubrn` commands.

# `ubrn` Commands

Running `ubrn --help` gives the following output:

```sh
Usage: uniffi-bindgen-react-native <COMMAND>

Commands:
checkout Checkout a given Github repo into `rust_modules`
build Build (and optionally generate code) for Android or iOS
generate Generate bindings or the turbo-module glue code from the Rust
help Print this message or the help of the given subcommand(s)

Options:
-h, --help Print help
```

## `checkout`
Checkout a given Git repo into `rust_modules`.

```sh
Usage: uniffi-bindgen-react-native checkout [OPTIONS] <REPO>

Arguments:
<REPO> The repository where to get the crate

Options:
--config <CONFIG>
--branch <BRANCH> The branch or tag which to checkout [default: main]
-h, --help Print help
```
The checkout command can be operated in two ways, either:
1. with a `REPO` argument and optional `--branch` argument. OR
2. with a config file which may specify a repo and branch, or just a `directory`.

## `build android`

Build the crate for use on an Android device or emulator, using `cargo ndk`, which in turn uses Android Native Development Kit.

```
Usage: uniffi-bindgen-react-native build android [OPTIONS] --config <CONFIG>
Options:
--config <CONFIG> The configuration file for this build
-r, --release Build a release build
-g, --and-generate Optionally generate the bindings and turbo-module code for the crate
-h, --help Print help
```

The configuration file refers to [the YAML configuration](config-yaml.md).

`--release` sets the release profile for `cargo`.

`--and-generate` is a convenience option to pass the built library file to `generate bindings` and `generate turbo-module`.

Once the library files (one for each target) are created, they are copied into the `jniLibs` specified by the YAML configuration.

```admonish note
React Native requires that the Rust library be built as a static library. The CMake based build will combine the C++ with the static library into a shared object.
To configure Rust to build a static library, you should ensure `staticlib` is in the `crate-type` list in the `[lib]` section of the `Cargo.toml` file. Minimally, this should be in the `Cargo.toml` manifest file:
<pre>
<code class="hljs">[lib]
crate-type = ["staticlib"]
</code>
</pre>
```


## `build ios`

Build the crate for use on an iOS device or simulator.
```
Usage: uniffi-bindgen-react-native build ios [OPTIONS] --config <CONFIG>
Options:
--config <CONFIG> The configuration file for this build
--sim-only Only build for the simulator
--no-sim Exclude builds for the simulator
-r, --release Build a release build
-g, --and-generate Optionally generate the bindings and turbo-module code for the crate
-h, --help Print help
```
The configuration file refers to [the YAML configuration](config-yaml.md).

`--sim-only` and `--no-sim` restricts the targets to targets with/without `sim` in the target triple.

`--and-generate` is a convenience option to pass the built library file to `generate bindings` and `generate turbo-module`.

Once the target libraries are compiled, and a config file is specified, they are passed to `xcodebuild -create-xcframework` to generate an `xcframework`.

```admonish note
React Native requires that the Rust library be built as a static library. The `xcodebuild` based build will combine the C++ with the static library `.xcframework` file.
To configure Rust to build a static library, you should ensure `staticlib` is in the `crate-type` list in the `[lib]` section of the `Cargo.toml` file. Minimally, this should be in the `Cargo.toml` manifest file:
<pre>
<code class="hljs">[lib]
crate-type = ["staticlib"]
</code>
</pre>
```


## `generate bindings`
Generate the just the bindings. In most cases, this command should not be called directly, but with the build, with `--and-generate`.

```admonish info
This command follows the command line format of other `uniffi-bindgen` commands. Most arguments are passed straight to [`uniffi-bindgen::library_mode::generate_bindings`](https://docs.rs/uniffi_bindgen/0.28/uniffi_bindgen/library_mode/fn.generate_bindings.html).
For more/better documentation, please see the linked docs.
```

```admonish warning
Because this mirrors other `uniffi-bindgen`s, the `--config` option here is asking for a [`uniffi.toml`](uniffi-toml) file.
```

This command will generate two typescript files and two C++ files per Uniffi namespace. These are: `namespace.ts`, `namespace-ffi.ts`, `namespace.h`, `namespace.cpp`, substituting `namespace` for names derived from the Rust crate.

The [namespace is defined as](https://docs.rs/uniffi_bindgen/latest/uniffi_bindgen/interface/struct.ComponentInterface.html#method.namespace):

> The string namespace within which this API should be presented to the caller.
>
> This string would typically be used to prefix function names in the FFI, to build a package or module name for the foreign language, etc.
It may also be thought of as a crate or sub-crate which exports uniffi API.

The C++ files will be put into the `--cpp-dir` and the typescript files into the `--ts-dir`.

The C++ files can register themselves with the Hermes runtime.

```
Usage: uniffi-bindgen-react-native generate bindings [OPTIONS] --ts-dir <TS_DIR> --cpp-dir <CPP_DIR> <SOURCE>
Arguments:
<SOURCE>
A UDL file or library file
Options:
--lib-file <LIB_FILE>
The path to a dynamic library to attempt to extract the definitions from and extend the component interface with
--crate <CRATE_NAME>
Override the default crate name that is guessed from UDL file path.
In library mode, this
--config <CONFIG>
The location of the uniffi.toml file
--library
Treat the input file as a library, extracting any Uniffi definitions from that
--no-format
By default, bindgen will attempt to format the code with prettier and clang-format
--ts-dir <TS_DIR>
The directory in which to put the generated Typescript
--cpp-dir <CPP_DIR>
The directory in which to put the generated C++
-h, --help
Print help (see a summary with '-h')
```
## `generate turbo-module`
Generate the TurboModule code to plug the bindings into the app.

More details about the files generated is shown [here](turbo-module-files.md).

```
Usage: uniffi-bindgen-react-native generate turbo-module --config <CONFIG> [NAMESPACES]...
Arguments:
[NAMESPACES]... The namespaces that are generated by `generate bindings`
Options:
--config <CONFIG> The configuration file for this build
-h, --help Print help
```

The namespaces in the commmand line are derived from the crate that has had its bindings created.

```admonish info
The locations of the files are derived from [the configuration file](config-yaml.md) and the project's package.json` file.
The relationships between files are preserved-- e.g. where one file points to another via a relative path, the relative path is calculated from these locations.
```

## `help`

Prints the help message.

```
Usage: uniffi-bindgen-react-native <COMMAND>
Commands:
checkout Checkout a given Github repo into `rust_modules`
build Build (and optionally generate code) for Android or iOS
generate Generate bindings or the turbo-module glue code from the Rust
help Print this message or the help of the given subcommand(s)
Options:
-h, --help Print help
```

You can add `--help` to any command to get more information about that command.
148 changes: 148 additions & 0 deletions docs/src/api/config-yaml.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
# Configuration for `uniffi-bindgen-react-native`

The configuration yaml file is a collection of configuration options used in one or more [commands](commandline.md).

The file is designed to be easy to start. A **minimal** configuation would be:

```yaml
crate:
directory: ./rust
manifest-file: Cargo.toml
```
Getting started from here would require a command to start the Rust:
```sh
cargo init --lib ./rust
cd ./rust
cargo add uniffi
```

# YAML entries

## `crate`

```yaml
crate:
manifest-path: crates/my-api/Cargo.toml
repo: https://github.com/example/my-rust-sdk
branch: main
```
In this case, the `ubrn checkout` command will clone the given repo with the branch/ref into the `rust_modules` directory of the project.

If run a second time, no overwriting will occur.

The `manifest-path` is the path relative to the root of the Rust workspace directory. In this case, the manifest is expected to be, relative to your React Native library project: `./rust_modules/my-rust-sdk/crates/my-api/Cargo.tml`.

```yaml
crate:
directory: ./rust
manifest-path: crates/my-api/Cargo.toml
```
In this case, the `./rust` directory tells `ubrn` where the Rust workspace is, relative to your React Native library project. The `manifest-path` is the relative path from the workspace file to the crate which will be used to build bindings.

## `bindings`

This section governs the generation of the bindings— the nitty-gritty of the Rust API translated into Typescript. This is mostly the location on disk of where these files will end up, but also has a second configuration file.

```yaml
bindings:
cpp: cpp/bindings
ts: ts/bindings
uniffiToml: ./uniffi.toml
```
The [`uniffi.toml` file](uniffi-toml.md) configures custom types, to further customize the conversion into Typescript data-types.

If missing, the defaults will be used:
```
bindings:
cpp: cpp/generated
ts: ts/generated
```
## `android`

This is to configure the build steps for the Rust, the bindings, and the turbo-module code for Android.

This section can be completely missed out, as sensible defaults are provided, but can also be customized:

```yaml
android:
directory: ./android
cargoExtras: []
targets:
- aarch64-linux-android
- armv7-linux-androideabi
- i686-linux-android
- x86_64-linux-android
apiLevel: 21
jniLibs: src/main/jniLibs
packageName: <DERIVED FROM package.json>
```

The `directory` is the location of the Android project, relative to the root of the React Native library project.

`targets` is a list of targets to build for. The Rust source code is built once per target.

`cargoExtras` is a list of extra arguments passed directly to the `cargo build` command.

`apiLevel` is the minimum API level to target: this is passed to the `cargo ndk` command as a `--platform` argument.

```admonish tip
Reducing the number of targets to build for will speed up the edit-compile-run cycle.
```

`packageName` is the name of the Android package that Codegen used to generate the TurboModule. This is derived from the `package.json` file, and can almost always be left.

To customize the `packageName`, you should edit or add the entry at the path `codegenConfig`/`android`/`javaPackageName` in `package.json`.

## `ios`

This is to configure the build steps for the Rust, the bindings, and the turbo-module code for iOS.

This section can be completely missed out, as sensible defaults are provided, but can also be customized:

```yaml
ios:
directory: ios
cargoExtras:: []
targets:
- aarch64-apple-ios
- aarch64-apple-ios-sim
xcodebuildExtras: []
frameworkName: build/MyFramework
```


The `directory` is the location of the iOS project, relative to the root of the React Native library project.

`targets` is a list of targets to build for. The Rust source code is built once per target.

`cargoExtras` is a list of extra arguments passed directly to the `cargo build` command.

`xcodebuildExtras` is a list of extra arguments passed directly to the `xcodebuild` command.

## `turboModule`

This section configures the location of the Typescript and C++ files generated by the `generate turbo-module` command.

If absent, the defaults will be used:

```yaml
turboModule:
ts: src
cpp: cpp
```
The Typescript files are the `index.ts` file, and the Codegen installer file.

```admonish info
By default, the `index.ts` file is intended to be the entry point for your library.

In this case, changing the location of the `ts` directory will require changing the `main` entry in the `package.json` file.
```

## `noOverwrite`

This list of [glob patterns](https://en.wikipedia.org/wiki/Glob_(programming)) of file that should not be generated or overwritten by the `--and-generate` flag, and the `generate turbo-module` command.

This is useful if you want to customize one or more of the generated files, and not losen those changes.
Loading

0 comments on commit 48a01ca

Please sign in to comment.