1 # `aarch64-fuchsia` and `x86_64-fuchsia`
5 [Fuchsia] is a modern open source operating system that's simple, secure,
6 updatable, and performant.
12 - Tyler Mandry ([@tmandry](https://github.com/tmandry))
13 - Dan Johnson ([@computerdruid](https://github.com/computerdruid))
14 - David Koloski ([@djkoloski](https://github.com/djkoloski))
15 - Andrew Pollack ([@andrewpollack](https://github.com/andrewpollack))
16 - Joseph Ryan ([@P1n3appl3](https://github.com/P1n3appl3))
18 As the team evolves over time, the specific members listed here may differ from
19 the members reported by the API. The API should be considered to be
20 authoritative if this occurs. Instead of pinging individual members, use
21 `@rustbot ping fuchsia` to contact the team on GitHub.
25 1. [Requirements](#requirements)
26 1. [Walkthrough structure](#walkthrough-structure)
27 1. [Compiling a Rust binary targeting Fuchsia](#compiling-a-rust-binary-targeting-fuchsia)
28 1. [Targeting Fuchsia with rustup and cargo](#targeting-fuchsia-with-rustup-and-cargo)
29 1. [Targeting Fuchsia with a compiler built from source](#targeting-fuchsia-with-a-compiler-built-from-source)
30 1. [Creating a Fuchsia package](#creating-a-fuchsia-package)
31 1. [Creating a Fuchsia component](#creating-a-fuchsia-component)
32 1. [Building a Fuchsia package](#building-a-fuchsia-package)
33 1. [Publishing a Fuchsia package](#publishing-a-fuchsia-package)
34 1. [Creating a Fuchsia package repository](#creating-a-fuchsia-package-repository)
35 1. [Publishing Fuchsia package to repository](#publishing-fuchsia-package-to-repository)
36 1. [Running a Fuchsia component on an emulator](#running-a-fuchsia-component-on-an-emulator)
37 1. [Starting the Fuchsia emulator](#starting-the-fuchsia-emulator)
38 1. [Watching emulator logs](#watching-emulator-logs)
39 1. [Serving a Fuchsia package](#serving-a-fuchsia-package)
40 1. [Running a Fuchsia component](#running-a-fuchsia-component)
41 1. [`.gitignore` extensions](#gitignore-extensions)
42 1. [Testing](#testing)
43 1. [Running unit tests](#running-unit-tests)
44 1. [Running the compiler test suite](#running-the-compiler-test-suite)
48 This target is cross-compiled from a host environment. You will need a recent
49 copy of the [Fuchsia SDK], which provides the tools, libraries, and binaries
50 required to build and link programs for Fuchsia.
52 Development may also be done from the [source tree].
54 Fuchsia targets support `std` and follow the `sysv64` calling convention on
55 x86_64. Fuchsia binaries use the ELF file format.
57 ## Walkthrough structure
59 This walkthrough will cover:
61 1. Compiling a Rust binary targeting Fuchsia.
62 1. Building a Fuchsia package.
63 1. Publishing and running a Fuchsia package to a Fuchsia emulator.
65 For the purposes of this walkthrough, we will only target `x86_64-fuchsia`.
67 ## Compiling a Rust binary targeting Fuchsia
69 Today, there are two main ways to build a Rust binary targeting Fuchsia
70 using the Fuchsia SDK:
71 1. Allow [rustup] to handle the installation of Fuchsia targets for you.
72 1. Build a toolchain locally that can target Fuchsia.
74 ### Targeting Fuchsia with rustup and cargo
76 The easiest way to build a Rust binary targeting Fuchsia is by allowing [rustup]
77 to handle the installation of Fuchsia targets for you. This can be done by issuing
78 the following commands:
81 rustup target add x86_64-fuchsia
82 rustup target add aarch64-fuchsia
85 After installing our Fuchsia targets, we can now compile a Rust binary that targets
88 To create our Rust project, we can issue a standard `cargo` command as follows:
90 **From base working directory**
92 cargo new hello_fuchsia
95 The rest of this walkthrough will take place from `hello_fuchsia`, so we can
96 change into that directory now:
102 *Note: From this point onwards, all commands will be issued from the `hello_fuchsia/`
103 directory, and all `hello_fuchsia/` prefixes will be removed from references for sake of brevity.*
105 We can edit our `src/main.rs` to include a test as follows:
110 println!("Hello Fuchsia!");
115 assert_eq!(2 + 2, 4);
119 In addition to the standard workspace created, we will want to create a
120 `.cargo/config.toml` file to link necessary libraries
123 **`.cargo/config.toml`**
125 [target.x86_64-fuchsia]
128 "-Lnative=<SDK_PATH>/arch/x64/lib",
129 "-Lnative=<SDK_PATH>/arch/x64/sysroot/lib"
133 *Note: Make sure to fill out `<SDK_PATH>` with the path to the downloaded [Fuchsia SDK].*
135 These options configure the following:
137 * `-Lnative=${SDK_PATH}/arch/${ARCH}/lib`: Link against Fuchsia libraries from
139 * `-Lnative=${SDK_PATH}/arch/${ARCH}/sysroot/lib`: Link against Fuchsia kernel
140 libraries from the SDK
142 In total, our new project will look like:
144 **Current directory structure**
154 Finally, we can build our rust binary as:
157 cargo build --target x86_64-fuchsia
160 Now we have a Rust binary at `target/x86_64-fuchsia/debug/hello_fuchsia`,
161 targeting our desired Fuchsia target.
163 **Current directory structure**
177 ### Targeting Fuchsia with a compiler built from source
179 An alternative to the first workflow is to target Fuchsia by using
180 `rustc` built from source.
182 Before building Rust for Fuchsia, you'll need a clang toolchain that supports
183 Fuchsia as well. A recent version (14+) of clang should be sufficient to compile
186 x86-64 and AArch64 Fuchsia targets can be enabled using the following
189 In `config.toml`, add:
193 target = ["<host_platform>", "aarch64-fuchsia", "x86_64-fuchsia"]
196 Additionally, the following environment variables must be configured (for
197 example, using a script like `config-env.sh`):
200 # Configure this environment variable to be the path to the downloaded SDK
201 export SDK_PATH="<SDK path goes here>"
203 export CFLAGS_aarch64_fuchsia="--target=aarch64-fuchsia --sysroot=${SDK_PATH}/arch/arm64/sysroot -I${SDK_PATH}/pkg/fdio/include"
204 export CXXFLAGS_aarch64_fuchsia="--target=aarch64-fuchsia --sysroot=${SDK_PATH}/arch/arm64/sysroot -I${SDK_PATH}/pkg/fdio/include"
205 export LDFLAGS_aarch64_fuchsia="--target=aarch64-fuchsia --sysroot=${SDK_PATH}/arch/arm64/sysroot -L${SDK_PATH}/arch/arm64/lib"
206 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"
207 export CFLAGS_x86_64_fuchsia="--target=x86_64-fuchsia --sysroot=${SDK_PATH}/arch/x64/sysroot -I${SDK_PATH}/pkg/fdio/include"
208 export CXXFLAGS_x86_64_fuchsia="--target=x86_64-fuchsia --sysroot=${SDK_PATH}/arch/x64/sysroot -I${SDK_PATH}/pkg/fdio/include"
209 export LDFLAGS_x86_64_fuchsia="--target=x86_64-fuchsia --sysroot=${SDK_PATH}/arch/x64/sysroot -L${SDK_PATH}/arch/x64/lib"
210 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"
213 These can be run together in a shell environment by executing
214 `(source config-env.sh && ./x.py install)`.
216 Once `rustc` is installed, we can create a new working directory to work from,
217 `hello_fuchsia` along with `hello_fuchsia/src`:
225 *Note: From this point onwards, all commands will be issued from the `hello_fuchsia/`
226 directory, and all `hello_fuchsia/` prefixes will be removed from references for sake of brevity.*
228 There, we can create a new file named `src/hello_fuchsia.rs`:
230 **`src/hello_fuchsia.rs`**
233 println!("Hello Fuchsia!");
238 assert_eq!(2 + 2, 4);
242 **Current directory structure**
249 Using your freshly installed `rustc`, you can compile a binary for Fuchsia using
250 the following options:
252 * `--target x86_64-fuchsia`/`--target aarch64-fuchsia`: Targets the Fuchsia
253 platform of your choice
254 * `-Lnative ${SDK_PATH}/arch/${ARCH}/lib`: Link against Fuchsia libraries from
256 * `-Lnative ${SDK_PATH}/arch/${ARCH}/sysroot/lib`: Link against Fuchsia kernel
257 libraries from the SDK
259 Putting it all together:
262 # Configure these for the Fuchsia target of your choice
263 TARGET_ARCH="<x86_64-fuchsia|aarch64-fuchsia>"
267 --target ${TARGET_ARCH} \
268 -Lnative=${SDK_PATH}/arch/${ARCH}/lib \
269 -Lnative=${SDK_PATH}/arch/${ARCH}/sysroot/lib \
270 --out-dir bin src/hello_fuchsia.rs
273 **Current directory structure**
277 ┃ ┗━ hello_fuchsia.rs
282 ## Creating a Fuchsia package
284 Before moving on, double check your directory structure:
286 **Current directory structure**
289 ┣━ src/ (if using rustc)
290 ┃ ┗━ hello_fuchsia.rs ...
292 ┃ ┗━ hello_fuchsia ...
293 ┣━ src/ (if using cargo)
296 ┗━ x86_64-fuchsia/ ...
301 With our Rust binary built, we can move to creating a Fuchsia package.
302 On Fuchsia, a package is the unit of distribution for software. We'll need to
303 create a new package directory where we will place files like our finished
304 binary and any data it may need.
306 To start, make the `pkg`, and `pkg/meta` directories:
313 **Current directory structure**
320 Now, create the following files inside:
322 **`pkg/meta/package`**
325 "name": "hello_fuchsia",
330 The `package` file describes our package's name and version number. Every
331 package must contain one.
333 **`pkg/hello_fuchsia.manifest`**
335 bin/hello_fuchsia=target/x86_64-fuchsia/debug/hello_fuchsia # If using cargo...
336 bin/hello_fuchsia=bin/hello_fuchsia # If using rustc...
337 lib/ld.so.1=<SDK_PATH>/arch/x64/sysroot/dist/lib/ld.so.1
338 lib/libfdio.so=<SDK_PATH>/arch/x64/dist/libfdio.so
339 meta/package=pkg/meta/package
340 meta/hello_fuchsia.cm=pkg/meta/hello_fuchsia.cm
343 *Note: Relative manifest paths are resolved starting from the working directory
344 of `pm`. Make sure to fill out `<SDK_PATH>` with the path to the downloaded
347 The `.manifest` file will be used to describe the contents of the package by
348 relating their location when installed to their location on the file system. The
349 `bin/hello_fuchsia=` entry will be different depending on how your Rust binary
350 was built, so choose accordingly.
352 **Current directory structure**
358 ┗━ hello_fuchsia.manifest
361 ### Creating a Fuchsia component
363 On Fuchsia, components require a component manifest written in Fuchsia's markup
364 language called CML. The Fuchsia devsite contains an [overview of CML] and a
365 [reference for the file format]. Here's a basic one that can run our single binary:
367 **`pkg/hello_fuchsia.cml`**
370 include: [ "syslog/client.shard.cml" ],
373 binary: "bin/hello_fuchsia",
378 **Current directory structure**
384 ┣━ hello_fuchsia.manifest
388 Now we can compile that CML into a component manifest:
391 ${SDK_PATH}/tools/${ARCH}/cmc compile \
392 pkg/hello_fuchsia.cml \
393 --includepath ${SDK_PATH}/pkg \
394 -o pkg/meta/hello_fuchsia.cm
397 *Note: `--includepath` tells the compiler where to look for `include`s from our CML.
398 In our case, we're only using `syslog/client.shard.cml`.*
400 **Current directory structure**
406 ┃ ┗━ hello_fuchsia.cm
407 ┣━ hello_fuchsia.manifest
411 ### Building a Fuchsia package
413 Next, we'll build a package manifest as defined by our manifest:
416 ${SDK_PATH}/tools/${ARCH}/pm \
417 -o pkg/hello_fuchsia_manifest \
418 -m pkg/hello_fuchsia.manifest \
420 -output-package-manifest pkg/hello_fuchsia_package_manifest
423 This will produce `pkg/hello_fuchsia_manifest/` which is a package manifest we can
424 publish directly to a repository.
426 **Current directory structure**
432 ┃ ┗━ hello_fuchsia.cm
433 ┣━ hello_fuchsia_manifest/
435 ┣━ hello_fuchsia.manifest
437 ┗━ hello_fuchsia_package_manifest
440 We are now ready to publish the package.
442 ## Publishing a Fuchsia package
444 With our package and component manifests setup,
445 we can now publish our package. The first step will
446 be to create a Fuchsia package repository to publish
449 ### Creating a Fuchsia package repository
451 We can set up our repository with:
454 ${SDK_PATH}/tools/${ARCH}/pm newrepo \
458 **Current directory structure**
464 ┃ ┗━ hello_fuchsia.cm
465 ┣━ hello_fuchsia_manifest/
469 ┣━ hello_fuchsia.manifest
471 ┗━ hello_fuchsia_package_manifest
474 ## Publishing Fuchsia package to repository
476 We can publish our new package to that repository with:
479 ${SDK_PATH}/tools/${ARCH}/pm publish \
481 -lp -f <(echo "pkg/hello_fuchsia_package_manifest")
484 Then we can add the repository to `ffx`'s package server as `hello-fuchsia` using:
487 ${SDK_PATH}/tools/${ARCH}/ffx repository add-from-pm \
492 ## Running a Fuchsia component on an emulator
494 At this point, we are ready to run our Fuchsia
495 component. For reference, our final directory
496 structure will look like:
498 **Final directory structure**
501 ┣━ src/ (if using rustc)
502 ┃ ┗━ hello_fuchsia.rs ...
504 ┃ ┗━ hello_fuchsia ...
505 ┣━ src/ (if using cargo)
508 ┃ ┗━ x86_64-fuchsia/ ...
510 ┃ ┗━ hello_fuchsia ...
514 ┃ ┗━ hello_fuchsia.cm
515 ┣━ hello_fuchsia_manifest/
519 ┣━ hello_fuchsia.manifest
521 ┗━ hello_fuchsia_package_manifest
524 ### Starting the Fuchsia emulator
526 Start a Fuchsia emulator in a new terminal using:
529 ${SDK_PATH}/tools/${ARCH}/ffx product-bundle get workstation_eng.qemu-${ARCH}
530 ${SDK_PATH}/tools/${ARCH}/ffx emu start workstation_eng.qemu-${ARCH} --headless
533 ### Watching emulator logs
535 Once the emulator is running, open a separate terminal to watch the emulator logs:
537 **In separate terminal**
539 ${SDK_PATH}/tools/${ARCH}/ffx log \
543 ### Serving a Fuchsia package
545 Now, start a package repository server to serve our
546 package to the emulator:
549 ${SDK_PATH}/tools/${ARCH}/ffx repository server start
552 Once the repository server is up and running, register it with the target Fuchsia system running in the emulator:
555 ${SDK_PATH}/tools/${ARCH}/ffx target repository register \
556 --repository hello-fuchsia
559 ### Running a Fuchsia component
561 Finally, run the component:
564 ${SDK_PATH}/tools/${ARCH}/ffx component run \
565 fuchsia-pkg://hello-fuchsia/hello_fuchsia_manifest#meta/hello_fuchsia.cm
568 On reruns of the component, the `--recreate` argument may also need to be
572 ${SDK_PATH}/tools/${ARCH}/ffx component run \
574 fuchsia-pkg://hello-fuchsia/hello_fuchsia_manifest#meta/hello_fuchsia.cm
577 ## `.gitignore` extensions
579 Optionally, we can create/extend our `.gitignore` file to ignore files and
580 directories that are not helpful to track:
584 pkg/meta/hello_fuchsia.cm
585 pkg/hello_fuchsia_manifest
586 pkg/hello_fuchsia_package_manifest
591 ### Running unit tests
593 Tests can be run in the same way as a regular binary.
595 * If using `cargo`, you can simply pass `test --no-run`
596 to the `cargo` invocation and then repackage and rerun the Fuchsia package. From our previous example,
597 this would look like `cargo test --target x86_64-fuchsia --no-run`, and moving the executable
598 binary path found from the line `Executable unittests src/main.rs (target/x86_64-fuchsia/debug/deps/hello_fuchsia-<HASH>)`
599 into `pkg/hello_fuchsia.manifest`.
601 * If using the compiled `rustc`, you can simply pass `--test`
602 to the `rustc` invocation and then repackage and rerun the Fuchsia package.
604 The test harness will run the applicable unit tests.
606 Often when testing, you may want to pass additional command line arguments to
607 your binary. Additional arguments can be set in the component manifest:
609 **`pkg/hello_fuchsia.cml`**
612 include: [ "syslog/client.shard.cml" ],
615 binary: "bin/hello_fuchsia",
621 This will pass the argument `it_works` to the binary, filtering the tests to
622 only those tests that match the pattern. There are many more configuration
623 options available in CML including environment variables. More documentation is
624 available on the [Fuchsia devsite].
626 ### Running the compiler test suite
628 Running the Rust test suite on Fuchsia is [not currently supported], but work is
629 underway to enable it.
631 [Fuchsia team]: https://team-api.infra.rust-lang.org/v1/teams/fuchsia.json
632 [Fuchsia]: https://fuchsia.dev/
633 [source tree]: https://fuchsia.dev/fuchsia-src/get-started/learn/build
634 [rustup]: https://rustup.rs/
635 [cargo]: https://doc.rust-lang.org/cargo/
636 [Fuchsia SDK]: https://chrome-infra-packages.appspot.com/p/fuchsia/sdk/core
637 [overview of CML]: https://fuchsia.dev/fuchsia-src/concepts/components/v2/component_manifests
638 [reference for the file format]: https://fuchsia.dev/reference/cml
639 [Fuchsia devsite]: https://fuchsia.dev/reference/cml
640 [not currently supported]: https://fxbug.dev/105393