blob: 6e245fb00f84c0c7deba4cceecf9e136f1730cc1 [file] [log] [blame]
#!/usr/bin/env -S python3 -B
# Copyright (c) 2021 Project CHIP 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
#
# http://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.
from runner import PrintOnlyRunner, ShellRunner
import build
import coloredlogs
import click
import logging
import os
import sys
sys.path.append(os.path.abspath(os.path.dirname(__file__)))
# Supported log levels, mapping string values required for argument
# parsing into logging constants
__LOG_LEVELS__ = {
'debug': logging.DEBUG,
'info': logging.INFO,
'warn': logging.WARN,
'fatal': logging.FATAL,
}
def ValidateRepoPath(context, parameter, value):
"""Validates that the given path looks like a valid chip repository checkout."""
if value.startswith('/TEST/'):
# Hackish command to allow for unit testing
return value
for name in ['BUILD.gn', '.gn', os.path.join('scripts', 'bootstrap.sh')]:
expected_file = os.path.join(value, name)
if not os.path.exists(expected_file):
raise click.BadParameter(
"'%s' does not look like a valid repository path: %s not found." %
(value, expected_file))
return value
@click.group(chain=True)
@click.option(
'--log-level',
default='INFO',
type=click.Choice(__LOG_LEVELS__.keys(), case_sensitive=False),
help='Determines the verbosity of script output.')
@click.option(
'--platform',
default=[],
type=click.Choice(build.PLATFORMS + ['all'], case_sensitive=False),
multiple=True,
help='Platform to use for compilation. Empty will default to a linux host build'
)
@click.option(
'--board',
default=[],
type=click.Choice(build.BOARDS, case_sensitive=False),
multiple=True,
help='Specific board to compile for. Empty will use --platform to determine suitable boards.'
)
@click.option(
'--app',
default=[],
type=click.Choice(build.APPLICATIONS, case_sensitive=False),
multiple=True,
help='What example application to build. Empty will find suitable applications.'
)
@click.option(
'--enable-flashbundle',
default=False,
is_flag=True,
help='Also generate the flashbundles for the app.'
)
@click.option(
'--repo',
default='.',
callback=ValidateRepoPath,
help='Path to the root of the CHIP SDK repository checkout.')
@click.option(
'--out-prefix',
default='./out',
type=click.Path(file_okay=False, resolve_path=True),
help='Prefix for the generated file output.')
@click.option(
'--clean',
default=False,
is_flag=True,
help='Clean output directory before running the command')
@click.option(
'--dry-run',
default=False,
is_flag=True,
help='Only print out shell commands that would be executed')
@click.option(
'--dry-run-output',
default="-",
type=click.File("wt"),
help='Where to write the dry run output')
@click.pass_context
def main(context, log_level, platform, board, app, repo, out_prefix, clean,
dry_run, dry_run_output, enable_flashbundle):
# Ensures somewhat pretty logging of what is going on
coloredlogs.install(
level=__LOG_LEVELS__[log_level],
fmt='%(asctime)s %(name)s %(levelname)-7s %(message)s')
if not 'PW_PROJECT_ROOT' in os.environ:
raise click.UsageError("""
PW_PROJECT_ROOT not in current environment.
Please make sure you `source scripts/bootstrap.sh` or `source scripts/activate.sh`
before running this script.
""".strip())
# Support an 'all platforms' choice
if 'all' in platform:
platform = build.PLATFORMS
if dry_run:
runner = PrintOnlyRunner(dry_run_output)
else:
runner = ShellRunner()
context.obj = build.Context(
repository_path=repo, output_prefix=out_prefix, runner=runner)
context.obj.SetupBuilders(
platforms=[build.Platform.FromArgName(name) for name in platform],
boards=[build.Board.FromArgName(name) for name in board],
applications=[build.Application.FromArgName(name) for name in app],
enable_flashbundle=enable_flashbundle)
if clean:
context.obj.CleanOutputDirectories()
@main.command(
'gen', help='Generate ninja/makefiles (but does not run the compilation)')
@click.pass_context
def cmd_generate(context):
context.obj.Generate()
@main.command('build', help='generate and run ninja/make as needed to compile')
@click.option(
'--copy-artifacts-to',
default=None,
type=click.Path(file_okay=False, resolve_path=True),
help='Prefix for the generated file output.')
@click.option(
'--create-archives',
default=None,
type=click.Path(file_okay=False, resolve_path=True),
help='Prefix of compressed archives of the generated files.')
@click.pass_context
def cmd_build(context, copy_artifacts_to, create_archives):
context.obj.Build()
if copy_artifacts_to:
context.obj.CopyArtifactsTo(copy_artifacts_to)
if create_archives:
context.obj.CreateArtifactArchives(create_archives)
if __name__ == '__main__':
main()