]>
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 FG |
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 | ||
f2b60f7d FG |
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 | ||
064997fb FG |
51 | ## Requirements |
52 | ||
f2b60f7d FG |
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. | |
064997fb | 56 | |
f2b60f7d | 57 | Development may also be done from the [source tree]. |
064997fb | 58 | |
f2b60f7d | 59 | Fuchsia targets support `std` and follow the `sysv64` calling convention on |
064997fb FG |
60 | x86_64. Fuchsia binaries use the ELF file format. |
61 | ||
f2b60f7d FG |
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 | ||
9c376795 | 70 | For the purposes of this walkthrough, we will only target `x86_64-unknown-fuchsia`. |
f2b60f7d FG |
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 | |
9c376795 FG |
86 | rustup target add x86_64-unknown-fuchsia |
87 | rustup target add aarch64-unknown-fuchsia | |
f2b60f7d FG |
88 | ``` |
89 | ||
90 | After installing our Fuchsia targets, we can now compile a Rust binary that targets | |
91 | Fuchsia. | |
92 | ||
9c376795 | 93 | To create our Rust project, we can use [`cargo`][cargo] as follows: |
f2b60f7d FG |
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 | |
9c376795 | 130 | [target.x86_64-unknown-fuchsia] |
f2b60f7d FG |
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 | |
9c376795 | 162 | cargo build --target x86_64-unknown-fuchsia |
f2b60f7d FG |
163 | ``` |
164 | ||
9c376795 | 165 | Now we have a Rust binary at `target/x86_64-unknown-fuchsia/debug/hello_fuchsia`, |
f2b60f7d FG |
166 | targeting our desired Fuchsia target. |
167 | ||
168 | **Current directory structure** | |
169 | ```txt | |
170 | hello_fuchsia/ | |
171 | ┣━ src/ | |
172 | ┃ ┗━ main.rs | |
173 | ┣━ target/ | |
9c376795 | 174 | ┃ ┗━ x86_64-unknown-fuchsia/ |
f2b60f7d FG |
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. | |
064997fb FG |
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 | ||
064997fb | 191 | x86-64 and AArch64 Fuchsia targets can be enabled using the following |
487cf647 | 192 | configuration in `config.toml`: |
064997fb FG |
193 | |
194 | ```toml | |
195 | [build] | |
9c376795 | 196 | target = ["<host_platform>", "aarch64-unknown-fuchsia", "x86_64-unknown-fuchsia"] |
487cf647 FG |
197 | |
198 | [rust] | |
199 | lld = true | |
200 | ||
9c376795 FG |
201 | [llvm] |
202 | download-ci-llvm = false | |
203 | ||
204 | [target.x86_64-unknown-fuchsia] | |
487cf647 FG |
205 | cc = "clang" |
206 | cxx = "clang++" | |
207 | ||
9c376795 | 208 | [target.aarch64-unknown-fuchsia] |
487cf647 FG |
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" | |
064997fb FG |
230 | ``` |
231 | ||
487cf647 FG |
232 | Next, the following environment variables must be configured. For example, using |
233 | a script we name `config-env.sh`: | |
064997fb FG |
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 | ||
9c376795 FG |
239 | export CFLAGS_aarch64_unknown_fuchsia="--target=aarch64-unknown-fuchsia --sysroot=${SDK_PATH}/arch/arm64/sysroot -I${SDK_PATH}/pkg/fdio/include" |
240 | export CXXFLAGS_aarch64_unknown_fuchsia="--target=aarch64-unknown-fuchsia --sysroot=${SDK_PATH}/arch/arm64/sysroot -I${SDK_PATH}/pkg/fdio/include" | |
241 | export LDFLAGS_aarch64_unknown_fuchsia="--target=aarch64-unknown-fuchsia --sysroot=${SDK_PATH}/arch/arm64/sysroot -L${SDK_PATH}/arch/arm64/lib" | |
242 | 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" | |
243 | export CFLAGS_x86_64_unknown_fuchsia="--target=x86_64-unknown-fuchsia --sysroot=${SDK_PATH}/arch/x64/sysroot -I${SDK_PATH}/pkg/fdio/include" | |
244 | export CXXFLAGS_x86_64_unknown_fuchsia="--target=x86_64-unknown-fuchsia --sysroot=${SDK_PATH}/arch/x64/sysroot -I${SDK_PATH}/pkg/fdio/include" | |
245 | export LDFLAGS_x86_64_unknown_fuchsia="--target=x86_64-unknown-fuchsia --sysroot=${SDK_PATH}/arch/x64/sysroot -L${SDK_PATH}/arch/x64/lib" | |
246 | 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 |
247 | ``` |
248 | ||
487cf647 FG |
249 | Finally, the Rust compiler can be built and installed: |
250 | ||
251 | ```sh | |
252 | (source config-env.sh && ./x.py install) | |
253 | ``` | |
064997fb | 254 | |
f2b60f7d FG |
255 | Once `rustc` is installed, we can create a new working directory to work from, |
256 | `hello_fuchsia` along with `hello_fuchsia/src`: | |
064997fb | 257 | |
f2b60f7d FG |
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.* | |
064997fb | 266 | |
f2b60f7d | 267 | There, we can create a new file named `src/hello_fuchsia.rs`: |
064997fb | 268 | |
f2b60f7d | 269 | **`src/hello_fuchsia.rs`** |
064997fb FG |
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 | ||
f2b60f7d FG |
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 | ||
9c376795 | 291 | * `--target x86_64-unknown-fuchsia`/`--target aarch64-unknown-fuchsia`: Targets the Fuchsia |
f2b60f7d FG |
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 | |
064997fb | 297 | |
f2b60f7d | 298 | Putting it all together: |
064997fb | 299 | |
f2b60f7d FG |
300 | ```sh |
301 | # Configure these for the Fuchsia target of your choice | |
9c376795 | 302 | TARGET_ARCH="<x86_64-unknown-fuchsia|aarch64-unknown-fuchsia>" |
f2b60f7d FG |
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/ | |
9c376795 FG |
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-unknown-fuchsia/ ... | |
336 | ┗━ debug/ ... | |
337 | ┗━ hello_fuchsia ... | |
f2b60f7d FG |
338 | ``` |
339 | ||
340 | With our Rust binary built, we can move to creating a Fuchsia package. | |
064997fb FG |
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 | |
f2b60f7d FG |
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 | ``` | |
064997fb | 351 | |
f2b60f7d | 352 | **Current directory structure** |
064997fb | 353 | ```txt |
f2b60f7d FG |
354 | hello_fuchsia/ |
355 | ┗━ pkg/ | |
356 | ┗━ meta/ | |
064997fb FG |
357 | ``` |
358 | ||
f2b60f7d | 359 | Now, create the following files inside: |
064997fb | 360 | |
f2b60f7d | 361 | **`pkg/meta/package`** |
064997fb | 362 | ```json |
f2b60f7d FG |
363 | { |
364 | "name": "hello_fuchsia", | |
365 | "version": "0" | |
366 | } | |
064997fb FG |
367 | ``` |
368 | ||
369 | The `package` file describes our package's name and version number. Every | |
370 | package must contain one. | |
371 | ||
f2b60f7d FG |
372 | **`pkg/hello_fuchsia.manifest` if using cargo** |
373 | ```txt | |
9c376795 | 374 | bin/hello_fuchsia=target/x86_64-unknown-fuchsia/debug/hello_fuchsia |
f2b60f7d FG |
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** | |
064997fb | 382 | ```txt |
f2b60f7d | 383 | bin/hello_fuchsia=bin/hello_fuchsia |
064997fb FG |
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 | |
f2b60f7d FG |
386 | meta/package=pkg/meta/package |
387 | meta/hello_fuchsia.cm=pkg/meta/hello_fuchsia.cm | |
064997fb FG |
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 | |
f2b60f7d FG |
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. | |
064997fb | 398 | |
f2b60f7d FG |
399 | **Current directory structure** |
400 | ```txt | |
401 | hello_fuchsia/ | |
402 | ┗━ pkg/ | |
403 | ┣━ meta/ | |
404 | ┃ ┗━ package | |
405 | ┗━ hello_fuchsia.manifest | |
064997fb FG |
406 | ``` |
407 | ||
f2b60f7d | 408 | ### Creating a Fuchsia component |
064997fb | 409 | |
f2b60f7d | 410 | On Fuchsia, components require a component manifest written in Fuchsia's markup |
064997fb FG |
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 | ||
f2b60f7d | 414 | **`pkg/hello_fuchsia.cml`** |
064997fb FG |
415 | ```txt |
416 | { | |
417 | include: [ "syslog/client.shard.cml" ], | |
418 | program: { | |
419 | runner: "elf", | |
420 | binary: "bin/hello_fuchsia", | |
421 | }, | |
422 | } | |
423 | ``` | |
424 | ||
f2b60f7d FG |
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 | ||
064997fb FG |
435 | Now we can compile that CML into a component manifest: |
436 | ||
437 | ```sh | |
f2b60f7d FG |
438 | ${SDK_PATH}/tools/${ARCH}/cmc compile \ |
439 | pkg/hello_fuchsia.cml \ | |
440 | --includepath ${SDK_PATH}/pkg \ | |
441 | -o pkg/meta/hello_fuchsia.cm | |
064997fb FG |
442 | ``` |
443 | ||
f2b60f7d FG |
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`.* | |
064997fb | 446 | |
f2b60f7d FG |
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 | ``` | |
064997fb | 457 | |
f2b60f7d FG |
458 | ### Building a Fuchsia package |
459 | ||
460 | Next, we'll build a package manifest as defined by our manifest: | |
064997fb FG |
461 | |
462 | ```sh | |
f2b60f7d FG |
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 | |
064997fb FG |
486 | ``` |
487 | ||
f2b60f7d FG |
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: | |
064997fb FG |
500 | |
501 | ```sh | |
f2b60f7d FG |
502 | ${SDK_PATH}/tools/${ARCH}/pm newrepo \ |
503 | -repo pkg/repo | |
064997fb FG |
504 | ``` |
505 | ||
f2b60f7d FG |
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: | |
064997fb FG |
525 | |
526 | ```sh | |
f2b60f7d FG |
527 | ${SDK_PATH}/tools/${ARCH}/pm publish \ |
528 | -repo pkg/repo \ | |
529 | -lp -f <(echo "pkg/hello_fuchsia_package_manifest") | |
064997fb FG |
530 | ``` |
531 | ||
f2b60f7d | 532 | Then we can add the repository to `ffx`'s package server as `hello-fuchsia` using: |
064997fb FG |
533 | |
534 | ```sh | |
f2b60f7d FG |
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/ | |
9c376795 FG |
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-unknown-fuchsia/ ... | |
557 | ┃ ┗━ debug/ ... | |
558 | ┃ ┗━ hello_fuchsia ... | |
f2b60f7d FG |
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 | |
064997fb FG |
570 | ``` |
571 | ||
f2b60f7d | 572 | ### Starting the Fuchsia emulator |
064997fb FG |
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 | ||
f2b60f7d FG |
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: | |
064997fb FG |
595 | |
596 | ```sh | |
f2b60f7d | 597 | ${SDK_PATH}/tools/${ARCH}/ffx repository server start |
064997fb FG |
598 | ``` |
599 | ||
f2b60f7d | 600 | Once the repository server is up and running, register it with the target Fuchsia system running in the emulator: |
064997fb FG |
601 | |
602 | ```sh | |
f2b60f7d FG |
603 | ${SDK_PATH}/tools/${ARCH}/ffx target repository register \ |
604 | --repository hello-fuchsia | |
064997fb FG |
605 | ``` |
606 | ||
f2b60f7d FG |
607 | ### Running a Fuchsia component |
608 | ||
064997fb FG |
609 | Finally, run the component: |
610 | ||
611 | ```sh | |
f2b60f7d FG |
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 | |
064997fb FG |
615 | ``` |
616 | ||
617 | On reruns of the component, the `--recreate` argument may also need to be | |
618 | passed. | |
619 | ||
f2b60f7d FG |
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 | ||
064997fb FG |
639 | ## Testing |
640 | ||
641 | ### Running unit tests | |
642 | ||
f2b60f7d FG |
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, | |
9c376795 FG |
647 | this would look like `cargo test --target x86_64-unknown-fuchsia --no-run`, and moving the executable |
648 | binary path found from the line `Executable unittests src/main.rs (target/x86_64-unknown-fuchsia/debug/deps/hello_fuchsia-<HASH>)` | |
f2b60f7d FG |
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. | |
064997fb FG |
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 | ||
f2b60f7d | 659 | **`pkg/hello_fuchsia.cml`** |
064997fb FG |
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 | |
f2b60f7d | 674 | available on the [Fuchsia devsite]. |
064997fb FG |
675 | |
676 | ### Running the compiler test suite | |
677 | ||
487cf647 FG |
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 | |
9c376795 | 708 | run the full `tests/ui` test suite: |
487cf647 FG |
709 | |
710 | ```sh | |
711 | ( \ | |
712 | source config-env.sh && \ | |
713 | ./x.py \ | |
714 | --config config.toml \ | |
715 | --stage=2 \ | |
9c376795 FG |
716 | test tests/ui \ |
717 | --target x86_64-unknown-fuchsia \ | |
487cf647 FG |
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 | ``` | |
064997fb | 744 | |
f2b60f7d FG |
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 -- \ | |
9c376795 | 761 | --symbol-path target/x86_64-unknown-fuchsia/debug |
f2b60f7d FG |
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 -- \ | |
9c376795 | 857 | --symbol-path target/x86_64-unknown-fuchsia/debug \ |
f2b60f7d FG |
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/ | |
9c376795 | 873 | [cargo]: ../../cargo/index.html |
f2b60f7d FG |
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 | |
064997fb | 878 | [not currently supported]: https://fxbug.dev/105393 |
f2b60f7d FG |
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/ |