Every component has a declaration that describes the component's attributes and
capabilities. For components that are distributed in packages, the declaration
is expressed using a **component manifest file** and loaded with the help of a
**component resolver**.

![Diagram showing how components are declared using a "component manifest." The
manifest is compiled by the developer tools and resolved onto the device at
runtime.](https://fuchsia.dev/static/docs/get-started/images/components/component-manifest.png)

You declare components using component manifest language (CML) files. At build
time, the Component Manifest Compiler (`cmc`) tool validates and compiles the
manifest source into a binary format (`.cm`) and stores it in the component's
package. At runtime, component resolvers load the binary manifest into a
[ComponentDecl](https://fuchsia.dev/reference/fidl/fuchsia.component.decl#Component)
FIDL structure for


[](https://fuchsia.dev/docs/glossary#component-manager)


.

## Component manifests

CML files are [JSON5](https://json5.org/) files that end with a
`.cml` extension. Below is an example CML manifest file for a simple component
running an ELF binary that prints a "Hello, World" message to the system log:

    {
        // Information about the program to run.
        program: {
            // Use the built-in ELF runner.
            runner: "elf",
            // The binary to run for this component.
            binary: "bin/hello",
            // Program arguments
            args: [
                "Hello",
                "World!",
            ],
        },

        // Capabilities used by this component.
        use: [
            { protocol: "fuchsia.logger.LogSink" },
        ],
    }

This file declares two main sections of information about the component:

> [!NOTE]
> **Note:** For more details on component manifests, see [component manifests](https://fuchsia.dev/docs/concepts/components/v2/component_manifests).

- `program`: Describes the executable information such as the binary file, program arguments, and the associated runtime. In this example, a binary is compiled as an ELF executable and uses the built-in [ELF runner](https://fuchsia.dev/docs/concepts/components/v2/elf_runner).
- `use`: Declares the capabilities this component requires to run. In this example, the `fuchsia.logger.LogSink` protocol enables the component to write messages to the system log (`syslog`).

## Manifest shards

Some collections of capabilities represent use case requirements that are common
to many components in the system, such as logging. To simplify including these
capabilities in your components, the framework abstracts them into
**manifest shards** that can be included in your CML source file.

Below is an equivalent CML to the previous example. In this case, the necessary
logging capabilities are provided by including
`diagnostics/syslog/client.shard.cml` instead of declaring
`fuchsia.logger.LogSink` explicitly:

    {
        include: [ "syslog/client.shard.cml" ],

        // Information about the program to run.
        program: {
            // Use the built-in ELF runner.
            runner: "elf",
            // The binary to run for this component.
            binary: "bin/hello-world",
            // Program arguments
            args: [
                "Hello",
                "World!",
            ],
        },
    }

> [!IMPORTANT]
> To review the merged CML output with all includes resolved, run the `fx cmc include` command with your manifest. For more details, see the [reference documentation](https://fuchsia.dev/docs/reference/tools/sdk/cmc).

## Building components

The Fuchsia build system provides templates as GN imports in
[`//build/components.gni`](https://cs.opensource.google/fuchsia/fuchsia/+/main:/build/components.gni) to build and package software
into Fuchsia components. Below is an example of a `BUILD.gn` file for a simple
C++ component:


    import("//build/components.gni")

    executable("bin") {
      sources = [ "main.cc" ]
    }

    resource("my_file") {
      sources = [ "my_file.txt" ]
      outputs = [ "data/{{source_file_part}}" ]
    }

    fuchsia_component("hello-world-component") {
      component_name = "hello-world"
      deps = [
        ":bin",
        ":my_file",
      ]
      manifest = "meta/hello-world.cml"
    }

    fuchsia_package("hello-world") {
      package-name = "hello-world"
      deps = [
        ":hello-world-component",
      ]
    }

This file contains the following main elements:

- `executable()`: Compiles the source code into a binary. This target varies depending on the programming language. For example, an `executable` target can be used for C++, `rustc_binary` for Rust, `go_binary` for Golang.
- `resource()`: Optional named collection of data files to copy as resources into another GN target. These files are accessible to the binary inside the component's namespace.
- `fuchsia_component()`: Collects the binary, component manifest, and additional resources together into a single target. This target compiles the manifest source into a component declaration using `cmc`.
- `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.

Packages can contain multiple components, listed as `deps` in the
`fuchsia_package()` template. You can simplify the build file for packages
containing only one component using the `fuchsia_package_with_single_component()`
template.

The following simplified `BUILD.gn` example is equivalent to the previous
example:


    import("//build/components.gni")

    executable("bin") {
      sources = [ "main.cc" ]
    }

    resource("my_file") {
      sources = [ "my_file.txt" ]
      outputs = [ "data/{{source_file_part}}" ]
    }

    fuchsia_package_with_single_component("hello-world") {
      manifest = "meta/hello-world.cml"
      deps = [
        ":bin",
        ":my_file",
      ]
    }

> [!NOTE]
> **Note:** For more details on the GN syntax of the component build rules, see the [components build reference](https://fuchsia.dev/docs/development/components/build).

## 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 project scaffold for a new component called `echo-args` in
the `//vendor/fuchsia-codelab` directory:

    mkdir -p vendor/fuchsia-codelab/echo-args

Create the following file and directory structure in the new project directory:

### Rust

    //vendor/fuchsia-codelab/echo-args
                            |- BUILD.gn
                            |- meta
                            |   |- echo.cml
                            |
                            |- src
                                |- main.rs

- `BUILD.gn`: GN build targets for the executable binaries, component, and package.
- `meta/echo.cml`: Manifest declaring the component's executable and required capabilities.
- `src/main.rs`: Source code for the Rust executable binary and unit tests.

### C++

    //vendor/fuchsia-codelab/echo-args
                            |- BUILD.gn
                            |- meta
                            |   |- echo.cml
                            |
                            |- echo_component.cc
                            |- echo_component.h
                            |- main.cc

- `BUILD.gn`: GN 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.
Add the following contents to `meta/echo.cml`:

### Rust

`echo-args/meta/echo.cml`:

    {
        include: [
            // Enable logging on stdout
            "syslog/client.shard.cml",
        ],

        // Information about the program to run.
        program: {
            // Use the built-in ELF runner.
            runner: "elf",

            // The binary to run for this component.
            binary: "bin/echo-args",

            // Program arguments
            args: [
                "Alice",
                "Bob",
            ],

            // Program environment variables
            environ: [ "FAVORITE_ANIMAL=Spot" ],
        },
    }

### C++

`echo-args/meta/echo.cml`:

    {
        include: [
            // Enable logging.
            "syslog/client.shard.cml",
        ],

        // Information about the program to run.
        program: {
            // Use the built-in ELF runner.
            runner: "elf",

            // The binary to run for this component.
            binary: "bin/echo-args",

            // Program arguments
            args: [
                "Alice",
                "Bob",
            ],

            // Program environment variables
            environ: [ "FAVORITE_ANIMAL=Spot" ],
        },
    }

### Log the arguments

Open the source file for the main executable and add the following import statements:

### Rust

`echo-args/src/main.rs`:

    use log::info;

### C++

`echo-args/main.cc`:

    #include <lib/syslog/cpp/log_settings.h>
    #include <lib/syslog/cpp/macros.h>

    #include <cstdlib>
    #include <iostream>

    #include "vendor/fuchsia-codelab/echo-args/echo_component.h"

Add the following code to implement the `main()` function:

### Rust

`echo-args/src/main.rs`:

    #[fuchsia::main(logging = true)]
    async fn main() -> Result<(), anyhow::Error> {
        // Read program arguments, and strip off binary name
        let mut args: Vec<String> = std::env::args().collect();
        args.remove(0);

        // Include environment variables
        let animal = std::env::var("FAVORITE_ANIMAL").unwrap();
        args.push(animal);

        // Print a greeting to syslog
        info!("Hello, {}!", greeting(&args));

        Ok(())
    }

> [!IMPORTANT]
> The `fuchsia::main` attribute removes some common boilerplate for component execution in Rust, such as initializing logging or async execution behavior.

### C++

`echo-args/main.cc`:

    int main(int argc, const char* argv[], char* envp[]) {
      fuchsia_logging::LogSettingsBuilder builder;
      builder.WithTags({"echo"}).BuildAndInitialize();
      // Read program arguments, and exclude the binary name in argv[0]
      std::vector<std::string> arguments;
      for (int i = 1; i < argc; i++) {
        arguments.push_back(argv[i]);
      }

      // Include environment variables
      const char* favorite_animal = std::getenv("FAVORITE_ANIMAL");
      arguments.push_back(favorite_animal);

      // Print a greeting to syslog
      FX_LOG_KV(INFO, "Hello", FX_KV("greeting", echo::greeting(arguments).c_str()));

      return 0;
    }

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

Add the following code to implement the `greeting()` function:

### Rust

`echo-args/src/main.rs`:

    // Return a proper greeting for the list
    fn greeting(names: &Vec<String>) -> String {
        // Join the list of names based on length
        match names.len() {
            0 => String::from("Nobody"),
            1 => names.join(""),
            2 => names.join(" and "),
            _ => names.join(", "),
        }
    }

### C++

`echo-args/echo_component.h`:

    #include <string>
    #include <vector>

    namespace echo {

    std::string greeting(std::vector<std::string>& names);

    }  // namespace echo

`echo-args/echo_component.cc`:

    #include "vendor/fuchsia-codelab/echo-args/echo_component.h"

    #include <numeric>

    namespace echo {

    static std::string join(std::vector<std::string>& input_list, const std::string& separator) {
      return std::accumulate(std::begin(input_list), std::end(input_list), std::string(""),
                             [&separator](std::string current, std::string& next) {
                               return current.empty() ? next : (std::move(current) + separator + next);
                             });
    }

    // Return a proper greeting for the list
    std::string greeting(std::vector<std::string>& names) {
      // Join the list of names based on length
      auto number_of_names = names.size();
      switch (number_of_names) {
        case 0:
          return "Nobody!";
        case 1:
          return join(names, "");
        case 2:
          return join(names, " and ");
        default:
          return join(names, ", ");
      }
    }

    }  // namespace echo

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

> [!IMPORTANT]
> **Logging and standard streams**
>
> Fuchsia has two main logging buffers; the system log (`syslog`)
> and the kernel's debug log (`klog`). By default, components only
> have stream handles for stdout and stderr available to record log messages
> from your code if they have access to the system log. Fuchsia also has logging
> libraries available for greater control over metadata and format of
> messages.
>
> For more details on logging from your code, see
> [Recording Logs](https://fuchsia.dev/docs/development/diagnostics/logs/recording).

### Add to the build configuration

Update the program's dependencies in your `BUILD.gn` file:

### Rust

`echo-args/BUILD.gn`:

    import("//build/components.gni")
    import("//build/rust/rustc_binary.gni")


    group("echo-args") {
      testonly = true
      deps = [
        ":package",
      ]
    }

    rustc_binary("bin") {
      output_name = "echo-args"
      edition = "2024"

      # Generates a GN target for unit-tests with the label `bin_test`,
      # and a binary named `echo_bin_test`.
      with_unit_tests = true

      deps = [
        "//src/lib/fuchsia",
        "//third_party/rust_crates:anyhow",
        "//third_party/rust_crates:log",
      ]

      sources = [ "src/main.rs" ]
    }

    fuchsia_component("component") {
      component_name = "echo-args"
      manifest = "meta/echo.cml"
      deps = [ ":bin" ]
    }

    fuchsia_package("package") {
      package_name = "echo-args"
      deps = [ ":component" ]
    }

### C++

`echo-args/BUILD.gn`:

    import("//build/components.gni")


    group("echo-args") {
      testonly = true
      deps = [
        ":package",
      ]
    }

    executable("bin") {
      output_name = "echo-args"

      sources = [ "main.cc" ]

      deps = [
        ":cpp-lib",
        "//sdk/lib/async-default",
        "//sdk/lib/async-loop:async-loop-cpp",
        "//sdk/lib/async-loop:async-loop-default",
        "//sdk/lib/syslog/cpp",
      ]
    }

    source_set("cpp-lib") {
      sources = [
        "echo_component.cc",
        "echo_component.h",
      ]
    }

    fuchsia_component("component") {
      component_name = "echo-args"
      manifest = "meta/echo.cml"
      deps = [ ":bin" ]
    }

    fuchsia_package("package") {
      package_name = "echo-args"
      deps = [ ":component" ]
    }

Add your new component to the build configuration:

    fx set workstation_eng.x64 --with //vendor/fuchsia-codelab/echo-args

Run `fx build` and verify that the build completes successfully:

    fx build

In the next section, you'll integrate this component into the build and test the
output in the system log.
[](https://issues.fuchsia.dev/issues/new?component=1439230&template=1881640&description=Issue+on:+https://fuchsia.dev/docs/get-started/learn/components/declaring-components.md "Report a bug or suggest improvements on this page") [](https://cs.opensource.google/fuchsia/fuchsia/+/main:docs/get-started/learn/components/declaring-components.md "View the source code of this page") [](https://ci.android.com/edit?repo=fuchsia/fuchsia/main&file=docs/get-started/learn/components/declaring-components.md&cloneRepo=fuchsia/fuchsia:refs/heads/main&fullPath=fuchsia/docs/get-started/learn/components/declaring-components.md "Edit the source code of this page")