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