|  | # Fuchsia Build System: Variants | 
|  |  | 
|  | The Fuchsia GN build machinery allows for separate components to be built | 
|  | in different "variants".  A variant usually just means using extra compiler | 
|  | options, but they can do more than that if you write some more GN code. | 
|  | The variants defined so far enable things like | 
|  | [sanitizers](https://github.com/google/sanitizers/wiki) and | 
|  | [LTO](https://llvm.org/docs/LinkTimeOptimization.html). | 
|  |  | 
|  | The GN build argument | 
|  | [`select_variant`](/docs/gen/build_arguments.md#select_variant) | 
|  | controls which components are built in which variants.  It applies | 
|  | automatically to every `executable`, `loadable_module`, or `driver_module` | 
|  | target in GN files.  It's a flexible mechanism in which you give a list of | 
|  | matching rules to apply to each target to decide which variant to use (if | 
|  | any).  To support this flexibility, the value for `select_variant` uses a | 
|  | detailed GN syntax.  For simple cases, this can just be a list of strings. | 
|  |  | 
|  | Using `fx set`: | 
|  |  | 
|  | ```sh | 
|  | fx set core.x64 --variant=host_asan --variant=asan/cat --variant=asan/ledger | 
|  | ``` | 
|  |  | 
|  | Alternatively, you can add or modify the variants on an existing build by | 
|  | editing the GN args (substituting your build's GN output directory | 
|  | for `out/default` as necessary): | 
|  |  | 
|  | ```sh | 
|  | gn args out/default | 
|  | ``` | 
|  |  | 
|  | That command will bring up an editor. Append to that file: | 
|  |  | 
|  | ``` | 
|  | select_variant = [ "host_asan", "asan/cat", "asan/ledger" ] | 
|  | ``` | 
|  |  | 
|  | 1. The first switch applies the `host_asan` matching rule, which enables | 
|  | [AddressSanitizer](https://clang.llvm.org/docs/AddressSanitizer.html) | 
|  | for all the executables built to run on the build host. | 
|  |  | 
|  | 2. The second switch applies the `asan` matching rule, which enables | 
|  | AddressSanitizer for executables built to run on the target (i.e. the | 
|  | Fuchsia device).  The `/cat` suffix constrains this matching rule only | 
|  | to the binary named `cat`. | 
|  |  | 
|  | 3. The third switch is like the second, but matches the binary named `ledger`. | 
|  |  | 
|  | The GN code supports much more flexible matching rules than just the binary | 
|  | name, but there are no shorthands for those. See the | 
|  | [`select_variant`](/docs/gen/build_arguments.md#select_variant) | 
|  | build argument documentation for more details. | 
|  |  | 
|  | To see the list of variants available and learn more about how to define | 
|  | new ones, see the | 
|  | [`known_variants`](/docs/gen/build_arguments.md#known_variants) | 
|  | build argument. | 
|  |  | 
|  | ## Troubleshooting notes | 
|  |  | 
|  | ### Replicating ASan failures | 
|  |  | 
|  | Our commit queue runs tests in an ASan-enabled configuration. To replicate the | 
|  | build in this configuration, use the following `args.gn` file: | 
|  |  | 
|  | ```sh | 
|  | import("//boards/<x64-or-arm64>.gni") | 
|  | import("//products/core.gni") | 
|  |  | 
|  | base_package_labels+=[ "//bundles/buildbot:core" ] | 
|  | goma_dir="<path-to-goma-dir>" | 
|  | is_debug=true | 
|  | select_variant=["asan","host_asan"] | 
|  | target_cpu="<x64-or-arm64>" | 
|  | use_goma=true | 
|  | ``` | 
|  |  | 
|  | Replace `x64-or-arm64` with your desired target architecture, and replace | 
|  | `<path-to-goma-dir>` with the path to your goma dir (for those who use goma). This | 
|  | can also be generated from the command line with: | 
|  |  | 
|  | ```sh | 
|  | fx set core.x64 --with-base //bundles/buildbot:core --variant host_asan --variant asan --goma | 
|  | ``` | 
|  |  | 
|  | Note that this will build all of the tests that are run by the commit queue and | 
|  | install them in the system image. This may be undesirable for two reasons: | 
|  |  | 
|  | * Building all of the tests is typically slow and unnecessary. Developers may | 
|  | find it more effective to limit the package labels to the tests they need. | 
|  | * Installing all of the tests in the system image ahead of time means that the | 
|  | software deployment workflow does not get exercised. | 
|  |  | 
|  | ### Launching executables from within ASan-enabled binaries | 
|  |  | 
|  | If you are trying to use the ASan variant, you may encounter an error that looks | 
|  | like this: | 
|  |  | 
|  | ```sh | 
|  | launcher: error: Launch: elf_load: handle_interp failed | 
|  | dlsvc: could not open 'asan/ld.so.1' | 
|  | ``` | 
|  |  | 
|  | Fuchsia is structured around packages and components. Each component contains | 
|  | all of the shared libraries it needs to run. This helps Fuchsia avoid library | 
|  | versioning issues that plague other operating systems. It also means that, if | 
|  | you want to run a binary from within a component, you must provide the | 
|  | appropriate shared library loader for that binary. | 
|  |  | 
|  | There are a set of command line programs located in the `/boot/` directory of | 
|  | Fuchsia installs that are not contained in packages, but in the boot filesystem. | 
|  | These programs do not have their own shared library loader, and will use | 
|  | whatever shared libraries the component executing them provides. This normally | 
|  | works, as programs like `sh` and `ls` have very minimal, very common | 
|  | dependencies. However, there's no guarantee that the component's package will | 
|  | have sufficient or compatible shared libraries for the command line program's | 
|  | needs. ASan-enabled packages usually do not contain the right launcher for these | 
|  | programs, so most ASan-enabled components cannot run executables out of | 
|  | `/boot`. If an ASan-enabled component tries to do so, it gets the error above. | 
|  |  | 
|  | Fortunately, it turns out that the fix involves doing what all packages should | 
|  | do anyway, which is to declare their dependencies explicitly. If your package | 
|  | depends on a binary, it should declare it as a dependency, and then use that | 
|  | declared dependency instead of the one in the `/boot` directory. In the case of | 
|  | our build system, the `zircon_extras_manifest` rule defined in | 
|  | `//build/config/fuchsia/zircon_images.gni` will allow you to depend on any of | 
|  | the binaries found in the `/boot` directory. They will be installed in | 
|  | `/pkg/bin/`, and you should execute them from there. |