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