Google is committed to advancing racial equity for Black communities. See how.

Creating a FIDL library

Prerequisites

This tutorial expects that you have completed the Getting Started guide and are able to build and run Fuchsia (whether using fx qemu or on actual hardware). You should be familiar with running components on Fuchsia using fx serve and fx shell run, which are covered in Run an example component. This tutorial is the first of the sequence of FIDL tutorials listed in the overview.

Overview

In this tutorial, we will define a FIDL library fuchsia.examples. Defining the FIDL library lets us compile the .fidl files using fx build and check for any errors. It also creates targets that can be included to depend on the bindings for the new library. The bindings tutorials, as well as the prerequisites for this tutorial are listed in the FIDL tutorials overview.

Define the FIDL library

The example code for this tutorial is in //examples/fidl/fuchsia.examples.

We've chosen the directory name to match the library name, which is the convention taken by the libraries defined in the Fuchsia IDK in //sdk/fidl such as //sdk/fidl/fuchsia.url or //sdk/fidl/fuchsia.ui.text.

FIDL file names use the .fidl extension. Analogous to C header files, FIDL files define data types and declare functional interfaces. These declarations are used in conjunction with FIDL-specific data types to communicate between FIDL endpoints.

The following are some examples of various FIDL language features as defined in //examples/fidl/fuchsia.examples/types.test.fidl:

library fuchsia.examples;

const BOARD_SIZE uint8 = 9;
const NAME string = "Tic-Tac-Toe";

type FileMode = strict bits : uint16 {
    READ = 0b001;
    WRITE = 0b010;
    EXECUTE = 0b100;
};

type LocationType = strict enum {
    MUSEUM = 1;
    AIRPORT = 2;
    RESTAURANT = 3;
};

type Color = struct {
    id uint32;
    name string:MAX_STRING_LENGTH = "red";
};

type JsonValue = strict union {
    1: reserved;
    2: int_value int32;
    3: string_value string:MAX_STRING_LENGTH;
};

type User = table {
    1: reserved;
    2: age uint8;
    3: name string:MAX_STRING_LENGTH;
};

type GameState = struct {};

protocol TicTacToe {
    StartGame(struct {
        start_first bool;
    });
    MakeMove(struct {
        row uint8;
        col uint8;
    }) -> (struct {
        success bool;
        new_state box<GameState>;
    });
    -> OnOpponentMove(struct {
        new_state GameState;
    });
};

and also add a protocol to examples/fidl/fuchsia.examples/echo.test.fidl:

// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
library fuchsia.examples;

const MAX_STRING_LENGTH uint64 = 32;

@discoverable
protocol Echo {
    EchoString(struct {
        value string:MAX_STRING_LENGTH;
    }) -> (struct {
        response string:MAX_STRING_LENGTH;
    });
    SendString(struct {
        value string:MAX_STRING_LENGTH;
    });
    -> OnString(struct {
        response string:MAX_STRING_LENGTH;
    });
};

@discoverable
protocol EchoLauncher {
    GetEcho(struct {
        echo_prefix string:MAX_STRING_LENGTH;
    }) -> (resource struct {
        response client_end:Echo;
    });
    GetEchoPipelined(resource struct {
        echo_prefix string:MAX_STRING_LENGTH;
        request server_end:Echo;
    });
};

service EchoService {
    regular_echo client_end:Echo;
    reversed_echo client_end:Echo;
};

The test.fidl extension is used instead of just .fidl, since exemptions to certain requirements like linting or API review are applied to test.fidl files. You should use .fidl when writing your own FIDL files.

Create a GN target for the FIDL library

Now we can define a target for our FIDL library that other code can depend on:

# Copyright 2020 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# Import the fidl GN template.
import("//build/fidl/fidl.gni")

# Define a target for our FIDL library by passing it the FIDL source files
# that make up the library.
fidl("fuchsia.examples") {
  sources = [
    "echo.test.fidl",
    "types.test.fidl",
  ]
  fuzzers = [
    {
      protocol = "fuchsia.examples.Echo"
    },
  ]
}

The fuzzers = [...] line is only needed to enable fuzzing of protocols from the library (see FIDL fuzzing), and can otherwise be omitted.

The bindings tutorials can use the bindings for our FIDL library by depending on targets generated by the GN fidl template.

Compile the FIDL library

You can build the .fidl files and check for syntax errors by including the target in your build config:

fx set core.x64 --with //examples/fidl/fuchsia.examples

Then run fx build examples/fidl/fuchsia.examples.