tools/corrosion/doc/src/usage.md
branchtransitional_engine
changeset 16021 6a3dc15b78b9
child 16038 d903f8d2395a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/corrosion/doc/src/usage.md	Wed Aug 28 15:31:51 2024 +0200
@@ -0,0 +1,320 @@
+## Usage
+
+### Automatically import crate targets with `corrosion_import_crate`
+
+In order to integrate a Rust crate into CMake, you first need to import Rust crates from
+a [package] or [workspace]. Corrosion provides `corrosion_import_crate()` to automatically import
+crates defined in a Cargo.toml Manifest file:
+
+{{#include ../../cmake/Corrosion.cmake:corrosion-import-crate}}
+
+Corrosion will use `cargo metadata` to add a cmake target for each crate defined in the Manifest file
+and add the necessary rules to build the targets.
+For Rust executables an [`IMPORTED`] executable target is created with the same name as defined in the `[[bin]]`
+section of the Manifest corresponding to this target.
+If no such name was defined the target name defaults to the Rust package name.
+For Rust library targets an [`INTERFACE`] library target is created with the same name as defined in the `[lib]`
+section of the Manifest. This `INTERFACE` library links an internal corrosion target, which is either a
+`SHARED` or `STATIC` `IMPORTED` library, depending on the Rust crate type (`cdylib` vs `staticlib`).
+
+The created library targets can be linked into other CMake targets by simply using [target_link_libraries].
+
+Corrosion will by default copy the produced Rust artifacts into `${CMAKE_CURRENT_BINARY_DIR}`. The target location
+can be changed by setting the CMake `OUTPUT_DIRECTORY` target properties on the imported Rust targets.
+See the [OUTPUT_DIRECTORY](#cmake-output_directory-target-properties-and-imported_location) section for more details.
+
+Many of the options available for `corrosion_import_crate` can also be individually set per
+target, see [Per Target options](#per-target-options) for details.
+
+[package]: https://doc.rust-lang.org/book/ch07-01-packages-and-crates.html
+[workspace]: https://doc.rust-lang.org/cargo/reference/workspaces.html
+[`IMPORTED`]: https://cmake.org/cmake/help/latest/prop_tgt/IMPORTED.html
+[`INTERFACE`]: https://cmake.org/cmake/help/latest/command/add_library.html#interface-libraries
+[target_link_libraries]: https://cmake.org/cmake/help/latest/command/target_link_libraries.html
+
+### Per Target options
+
+Some configuration options can be specified individually for each target. You can set them via the
+`corrosion_set_xxx()` functions specified below:
+
+- `corrosion_set_env_vars(<target_name> <key1=value1> [... <keyN=valueN>])`: Define environment variables
+  that should be set during the invocation of `cargo build` for the specified target. Please note that
+  the environment variable will only be set for direct builds of the target via cmake, and not for any
+  build where cargo built the crate in question as a dependency for another target.
+  The environment variables may contain generator expressions.
+- `corrosion_add_target_rustflags(<target_name> <rustflag> [... <rustflagN>])`: When building the target,
+  the `RUSTFLAGS` environment variable will contain the flags added via this function. Please note that any
+  dependencies (built by cargo) will also see these flags. See also: `corrosion_add_target_local_rustflags`.
+- `corrosion_add_target_local_rustflags(target_name rustc_flag [more_flags ...])`: Support setting
+  rustflags for only the main target (crate) and none of its dependencies.
+  This is useful in cases where you only need rustflags on the main-crate, but need to set different
+  flags for different targets. Without "local" Rustflags this would require rebuilds of the
+  dependencies when switching targets.
+- `corrosion_set_hostbuild(<target_name>)`: The target should be compiled for the Host target and ignore any
+  cross-compile configuration.
+- `corrosion_set_features(<target_name> [ALL_FEATURES <Bool>] [NO_DEFAULT_FEATURES] [FEATURES <feature1> ... ])`:
+  For a given target, enable specific features via `FEATURES`, toggle `ALL_FEATURES` on or off or disable all features
+  via `NO_DEFAULT_FEATURES`. For more information on features, please see also the
+  [cargo reference](https://doc.rust-lang.org/cargo/reference/features.html).
+- `corrosion_set_cargo_flags(<target_name> <flag1> ...])`:
+  For a given target, add options and flags at the end of `cargo build` invocation. This will be appended after any
+  arguments passed through the `FLAGS` during the crate import.
+- `corrosion_set_linker(target_name linker)`: Use `linker` to link the target.
+  Please note that this only has an effect for targets where the final linker invocation is done
+  by cargo, i.e. targets where foreign code is linked into rust code and not the other way around.
+  Please also note that if you are cross-compiling and specify a linker such as `clang`, you are
+  responsible for also adding a rustflag which adds the necessary `--target=` argument for the
+  linker.
+
+
+### Global Corrosion Options
+All of the following variables are evaluated automatically in most cases. In typical cases you
+shouldn't need to alter any of these. If you do want to specify them manually, make sure to set
+them **before** `find_package(Corrosion REQUIRED)`.
+
+- `Rust_TOOLCHAIN:STRING` - Specify a named rustup toolchain to use. Changes to this variable
+  resets all other options. Default: If the first-found `rustc` is a `rustup` proxy, then the default
+  rustup toolchain (see `rustup show`) is used. Otherwise, the variable is unset by default.
+- `Rust_ROOT:STRING` - CMake provided. Path to a Rust toolchain to use. This is an alternative if
+  you want to select a specific Rust toolchain, but it's not managed by rustup. Default: Nothing
+- `Rust_COMPILER:STRING` - Path to `rustc`, which should be used for compiling or for toolchain
+  detection (if it is a `rustup` proxy). Default: The `rustc` in the first-found toolchain, either
+  from `rustup`, or from a toolchain available in the user's `PATH`.
+- `Rust_RESOLVE_RUSTUP_TOOLCHAINS:BOOL` - If the found `rustc` is a `rustup` proxy, resolve a
+  concrete path to a specific toolchain managed by `rustup`, according to the `rustup` toolchain
+  selection rules and other options detailed here. If this option is turned off, the found `rustc`
+  will be used as-is to compile, even if it is a `rustup` proxy, which might increase compilation
+  time. Default: `ON` if the found `rustc` is a rustup proxy or a `rustup` managed toolchain was
+  requested, `OFF` otherwise. Forced `OFF` if `rustup` was not found.
+- `Rust_CARGO:STRING` - Path to `cargo`. Default: the `cargo` installed next to `${Rust_COMPILER}`.
+- `Rust_CARGO_TARGET:STRING` - The default target triple to build for. Alter for cross-compiling.
+  Default: On Visual Studio Generator, the matching triple for `CMAKE_VS_PLATFORM_NAME`. Otherwise,
+  the default target triple reported by `${Rust_COMPILER} --version --verbose`.
+- `CORROSION_NATIVE_TOOLING:BOOL` - Use a native tool (written in Rust) as part of Corrosion. This
+  option increases the configure-time significantly unless Corrosion is installed.
+  Default: `OFF` if CMake >= 3.19.0. Forced `ON` for CMake < 3.19.
+
+
+#### Developer/Maintainer Options
+These options are not used in the course of normal Corrosion usage, but are used to configure how
+Corrosion is built and installed. Only applies to Corrosion builds and subdirectory uses.
+
+- `CORROSION_DEV_MODE:BOOL` - Indicates that Corrosion is being actively developed. Default: `OFF`
+  if Corrosion is a subdirectory, `ON` if it is the top-level project
+- `CORROSION_BUILD_TESTS:BOOL` - Build the Corrosion tests. Default: `Off` if Corrosion is a
+  subdirectory, `ON` if it is the top-level project
+- `CORROSION_GENERATOR_EXECUTABLE:STRING` - Specify a path to the corrosion-generator executable.
+  This is to support scenarios where it's easier to build corrosion-generator outside of the normal
+  bootstrap path, such as in the case of package managers that make it very easy to import Rust
+  crates for fully reproducible, offline builds.
+- `CORROSION_INSTALL_EXECUTABLE:BOOL` - Controls whether corrosion-generator is installed with the
+  package. Default: `ON` with `CORROSION_GENERATOR_EXECUTABLE` unset, otherwise `OFF`
+
+
+### Information provided by Corrosion
+
+For your convenience, Corrosion sets a number of variables which contain information about the version of the rust
+toolchain. You can use the CMake version comparison operators
+(e.g. [`VERSION_GREATER_EQUAL`](https://cmake.org/cmake/help/latest/command/if.html#version-comparisons)) on the main
+variable (e.g. `if(Rust_VERSION VERSION_GREATER_EQUAL "1.57.0")`), or you can inspect the major, minor and patch
+versions individually.
+- `Rust_VERSION<_MAJOR|_MINOR|_PATCH>` - The version of rustc.
+- `Rust_CARGO_VERSION<_MAJOR|_MINOR|_PATCH>` - The cargo version.
+- `Rust_LLVM_VERSION<_MAJOR|_MINOR|_PATCH>` - The LLVM version used by rustc.
+- `Rust_IS_NIGHTLY` - 1 if a nightly toolchain is used, otherwise 0. Useful for selecting an unstable feature for a
+  crate, that is only available on nightly toolchains.
+- Cache variables containing information based on the target triple for the selected target
+  as well as the default host target:
+  - `Rust_CARGO_TARGET_ARCH`, `Rust_CARGO_HOST_ARCH`: e.g. `x86_64` or `aarch64`
+  - `Rust_CARGO_TARGET_VENDOR`, `Rust_CARGO_HOST_VENDOR`: e.g. `apple`, `pc`, `unknown` etc.
+  - `Rust_CARGO_TARGET_OS`, `Rust_CARGO_HOST_OS`:  e.g. `darwin`, `linux`, `windows`, `none`
+  - `Rust_CARGO_TARGET_ENV`, `Rust_CARGO_HOST_ENV`: e.g. `gnu`, `musl`
+
+
+
+
+### Selecting a custom cargo profile
+
+[Rust 1.57](https://blog.rust-lang.org/2021/12/02/Rust-1.57.0.html) stabilized the support for custom
+[profiles](https://doc.rust-lang.org/cargo/reference/profiles.html). If you are using a sufficiently new rust toolchain,
+you may select a custom profile by adding the optional argument `PROFILE <profile_name>` to
+`corrosion_import_crate()`. If you do not specify a profile, or you use an older toolchain, corrosion will select
+the standard `dev` profile if the CMake config is either `Debug` or unspecified. In all other cases the `release`
+profile is chosen for cargo.
+
+### Importing C-Style Libraries Written in Rust
+Corrosion makes it completely trivial to import a crate into an existing CMake project. Consider
+a project called [rust2cpp](test/rust2cpp/rust2cpp) with the following file structure:
+```
+rust2cpp/
+    rust/
+        src/
+            lib.rs
+        Cargo.lock
+        Cargo.toml
+    CMakeLists.txt
+    main.cpp
+```
+
+This project defines a simple Rust lib crate, like so, in [`rust2cpp/rust/Cargo.toml`](test/rust2cpp/rust2cpp/rust/Cargo.toml):
+```toml
+[package]
+name = "rust-lib"
+version = "0.1.0"
+authors = ["Andrew Gaspar <andrew.gaspar@outlook.com>"]
+license = "MIT"
+edition = "2018"
+
+[dependencies]
+
+[lib]
+crate-type=["staticlib"]
+```
+
+In addition to `"staticlib"`, you can also use `"cdylib"`. In fact, you can define both with a
+single crate and switch between which is used using the standard
+[`BUILD_SHARED_LIBS`](https://cmake.org/cmake/help/latest/variable/BUILD_SHARED_LIBS.html) variable.
+
+This crate defines a simple crate called `rust-lib`. Importing this crate into your
+[CMakeLists.txt](test/rust2cpp/CMakeLists.txt) is trivial:
+```cmake
+# Note: you must have already included Corrosion for `corrosion_import_crate` to be available. See # the `Installation` section above.
+
+corrosion_import_crate(MANIFEST_PATH rust/Cargo.toml)
+```
+
+Now that you've imported the crate into CMake, all of the executables, static libraries, and dynamic
+libraries defined in the Rust can be directly referenced. So, merely define your C++ executable as
+normal in CMake and add your crate's library using target_link_libraries:
+```cmake
+add_executable(cpp-exe main.cpp)
+target_link_libraries(cpp-exe PUBLIC rust-lib)
+```
+
+That's it! You're now linking your Rust library to your C++ library.
+
+#### Generate Bindings to Rust Library Automatically
+
+Currently, you must manually declare bindings in your C or C++ program to the exported routines and
+types in your Rust project. You can see boths sides of this in
+[the Rust code](test/rust2cpp/rust2cpp/rust/src/lib.rs) and in [the C++ code](test/rust2cpp/rust2cpp/main.cpp).
+
+Integration with [cbindgen](https://github.com/eqrion/cbindgen) is
+planned for the future.
+
+### Importing Libraries Written in C and C++ Into Rust
+
+The rust targets can be imported with `corrosion_import_crate()` into CMake.
+For targets where the linker should be invoked by Rust corrosion provides
+`corrosion_link_libraries()` to link your C/C++ libraries with the Rust target.
+For additional linker flags you may use `corrosion_add_target_local_rustflags()`
+and pass linker arguments via the `-Clink-args` flag to rustc. These flags will
+only be passed to the final rustc invocation and not affect any rust dependencies.
+
+C bindings can be generated via [bindgen](https://github.com/rust-lang/rust-bindgen).
+Corrosion does not offer any direct integration yet, but you can either generate the
+bindings in the build-script of your crate, or generate the bindings as a CMake build step
+(e.g. a custom target) and add a dependency from `cargo-prebuild_<rust_target>` to your
+custom target for generating the bindings.
+
+Example:
+
+```cmake
+# Import your Rust targets
+corrosion_import_crate(MANIFEST_PATH rust/Cargo.toml)
+# Link C/C++ libraries with your Rust target
+corrosion_link_libraries(target_name c_library)
+# Optionally explicitly define which linker to use.
+corrosion_set_linker(target_name your_custom_linker)
+# Optionally set linker arguments
+corrosion_add_target_local_rustflags(target_name "-Clink-args=<linker arguments>")
+# Optionally tell CMake that the rust crate depends on another target (e.g. a code generator)
+add_dependencies(cargo-prebuild_<target_name> custom_bindings_target)
+```
+
+### Cross Compiling
+Corrosion attempts to support cross-compiling as generally as possible, though not all
+configurations are tested. Cross-compiling is explicitly supported in the following scenarios.
+
+In all cases, you will need to install the standard library for the Rust target triple. When using
+Rustup, you can use it to install the target standard library:
+
+```bash
+rustup target add <target-rust-triple>
+```
+
+If the target triple is automatically derived, Corrosion will print the target during configuration.
+For example:
+
+```
+-- Rust Target: aarch64-linux-android
+```
+
+#### Windows-to-Windows
+Corrosion supports cross-compiling between arbitrary Windows architectures using the Visual Studio
+Generator. For example, to cross-compile for ARM64 from any platform, simply set the `-A`
+architecture flag:
+
+```bash
+cmake -S. -Bbuild-arm64 -A ARM64
+cmake --build build-arm64
+```
+
+Please note that for projects containing a build-script at least Rust 1.54 is required due to a bug
+in previous cargo versions, which causes the build-script to incorrectly be built for the target
+platform.
+
+#### Linux-to-Linux
+In order to cross-compile on Linux, you will need to install a cross-compiler. For example, on
+Ubuntu, to cross compile for 64-bit Little-Endian PowerPC Little-Endian, install
+`g++-powerpc64le-linux-gnu` from apt-get:
+
+```bash
+sudo apt install g++-powerpc64le-linux-gnu
+```
+
+Currently, Corrosion does not automatically determine the target triple while cross-compiling on
+Linux, so you'll need to specify a matching `Rust_CARGO_TARGET`.
+
+```bash
+cmake -S. -Bbuild-ppc64le -DRust_CARGO_TARGET=powerpc64le-unknown-linux-gnu -DCMAKE_CXX_COMPILER=powerpc64le-linux-gnu-g++
+cmake --build build-ppc64le
+```
+
+#### Android
+
+Cross-compiling for Android is supported on all platforms with the Makefile and Ninja generators,
+and the Rust target triple will automatically be selected. The CMake
+[cross-compiling instructions for Android](https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html#cross-compiling-for-android)
+apply here. For example, to build for ARM64:
+
+```bash
+cmake -S. -Bbuild-android-arm64 -GNinja -DCMAKE_SYSTEM_NAME=Android \
+      -DCMAKE_ANDROID_NDK=/path/to/android-ndk-rxxd -DCMAKE_ANDROID_ARCH_ABI=arm64-v8a
+```
+
+**Important note:** The Android SDK ships with CMake 3.10 at newest, which Android Studio will
+prefer over any CMake you've installed locally. CMake 3.10 is insufficient for using Corrosion,
+which requires a minimum of CMake 3.15. If you're using Android Studio to build your project,
+follow the instructions in the Android Studio documentation for
+[using a specific version of CMake](https://developer.android.com/studio/projects/install-ndk#vanilla_cmake).
+
+
+### CMake `OUTPUT_DIRECTORY` target properties and `IMPORTED_LOCATION`
+
+Corrosion respects the following `OUTPUT_DIRECTORY` target properties on CMake >= 3.19:
+-   [ARCHIVE_OUTPUT_DIRECTORY](https://cmake.org/cmake/help/latest/prop_tgt/ARCHIVE_OUTPUT_DIRECTORY.html)
+-   [LIBRARY_OUTPUT_DIRECTORY](https://cmake.org/cmake/help/latest/prop_tgt/LIBRARY_OUTPUT_DIRECTORY.html)
+-   [RUNTIME_OUTPUT_DIRECTORY](https://cmake.org/cmake/help/latest/prop_tgt/RUNTIME_OUTPUT_DIRECTORY.html)
+-   [PDB_OUTPUT_DIRECTORY](https://cmake.org/cmake/help/latest/prop_tgt/PDB_OUTPUT_DIRECTORY.html)
+
+If the target property is set (e.g. by defining the `CMAKE_XYZ_OUTPUT_DIRECTORY` variable before calling
+`corrosion_import_crate()`), corrosion will copy the built rust artifacts to the location defined in the
+target property.
+Due to limitations in CMake these target properties are evaluated in a deferred manner, to
+support the user setting the target properties after the call to `corrosion_import_crate()`.
+This has the side effect that the `IMPORTED_LOCATION` property will be set late, and users should not
+use `get_property` to read `IMPORTED_LOCATION` at configure time. Instead, generator expressions
+should be used to get the location of the target artifact.
+If `IMPORTED_LOCATION` is needed at configure time users may use `cmake_language(DEFER CALL ...)` to defer
+evaluation to after the `IMPORTED_LOCATION` property is set.