]> git.lizzy.rs Git - rust.git/blob - src/doc/rustc/src/platform-support/fuchsia.md
Auto merge of #105890 - Nilstrieb:inline-fmt-part-1, r=jackh726
[rust.git] / src / doc / rustc / src / platform-support / fuchsia.md
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 ## Target maintainers
9
10 The [Fuchsia team]:
11
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))
17
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.
22
23 ## Table of contents
24
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)
45 1. [Debugging](#debugging)
46     1. [`zxdb`](#zxdb)
47     1. [Attaching `zxdb`](#attaching-zxdb)
48     1. [Using `zxdb`](#using-zxdb)
49     1. [Displaying source code in `zxdb`](#displaying-source-code-in-zxdb)
50
51 ## Requirements
52
53 This target is cross-compiled from a host environment. You will need a recent
54 copy of the [Fuchsia SDK], which provides the tools, libraries, and binaries
55 required to build and link programs for Fuchsia.
56
57 Development may also be done from the [source tree].
58
59 Fuchsia targets support `std` and follow the `sysv64` calling convention on
60 x86_64. Fuchsia binaries use the ELF file format.
61
62 ## Walkthrough structure
63
64 This walkthrough will cover:
65
66 1. Compiling a Rust binary targeting Fuchsia.
67 1. Building a Fuchsia package.
68 1. Publishing and running a Fuchsia package to a Fuchsia emulator.
69
70 For the purposes of this walkthrough, we will only target `x86_64-fuchsia`.
71
72 ## Compiling a Rust binary targeting Fuchsia
73
74 Today, there are two main ways to build a Rust binary targeting Fuchsia
75 using the Fuchsia SDK:
76 1. Allow [rustup] to handle the installation of Fuchsia targets for you.
77 1. Build a toolchain locally that can target Fuchsia.
78
79 ### Targeting Fuchsia with rustup and cargo
80
81 The easiest way to build a Rust binary targeting Fuchsia is by allowing [rustup]
82 to handle the installation of Fuchsia targets for you. This can be done by issuing
83 the following commands:
84
85 ```sh
86 rustup target add x86_64-fuchsia
87 rustup target add aarch64-fuchsia
88 ```
89
90 After installing our Fuchsia targets, we can now compile a Rust binary that targets
91 Fuchsia.
92
93 To create our Rust project, we can use [`cargo`][cargo] as follows:
94
95 **From base working directory**
96 ```sh
97 cargo new hello_fuchsia
98 ```
99
100 The rest of this walkthrough will take place from `hello_fuchsia`, so we can
101 change into that directory now:
102
103 ```sh
104 cd hello_fuchsia
105 ```
106
107 *Note: From this point onwards, all commands will be issued from the `hello_fuchsia/`
108 directory, and all `hello_fuchsia/` prefixes will be removed from references for sake of brevity.*
109
110 We can edit our `src/main.rs` to include a test as follows:
111
112 **`src/main.rs`**
113 ```rust
114 fn main() {
115     println!("Hello Fuchsia!");
116 }
117
118 #[test]
119 fn it_works() {
120     assert_eq!(2 + 2, 4);
121 }
122 ```
123
124 In addition to the standard workspace created, we will want to create a
125 `.cargo/config.toml` file to link necessary libraries
126 during compilation:
127
128 **`.cargo/config.toml`**
129 ```txt
130 [target.x86_64-fuchsia]
131
132 rustflags = [
133     "-Lnative=<SDK_PATH>/arch/x64/lib",
134     "-Lnative=<SDK_PATH>/arch/x64/sysroot/lib"
135 ]
136 ```
137
138 *Note: Make sure to fill out `<SDK_PATH>` with the path to the downloaded [Fuchsia SDK].*
139
140 These options configure the following:
141
142 * `-Lnative=${SDK_PATH}/arch/${ARCH}/lib`: Link against Fuchsia libraries from
143   the SDK
144 * `-Lnative=${SDK_PATH}/arch/${ARCH}/sysroot/lib`: Link against Fuchsia sysroot
145   libraries from the SDK
146
147 In total, our new project will look like:
148
149 **Current directory structure**
150 ```txt
151 hello_fuchsia/
152 ┣━ src/
153 ┃  ┗━ main.rs
154 ┣━ Cargo.toml
155 ┗━ .cargo/
156    ┗━ config.toml
157 ```
158
159 Finally, we can build our rust binary as:
160
161 ```sh
162 cargo build --target x86_64-fuchsia
163 ```
164
165 Now we have a Rust binary at `target/x86_64-fuchsia/debug/hello_fuchsia`,
166 targeting our desired Fuchsia target.
167
168 **Current directory structure**
169 ```txt
170 hello_fuchsia/
171 ┣━ src/
172 ┃  ┗━ main.rs
173 ┣━ target/
174 ┃  ┗━ x86_64-fuchsia/
175 ┃     ┗━ debug/
176 ┃        ┗━ hello_fuchsia
177 ┣━ Cargo.toml
178 ┗━ .cargo/
179    ┗━ config.toml
180 ```
181
182 ### Targeting Fuchsia with a compiler built from source
183
184 An alternative to the first workflow is to target Fuchsia by using
185 `rustc` built from source.
186
187 Before building Rust for Fuchsia, you'll need a clang toolchain that supports
188 Fuchsia as well. A recent version (14+) of clang should be sufficient to compile
189 Rust for Fuchsia.
190
191 x86-64 and AArch64 Fuchsia targets can be enabled using the following
192 configuration in `config.toml`:
193
194 ```toml
195 [build]
196 target = ["<host_platform>", "aarch64-fuchsia", "x86_64-fuchsia"]
197
198 [rust]
199 lld = true
200
201 [llvm]
202 download-ci-llvm = false
203
204 [target.x86_64-fuchsia]
205 cc = "clang"
206 cxx = "clang++"
207
208 [target.aarch64-fuchsia]
209 cc = "clang"
210 cxx = "clang++"
211 ```
212
213 Though not strictly required, you may also want to use `clang` for your host
214 target as well:
215
216 ```toml
217 [target.<host_platform>]
218 cc = "clang"
219 cxx = "clang++"
220 ```
221
222 By default, the Rust compiler installs itself to `/usr/local` on most UNIX
223 systems. You may want to install it to another location (e.g. a local `install`
224 directory) by setting a custom prefix in `config.toml`:
225
226 ```toml
227 [install]
228 # Make sure to use the absolute path to your install directory
229 prefix = "<RUST_SRC_PATH>/install"
230 ```
231
232 Next, the following environment variables must be configured. For example, using
233 a script we name `config-env.sh`:
234
235 ```sh
236 # Configure this environment variable to be the path to the downloaded SDK
237 export SDK_PATH="<SDK path goes here>"
238
239 export CFLAGS_aarch64_fuchsia="--target=aarch64-fuchsia --sysroot=${SDK_PATH}/arch/arm64/sysroot -I${SDK_PATH}/pkg/fdio/include"
240 export CXXFLAGS_aarch64_fuchsia="--target=aarch64-fuchsia --sysroot=${SDK_PATH}/arch/arm64/sysroot -I${SDK_PATH}/pkg/fdio/include"
241 export LDFLAGS_aarch64_fuchsia="--target=aarch64-fuchsia --sysroot=${SDK_PATH}/arch/arm64/sysroot -L${SDK_PATH}/arch/arm64/lib"
242 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"
243 export CFLAGS_x86_64_fuchsia="--target=x86_64-fuchsia --sysroot=${SDK_PATH}/arch/x64/sysroot -I${SDK_PATH}/pkg/fdio/include"
244 export CXXFLAGS_x86_64_fuchsia="--target=x86_64-fuchsia --sysroot=${SDK_PATH}/arch/x64/sysroot -I${SDK_PATH}/pkg/fdio/include"
245 export LDFLAGS_x86_64_fuchsia="--target=x86_64-fuchsia --sysroot=${SDK_PATH}/arch/x64/sysroot -L${SDK_PATH}/arch/x64/lib"
246 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"
247 ```
248
249 Finally, the Rust compiler can be built and installed:
250
251 ```sh
252 (source config-env.sh && ./x.py install)
253 ```
254
255 Once `rustc` is installed, we can create a new working directory to work from,
256 `hello_fuchsia` along with `hello_fuchsia/src`:
257
258 ```sh
259 mkdir hello_fuchsia
260 cd hello_fuchsia
261 mkdir src
262 ```
263
264 *Note: From this point onwards, all commands will be issued from the `hello_fuchsia/`
265 directory, and all `hello_fuchsia/` prefixes will be removed from references for sake of brevity.*
266
267 There, we can create a new file named `src/hello_fuchsia.rs`:
268
269 **`src/hello_fuchsia.rs`**
270 ```rust
271 fn main() {
272     println!("Hello Fuchsia!");
273 }
274
275 #[test]
276 fn it_works() {
277     assert_eq!(2 + 2, 4);
278 }
279 ```
280
281 **Current directory structure**
282 ```txt
283 hello_fuchsia/
284 ┗━ src/
285     ┗━ hello_fuchsia.rs
286 ```
287
288 Using your freshly installed `rustc`, you can compile a binary for Fuchsia using
289 the following options:
290
291 * `--target x86_64-fuchsia`/`--target aarch64-fuchsia`: Targets the Fuchsia
292   platform of your choice
293 * `-Lnative ${SDK_PATH}/arch/${ARCH}/lib`: Link against Fuchsia libraries from
294   the SDK
295 * `-Lnative ${SDK_PATH}/arch/${ARCH}/sysroot/lib`: Link against Fuchsia sysroot
296   libraries from the SDK
297
298 Putting it all together:
299
300 ```sh
301 # Configure these for the Fuchsia target of your choice
302 TARGET_ARCH="<x86_64-fuchsia|aarch64-fuchsia>"
303 ARCH="<x64|aarch64>"
304
305 rustc \
306     --target ${TARGET_ARCH} \
307     -Lnative=${SDK_PATH}/arch/${ARCH}/lib \
308     -Lnative=${SDK_PATH}/arch/${ARCH}/sysroot/lib \
309     --out-dir bin src/hello_fuchsia.rs
310 ```
311
312 **Current directory structure**
313 ```txt
314 hello_fuchsia/
315 ┣━ src/
316 ┃   ┗━ hello_fuchsia.rs
317 ┗━ bin/
318    ┗━ hello_fuchsia
319 ```
320
321 ## Creating a Fuchsia package
322
323 Before moving on, double check your directory structure:
324
325 **Current directory structure**
326 ```txt
327 hello_fuchsia/
328 ┣━ src/                     (if using rustc)
329 ┃   ┗━ hello_fuchsia.rs     ...
330 ┣━ bin/                     ...
331 ┃  ┗━ hello_fuchsia         ...
332 ┣━ src/                     (if using cargo)
333 ┃  ┗━ main.rs               ...
334 ┗━ target/                  ...
335    ┗━ x86_64-fuchsia/       ...
336       ┗━ debug/             ...
337          ┗━ hello_fuchsia   ...
338 ```
339
340 With our Rust binary built, we can move to creating a Fuchsia package.
341 On Fuchsia, a package is the unit of distribution for software. We'll need to
342 create a new package directory where we will place files like our finished
343 binary and any data it may need.
344
345 To start, make the `pkg`, and `pkg/meta` directories:
346
347 ```sh
348 mkdir pkg
349 mkdir pkg/meta
350 ```
351
352 **Current directory structure**
353 ```txt
354 hello_fuchsia/
355 ┗━ pkg/
356    ┗━ meta/
357 ```
358
359 Now, create the following files inside:
360
361 **`pkg/meta/package`**
362 ```json
363 {
364   "name": "hello_fuchsia",
365   "version": "0"
366 }
367 ```
368
369 The `package` file describes our package's name and version number. Every
370 package must contain one.
371
372 **`pkg/hello_fuchsia.manifest` if using cargo**
373 ```txt
374 bin/hello_fuchsia=target/x86_64-fuchsia/debug/hello_fuchsia
375 lib/ld.so.1=<SDK_PATH>/arch/x64/sysroot/dist/lib/ld.so.1
376 lib/libfdio.so=<SDK_PATH>/arch/x64/dist/libfdio.so
377 meta/package=pkg/meta/package
378 meta/hello_fuchsia.cm=pkg/meta/hello_fuchsia.cm
379 ```
380
381 **`pkg/hello_fuchsia.manifest` if using rustc**
382 ```txt
383 bin/hello_fuchsia=bin/hello_fuchsia
384 lib/ld.so.1=<SDK_PATH>/arch/x64/sysroot/dist/lib/ld.so.1
385 lib/libfdio.so=<SDK_PATH>/arch/x64/dist/libfdio.so
386 meta/package=pkg/meta/package
387 meta/hello_fuchsia.cm=pkg/meta/hello_fuchsia.cm
388 ```
389
390 *Note: Relative manifest paths are resolved starting from the working directory
391 of `pm`. Make sure to fill out `<SDK_PATH>` with the path to the downloaded
392 SDK.*
393
394 The `.manifest` file will be used to describe the contents of the package by
395 relating their location when installed to their location on the file system. The
396 `bin/hello_fuchsia=` entry will be different depending on how your Rust binary
397 was built, so choose accordingly.
398
399 **Current directory structure**
400 ```txt
401 hello_fuchsia/
402 ┗━ pkg/
403    ┣━ meta/
404    ┃  ┗━ package
405    ┗━ hello_fuchsia.manifest
406 ```
407
408 ### Creating a Fuchsia component
409
410 On Fuchsia, components require a component manifest written in Fuchsia's markup
411 language called CML. The Fuchsia devsite contains an [overview of CML] and a
412 [reference for the file format]. Here's a basic one that can run our single binary:
413
414 **`pkg/hello_fuchsia.cml`**
415 ```txt
416 {
417     include: [ "syslog/client.shard.cml" ],
418     program: {
419         runner: "elf",
420         binary: "bin/hello_fuchsia",
421     },
422 }
423 ```
424
425 **Current directory structure**
426 ```txt
427 hello_fuchsia/
428 ┗━ pkg/
429    ┣━ meta/
430    ┃  ┗━ package
431    ┣━ hello_fuchsia.manifest
432    ┗━ hello_fuchsia.cml
433 ```
434
435 Now we can compile that CML into a component manifest:
436
437 ```sh
438 ${SDK_PATH}/tools/${ARCH}/cmc compile \
439     pkg/hello_fuchsia.cml \
440     --includepath ${SDK_PATH}/pkg \
441     -o pkg/meta/hello_fuchsia.cm
442 ```
443
444 *Note: `--includepath` tells the compiler where to look for `include`s from our CML.
445 In our case, we're only using `syslog/client.shard.cml`.*
446
447 **Current directory structure**
448 ```txt
449 hello_fuchsia/
450 ┗━ pkg/
451    ┣━ meta/
452    ┃  ┣━ package
453    ┃  ┗━ hello_fuchsia.cm
454    ┣━ hello_fuchsia.manifest
455    ┗━ hello_fuchsia.cml
456 ```
457
458 ### Building a Fuchsia package
459
460 Next, we'll build a package manifest as defined by our manifest:
461
462 ```sh
463 ${SDK_PATH}/tools/${ARCH}/pm \
464     -api-level $(${SDK_PATH}/tools/${ARCH}/ffx version -v | grep "api-level" | head -1 |  awk -F ' ' '{print $2}') \
465     -o pkg/hello_fuchsia_manifest \
466     -m pkg/hello_fuchsia.manifest \
467     build \
468     -output-package-manifest pkg/hello_fuchsia_package_manifest
469 ```
470
471 This will produce `pkg/hello_fuchsia_manifest/` which is a package manifest we can
472 publish directly to a repository.
473
474 **Current directory structure**
475 ```txt
476 hello_fuchsia/
477 ┗━ pkg/
478    ┣━ meta/
479    ┃  ┣━ package
480    ┃  ┗━ hello_fuchsia.cm
481    ┣━ hello_fuchsia_manifest/
482    ┃  ┗━ ...
483    ┣━ hello_fuchsia.manifest
484    ┣━ hello_fuchsia.cml
485    ┗━ hello_fuchsia_package_manifest
486 ```
487
488 We are now ready to publish the package.
489
490 ## Publishing a Fuchsia package
491
492 With our package and component manifests setup,
493 we can now publish our package. The first step will
494 be to create a Fuchsia package repository to publish
495 to.
496
497 ### Creating a Fuchsia package repository
498
499 We can set up our repository with:
500
501 ```sh
502 ${SDK_PATH}/tools/${ARCH}/pm newrepo \
503     -repo pkg/repo
504 ```
505
506 **Current directory structure**
507 ```txt
508 hello_fuchsia/
509 ┗━ pkg/
510    ┣━ meta/
511    ┃  ┣━ package
512    ┃  ┗━ hello_fuchsia.cm
513    ┣━ hello_fuchsia_manifest/
514    ┃  ┗━ ...
515    ┣━ repo/
516    ┃  ┗━ ...
517    ┣━ hello_fuchsia.manifest
518    ┣━ hello_fuchsia.cml
519    ┗━ hello_fuchsia_package_manifest
520 ```
521
522 ## Publishing Fuchsia package to repository
523
524 We can publish our new package to that repository with:
525
526 ```sh
527 ${SDK_PATH}/tools/${ARCH}/pm publish \
528     -repo pkg/repo \
529     -lp -f <(echo "pkg/hello_fuchsia_package_manifest")
530 ```
531
532 Then we can add the repository to `ffx`'s package server as `hello-fuchsia` using:
533
534 ```sh
535 ${SDK_PATH}/tools/${ARCH}/ffx repository add-from-pm \
536     pkg/repo \
537     -r hello-fuchsia
538 ```
539
540 ## Running a Fuchsia component on an emulator
541
542 At this point, we are ready to run our Fuchsia
543 component. For reference, our final directory
544 structure will look like:
545
546 **Final directory structure**
547 ```txt
548 hello_fuchsia/
549 ┣━ src/                     (if using rustc)
550 ┃   ┗━ hello_fuchsia.rs     ...
551 ┣━ bin/                     ...
552 ┃  ┗━ hello_fuchsia         ...
553 ┣━ src/                     (if using cargo)
554 ┃  ┗━ main.rs               ...
555 ┣━ target/                  ...
556 ┃  ┗━ x86_64-fuchsia/       ...
557 ┃     ┗━ debug/             ...
558 ┃        ┗━ hello_fuchsia   ...
559 ┗━ pkg/
560    ┣━ meta/
561    ┃  ┣━ package
562    ┃  ┗━ hello_fuchsia.cm
563    ┣━ hello_fuchsia_manifest/
564    ┃  ┗━ ...
565    ┣━ repo/
566    ┃  ┗━ ...
567    ┣━ hello_fuchsia.manifest
568    ┣━ hello_fuchsia.cml
569    ┗━ hello_fuchsia_package_manifest
570 ```
571
572 ### Starting the Fuchsia emulator
573
574 Start a Fuchsia emulator in a new terminal using:
575
576 ```sh
577 ${SDK_PATH}/tools/${ARCH}/ffx product-bundle get workstation_eng.qemu-${ARCH}
578 ${SDK_PATH}/tools/${ARCH}/ffx emu start workstation_eng.qemu-${ARCH} --headless
579 ```
580
581 ### Watching emulator logs
582
583 Once the emulator is running, open a separate terminal to watch the emulator logs:
584
585 **In separate terminal**
586 ```sh
587 ${SDK_PATH}/tools/${ARCH}/ffx log \
588     --since now
589 ```
590
591 ### Serving a Fuchsia package
592
593 Now, start a package repository server to serve our
594 package to the emulator:
595
596 ```sh
597 ${SDK_PATH}/tools/${ARCH}/ffx repository server start
598 ```
599
600 Once the repository server is up and running, register it with the target Fuchsia system running in the emulator:
601
602 ```sh
603 ${SDK_PATH}/tools/${ARCH}/ffx target repository register \
604     --repository hello-fuchsia
605 ```
606
607 ### Running a Fuchsia component
608
609 Finally, run the component:
610
611 ```sh
612 ${SDK_PATH}/tools/${ARCH}/ffx component run \
613     /core/ffx-laboratory:hello_fuchsia \
614     fuchsia-pkg://hello-fuchsia/hello_fuchsia_manifest#meta/hello_fuchsia.cm
615 ```
616
617 On reruns of the component, the `--recreate` argument may also need to be
618 passed.
619
620 ```sh
621 ${SDK_PATH}/tools/${ARCH}/ffx component run \
622     --recreate \
623     /core/ffx-laboratory:hello_fuchsia \
624     fuchsia-pkg://hello-fuchsia/hello_fuchsia_manifest#meta/hello_fuchsia.cm
625 ```
626
627 ## `.gitignore` extensions
628
629 Optionally, we can create/extend our `.gitignore` file to ignore files and
630 directories that are not helpful to track:
631
632 ```txt
633 pkg/repo
634 pkg/meta/hello_fuchsia.cm
635 pkg/hello_fuchsia_manifest
636 pkg/hello_fuchsia_package_manifest
637 ```
638
639 ## Testing
640
641 ### Running unit tests
642
643 Tests can be run in the same way as a regular binary.
644
645 * If using `cargo`, you can simply pass `test --no-run`
646 to the `cargo` invocation and then repackage and rerun the Fuchsia package. From our previous example,
647 this would look like `cargo test --target x86_64-fuchsia --no-run`, and moving the executable
648 binary path found from the line `Executable unittests src/main.rs (target/x86_64-fuchsia/debug/deps/hello_fuchsia-<HASH>)`
649 into `pkg/hello_fuchsia.manifest`.
650
651 * If using the compiled `rustc`, you can simply pass `--test`
652 to the `rustc` invocation and then repackage and rerun the Fuchsia package.
653
654 The test harness will run the applicable unit tests.
655
656 Often when testing, you may want to pass additional command line arguments to
657 your binary. Additional arguments can be set in the component manifest:
658
659 **`pkg/hello_fuchsia.cml`**
660 ```txt
661 {
662     include: [ "syslog/client.shard.cml" ],
663     program: {
664         runner: "elf",
665         binary: "bin/hello_fuchsia",
666         args: ["it_works"],
667     },
668 }
669 ```
670
671 This will pass the argument `it_works` to the binary, filtering the tests to
672 only those tests that match the pattern. There are many more configuration
673 options available in CML including environment variables. More documentation is
674 available on the [Fuchsia devsite].
675
676 ### Running the compiler test suite
677
678 The commands in this section assume that they are being run from inside your
679 local Rust source checkout:
680
681 ```sh
682 cd ${RUST_SRC_PATH}
683 ```
684
685 To run the Rust test suite on an emulated Fuchsia device, you must install the
686 Rust compiler locally. See "[Targeting Fuchsia with a compiler built from source](#targeting-fuchsia-with-a-compiler-built-from-source)"
687 for the steps to build locally.
688
689 You'll also need to download a copy of the Fuchsia SDK. The current minimum
690 supported SDK version is [9.20220726.1.1](https://chrome-infra-packages.appspot.com/p/fuchsia/sdk/core/linux-amd64/+/version:9.20220726.1.1).
691
692 Fuchsia's test runner interacts with the Fuchsia emulator and is located at
693 `src/ci/docker/scripts/fuchsia-test-runner.py`. We can use it to start our
694 test environment with:
695
696 ```sh
697 src/ci/docker/scripts/fuchsia-test-runner.py start
698     --rust ${RUST_SRC_PATH}/install
699     --sdk ${SDK_PATH}
700     --target-arch {x64,arm64}
701 ```
702
703 Where `${RUST_SRC_PATH}/install` is the `prefix` set in `config.toml` and
704 `${SDK_PATH}` is the path to the downloaded and unzipped SDK.
705
706 Once our environment is started, we can run our tests using `x.py` as usual. The
707 test runner script will run the compiled tests on an emulated Fuchsia device. To
708 run the full `src/test/ui` test suite:
709
710 ```sh
711 ( \
712     source config-env.sh &&                                                   \
713     ./x.py                                                                    \
714     --config config.toml                                                      \
715     --stage=2                                                                 \
716     test src/test/ui                                                          \
717     --target x86_64-fuchsia                                                   \
718     --run=always --jobs 1                                                     \
719     --test-args --target-rustcflags                                           \
720     --test-args -L                                                            \
721     --test-args --target-rustcflags                                           \
722     --test-args ${SDK_PATH}/arch/{x64|arm64}/sysroot/lib                      \
723     --test-args --target-rustcflags                                           \
724     --test-args -L                                                            \
725     --test-args --target-rustcflags                                           \
726     --test-args ${SDK_PATH}/arch/{x64|arm64}/lib                              \
727     --test-args --target-rustcflags                                           \
728     --test-args -Cpanic=abort                                                 \
729     --test-args --target-rustcflags                                           \
730     --test-args -Zpanic_abort_tests                                           \
731     --test-args --remote-test-client                                          \
732     --test-args src/ci/docker/scripts/fuchsia-test-runner.py                  \
733 )
734 ```
735
736 *Note: The test suite cannot be run in parallel at the moment, so `x.py`
737 must be run with `--jobs 1` to ensure only one test runs at a time.*
738
739 When finished, the test runner can be used to stop the test environment:
740
741 ```sh
742 src/ci/docker/scripts/fuchsia-test-runner.py stop
743 ```
744
745 ## Debugging
746
747 ### `zxdb`
748
749 Debugging components running on a Fuchsia emulator can be done using the
750 console-mode debugger: [zxdb]. We will demonstrate attaching necessary symbol
751 paths to debug our `hello-fuchsia` component.
752
753 ### Attaching `zxdb`
754
755 In a separate terminal, issue the following command from our `hello_fuchsia`
756 directory to launch `zxdb`:
757
758 **In separate terminal**
759 ```sh
760 ${SDK_PATH}/tools/${ARCH}/ffx debug connect -- \
761     --symbol-path target/x86_64-fuchsia/debug
762 ```
763
764 * `--symbol-path` gets required symbol paths, which are
765 necessary for stepping through your program.
766
767 The "[displaying source code in `zxdb`](#displaying-source-code-in-zxdb)" section describes how you can
768 display Rust and/or Fuchsia source code in your debugging session.
769
770 ### Using `zxdb`
771
772 Once launched, you will be presented with the window:
773
774 ```sh
775 Connecting (use "disconnect" to cancel)...
776 Connected successfully.
777 👉 To get started, try "status" or "help".
778 [zxdb]
779 ```
780
781 To attach to our program, we can run:
782
783 ```sh
784 [zxdb] attach hello_fuchsia
785 ```
786
787 **Expected output**
788 ```sh
789 Waiting for process matching "hello_fuchsia".
790 Type "filter" to see the current filters.
791 ```
792
793 Next, we can create a breakpoint at main using "b main":
794
795 ```sh
796 [zxdb] b main
797 ```
798
799 **Expected output**
800 ```sh
801 Created Breakpoint 1 @ main
802 ```
803
804 Finally, we can re-run the "hello_fuchsia" component from our original
805 terminal:
806
807 ```sh
808 ${SDK_PATH}/tools/${ARCH}/ffx component run \
809     --recreate \
810     fuchsia-pkg://hello-fuchsia/hello_fuchsia_manifest#meta/hello_fuchsia.cm
811 ```
812
813 Once our component is running, our `zxdb` window will stop execution
814 in our main as desired:
815
816 **Expected output**
817 ```txt
818 Breakpoint 1 now matching 1 addrs for main
819 🛑 on bp 1 hello_fuchsia::main() • main.rs:2
820    1 fn main() {
821  ▶ 2     println!("Hello Fuchsia!");
822    3 }
823    4
824 [zxdb]
825 ```
826
827 `zxdb` has similar commands to other debuggers like [gdb].
828 To list the available commands, run "help" in the
829 `zxdb` window or visit [the zxdb documentation].
830
831 ```sh
832 [zxdb] help
833 ```
834
835 **Expected output**
836 ```sh
837 Help!
838
839   Type "help <command>" for command-specific help.
840
841 Other help topics (see "help <topic>")
842 ...
843 ```
844
845 ### Displaying source code in `zxdb`
846
847 By default, the debugger will not be able to display
848 source code while debugging. For our user code, we displayed
849 source code by pointing our debugger to our debug binary via
850 the `--symbol-path` arg. To display library source code in
851 the debugger, you must provide paths to the source using
852 `--build-dir`. For example, to display the Rust and Fuchsia
853 source code:
854
855 ```sh
856 ${SDK_PATH}/tools/${ARCH}/ffx debug connect -- \
857     --symbol-path target/x86_64-fuchsia/debug \
858     --build-dir ${RUST_SRC_PATH}/rust \
859     --build-dir ${FUCHSIA_SRC_PATH}/fuchsia/out/default
860 ```
861
862  * `--build-dir` links against source code paths, which
863  are not strictly necessary for debugging, but is a nice-to-have
864  for displaying source code in `zxdb`.
865
866  Linking to a Fuchsia checkout can help with debugging Fuchsia libraries,
867  such as [fdio].
868
869 [Fuchsia team]: https://team-api.infra.rust-lang.org/v1/teams/fuchsia.json
870 [Fuchsia]: https://fuchsia.dev/
871 [source tree]: https://fuchsia.dev/fuchsia-src/get-started/learn/build
872 [rustup]: https://rustup.rs/
873 [cargo]: ../../cargo/index.html
874 [Fuchsia SDK]: https://chrome-infra-packages.appspot.com/p/fuchsia/sdk/core
875 [overview of CML]: https://fuchsia.dev/fuchsia-src/concepts/components/v2/component_manifests
876 [reference for the file format]: https://fuchsia.dev/reference/cml
877 [Fuchsia devsite]: https://fuchsia.dev/reference/cml
878 [not currently supported]: https://fxbug.dev/105393
879 [zxdb]: https://fuchsia.dev/fuchsia-src/development/debugger
880 [gdb]: https://www.sourceware.org/gdb/
881 [the zxdb documentation]: https://fuchsia.dev/fuchsia-src/development/debugger
882 [fdio]: https://cs.opensource.google/fuchsia/fuchsia/+/main:sdk/lib/fdio/