Declaring components

<<../../../_common/components/_declaring_intro.md>>

<<../../../_common/components/_declaring_manifests.md>>

<<../../../_common/components/_declaring_shards.md>>

Building components

The Fuchsia SDK system provides Bazel rules to build and package software into Fuchsia components. The Fuchsia SDK environment makes these rules available within a Bazel workspace{:.external} directory.

Within the Bazel workspace, you declare Fuchsia packages and components as Bazel targets{:.external} within a Bazel package{:.external}, described by a BUILD.bazel file.

Below is an example of a BUILD.bazel file for a simple C++ component:

# Build rules provided by the Fuchsia SDK
load(
    "fuchsia_cc_binary",
    "fuchsia_component",
    "fuchsia_component_manifest",
    "fuchsia_package",
)

fuchsia_cc_binary(
    name = "hello_world",
    srcs = [
        "hello_world.cc",
    ],
)

fuchsia_component_manifest(
    name = "manifest",
    src = "meta/hello_world.cml",
)

fuchsia_component(
    name = "component",
    manifest = ":manifest",
    deps = [":hello_world"],
)

fuchsia_package(
    name = "pkg",
    package_name = "hello_world",
    visibility = ["//visibility:public"],
    deps = [
        ":component",
    ],
)

This file contains the following main elements:

  • fuchsia_cc_binary(): Compiles the C++ source code into a binary, including any necessary library dependencies.
  • fuchsia_component_manifest(): Compiles the component manifest source file (.cml) into a binary component declaration using cmc.
  • fuchsia_component(): Collects the binary, component manifest, and additional resources together into a single target.
  • fuchsia_package(): Unit of distribution for components. Allows one or more components to be hosted in a package repository and included in the target device's package sets. This target generates the package metadata and builds the Fuchsia Archive (.far) file.

Exercise: Create a new component

In this exercise, you'll build and run a basic component that reads the program arguments and echoes a greeting out the system log.

To begin, create a new project directory in your Bazel workspace for a new component called echo:

mkdir -p fuchsia-codelab/echo

After you complete this section, the project should have the following directory structure:

//fuchsia-codelab/echo
                  |- BUILD.bazel
                  |- meta
                  |   |- echo.cml
                  |
                  |- echo_component.cc
                  |- echo_component.h
                  |- main.cc
  • BUILD.bazel: Bazel build targets for the executable binaries, component, and package.
  • meta/echo.cml: Manifest declaring the component's executable and required capabilities.
  • echo_component.cc: Source code for the C++ component functionality.
  • main.cc: Source code for the C++ executable binary main entry point.

Add program arguments

The component manifest file defines the attributes of the component‘s executable, including program arguments, and the component’s capabilities.

Create echo/meta/echo.cml and add the following contents:

echo/meta/echo.cml:

{% includecode gerrit_repo="fuchsia/sdk-samples/getting-started" gerrit_path="src/echo/meta/echo.cml" region_tag="manifest" adjust_indentation="auto" %}

Log the arguments

Create the echo/main.cc source file for the main executable and add the following import statements:

echo/main.cc:

{% includecode gerrit_repo="fuchsia/sdk-samples/getting-started" gerrit_path="src/echo/main.cc" region_tag="imports" adjust_indentation="auto" %}

#include "echo_component.h"

Add the following code for the the main() function:

echo/main.cc:

{% includecode gerrit_repo="fuchsia/sdk-samples/getting-started" gerrit_path="src/echo/main.cc" region_tag="main" adjust_indentation="auto" %}

This code reads the program arguments and passes them to a function called greeting() to generate a response for the syslog entry.

Create echo/echo_component.h and echo/echo_component.cc, including the following code to implement the greeting() function:

echo/echo_component.h:

{% includecode gerrit_repo="fuchsia/sdk-samples/getting-started" gerrit_path="src/echo/echo_component.h" region_tag="greeting" adjust_indentation="auto" %}

echo/echo_component.cc:

#include "echo_component.h"

{% includecode gerrit_repo="fuchsia/sdk-samples/getting-started" gerrit_path="src/echo/echo_component.cc" region_tag="greeting" adjust_indentation="auto" %}

This function creates a simple string from the list of provided arguments based on the length of the list.

Add to the build configuration

Create the echo/BUILD.bazel file and add the following build rules to include the new component in the build configuration:

echo/BUILD.bazel:

{% includecode gerrit_repo="fuchsia/sdk-samples/getting-started" gerrit_path="src/echo/BUILD.bazel" region_tag="imports" adjust_indentation="auto" exclude_regexp="fuchsia_cc_test|fuchsia_test_package|if_fuchsia" %}

{% includecode gerrit_repo="fuchsia/sdk-samples/getting-started" gerrit_path="src/echo/BUILD.bazel" region_tag="echo" adjust_indentation="auto" %}

Run bazel build and verify that the build completes successfully:

bazel build --config=fuchsia_x64 //fuchsia-codelab/echo:pkg \
    --publish_to=$HOME/.package_repos/sdk-samples

In the next section, you'll integrate this component into the build and test the output in the system log.