summaryrefslogtreecommitdiff
path: root/zephyr/zmake/zmake/zmake.py
diff options
context:
space:
mode:
Diffstat (limited to 'zephyr/zmake/zmake/zmake.py')
-rw-r--r--zephyr/zmake/zmake/zmake.py360
1 files changed, 126 insertions, 234 deletions
diff --git a/zephyr/zmake/zmake/zmake.py b/zephyr/zmake/zmake/zmake.py
index d4af57a738..b7a81a3b9b 100644
--- a/zephyr/zmake/zmake/zmake.py
+++ b/zephyr/zmake/zmake/zmake.py
@@ -1,4 +1,4 @@
-# Copyright 2020 The Chromium OS Authors. All rights reserved.
+# Copyright 2020 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
@@ -11,7 +11,6 @@ import pathlib
import re
import shutil
import subprocess
-import uuid
from typing import Dict, Optional, Set, Union
import zmake.build_config
@@ -153,7 +152,7 @@ class Zmake:
# pylint: disable=too-many-instance-attributes
- def __init__( # pylint: disable=too-many-arguments
+ def __init__(
self,
checkout=None,
jobserver: Optional[zmake.jobserver.JobClient] = None,
@@ -171,12 +170,16 @@ class Zmake:
if zephyr_base:
self.zephyr_base = zephyr_base
else:
- self.zephyr_base = self.checkout / "src" / "third_party" / "zephyr" / "main"
+ self.zephyr_base = (
+ self.checkout / "src" / "third_party" / "zephyr" / "main"
+ )
if modules_dir:
self.module_paths = zmake.modules.locate_from_directory(modules_dir)
else:
- self.module_paths = zmake.modules.locate_from_checkout(self.checkout)
+ self.module_paths = zmake.modules.locate_from_checkout(
+ self.checkout
+ )
if jobserver:
self.jobserver = jobserver
@@ -198,40 +201,45 @@ class Zmake:
return self._checkout.resolve()
def _resolve_projects(
- self, project_names, all_projects=False, host_tests_only=False
+ self,
+ project_names,
+ all_projects=False,
) -> Set[zmake.project.Project]:
"""Finds all projects for the specified command line flags.
Returns a list of projects.
"""
- found_projects = zmake.project.find_projects(self.module_paths["ec"] / "zephyr")
+ found_projects = zmake.project.find_projects(
+ self.module_paths["ec"] / "zephyr"
+ )
if all_projects:
projects = set(found_projects.values())
- elif host_tests_only:
- projects = {p for p in found_projects.values() if p.config.is_test}
else:
projects = set()
for project_name in project_names:
try:
projects.add(found_projects[project_name])
except KeyError as e:
- raise KeyError("No project named {}".format(project_name)) from e
+ raise KeyError(
+ "No project named {}".format(project_name)
+ ) from e
return projects
- def configure( # pylint: disable=too-many-arguments,too-many-locals
+ def configure(
self,
project_names,
build_dir=None,
toolchain=None,
build_after_configure=False,
- test_after_configure=False,
clobber=False,
bringup=False,
coverage=False,
allow_warnings=False,
all_projects=False,
- host_tests_only=False,
extra_cflags=None,
+ delete_intermediates=False,
+ static_version=False,
+ save_temps=False,
):
"""Locate and configure the specified projects."""
# Resolve build_dir if needed.
@@ -241,10 +249,11 @@ class Zmake:
projects = self._resolve_projects(
project_names,
all_projects=all_projects,
- host_tests_only=host_tests_only,
)
for project in projects:
- project_build_dir = pathlib.Path(build_dir) / project.config.project_name
+ project_build_dir = (
+ pathlib.Path(build_dir) / project.config.project_name
+ )
self.executor.append(
func=functools.partial(
self._configure,
@@ -252,13 +261,15 @@ class Zmake:
build_dir=project_build_dir,
toolchain=toolchain,
build_after_configure=build_after_configure,
- test_after_configure=test_after_configure,
clobber=clobber,
bringup=bringup,
coverage=coverage,
allow_warnings=allow_warnings,
extra_cflags=extra_cflags,
multiproject=len(projects) > 1,
+ delete_intermediates=delete_intermediates,
+ static_version=static_version,
+ save_temps=save_temps,
)
)
if self._sequential:
@@ -268,16 +279,6 @@ class Zmake:
result = self.executor.wait()
if result:
return result
- test_projects = [p for p in projects if p.config.is_test]
- if len(test_projects) > 1 and coverage and test_after_configure:
- result = self._merge_lcov_files(
- projects=test_projects,
- build_dir=build_dir,
- output_file=build_dir / "all_tests.info",
- )
- if result:
- self.failed_projects.append(str(build_dir / "all_tests.info"))
- return result
non_test_projects = [p for p in projects if not p.config.is_test]
if len(non_test_projects) > 1 and coverage and build_after_configure:
result = self._merge_lcov_files(
@@ -290,7 +291,7 @@ class Zmake:
return result
return 0
- def build( # pylint: disable=too-many-arguments
+ def build(
self,
project_names,
build_dir=None,
@@ -300,8 +301,10 @@ class Zmake:
coverage=False,
allow_warnings=False,
all_projects=False,
- host_tests_only=False,
extra_cflags=None,
+ delete_intermediates=False,
+ static_version=False,
+ save_temps=False,
):
"""Locate and build the specified projects."""
return self.configure(
@@ -313,133 +316,57 @@ class Zmake:
coverage=coverage,
allow_warnings=allow_warnings,
all_projects=all_projects,
- host_tests_only=host_tests_only,
extra_cflags=extra_cflags,
build_after_configure=True,
+ delete_intermediates=delete_intermediates,
+ static_version=static_version,
+ save_temps=save_temps,
)
- def test( # pylint: disable=too-many-arguments,too-many-locals
+ def test( # pylint: disable=unused-argument
self,
project_names,
- build_dir=None,
- toolchain=None,
- clobber=False,
- bringup=False,
- coverage=False,
- allow_warnings=False,
- all_projects=False,
- host_tests_only=False,
- extra_cflags=None,
- no_rebuild=False,
):
- """Locate and build the specified projects."""
- if not no_rebuild:
- return self.configure(
- project_names,
- build_dir=build_dir,
- toolchain=toolchain,
- clobber=clobber,
- bringup=bringup,
- coverage=coverage,
- allow_warnings=allow_warnings,
- all_projects=all_projects,
- host_tests_only=host_tests_only,
- extra_cflags=extra_cflags,
- test_after_configure=True,
- )
- # Resolve build_dir if needed.
- if not build_dir:
- build_dir = self.module_paths["ec"] / "build" / "zephyr"
+ """Build and run tests for the specified projects.
- projects = self._resolve_projects(
- project_names,
- all_projects=all_projects,
- host_tests_only=host_tests_only,
+ Using zmake to run tests is no longer supported. Use twister.
+ """
+ self.logger.error(
+ "zmake test is deprecated. Use twister -T zephyr/test/<test_dir>."
)
- test_projects = [p for p in projects if p.config.is_test]
- for project in test_projects:
- project_build_dir = pathlib.Path(build_dir) / project.config.project_name
- gcov = "gcov.sh-not-found"
- for build_name, _ in project.iter_builds():
- target_build_dir = project_build_dir / "build-{}".format(build_name)
- gcov = target_build_dir / "gcov.sh"
- self.executor.append(
- func=functools.partial(
- self._run_test,
- project=project,
- coverage=coverage,
- gcov=gcov,
- build_dir=project_build_dir,
- lcov_file=project_build_dir / "output" / "zephyr.info",
- timeout=project.config.test_timeout_secs,
- )
- )
- if self._sequential:
- result = self.executor.wait()
- if result:
- return result
- result = self.executor.wait()
- if result:
- return result
- if len(test_projects) > 1 and coverage:
- result = self._merge_lcov_files(
- projects=test_projects,
- build_dir=build_dir,
- output_file=build_dir / "all_tests.info",
- )
- if result:
- self.failed_projects.append(str(build_dir / "all_tests.info"))
- return result
+
return 0
- def testall( # pylint: disable=too-many-arguments
+ def testall(
self,
- build_dir=None,
- toolchain=None,
- clobber=False,
- bringup=False,
- coverage=False,
- allow_warnings=False,
):
- """Locate and build all the projects."""
- return self.test(
- [],
- build_dir=build_dir,
- toolchain=toolchain,
- clobber=clobber,
- bringup=bringup,
- coverage=coverage,
- allow_warnings=allow_warnings,
- all_projects=True,
+ """Build and run tests for all projects.
+
+ Using zmake to run tests is no longer supported. Use twister.
+ """
+ self.logger.error(
+ "zmake testall is deprecated. To build all packages, use zmake build -a."
)
+ return self.test([])
def _configure(
self,
project,
- build_dir=None,
+ build_dir: pathlib.Path,
toolchain=None,
build_after_configure=False,
- test_after_configure=False,
clobber=False,
bringup=False,
coverage=False,
allow_warnings=False,
extra_cflags=None,
multiproject=False,
+ delete_intermediates=False,
+ static_version=False,
+ save_temps=False,
):
- # pylint: disable=too-many-arguments,too-many-locals,too-many-branches
- # pylint: disable=too-many-statements
"""Set up a build directory to later be built by "zmake build"."""
try:
- # Resolve build_dir if needed.
- if not build_dir:
- build_dir = (
- self.module_paths["ec"]
- / "build"
- / "zephyr"
- / project.config.project_name
- )
-
# Clobber build directory if requested.
if clobber and build_dir.exists():
self.logger.info(
@@ -449,14 +376,34 @@ class Zmake:
generated_include_dir = (build_dir / "include").resolve()
base_config = zmake.build_config.BuildConfig(
- environ_defs={"ZEPHYR_BASE": str(self.zephyr_base), "PATH": "/usr/bin"},
cmake_defs={
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON",
"DTS_ROOT": str(self.module_paths["ec"] / "zephyr"),
"SYSCALL_INCLUDE_DIRS": str(
- self.module_paths["ec"] / "zephyr" / "include" / "drivers"
+ self.module_paths["ec"]
+ / "zephyr"
+ / "include"
+ / "drivers"
),
+ "USER_CACHE_DIR": str(
+ self.module_paths["ec"]
+ / "build"
+ / "zephyr"
+ / "user-cache"
+ ),
+ "ZEPHYR_BASE": str(self.zephyr_base),
"ZMAKE_INCLUDE_DIR": str(generated_include_dir),
+ "ZMAKE_PROJECT_NAME": project.config.project_name,
+ **(
+ {"EXTRA_EC_VERSION_FLAGS": "--static"}
+ if static_version
+ else {}
+ ),
+ **(
+ {"EXTRA_CFLAGS": "-save-temps=obj"}
+ if save_temps
+ else {}
+ ),
},
)
@@ -473,7 +420,9 @@ class Zmake:
dts_overlay_config = project.find_dts_overlays(module_paths)
- toolchain_support = project.get_toolchain(module_paths, override=toolchain)
+ toolchain_support = project.get_toolchain(
+ module_paths, override=toolchain
+ )
toolchain_config = toolchain_support.get_build_config()
if bringup:
@@ -501,7 +450,7 @@ class Zmake:
)
if not build_dir.exists():
- build_dir = build_dir.mkdir()
+ build_dir.mkdir()
if not generated_include_dir.exists():
generated_include_dir.mkdir()
processes = []
@@ -542,7 +491,9 @@ class Zmake:
shutil.rmtree(output_dir)
self.logger.info(
- "Configuring %s:%s.", project.config.project_name, build_name
+ "Configuring %s:%s.",
+ project.config.project_name,
+ build_name,
)
kconfig_file = build_dir / "kconfig-{}.conf".format(build_name)
@@ -586,51 +537,50 @@ class Zmake:
# To reconstruct a Project object later, we need to know the
# name and project directory.
- (build_dir / "project_name.txt").write_text(project.config.project_name)
- util.update_symlink(project.config.project_dir, build_dir / "project")
+ (build_dir / "project_name.txt").write_text(
+ project.config.project_name
+ )
+ util.update_symlink(
+ project.config.project_dir, build_dir / "project"
+ )
output_files = []
- if build_after_configure or test_after_configure:
+ if build_after_configure:
result = self._build(
build_dir=build_dir,
project=project,
coverage=coverage,
output_files_out=output_files,
multiproject=multiproject,
+ static_version=static_version,
)
if result:
self.failed_projects.append(project.config.project_name)
return result
- if test_after_configure and project.config.is_test:
- gcov = "gcov.sh-not-found"
- for build_name, _ in project.iter_builds():
- target_build_dir = build_dir / "build-{}".format(build_name)
- gcov = target_build_dir / "gcov.sh"
- self.executor.append(
- func=functools.partial(
- self._run_test,
- project=project,
- coverage=coverage,
- gcov=gcov,
- build_dir=build_dir,
- lcov_file=build_dir / "output" / "zephyr.info",
- timeout=project.config.test_timeout_secs,
- )
- )
+
+ if delete_intermediates:
+ outdir = build_dir / "output"
+ for child in build_dir.iterdir():
+ if child != outdir:
+ logging.debug("Deleting %s", child)
+ if not child.is_symlink() and child.is_dir():
+ shutil.rmtree(child)
+ else:
+ child.unlink()
return 0
except Exception:
self.failed_projects.append(project.config.project_name)
raise
- def _build( # pylint: disable=too-many-arguments
+ def _build(
self,
build_dir,
project: zmake.project.Project,
output_files_out=None,
coverage=False,
multiproject=False,
+ static_version=False,
):
- # pylint: disable=too-many-locals,too-many-branches
"""Build a pre-configured build directory."""
def wait_and_check_success(procs, writers):
@@ -669,9 +619,10 @@ class Zmake:
# Compute the version string.
version_string = zmake.version.get_version_string(
- project,
+ project.config.project_name,
build_dir / "zephyr_base",
zmake.modules.locate_from_directory(build_dir / "modules"),
+ static=static_version,
)
# The version header needs to generated during the build phase
@@ -680,6 +631,8 @@ class Zmake:
zmake.version.write_version_header(
version_string,
build_dir / "include" / "ec_version.h",
+ "zmake",
+ static=static_version,
)
gcov = "gcov.sh-not-found"
@@ -708,10 +661,15 @@ class Zmake:
stderr=subprocess.PIPE,
encoding="utf-8",
errors="replace",
+ # TODO(b/239619222): Filter os.environ for ninja.
+ env=os.environ,
)
job_id = "{}:{}".format(project.config.project_name, build_name)
dirs[build_name].mkdir(parents=True, exist_ok=True)
- build_log = open(dirs[build_name] / "build.log", "w")
+ build_log = open( # pylint:disable=consider-using-with
+ dirs[build_name] / "build.log",
+ "w",
+ )
out = zmake.multiproc.LogWriter.log_output(
logger=self.logger,
log_level=logging.INFO,
@@ -751,11 +709,17 @@ class Zmake:
if coverage and not project.config.is_test:
with self.jobserver.get_job():
self._run_lcov(
- build_dir, output_dir / "zephyr.info", initial=True, gcov=gcov
+ build_dir,
+ output_dir / "zephyr.info",
+ initial=True,
+ gcov=gcov,
)
else:
for output_file, output_name in project.packer.pack_firmware(
- packer_work_dir, self.jobserver, dirs, version_string=version_string
+ packer_work_dir,
+ self.jobserver,
+ dirs,
+ version_string=version_string,
):
shutil.copy2(output_file, output_dir / output_name)
self.logger.debug("Output file '%s' created.", output_file)
@@ -763,86 +727,12 @@ class Zmake:
return 0
- def _run_test( # pylint: disable=too-many-arguments
+ def _run_lcov(
self,
- project: zmake.project.Project,
- coverage,
- gcov,
build_dir,
lcov_file,
- timeout=None,
- ):
- """Run a single test, with goma if enabled.
-
- Args:
- project: The project to run the test from.
- coverage: True if coverage is enabled.
- gcov: Path to the gcov binary.
- build_dir: Path to the build directory
- lcov_file: Output path for the generated lcov file.
- """
-
- try:
- cmd = []
- if self.goma:
- cmd.append(self.gomacc)
-
- elf_file = build_dir / "output" / "zephyr.elf"
- cmd.append(elf_file)
-
- execution_tmp_dir = build_dir / "tmp" / str(uuid.uuid4())
- execution_tmp_dir.mkdir(parents=True, exist_ok=True)
- for arg in project.config.test_args:
- cmd.append(arg.format(test_temp_dir=execution_tmp_dir))
-
- def _run():
- self.logger.info("Running tests in %s.", elf_file)
- proc = self.jobserver.popen(
- cmd,
- cwd=elf_file.parent,
- stdin=subprocess.DEVNULL,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- encoding="utf-8",
- errors="replace",
- )
- job_id = "test {}".format(elf_file)
- zmake.multiproc.LogWriter.log_output(
- self.logger,
- logging.DEBUG,
- proc.stdout,
- job_id=job_id,
- )
- zmake.multiproc.LogWriter.log_output(
- self.logger,
- logging.ERROR,
- proc.stderr,
- job_id=job_id,
- )
- try:
- if proc.wait(timeout=timeout):
- raise OSError(get_process_failure_msg(proc))
- if coverage:
- self._run_lcov(build_dir, lcov_file, initial=False, gcov=gcov)
- except subprocess.TimeoutExpired as e:
- proc.terminate()
- try:
- proc.wait(timeout=1)
- except subprocess.TimeoutExpired:
- proc.kill()
- raise e
-
- if self.goma:
- _run()
- else:
- with self.jobserver.get_job():
- _run()
- except Exception:
- self.failed_projects.append(project.config.project_name)
- raise
-
- def _run_lcov(
- self, build_dir, lcov_file, initial=False, gcov: Union[os.PathLike, str] = ""
+ initial=False,
+ gcov: Union[os.PathLike, str] = "",
):
gcov = os.path.abspath(gcov)
if initial:
@@ -895,7 +785,9 @@ class Zmake:
def _merge_lcov_files(self, projects, build_dir, output_file):
all_lcov_files = []
for project in projects:
- project_build_dir = pathlib.Path(build_dir) / project.config.project_name
+ project_build_dir = (
+ pathlib.Path(build_dir) / project.config.project_name
+ )
all_lcov_files.append(project_build_dir / "output" / "zephyr.info")
with self.jobserver.get_job():
# Merge info files into a single lcov.info