blob: 7dcdf97ad6acc6c07e093af3a6578f0d0bf5b817 [file] [log] [blame]
# Copyright 2023 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.
"""Default pw build script for upstream Pigweed.
Usage:
pw build --list
pw build --recipe default_gn
pw build --recipe default_* --watch
pw build --step gn_combined_build_check --step gn_python_*
pw build -C out/gn --watch
"""
import argparse
import logging
from pathlib import Path
import shutil
import sys
import pw_cli.env
import pw_presubmit.pigweed_presubmit
from pw_presubmit.build import gn_args
from pw_build.build_recipe import (
BuildCommand,
BuildRecipe,
should_gn_gen,
should_regenerate_cmake,
)
from pw_build.project_builder_presubmit_runner import (
get_parser,
main,
)
_LOG = logging.getLogger('pw_build')
_PW_ENV = pw_cli.env.pigweed_environment()
_REPO_ROOT = _PW_ENV.PW_PROJECT_ROOT
_PACKAGE_ROOT = _PW_ENV.PW_PACKAGE_ROOT
def gn_recipe() -> BuildRecipe:
"""Return the default_gn recipe."""
default_gn_gen_command = [
'gn',
'gen',
# NOTE: Not an f-string. BuildRecipe will replace with the out dir.
'{build_dir}',
'--export-compile-commands',
]
if shutil.which('ccache'):
default_gn_gen_command.append(gn_args(pw_command_launcher='ccache'))
return BuildRecipe(
build_dir=Path('out/gn'),
title='default_gn',
steps=[
BuildCommand(
run_if=should_gn_gen,
command=default_gn_gen_command,
),
BuildCommand(
build_system_command='ninja',
targets=['default'],
),
],
)
def bazel_recipe() -> BuildRecipe:
"""Return the default_bazel recipe."""
default_bazel_targets = ['//...:all']
return BuildRecipe(
build_dir=Path('out/bazel'),
title='default_bazel',
steps=[
BuildCommand(
build_system_command='bazel',
build_system_extra_args=[
'build',
'--verbose_failures',
'--worker_verbose',
],
targets=default_bazel_targets,
),
BuildCommand(
build_system_command='bazel',
build_system_extra_args=[
'test',
'--test_output=errors',
],
targets=default_bazel_targets,
),
],
)
def cmake_recipe() -> BuildRecipe:
"""Construct the default_cmake recipe."""
toolchain_path = (
_REPO_ROOT / 'pw_toolchain' / 'host_clang' / 'toolchain.cmake'
)
cmake_generate_command = [
'cmake',
'--fresh',
'--debug-output',
'-DCMAKE_MESSAGE_LOG_LEVEL=WARNING',
'-S',
str(_REPO_ROOT),
'-B',
# NOTE: Not an f-string. BuildRecipe will replace with the out dir.
'{build_dir}',
'-G',
'Ninja',
f'-DCMAKE_TOOLCHAIN_FILE={toolchain_path}',
'-DCMAKE_EXPORT_COMPILE_COMMANDS=1',
f'-Ddir_pw_third_party_nanopb={_PACKAGE_ROOT / "nanopb"}',
'-Dpw_third_party_nanopb_ADD_SUBDIRECTORY=ON',
f'-Ddir_pw_third_party_emboss={_PACKAGE_ROOT / "emboss"}',
f'-Ddir_pw_third_party_boringssl={_PACKAGE_ROOT / "boringssl"}',
]
if shutil.which('ccache'):
cmake_generate_command.append("-DCMAKE_C_COMPILER_LAUNCHER=ccache")
cmake_generate_command.append("-DCMAKE_CXX_COMPILER_LAUNCHER=ccache")
pw_package_install_steps = [
BuildCommand(
command=['pw', '--no-banner', 'package', 'install', package],
)
for package in ['emboss', 'nanopb', 'boringssl']
]
return BuildRecipe(
build_dir=Path('out/cmake'),
title='default_cmake',
steps=pw_package_install_steps
+ [
BuildCommand(
run_if=should_regenerate_cmake(cmake_generate_command),
command=cmake_generate_command,
),
BuildCommand(
build_system_command='ninja',
targets=pw_presubmit.pigweed_presubmit.CMAKE_TARGETS,
),
],
)
def pigweed_upstream_main() -> int:
"""Entry point for Pigweed upstream ``pw build`` command.
Defines one or more BuildRecipes and passes that along with all of Pigweed
upstream presubmit programs to the project_builder_presubmit_runner.main to
start a pw build invocation.
Returns:
An int representing the success or failure status of the build; 0 if
successful, 1 if failed.
Command line usage examples:
.. code-block:: bash
pw build --list
pw build --recipe default_gn
pw build --recipe default_* --watch
pw build --step gn_combined_build_check --step gn_python_*
pw build -C out/gn --watch
"""
return main(
presubmit_programs=pw_presubmit.pigweed_presubmit.PROGRAMS,
build_recipes=[
gn_recipe(),
bazel_recipe(),
cmake_recipe(),
],
default_root_logfile=Path('out/build.txt'),
)
def _build_argument_parser() -> argparse.ArgumentParser:
return get_parser(
pw_presubmit.pigweed_presubmit.PROGRAMS,
[
gn_recipe(),
bazel_recipe(),
cmake_recipe(),
],
)
if __name__ == '__main__':
sys.exit(pigweed_upstream_main())