|
| 1 | +# `aarch64-fuchsia` and `x86_64-fuchsia` |
| 2 | + |
| 3 | +**Tier: 2** |
| 4 | + |
| 5 | +[Fuchsia] is a modern open source operating system that's simple, secure, |
| 6 | +updatable, and performant. |
| 7 | + |
| 8 | +[Fuchsia]: https://fuchsia.dev/ |
| 9 | + |
| 10 | +## Target maintainers |
| 11 | + |
| 12 | +The [Fuchsia team]: |
| 13 | + |
| 14 | +[Fuchsia team]: https://team-api.infra.rust-lang.org/v1/teams/fuchsia.json |
| 15 | + |
| 16 | +- Tyler Mandry ([@tmandry](https://github.com/tmandry)) |
| 17 | +- Dan Johnson ([@computerdruid](https://github.com/computerdruid)) |
| 18 | +- David Koloski ([@djkoloski](https://github.com/djkoloski)) |
| 19 | +- Andrew Pollack ([@andrewpollack](https://github.com/andrewpollack)) |
| 20 | +- Joseph Ryan ([@P1n3appl3](https://github.com/P1n3appl3)) |
| 21 | + |
| 22 | +As the team evolves over time, the specific members listed here may differ from |
| 23 | +the members reported by the API. The API should be considered to be |
| 24 | +authoritative if this occurs. Instead of pinging individual members, use |
| 25 | +`@rustbot ping fuchsia` to contact the team on GitHub. |
| 26 | + |
| 27 | +## Requirements |
| 28 | + |
| 29 | +This target is cross-compiled from a host environment. Development may be done |
| 30 | +from the [source tree] or using the Fuchsia SDK. |
| 31 | + |
| 32 | +[source tree]: https://fuchsia.dev/fuchsia-src/get-started/learn/build |
| 33 | + |
| 34 | +Fuchsia targets support std and follow the `sysv64` calling convention on |
| 35 | +x86_64. Fuchsia binaries use the ELF file format. |
| 36 | + |
| 37 | +## Building the target |
| 38 | + |
| 39 | +Before building Rust for Fuchsia, you'll need a clang toolchain that supports |
| 40 | +Fuchsia as well. A recent version (14+) of clang should be sufficient to compile |
| 41 | +Rust for Fuchsia. |
| 42 | + |
| 43 | +You'll also need a recent copy of the [Fuchsia SDK], which provides the tools |
| 44 | +and binaries required to build and link programs for Fuchsia. |
| 45 | + |
| 46 | +[Fuchsia SDK]: https://chrome-infra-packages.appspot.com/p/fuchsia/sdk/core |
| 47 | + |
| 48 | +x86-64 and AArch64 Fuchsia targets can be enabled using the following |
| 49 | +configuration. |
| 50 | + |
| 51 | +In `config.toml`, add: |
| 52 | + |
| 53 | +```toml |
| 54 | +[build] |
| 55 | +target = ["<host_platform>", "aarch64-fuchsia", "x86_64-fuchsia"] |
| 56 | + |
| 57 | +[target.x86_64-fuchsia] |
| 58 | +llvm-libunwind = "in-tree" |
| 59 | + |
| 60 | +[target.aarch64-fuchsia] |
| 61 | +llvm-libunwind = "in-tree" |
| 62 | +``` |
| 63 | + |
| 64 | +Additionally, the following environment variables must be configured (for |
| 65 | +example, using a script like `config-env.sh`): |
| 66 | + |
| 67 | +```sh |
| 68 | +# Configure this environment variable to be the path to the downloaded SDK |
| 69 | +export SDK_PATH="<SDK path goes here>" |
| 70 | + |
| 71 | +export CFLAGS_aarch64_fuchsia="--target=aarch64-fuchsia --sysroot=${SDK_PATH}/arch/arm64/sysroot -I${SDK_PATH}/pkg/fdio/include" |
| 72 | +export CXXFLAGS_aarch64_fuchsia="--target=aarch64-fuchsia --sysroot=${SDK_PATH}/arch/arm64/sysroot -I${SDK_PATH}/pkg/fdio/include" |
| 73 | +export LDFLAGS_aarch64_fuchsia="--target=aarch64-fuchsia --sysroot=${SDK_PATH}/arch/arm64/sysroot -L${SDK_PATH}/arch/arm64/lib" |
| 74 | +export CARGO_TARGET_AARCH64_FUCHSIA_RUSTFLAGS="-C link-arg=--sysroot=${SDK_PATH}/arch/arm64/sysroot -Lnative=${SDK_PATH}/arch/arm64/sysroot/lib -Lnative=${SDK_PATH}/arch/arm64/lib" |
| 75 | +export CFLAGS_x86_64_fuchsia="--target=x86_64-fuchsia --sysroot=${SDK_PATH}/arch/x64/sysroot -I${SDK_PATH}/pkg/fdio/include" |
| 76 | +export CXXFLAGS_x86_64_fuchsia="--target=x86_64-fuchsia --sysroot=${SDK_PATH}/arch/x64/sysroot -I${SDK_PATH}/pkg/fdio/include" |
| 77 | +export LDFLAGS_x86_64_fuchsia="--target=x86_64-fuchsia --sysroot=${SDK_PATH}/arch/x64/sysroot -L${SDK_PATH}/arch/x64/lib" |
| 78 | +export CARGO_TARGET_X86_64_FUCHSIA_RUSTFLAGS="-C link-arg=--sysroot=${SDK_PATH}/arch/x64/sysroot -Lnative=${SDK_PATH}/arch/x64/sysroot/lib -Lnative=${SDK_PATH}/arch/x64/lib" |
| 79 | +``` |
| 80 | + |
| 81 | +These can be run together in a shell environment by executing |
| 82 | +`(source config-env.sh && ./x.py install)`. |
| 83 | + |
| 84 | +## Building Rust programs |
| 85 | + |
| 86 | +After compiling Rust binaries, you'll need to build a component, package it, and |
| 87 | +serve it to a Fuchsia device or emulator. All of this can be done using the |
| 88 | +Fuchsia SDK. |
| 89 | + |
| 90 | +As an example, we'll compile and run this simple program on a Fuchsia emulator: |
| 91 | + |
| 92 | +**`hello_fuchsia.rs`** |
| 93 | +```rust |
| 94 | +fn main() { |
| 95 | + println!("Hello Fuchsia!"); |
| 96 | +} |
| 97 | + |
| 98 | +#[test] |
| 99 | +fn it_works() { |
| 100 | + assert_eq!(2 + 2, 4); |
| 101 | +} |
| 102 | +``` |
| 103 | + |
| 104 | +Create a new file named `hello_fuchsia.rs` and fill out its contents with that |
| 105 | +code. |
| 106 | + |
| 107 | +### Create a package |
| 108 | + |
| 109 | +On Fuchsia, a package is the unit of distribution for software. We'll need to |
| 110 | +create a new package directory where we will place files like our finished |
| 111 | +binary and any data it may need. The working directory will have this layout: |
| 112 | + |
| 113 | +```txt |
| 114 | +hello_fuchsia.rs |
| 115 | +hello_fuchsia.cml |
| 116 | +package |
| 117 | +┣━ bin |
| 118 | +┃ ┗━ hello_fuchsia |
| 119 | +┣━ meta |
| 120 | +┃ ┣━ package |
| 121 | +┃ ┗━ hello_fuchsia.cm |
| 122 | +┗━ hello_fuchsia.manifest |
| 123 | +``` |
| 124 | + |
| 125 | +Make the `package`, `package/bin`, and `package/meta` directories and create the |
| 126 | +following files inside: |
| 127 | + |
| 128 | +**`package/meta/package`** |
| 129 | +```json |
| 130 | +{"name":"hello_fuchsia","version":0} |
| 131 | +``` |
| 132 | + |
| 133 | +The `package` file describes our package's name and version number. Every |
| 134 | +package must contain one. |
| 135 | + |
| 136 | +**`package/hello_fuchsia.manifest`** |
| 137 | +```txt |
| 138 | +bin/hello_fuchsia=package/bin/hello_fuchsia |
| 139 | +lib/ld.so.1=<SDK_PATH>/arch/x64/sysroot/dist/lib/ld.so.1 |
| 140 | +lib/libfdio.so=<SDK_PATH>/arch/x64/dist/libfdio.so |
| 141 | +meta/package=package/meta/package |
| 142 | +meta/hello_fuchsia.cm=package/meta/hello_fuchsia.cm |
| 143 | +``` |
| 144 | + |
| 145 | +*Note: Relative manifest paths are resolved starting from the working directory |
| 146 | +of `pm`. Make sure to fill out `<SDK_PATH>` with the path to the downloaded |
| 147 | +SDK.* |
| 148 | + |
| 149 | +The `.manifest` file will be used to describe the contents of the package by |
| 150 | +relating their location when installed to their location on the file system. You |
| 151 | +can use this to make a package pull files from other places, but for this |
| 152 | +example we'll just be placing everything in the `package` directory. |
| 153 | + |
| 154 | +### Compiling a binary |
| 155 | + |
| 156 | +Using your freshly compiled `rustc`, you can compile a binary for Fuchsia using |
| 157 | +the following options: |
| 158 | + |
| 159 | +* `--target x86_64-fuchsia`/`--target aarch64-fuchsia`: Targets the Fuchsia |
| 160 | + platform of your choice |
| 161 | +* `-Lnative ${SDK_PATH}/arch/${ARCH}/lib`: Link against Fuchsia libraries from |
| 162 | + the SDK |
| 163 | +* `-Lnative ${SDK_PATH}/arch/${ARCH}/sysroot/lib`: Link against Fuchsia kernel |
| 164 | + libraries from the SDK |
| 165 | + |
| 166 | +Putting it all together: |
| 167 | + |
| 168 | +```sh |
| 169 | +# Configure these for the Fuchsia target of your choice |
| 170 | +TARGET_ARCH="<x86_64-fuchsia|aarch64-fuchsia>" |
| 171 | +ARCH="<x64|aarch64>" |
| 172 | + |
| 173 | +rustc --target ${TARGET_ARCH} -Lnative=${SDK_PATH}/arch/${ARCH}/lib -Lnative=${SDK_PATH}/arch/${ARCH}/sysroot/lib -o package/bin/hello_fuchsia hello_fuchsia.rs |
| 174 | +``` |
| 175 | + |
| 176 | +### Bulding a component |
| 177 | + |
| 178 | +On Fuchsia, components require a component manifest written in Fuchia's markup |
| 179 | +language called CML. The Fuchsia devsite contains an [overview of CML] and a |
| 180 | +[reference for the file format]. Here's a basic one that can run our single binary: |
| 181 | + |
| 182 | +[overview of CML]: https://fuchsia.dev/fuchsia-src/concepts/components/v2/component_manifests |
| 183 | +[reference for the file format]: https://fuchsia.dev/reference/cml |
| 184 | + |
| 185 | +**`hello_fuchsia.cml`** |
| 186 | +```txt |
| 187 | +{ |
| 188 | + include: [ "syslog/client.shard.cml" ], |
| 189 | + program: { |
| 190 | + runner: "elf", |
| 191 | + binary: "bin/hello_fuchsia", |
| 192 | + }, |
| 193 | +} |
| 194 | +``` |
| 195 | + |
| 196 | +Now we can compile that CML into a component manifest: |
| 197 | + |
| 198 | +```sh |
| 199 | +${SDK_PATH}/tools/${ARCH}/cmc compile hello_fuchsia.cml --includepath ${SDK_PATH}/pkg -o package/meta/hello_fuchsia.cm |
| 200 | +``` |
| 201 | + |
| 202 | +`--includepath` tells the compiler where to look for `include`s from our CML. |
| 203 | +In our case, we're only using `syslog/client.shard.cml`. |
| 204 | + |
| 205 | +### Building and publishing a package |
| 206 | + |
| 207 | +Next, we'll build our package as defined by our manifest: |
| 208 | + |
| 209 | +```sh |
| 210 | +${SDK_PATH}/tools/${ARCH}/pm -o hello_fuchsia -m package/hello_fuchsia.manifest build -output-package-manifest hello_fuchsia_manifest |
| 211 | +``` |
| 212 | + |
| 213 | +This will produce `hello_fuchsia_manifest` which is a package manifest we can |
| 214 | +publish directly to a repository. We can set up that repository with: |
| 215 | + |
| 216 | +```sh |
| 217 | +${SDK_PATH}/tools/${ARCH}/pm newrepo -repo repo |
| 218 | +``` |
| 219 | + |
| 220 | +And then publish our new package to that repository with: |
| 221 | + |
| 222 | +```sh |
| 223 | +${SDK_PATH}/tools/${ARCH}/pm publish -repo repo -lp -f <(echo "hello_fuchsia_manifest") |
| 224 | +``` |
| 225 | + |
| 226 | +Then we can add it to `ffx`'s package server as `hello-fuchsia` using: |
| 227 | + |
| 228 | +```sh |
| 229 | +${SDK_PATH}/tools/${ARCH}/ffx repository add-from-pm repo -r hello-fuchsia |
| 230 | +``` |
| 231 | + |
| 232 | +### Starting the emulator |
| 233 | + |
| 234 | +Start a Fuchsia emulator in a new terminal using: |
| 235 | + |
| 236 | +```sh |
| 237 | +${SDK_PATH}/tools/${ARCH}/ffx product-bundle get workstation_eng.qemu-${ARCH} |
| 238 | +${SDK_PATH}/tools/${ARCH}/ffx emu start workstation_eng.qemu-${ARCH} --headless |
| 239 | +``` |
| 240 | + |
| 241 | +Then, once the emulator has been started: |
| 242 | + |
| 243 | +```sh |
| 244 | +${SDK_PATH}/tools/${ARCH}/ffx target repository register |
| 245 | +``` |
| 246 | + |
| 247 | +And watch the logs from the emulator in a separate terminal: |
| 248 | + |
| 249 | +```sh |
| 250 | +${SDK_PATH}/tools/${ARCH}/ffx log --since now |
| 251 | +``` |
| 252 | + |
| 253 | +Finally, run the component: |
| 254 | + |
| 255 | +```sh |
| 256 | +${SDK_PATH}/tools/${ARCH}/ffx component run fuchsia-pkg://hello-fuchsia/hello_fuchsia#meta/hello_fuchsia.cm |
| 257 | +``` |
| 258 | + |
| 259 | +On reruns of the component, the `--recreate` argument may also need to be |
| 260 | +passed. |
| 261 | + |
| 262 | +## Testing |
| 263 | + |
| 264 | +### Running unit tests |
| 265 | + |
| 266 | +Tests can be run in the same way as a regular binary, simply by passing `--test` |
| 267 | +to the `rustc` invocation and then repackaging and rerunning. The test harness |
| 268 | +will run the applicable unit tests. |
| 269 | + |
| 270 | +Often when testing, you may want to pass additional command line arguments to |
| 271 | +your binary. Additional arguments can be set in the component manifest: |
| 272 | + |
| 273 | +**`hello_fuchsia.cml`** |
| 274 | +```txt |
| 275 | +{ |
| 276 | + include: [ "syslog/client.shard.cml" ], |
| 277 | + program: { |
| 278 | + runner: "elf", |
| 279 | + binary: "bin/hello_fuchsia", |
| 280 | + args: ["it_works"], |
| 281 | + }, |
| 282 | +} |
| 283 | +``` |
| 284 | + |
| 285 | +This will pass the argument `it_works` to the binary, filtering the tests to |
| 286 | +only those tests that match the pattern. There are many more configuration |
| 287 | +options available in CML including environment variables. More documentation is |
| 288 | +available on the [Fuchsia devsite](https://fuchsia.dev/reference/cml). |
| 289 | + |
| 290 | +### Running the compiler test suite |
| 291 | + |
| 292 | +Running the Rust test suite on Fuchsia is [not currently supported], but work is |
| 293 | +underway to enable it. |
| 294 | + |
| 295 | +[not currently supported]: https://fxbug.dev/105393 |
0 commit comments