diff options
author | Jeremy Bettis <jbettis@google.com> | 2022-02-04 08:50:45 -0700 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2022-02-19 04:42:07 +0000 |
commit | 2d653eea9c0c70bd41cc8459885d9b0c13f2d27e (patch) | |
tree | c4016c6bc9d2603c3bb17b5bdf5b44e3a0d930f0 | |
parent | 88307eb2bf53f6324eb3c9a609993139880b0f7c (diff) | |
download | chrome-ec-2d653eea9c0c70bd41cc8459885d9b0c13f2d27e.tar.gz |
zmake: Implement zmake configure for multi-project.
Change zmake configure to work as described in go/zmake-cli-v2.
BRANCH=None
BUG=b:217788621
TEST=Various zmake configure cmds.
Cq-Include-Trybots: luci.chromeos.cq:cq-orchestrator
Cq-Depend: chromium:3462900
Change-Id: I58fa4d8427efff64c5764eac6ba4752a71785127
Signed-off-by: Jeremy Bettis <jbettis@google.com>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3445105
Reviewed-by: Jack Rosenthal <jrosenth@chromium.org>
Commit-Queue: Jeremy Bettis <jbettis@chromium.org>
Tested-by: Jeremy Bettis <jbettis@chromium.org>
-rw-r--r-- | .gitlab-ci.yml | 4 | ||||
-rw-r--r-- | docs/code_coverage.md | 4 | ||||
-rw-r--r-- | docs/reducing_ec_image_size.md | 4 | ||||
-rw-r--r-- | docs/zephyr/zephyr_build.md | 6 | ||||
-rw-r--r-- | zephyr/zmake/README.md | 12 | ||||
-rw-r--r-- | zephyr/zmake/tests/test_zmake.py | 4 | ||||
-rw-r--r-- | zephyr/zmake/zmake/__main__.py | 94 | ||||
-rw-r--r-- | zephyr/zmake/zmake/zmake.py | 168 |
8 files changed, 193 insertions, 103 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f36cc8b743..cb4e82fcba 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -72,7 +72,7 @@ seed_cache: script: - zmake --zephyr-base "${ZEPHYR_BASE}" --modules-dir "${MODULES_DIR}" -l DEBUG configure -b - -B "${BUILD_DIR}/${PROJECT}" -t ${TOOLCHAIN:-zephyr} + -B "${BUILD_DIR}" -t ${TOOLCHAIN:-zephyr} "${PROJECT}" - for b in "${BUILD_DIR}/${PROJECT}"/build-* ; do bdir=$(basename ${b}) ; @@ -98,7 +98,7 @@ seed_cache: script: - zmake --zephyr-base "${ZEPHYR_BASE}" --modules-dir "${MODULES_DIR}" -l DEBUG configure -b --coverage - -B "${BUILD_DIR}/${PROJECT}" -t ${TOOLCHAIN:-zephyr} + -B "${BUILD_DIR}" -t ${TOOLCHAIN:-zephyr} "${PROJECT}" - lcov --rc lcov_branch_coverage=1 -o "${BUILD_DIR}/${PROJECT}/output/merged_twister.info" -a "${BUILD_DIR}/${PROJECT}/output/zephyr.info" -a "${BUILD_DIR}/zephyr_codecov/fixed.info" - lcov --rc lcov_branch_coverage=1 -o "${BUILD_DIR}/${PROJECT}/output/merged_twister_no_ec.info" -e "${BUILD_DIR}/${PROJECT}/output/merged_twister.info" "${ZEPHYR_BASE}/**" "${MODULES_DIR}/**" diff --git a/docs/code_coverage.md b/docs/code_coverage.md index cddc7b671d..93637ac019 100644 --- a/docs/code_coverage.md +++ b/docs/code_coverage.md @@ -50,8 +50,8 @@ The coverage report top-level page is `build/ztest-coverage/coverage_rpt/index.html`. For manual coverage report you can run: -`zmake configure --test --coverage <PATH>` +`zmake configure --test --coverage <TESTNAME>` Example: -`zmake configure --test --coverage zephyr/test/drivers/` +`zmake configure --test --coverage test-drivers` `genhtml -q -o build/ztest-coverage/coverage_rpt/ build/zephyr/test-drivers/output/zephyr.info` diff --git a/docs/reducing_ec_image_size.md b/docs/reducing_ec_image_size.md index e7df161bca..d93d0b4840 100644 --- a/docs/reducing_ec_image_size.md +++ b/docs/reducing_ec_image_size.md @@ -122,10 +122,10 @@ images outside chroot before running the commands below. $ zmake configure -B /tmp/zephyr-volteer volteer # Build the RO image -$ ninja -C /tmp/zephyr-volteer/build-ro +$ ninja -C /tmp/zephyr-volteer/volteer/build-ro # Generate the ROM report, report sent to stdout -$ ninja -C /tmp/zephyr-volteer/build-ro rom_report +$ ninja -C /tmp/zephyr-volteer/volteer/build-ro rom_report ``` Please refer to the [Zephyr Optimization Tools][3] documentation for details on diff --git a/docs/zephyr/zephyr_build.md b/docs/zephyr/zephyr_build.md index b49e2ec4b1..c20d4f25e7 100644 --- a/docs/zephyr/zephyr_build.md +++ b/docs/zephyr/zephyr_build.md @@ -114,13 +114,13 @@ a rough guide. First configure the build with the project you want: ```bash -zmake configure -B /tmp/z/vol volteer +zmake configure -B /tmp/z volteer ``` Then build with just the target directory: ``` -zmake build /tmp/z/vol +zmake build /tmp/z/volteer ``` The output is in that directory: @@ -146,7 +146,7 @@ as well. It should be possible to do this with: ```bash -ninja -C /tmp/z/vol/build-ro menuconfig +ninja -C /tmp/z/volteer/build-ro menuconfig ``` However at present this does not work [b/184662866](http://b/184662866). diff --git a/zephyr/zmake/README.md b/zephyr/zmake/README.md index 6eb573154c..697daaab06 100644 --- a/zephyr/zmake/README.md +++ b/zephyr/zmake/README.md @@ -35,27 +35,29 @@ Chromium OS's meta-build tool for Zephyr ### zmake configure -**Usage:** `zmake configure [-h] [-t TOOLCHAIN] [--bringup] [--clobber] [--allow-warnings] [-B BUILD_DIR] [-b] [--test] project_name [-c]` +**Usage:** `zmake configure [-h] [-b] [--test] [-t TOOLCHAIN] [--bringup] [--clobber] [--allow-warnings] [-B BUILD_DIR] [-c] (-a | --host-tests-only | project_name [project_name ...])` #### Positional Arguments | | | |---|---| -| `project_name` | Name of the project to setup | +| `project_name` | Name(s) of the project(s) to build | #### Optional Arguments | | | |---|---| | `-h`, `--help` | show this help message and exit | +| `-b`, `--build` | Run the build after configuration | +| `--test` | Test the .elf file after building | | `-t TOOLCHAIN`, `--toolchain TOOLCHAIN` | Name of toolchain to use | | `--bringup` | Enable bringup debugging features | | `--clobber` | Delete existing build directories, even if configuration is unchanged | | `--allow-warnings` | Do not treat warnings as errors | -| `-B BUILD_DIR`, `--build-dir BUILD_DIR` | Build directory | -| `-b`, `--build` | Run the build after configuration | -| `--test` | Test the .elf file after configuration | +| `-B BUILD_DIR`, `--build-dir BUILD_DIR` | Root build directory, project files will be in ${build_dir}/${project_name} | | `-c`, `--coverage` | Enable CONFIG_COVERAGE Kconfig. | +| `-a`, `--all` | Select all projects | +| `--host-tests-only` | Select all test projects | ### zmake build diff --git a/zephyr/zmake/tests/test_zmake.py b/zephyr/zmake/tests/test_zmake.py index f2759e5af3..33f51b7221 100644 --- a/zephyr/zmake/tests/test_zmake.py +++ b/zephyr/zmake/tests/test_zmake.py @@ -156,7 +156,9 @@ EXTRAVERSION = ): if use_configure: zmk.configure( - "fakeproject", build_dir=pathlib.Path("build"), clobber=True + ["fakeproject"], + build_dir=pathlib.Path("build"), + clobber=True, ) else: with patch("zmake.version.write_version_header", autospec=True): diff --git a/zephyr/zmake/zmake/__main__.py b/zephyr/zmake/zmake/__main__.py index ab60a00657..e8700bda3a 100644 --- a/zephyr/zmake/zmake/__main__.py +++ b/zephyr/zmake/zmake/__main__.py @@ -180,28 +180,6 @@ def get_argparser(): "configure", help="Set up a build directory to be built later by the build subcommand", ) - configure.add_argument("-t", "--toolchain", help="Name of toolchain to use") - configure.add_argument( - "--bringup", - action="store_true", - dest="bringup", - help="Enable bringup debugging features", - ) - configure.add_argument( - "--clobber", - action="store_true", - dest="clobber", - help="Delete existing build directories, even if configuration is unchanged", - ) - configure.add_argument( - "--allow-warnings", - action="store_true", - default=False, - help="Do not treat warnings as errors", - ) - configure.add_argument( - "-B", "--build-dir", type=pathlib.Path, help="Build directory" - ) configure.add_argument( "-b", "--build", @@ -213,19 +191,9 @@ def get_argparser(): "--test", action="store_true", dest="test_after_configure", - help="Test the .elf file after configuration", - ) - configure.add_argument( - "project_name", - help="Name of the project to setup", - ) - configure.add_argument( - "-c", - "--coverage", - action="store_true", - dest="coverage", - help="Enable CONFIG_COVERAGE Kconfig.", + help="Test the .elf file after building", ) + add_common_configure_args(configure) build = sub.add_parser( "build", @@ -329,6 +297,64 @@ def get_argparser(): return parser, sub +def add_common_configure_args(sub_parser: argparse.ArgumentParser): + """Adds common arguments used by configure-like subcommands.""" + sub_parser.add_argument("-t", "--toolchain", help="Name of toolchain to use") + sub_parser.add_argument( + "--bringup", + action="store_true", + dest="bringup", + help="Enable bringup debugging features", + ) + sub_parser.add_argument( + "--clobber", + action="store_true", + dest="clobber", + help="Delete existing build directories, even if configuration is unchanged", + ) + sub_parser.add_argument( + "--allow-warnings", + action="store_true", + default=False, + help="Do not treat warnings as errors", + ) + sub_parser.add_argument( + "-B", + "--build-dir", + type=pathlib.Path, + help="Root build directory, project files will be in " + "${build_dir}/${project_name}", + ) + sub_parser.add_argument( + "-c", + "--coverage", + action="store_true", + dest="coverage", + help="Enable CONFIG_COVERAGE Kconfig.", + ) + group = sub_parser.add_mutually_exclusive_group(required=True) + group.add_argument( + "-a", + "--all", + action="store_true", + dest="all_projects", + help="Select all projects", + ) + group.add_argument( + "--host-tests-only", + action="store_true", + dest="host_tests_only", + help="Select all test projects", + ) + group.add_argument( + "project_names", + nargs="*", + metavar="project_name", + help="Name(s) of the project(s) to build", + default=[], + ) + + def main(argv=None): """The main function. diff --git a/zephyr/zmake/zmake/zmake.py b/zephyr/zmake/zmake/zmake.py index 4b5d6feacb..c175c0b90b 100644 --- a/zephyr/zmake/zmake/zmake.py +++ b/zephyr/zmake/zmake/zmake.py @@ -190,9 +190,30 @@ class Zmake: self._checkout = util.locate_cros_checkout() return self._checkout.resolve() + def _resolve_projects( + self, project_names, all_projects=False, host_tests_only=False + ): + """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") + if all_projects: + projects = found_projects.values() + elif host_tests_only: + projects = [p for p in found_projects.values() if p.config.is_test] + else: + projects = [] + for project_name in project_names: + try: + projects.append(found_projects[project_name]) + except KeyError as e: + raise KeyError("No project named {}".format(project_name)) from e + return projects + def configure( self, - project_name, + project_names, build_dir=None, toolchain=None, build_after_configure=False, @@ -201,25 +222,57 @@ class Zmake: bringup=False, coverage=False, allow_warnings=False, + all_projects=False, + host_tests_only=False, ): - """Locate a project by name or directory and then call _configure.""" - root_dir = self.module_paths["ec"] / "zephyr" - found_projects = zmake.project.find_projects(root_dir) - try: - project = found_projects[project_name] - except KeyError as e: - raise KeyError(f"No project named {project_name}") from e - return self._configure( - project=project, - build_dir=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, + """Locate and configure the specified projects.""" + # Resolve build_dir if needed. + if not build_dir: + build_dir = self.module_paths["ec"] / "build" / "zephyr" + + 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 + self.executor.append( + func=functools.partial( + self._configure, + project=project, + 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, + ) + ) + if self._sequential: + rv = self.executor.wait() + if rv: + return rv + rv = self.executor.wait() + if rv: + return rv + if len(projects) > 1 and coverage and test_after_configure: + rv = self._merge_lcov_files( + projects=[p for p in projects if p.config.is_test], + build_dir=build_dir, + output_file=build_dir / "all_tests.info", + ) + if rv: + return rv + if len(projects) > 1 and coverage and build_after_configure: + rv = self._merge_lcov_files( + projects=[p for p in projects if not p.config.is_test], + build_dir=build_dir, + output_file=build_dir / "all_builds.info", + ) + if rv: + return rv + return 0 def _configure( self, @@ -383,7 +436,7 @@ class Zmake: (build_dir / "project_name.txt").write_text(project.config.project_name) util.update_symlink(project.config.project_dir, build_dir / "project") - if test_after_configure: + if test_after_configure and project.config.is_test: return self.test( build_dir=build_dir, coverage=coverage, @@ -400,6 +453,7 @@ class Zmake: ) else: return self.build(build_dir=build_dir) + return 0 def build(self, build_dir, output_files_out=None, fail_on_warnings=False): """Build a pre-configured build directory.""" @@ -763,46 +817,18 @@ class Zmake: with self.jobserver.get_job(): return self._run_lcov(build_dir, lcov_file, initial=True, gcov=gcov) - def coverage(self, build_dir, clobber=False): - """Builds all targets with coverage enabled, and then runs the tests.""" + def _merge_lcov_files(self, projects, build_dir, output_file): all_lcov_files = [] - root_dir = self.module_paths["ec"] / "zephyr" - for project in zmake.project.find_projects(root_dir).values(): - is_test = project.config.is_test + for project in projects: project_build_dir = pathlib.Path(build_dir) / project.config.project_name - if is_test: - # Configure and run the test. - all_lcov_files.append(project_build_dir / "output" / "zephyr.info") - self.executor.append( - func=functools.partial( - self._configure, - project=project, - build_dir=project_build_dir, - build_after_configure=True, - test_after_configure=is_test, - coverage=True, - clobber=clobber, - ) - ) - else: - # Don't build non-test projects - self.logger.info("Skipping project %s", project.config.project_name) - if self._sequential: - rv = self.executor.wait() - if rv: - return rv - - rv = self.executor.wait() - if rv: - return rv - + all_lcov_files.append(project_build_dir / "output" / "zephyr.info") with self.jobserver.get_job(): # Merge info files into a single lcov.info - self.logger.info("Merging coverage data into %s.", build_dir / "lcov.info") + self.logger.info("Merging coverage data into %s.", output_file) cmd = [ "/usr/bin/lcov", "-o", - build_dir / "lcov.info", + output_file, "--rc", "lcov_branch_coverage=1", ] @@ -823,7 +849,41 @@ class Zmake: ) if proc.wait(): raise OSError(get_process_failure_msg(proc)) + return 0 + def coverage(self, build_dir, clobber=False): + """Builds all targets with coverage enabled, and then runs the tests.""" + root_dir = self.module_paths["ec"] / "zephyr" + projects = [ + p + for p in zmake.project.find_projects(root_dir).values() + if p.config.is_test + ] + for project in projects: + project_build_dir = pathlib.Path(build_dir) / project.config.project_name + # Configure and run the test. + self.executor.append( + func=functools.partial( + self._configure, + project=project, + build_dir=project_build_dir, + build_after_configure=True, + test_after_configure=True, + coverage=True, + clobber=clobber, + ) + ) + if self._sequential: + rv = self.executor.wait() + if rv: + return rv + + rv = self.executor.wait() + if rv: + return rv + + self._merge_lcov_files(projects, build_dir, build_dir / "lcov.info") + with self.jobserver.get_job(): # Find the common root dir prefixdir = os.path.commonprefix(list(self.module_paths.values())) @@ -841,8 +901,8 @@ class Zmake: prefixdir, "-s", "--branch-coverage", - ] - + all_lcov_files, + build_dir / "lcov.info", + ], stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding="utf-8", |