blob: 097dca85d0d945c335be66e6f8a695c135a5dff7 [file] [log] [blame]
Mike Frysingerf1ba7ad2022-09-12 05:42:57 -04001# Copyright 2019 The ChromiumOS Authors
Alex Kleinda35fcf2019-03-07 16:01:15 -07002# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Build target class and related functionality."""
6
Alex Kleinda35fcf2019-03-07 16:01:15 -07007import os
Alex Klein1a55dde2020-03-06 15:53:29 -07008import re
nohe@chromium.orgc78b38f2021-08-23 09:48:13 -07009from typing import Optional
Alex Kleinda35fcf2019-03-07 16:01:15 -070010
LaMont Jonesfeffd1b2020-08-05 18:24:59 -060011from chromite.api.gen.chromiumos import common_pb2
12
Alex Kleinda35fcf2019-03-07 16:01:15 -070013
14class Error(Exception):
Alex Klein1699fab2022-09-08 08:46:06 -060015 """Base module error class."""
Alex Kleinda35fcf2019-03-07 16:01:15 -070016
17
Alex Kleinda35fcf2019-03-07 16:01:15 -070018class BuildTarget(object):
Alex Klein1699fab2022-09-08 08:46:06 -060019 """Class to handle the build target information."""
Alex Kleinda35fcf2019-03-07 16:01:15 -070020
Alex Klein1699fab2022-09-08 08:46:06 -060021 def __init__(
22 self,
23 name: Optional[str],
24 profile: Optional[str] = None,
25 build_root: Optional[str] = None,
26 ):
27 """Build Target init.
Alex Kleinda35fcf2019-03-07 16:01:15 -070028
Alex Klein1699fab2022-09-08 08:46:06 -060029 Args:
30 name: The full name of the target.
31 profile: The profile name.
32 build_root: The path to the buildroot.
33 """
34 self._name = name or None
35 self.profile = profile
Alex Kleinda35fcf2019-03-07 16:01:15 -070036
Alex Klein1699fab2022-09-08 08:46:06 -060037 if build_root:
38 self.root = os.path.normpath(build_root)
39 else:
40 self.root = get_default_sysroot_path(self.name)
Alex Kleinda35fcf2019-03-07 16:01:15 -070041
Alex Klein1699fab2022-09-08 08:46:06 -060042 def __eq__(self, other):
43 if self.__class__ is other.__class__:
44 return (
45 self.name == other.name
46 and self.profile == other.profile
47 and self.root == other.root
48 )
Alex Klein171da612019-08-06 14:00:42 -060049
Alex Klein1699fab2022-09-08 08:46:06 -060050 return NotImplemented
Alex Klein171da612019-08-06 14:00:42 -060051
Alex Klein1699fab2022-09-08 08:46:06 -060052 def __hash__(self):
53 return hash(self.name)
Alex Klein171da612019-08-06 14:00:42 -060054
Alex Klein1699fab2022-09-08 08:46:06 -060055 def __str__(self):
56 return self.name
Alex Kleinaf0e0452019-06-03 18:10:01 -060057
Alex Klein1699fab2022-09-08 08:46:06 -060058 @property
59 def name(self):
60 return self._name
Alex Kleinda35fcf2019-03-07 16:01:15 -070061
Alex Klein1699fab2022-09-08 08:46:06 -060062 @property
63 def as_protobuf(self):
64 return common_pb2.BuildTarget(name=self.name or "")
LaMont Jonesfeffd1b2020-08-05 18:24:59 -060065
Alex Klein1699fab2022-09-08 08:46:06 -060066 @classmethod
67 def from_protobuf(cls, message):
68 return cls(name=message.name)
LaMont Jonesfeffd1b2020-08-05 18:24:59 -060069
Alex Klein1699fab2022-09-08 08:46:06 -060070 @property
71 def profile_protobuf(self):
72 return common_pb2.Profile(name=self.profile)
LaMont Jonesfeffd1b2020-08-05 18:24:59 -060073
Alex Klein1699fab2022-09-08 08:46:06 -060074 def full_path(self, *args):
75 """Turn a sysroot-relative path into an absolute path."""
76 return os.path.join(self.root, *[part.lstrip(os.sep) for part in args])
Michael Mortensen125bb012020-05-21 14:02:10 -060077
Alex Klein1699fab2022-09-08 08:46:06 -060078 def get_command(self, base_command: str) -> str:
79 """Get the build target's variant of the given base command.
Alex Klein309c7572020-01-27 10:55:01 -070080
Alex Klein1699fab2022-09-08 08:46:06 -060081 We create wrappers for many scripts that handle the build target's
82 arguments. Build the target-specific variant for such a command.
83 e.g. emerge -> emerge-eve.
Alex Klein309c7572020-01-27 10:55:01 -070084
Alex Klein1699fab2022-09-08 08:46:06 -060085 TODO: Add optional validation the command exists.
Alex Klein309c7572020-01-27 10:55:01 -070086
Alex Klein1699fab2022-09-08 08:46:06 -060087 Args:
88 base_command: The wrapped command.
Alex Klein309c7572020-01-27 10:55:01 -070089
Alex Klein1699fab2022-09-08 08:46:06 -060090 Returns:
91 The build target's command wrapper.
92 """
93 if self.is_host():
94 return base_command
Sloan Johnson48138052021-12-28 21:08:32 +000095
Alex Klein1699fab2022-09-08 08:46:06 -060096 return "%s-%s" % (base_command, self.name)
Alex Kleine1abe2c2019-08-14 10:29:46 -060097
Alex Klein1699fab2022-09-08 08:46:06 -060098 def is_host(self) -> bool:
99 """Check if the build target refers to the host."""
100 return not self.name
Sloan Johnson48138052021-12-28 21:08:32 +0000101
Alex Klein1a55dde2020-03-06 15:53:29 -0700102
Alex Klein62b7e1e2020-03-09 13:36:50 -0600103def get_default_sysroot_path(build_target_name=None):
Alex Klein1699fab2022-09-08 08:46:06 -0600104 """Get the default sysroot location or '/' if |build_target_name| is None."""
105 if build_target_name is None:
106 return "/"
107 return os.path.join("/build", build_target_name)
Alex Klein1a55dde2020-03-06 15:53:29 -0700108
109
Alex Klein5417f3d2021-07-09 15:23:02 -0600110def get_sdk_sysroot_path() -> str:
Alex Klein1699fab2022-09-08 08:46:06 -0600111 """Get the SDK's sysroot path.
Alex Klein5417f3d2021-07-09 15:23:02 -0600112
Alex Klein1699fab2022-09-08 08:46:06 -0600113 Convenience/clarification wrapper for get_default_sysroot_path for use when
114 explicitly fetching the SDK's sysroot path.
115 """
116 return get_default_sysroot_path()
Alex Klein5417f3d2021-07-09 15:23:02 -0600117
118
Alex Klein1a55dde2020-03-06 15:53:29 -0700119def is_valid_name(build_target_name):
Alex Klein1699fab2022-09-08 08:46:06 -0600120 """Validate |build_target_name| is a valid name."""
121 return bool(re.match(r"^[a-zA-Z0-9-_]+$", build_target_name))