# Copyright 2020 The Chromium OS Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. """Encapsulation of a build configuration.""" import zmake.util as util class BuildConfig: """A container for build configurations. A build config is a tuple of environment variables, cmake variables, kconfig definitons, and kconfig files. """ def __init__( self, environ_defs={}, cmake_defs={}, kconfig_defs={}, kconfig_files=[] ): self.environ_defs = dict(environ_defs) self.cmake_defs = dict(cmake_defs) self.kconfig_defs = dict(kconfig_defs) self.kconfig_files = kconfig_files def popen_cmake( self, jobclient, project_dir, build_dir, kconfig_path=None, **kwargs ): """Run Cmake with this config using a jobclient. Args: jobclient: A JobClient instance. project_dir: The project directory. build_dir: Directory to use for Cmake build. kconfig_path: The path to write out Kconfig definitions. kwargs: forwarded to popen. """ kconfig_files = list(self.kconfig_files) if kconfig_path: util.write_kconfig_file(kconfig_path, self.kconfig_defs) kconfig_files.append(kconfig_path) elif self.kconfig_defs: raise ValueError( "Cannot start Cmake on a config with Kconfig items without a " "kconfig_path" ) if kconfig_files: base_config = BuildConfig( environ_defs=self.environ_defs, cmake_defs=self.cmake_defs ) conf_file_config = BuildConfig( cmake_defs={ "CONF_FILE": ";".join(str(p.resolve()) for p in kconfig_files) } ) return (base_config | conf_file_config).popen_cmake( jobclient, project_dir, build_dir, **kwargs ) kwargs["env"] = dict(**kwargs.get("env", {}), **self.environ_defs) return jobclient.popen( [ "/usr/bin/cmake", "-S", project_dir, "-B", build_dir, "-GNinja", *("-D{}={}".format(*pair) for pair in self.cmake_defs.items()), ], **kwargs ) def __or__(self, other): """Combine two BuildConfig instances.""" if not isinstance(other, BuildConfig): raise TypeError( "Unsupported operation | for {} and {}".format(type(self), type(other)) ) return BuildConfig( environ_defs=dict(**self.environ_defs, **other.environ_defs), cmake_defs=dict(**self.cmake_defs, **other.cmake_defs), kconfig_defs=dict(**self.kconfig_defs, **other.kconfig_defs), kconfig_files=list({*self.kconfig_files, *other.kconfig_files}), ) def __repr__(self): return "BuildConfig({})".format( ", ".join( "{}={!r}".format(name, getattr(self, name)) for name in [ "environ_defs", "cmake_defs", "kconfig_defs", "kconfig_files", ] if getattr(self, name) ) )