pw_build_android#

Utilities for using Pigweed in Android platform

Unstable C++20

pw_build_android provides simple utilities and guidelines for building with Soong.

Quickstart#

Use the pw_android_common_backends cc_defaults in the Pigweed module library or binary rule to use a preselected set of backends common to most Android platform projects.

cc_binary {
    name: "my_app",
    host_supported: true,
    vendor: true,
    defaults: [
        "pw_android_common_backends",
    ],
    srcs: [
        "main.cc",
    ],
}

Basic blueprint files format#

All Pigweed Soong blueprint files must be named Android.bp, and include the folowing copyright header with the year adjusted and package.

// Copyright 2024 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

package {
    default_applicable_licenses: ["external_pigweed_license"],
}

The bpfmt tool in Android can be used to format a blueprint file, e.g. bpfmt -w Android.bp.

Common Android backends#

Soong doesn’t provide a simple way to select custom Pigweed backends, as is found in other build systems. Fortunately, most Android platform binaries will likely use the same common set of backends. Thus, Pigweed provides a cc_defaults rule named pw_android_common_backends with a selected set of common backends for Android platform binaries. This pw_android_common_backends rule will be used in all Pigweed modules and backends defined using Soong.

This table lists the backends selected by this rule:

Module libraries#

Module libraries are defined as cc_library_static rules and include the common Android backends via the pw_android_common_backends defaults.

Note

Every dependency has to be added as whole_static_libs to avoid dropping symbols on transitive dependencies.

cc_library_static {
    name: "pw_<MODULE_NAME>",
    cpp_std: "c++20",
    export_include_dirs: ["public"],
    vendor_available: true,
    host_supported: true,
    defaults: [
        "pw_android_common_backends",
    ],
    header_libs: [
        // Header library list for all the libraries in #include directives.
    ],
    export_header_lib_headers: [
        // Header library list for all the libraries in #include directives
        // in public header files only.
        // These entries must also be present in header_libs.
    ],
    whole_static_libs: [
        // Static library list for all static library dependencies, listed as
        // whole libraries to avoid dropping symbols in transitive
        // dependencies.
    ],
    export_static_lib_headers: [
        // Static library list for static libraries in #include directives in
        // public header files only.
        // These entries must also be present in whole_static_libs.
    ],
    srcs: [
        // List of source (.cc) files.
    ],
}

Module libraries with custom backends#

If a Pigweed module needs to be used with a backend different than the common Android backend, it should be defined as a cc_defaults rule following the pw_<MODULE_NAME>_no_backends name format, with the source files listed in a filegroup following the pw_<MODULE_NAME>_src_files name format and the include directories defined as a cc_library_headers following the pw_<MODULE_NAME>_include_dirs name format. A cc_static_library with the common Android backend should still be provided, which uses the mentioned cc_defaults.

Note

filegroup captures the absolute paths of the listed source files, so they can be addressed properly when the cc_defaults rule is used.

filegroup {
    name: "pw_<MODULE_NAME>_src_files",
    srcs: [
        // List of source (.cc) files.
    ],
}

 cc_library_headers {
     name: "pw_<MODULE_NAME>_include_dirs",
     export_include_dirs: [
         "public",
     ],
     vendor_available: true,
     host_supported: true,
 }

cc_defaults {
    name: "pw_<MODULE_NAME>_no_backends",
    cpp_std: "c++20",

    header_libs: [
        // Header library list for all the libraries in #include directives.
        "pw_<MODULE_NAME>_include_dirs"
    ],
    export_header_lib_headers: [
        // Header library list for all the libraries in #include directives
        // in public header files only.
        // These entries must also be present in header_libs.
    ],
    whole_static_libs: [
        // Static library list for all static library dependencies, listed as
        // whole libraries to avoid dropping symbols in transitive
        // dependencies.
    ],
    export_static_lib_headers: [
        // Static library list for static libraries in #include directives in
        // public header files only.
        // These entries must also be present in whole_static_libs.
    ],
    srcs: [
        "pw_<MODULE_NAME>_src_files",
    ],
}

cc_library_static {
    name: "pw_<MODULE_NAME>",
    cpp_std: "c++20",
    export_include_dirs: ["public"],
    defaults: [
        "pw_android_common_backends",
        "pw_<MODULE_NAME>_no_backends",
    ],
    vendor_available: true,
    host_supported: true,
}

Module libraries with configurable build flags#

If a Pigweed module provides user-configurable build flags it should be defined as a cc_defaults rule following the pw_<MODULE_NAME>_defaults name format. This hints the user that the rule must be initialized with the desired build flag values. Source files must be listed in a filegroup following the pw_<MODULE_NAME>_src_files name format and the include directories defined as a cc_library_headers following the pw_<MODULE_NAME>_include_dirs name format.

filegroup {
    name: "pw_<MODULE_NAME>_src_files",
    srcs: [
        // List of source (.cc) files.
    ],
}

 cc_library_headers {
     name: "pw_<MODULE_NAME>_include_dirs",
     export_include_dirs: [
         "public",
     ],
     vendor_available: true,
     host_supported: true,
 }

cc_defaults {
    name: "pw_<MODULE_NAME>_defaults",
    cpp_std: "c++20",

    header_libs: [
        // Header library list for all the libraries in #include directives.
        "pw_<MODULE_NAME>_include_dirs"
    ],
    export_header_lib_headers: [
        // Header library list for all the libraries in #include directives
        // in public header files only.
        // These entries must also be present in header_libs.
    ],
    whole_static_libs: [
        // Static library list for all static library dependencies, listed as
        // whole libraries to avoid dropping symbols in transitive
        // dependencies.
    ],
    export_static_lib_headers: [
        // Static library list for static libraries in #include directives in
        // public header files only.
        // These entries must also be present in whole_static_libs.
    ],
    srcs: [
        "pw_<MODULE_NAME>_src_files",
    ],
}

A downstream user can instantiate the pw_<MODULE_NAME>_defaults rule as follows.

Note

To avoid collisions the rule using the cc_defaults must have a unique name that distinguishes it from other rule names in Pigweed and other projects. It is recommended to suffix the project name.

cc_library_static {
    name: "pw_<MODULE_NAME>_<PROJECT_NAME>",
    cflags: [
        "-DPW_<MODULE_NAME>_<FLAG_NAME>=<FLAG_VALUE>",
    ],
    defaults: [
        "pw_<MODULE_NAME>_defaults",
    ],
}

Facades#

All facades must be defined as cc_library_headers if they don’t have srcs list. The facade names follow the pw_<MODULE_NAME>.<FACADE_NAME>. In the case there is only one facade in the module or <MODULE_NAME> is the same as <FACADE_NAME> follow pw_<MODULE_NAME>, e.g. pw_log.

Note

Facade names should not be suffixed with _headers.

cc_library_headers {
    name: "pw_<MODULE_NAME>.<FACADE_NAME>",
    cpp_std: "c++20",
    vendor_available: true,
    host_supported: true,
    export_include_dirs: ["public"],
}

If a facade requires a srcs list, it must be defined as a cc_defaults rule instead, with the source files listed in a filegroup following the pw_<MODULE_NAME>.<FACADE_NAME>_files name format or pw_<MODULE_NAME>_files if applicable.

Note

filegroup captures the absolute paths of the listed source files, so they can be addressed properly when the cc_defaults rule is used.

Note

Facades cannot be defined as cc_static_library because it wouldn’t be possible to build the facade without a backend.

filegroup {
    name: "pw_<MODULE_NAME>.<FACADE_NAME>_files",
    srcs: [
        // List of source (.cc) files.
    ],
}

cc_defaults {
    name: "pw_<MODULE_NAME>.<FACADE_NAME>",
    cpp_std: "c++20",
    export_include_dirs: ["public"],
    srcs: [
        "pw_<MODULE_NAME>.<FACADE_NAME>_files",
    ],
}

To assign a backend to a facade defined as cc_defaults the cc_defaults rule can be placed in the defaults list of a cc_static_library rule or binary rule that lists the facade’s backend as a dependency.

cc_static_library {
    name: "user_of_pw_<MODULE_NAME>.<FACADE_NAME>",
    cpp_std: "c++20",
    vendor_available: true,
    host_supported: true,
    defaults: [
        "pw_<MODULE_NAME>.<FACADE_NAME>",
    ],
    static_libs: [
        "backend_of_pw_<MODULE_NAME>.<FACADE_NAME>",
    ],
}

Alternatively, the cc_defaults rule can be placed in the defaults list of another cc_defaults rule where the latter rule may or may not list the facade’s backend. cc_defaults rules can be inherited many times. Facades can be used as long as the backends are assigned in cc_static_library or binary rules using the final cc_defaults as explained above.

Backends#

Backends are defined the same way as Module libraries. They must follow the pw_<MODULE_NAME>.<FACADE_NAME>_<BACKEND_NAME> name format or pw_<MODULE_NAME>_<BACKEND_NAME> if applicable.

Build flags#

Some build flags should be set for all Android targets; these flags are specified in pw_android_common_backends. These flags are as follows:

PW_FUNCTION_ENABLE_DYNAMIC_ALLOCATION#

As discussed in Dynamic allocation, this flag enables dynamic allocation of pw::Function, allowing it to exceed the inline size limit.

Android targets support dynamic allocation since the Android environment is not memory constrained. Thus, PW_FUNCTION_ENABLE_DYNAMIC_ALLOCATION is enabled in pw_android_common_backends. Components built with dynamic allocation disabled cannot be linked against components with dynamic allocation enabled.