blob: 0a37e6be12cb115a5b7a8e173ffef7384fa53822 [file] [log] [blame]
Alex Kleinda35fcf2019-03-07 16:01:15 -07001# Copyright 2019 The Chromium OS Authors. All rights reserved.
2# 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
Alex Kleinda35fcf2019-03-07 16:01:15 -07009
LaMont Jonesfeffd1b2020-08-05 18:24:59 -060010from chromite.api.gen.chromiumos import common_pb2
11
Alex Kleinda35fcf2019-03-07 16:01:15 -070012
13class Error(Exception):
14 """Base module error class."""
15
16
Alex Kleindf4a4482019-09-04 15:31:17 -060017class InvalidNameError(Error):
Alex Kleinda35fcf2019-03-07 16:01:15 -070018 """Error for invalid target name argument."""
19
20
21class BuildTarget(object):
22 """Class to handle the build target information."""
23
24 def __init__(self, name, profile=None, build_root=None):
25 """Build Target init.
26
27 Args:
28 name (str): The full name of the target.
29 profile (str): The profile name.
30 build_root (str): The path to the buildroot.
31 """
32 if not name:
33 raise InvalidNameError('Name is required.')
34
Alex Klein171da612019-08-06 14:00:42 -060035 self._name = name
Alex Kleinda35fcf2019-03-07 16:01:15 -070036 self.board, _, self.variant = name.partition('_')
37 self.profile = profile
38
39 if build_root:
40 self.root = os.path.normpath(build_root)
41 else:
Alex Klein1a55dde2020-03-06 15:53:29 -070042 self.root = get_default_sysroot_path(self.name)
Alex Kleinda35fcf2019-03-07 16:01:15 -070043
Alex Klein171da612019-08-06 14:00:42 -060044 def __eq__(self, other):
45 if self.__class__ is other.__class__:
46 return (self.name == other.name and self.profile == other.profile and
47 self.root == other.root)
48
49 return NotImplemented
50
51 def __hash__(self):
52 return hash(self.name)
53
Alex Kleinaf0e0452019-06-03 18:10:01 -060054 def __str__(self):
55 return self.name
56
Alex Klein171da612019-08-06 14:00:42 -060057 @property
58 def name(self):
59 return self._name
Alex Kleinda35fcf2019-03-07 16:01:15 -070060
LaMont Jonesfeffd1b2020-08-05 18:24:59 -060061 @property
62 def as_protobuf(self):
63 return common_pb2.BuildTarget(name=self.name)
64
65 @classmethod
66 def from_protobuf(cls, message):
67 return cls(name=message.name)
68
69 @property
70 def profile_protobuf(self):
71 return common_pb2.Profile(name=self.profile)
72
Michael Mortensen125bb012020-05-21 14:02:10 -060073 def full_path(self, *args):
74 """Turn a sysroot-relative path into an absolute path."""
75 return os.path.join(self.root, *[part.lstrip(os.sep) for part in args])
76
Alex Klein309c7572020-01-27 10:55:01 -070077 def get_command(self, base_command):
78 """Get the build target's variant of the given base command.
79
80 We create wrappers for many scripts that handle the build target's
81 arguments. Build the target-specific variant for such a command.
82 e.g. emerge -> emerge-eve.
83
84 TODO: Add optional validation the command exists.
85
86 Args:
87 base_command (str): The wrapped command.
88
89 Returns:
90 str: The build target's command wrapper.
91 """
92 return '%s-%s' % (base_command, self.name)
Alex Kleine1abe2c2019-08-14 10:29:46 -060093
Alex Klein1a55dde2020-03-06 15:53:29 -070094
Alex Klein62b7e1e2020-03-09 13:36:50 -060095def get_default_sysroot_path(build_target_name=None):
96 """Get the default sysroot location or '/' if |build_target_name| is None."""
97 if build_target_name is None:
98 return '/'
99 return os.path.join('/build', build_target_name)
Alex Klein1a55dde2020-03-06 15:53:29 -0700100
101
Alex Klein5417f3d2021-07-09 15:23:02 -0600102def get_sdk_sysroot_path() -> str:
103 """Get the SDK's sysroot path.
104
105 Convenience/clarification wrapper for get_default_sysroot_path for use when
106 explicitly fetching the SDK's sysroot path.
107 """
108 return get_default_sysroot_path()
109
110
Alex Klein1a55dde2020-03-06 15:53:29 -0700111def is_valid_name(build_target_name):
112 """Validate |build_target_name| is a valid name."""
113 return bool(re.match(r'^[a-zA-Z0-9-_]+$', build_target_name))