rust: Add README

Add a README.md to the rust subdirectory as a guideline for writing
s390-tools tools in Rust. This includes build integration, dependency
handling, and a few coding style hints. Rust related information
is also added to the main README.md.

Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
[hoeppner@linux.ibm.com: Adapt details in README.md]
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
Steffen Eiden
2023-07-17 12:53:51 +02:00
committed by Jan Höppner
parent dd82c26f87
commit 19c795be0d
2 changed files with 139 additions and 2 deletions

View File

@@ -310,13 +310,14 @@ build options:
| net-snmp | `HAVE_SNMP` | osasnmpd |
| glibc-static | `HAVE_LIBC_STATIC` | zfcpdump |
| openssl | `HAVE_OPENSSL` | genprotimg, zkey, libekmfweb, |
| | | libkmipclient, pvattest, zgetdump |
| | | libkmipclient, pvattest, zgetdump, |
| | | rust/pvsecret, |
| cryptsetup | `HAVE_CRYPTSETUP2` | zkey-cryptsetup |
| json-c | `HAVE_JSONC` | zkey-cryptsetup, libekmfweb, |
| | | libkmipclient |
| glib2 | `HAVE_GLIB2` | genprotimg, pvattest, zgetdump |
| libcurl | `HAVE_LIBCURL` | genprotimg, libekmfweb, libkmipclient,|
| | | pvattest |
| | | pvattest, rust/pvsecret, |
| libxml2 | `HAVE_LIBXML2` | libkmipclient |
| systemd | `HAVE_SYSTEMD` | hsavmcore |
| libudev | `HAVE_LIBUDEV` | cpacfstatsd |
@@ -340,6 +341,14 @@ Build and runtime requirements for specific tools
In the following more details on the build an runtime requirements of
the different tools are provided:
* rust/pvsecret:
For building pvsecret you need OpenSSL version 1.1.1 or newer
installed (openssl-devel.rpm). Also required is cargo and libcurl.
Tip: you may skip the pvsecret build by adding
`HAVE_OPENSSL=0`, `HAVE_LIBCURL=0`, or `HAVE_CARGO=0`.
The runtime requirements are: openssl-libs (>= 1.1.1).
* dbginfo.sh:
The tar package is required to archive collected data.

128
rust/README.md Normal file
View File

@@ -0,0 +1,128 @@
# s390-tools tools written in rust
## Setting up rust development and build environment
Please refer to the official documentation to set up a working rust environment:
https://www.rust-lang.org/learn/get-started
## Building rust code
### s390-tools build system
If `cargo` is installed a simple `make` should do the job. Note that,
compiling rust programs take significaltly longer than C code. To closely
monitor the prgress use `make V=1` By default release builds are made.
With `make CARGOFLAGS=<flags>` one can pass additional flags to cargo.
With `make HAVE_CARGO=0` one can turn of any compilation that requires cargo.
With `make CARGO=<...>` one can set the cargo binary
### cargo
If you need to run cargo directly, cd to each project you want to build and
issue your cargo commands. Do **NOT** forget to specify `--release` if you are
building tools for a release. The s390-tools expect the environment variable
`S390_TOOLS_RELEASE` to be present at build time. This is the version string the
rust tools provide.
Tpp: You can use `make version` to get the version string.
## Internal Libraries
* __utils__ _Library for rust tools that bundles common stuff for the 390-tools_
* currently only provides a macro to get the `S390_TOOLS_RELEASE` string
* __pv__ _Library for pv tools, providing uvdevice access, encryption utilities, and utilities for generating UV-request_
* requires openssl and libcurl for the feature `request`; use `HAVE_<OPENSSL|CURL>=0` to
disable build that use pv with the request feature.
## Tools
* __pvsecret__ _Manage secrets for IBM Secure Execution guests_
* requires pv with the `request` feature
## Writing new tools
We encourage to use Rust for new tools. However, for some use cases it makes
sense to use C and C is still allowed to be used for a new tool/library.
Exiting tools may be rewritten in Rust.
### What (third-party) crates can be used for s390-tools?
A huge list of libraries are made available through Rusts' ecosystem and is one
of many upsides. However, just like with Coding Style Guidlines, it is
important to limit the usage of those libraries so that within a project,
everyone is on the same page and that code written in Rust uses similar
approaches. It makes it easier for code review and maintainability in general.
The following list of crates should cover a wide variety of use cases. This list
is a start, but can change over time.
* [anyhow](https://crates.io/crates/anyhow)
* Flexible concrete Error type built on std::error::Error
* [byteorder](https://crates.io/crates/byteorder)
* Library for reading/writing numbers in big-endian and little-endian.
* [cfg-if](https://crates.io/crates/cfg-if)
* A macro to ergonomically define an item depending on a large number of
#[cfg] parameters. Structured like an if-else chain, the first matching
branch is the item that gets emitted.
* [clap](https://crates.io/crates/clap)
* A simple to use, efficient, and full-featured Command Line Argument Parser
* [curl](https://crates.io/crates/curl)
* Rust bindings to libcurl for making HTTP requests
* [libc](https://crates.io/crates/libc)
* Raw FFI bindings to platform libraries like libc.
* [log](https://crates.io/crates/log)
* A lightweight logging facade for Rust
* [openssl](https://crates.io/crates/openssl)
* OpenSSL bindings
* [serde](https://crates.io/crates/serde)
* A generic serialization/deserialization framework
* [serde_yaml](https://crates.io/crates/serde_yaml)
* YAML data format for Serde
* [thiserror](https://crates.io/crates/thiserror)
* derive(Error)
* [zerocopy](https://crates.io/crates/zerocopy)
* Utilities for zero-copy parsing and serialization
Dependencies used by the crates listed above can be used, too.
### Add new tool
To add a new tool issue `cargo new <TOOLNAME>` in the `rust` directory.
Add the tool to the _s390-tools_ build system:
```Makefile
CARGO_TARGETS := TOOLNAME
```
### Versions
Do not communicate the version defined in the `toml` file by default. Use
`release_string` from the `rust/utils` crate instead:
```rust
use utils::release_string;
fn print_version() {
println!(
"{} version {}\nCopyright IBM Corp. 2023",
env!("CARGO_PKG_NAME"), // collapes into the crates name
release_string!() // this (very likely) collapes into a compile time constant
);
}
```
### Unsafe rust
rust allows you to write unsafe rust. Try to avoid it, it can make rust
_unsafe_. If you need to, e.g. interacting with other languages like C, keep
the `unsafe` block as small as possible and add a reasoning using `// SAFETY:
`why this code is safe. Example:
```rust
// Get the raw pointer and do an ioctl.
//
// SAFETY: the passed pointer points to a valid memory region that
// contains the expected C-struct. The struct outlives this function.
unsafe {
let ptr: *mut ffi::uvio_ioctl_cb = cb as *mut _;
rc = ioctl(raw_fd, cmd, ptr);
}
```
### Coding style
Make `cargo fmt` and `cargo clippy` happy!
### Testing
Prefer writing tests using rustdoc. Use explicit rust tests for more edge case tests.