1# -*- coding: utf-8 -*-
2#
3# Copyright 2013 Oliver Tappe
4# Distributed under the terms of the MIT License.
5
6# -- MachineArchitecture ------------------------------------------------------
7
8# Defines the set of real machines architectures that are supported.
9class MachineArchitecture(str):
10	## REFACTOR collections.namedtuple might make more sense
11
12	ARM = 'arm'
13	ARM64 = 'arm64'
14	M68K = 'm68k'
15	PPC = 'ppc'
16	RISCV64 = 'riscv64'
17	SPARC = 'sparc'
18	X86 = 'x86'
19	X86_64 = 'x86_64'
20	X86_GCC2 = 'x86_gcc2'
21
22	@staticmethod
23	def getAll():
24		# TODO: fetch this from PackageKit?
25		return [
26			Architectures.ARM,
27			Architectures.ARM64,
28			Architectures.M68K,
29			Architectures.PPC,
30			Architectures.RISCV64,
31			Architectures.SPARC,
32			Architectures.X86,
33			Architectures.X86_64,
34			Architectures.X86_GCC2,
35		]
36
37	## REFACTOR make this a module constant as it will otherwise create an
38	## object on every call
39	@staticmethod
40	def getTripleFor(architecture):
41		archMap = {
42			Architectures.ARM: 'arm-unknown-haiku',
43			Architectures.ARM64: 'aarch64-unknown-haiku',
44			Architectures.M68K: 'm68k-unknown-haiku',
45			Architectures.PPC: 'powerpc-apple-haiku',
46			Architectures.RISCV64: 'riscv64-unknown-haiku',
47			Architectures.SPARC: 'sparc64-unknown-haiku',
48			Architectures.X86: 'i586-pc-haiku',
49			Architectures.X86_64: 'x86_64-unknown-haiku',
50			Architectures.X86_GCC2: 'i586-pc-haiku',
51				# Note: In theory it would make sense to use a different triple
52				# for x86_gcc2. Unfortunately that would cause us a lot of work
53				# to adjust the GNU autotools and autotools based build systems.
54		}
55		if architecture in archMap:
56			return archMap[architecture]
57		return None
58
59	@staticmethod
60	def findMatch(architecture):
61		"""Find a matching packaging architecture for the given architecture
62		   string that may e.g. be an architecture that uname() reports."""
63
64		architecture = architecture.lower()
65		if architecture in MachineArchitecture.getAll():
66			return architecture
67
68		# map "sparc64" to "sparc"
69		if architecture == 'sparc64':
70			return MachineArchitecture.SPARC
71
72		return None
73
74
75# -- Architectures ------------------------------------------------------------
76
77# The ARCHITECTURES key in a recipe describes the port's status on each
78# of the supported architectures.
79# Within the string, support for an architecture can be specified like this:
80#  'x86'  -> this port is known to work on the 'x86' architecture
81#  '?x86' -> this port has not been built/tested on the 'x86' architecture yet,
82#			it is expected to work, but that has not been verified
83#  '!x86' -> this port is known to have problems on the 'x86' architecture
84# An architecture missing from the status specification indicates that nothing
85# is known about the status of the port on this architecture.
86class Architectures(MachineArchitecture):
87	ANY = 'any'
88	SOURCE = 'source'
89
90	@staticmethod
91	def getAll():
92		return MachineArchitecture.getAll() + [
93			Architectures.ANY,
94			Architectures.SOURCE,
95		]
96
97
98# -- Status -------------------------------------------------------------------
99
100# Allowed status for a port on a specific architecure
101class Status(str):
102	BROKEN = 'broken'
103	STABLE = 'stable'
104	UNSUPPORTED = 'unsupported'
105	UNTESTED = 'untested'
106
107
108# -- Phase --------------------------------------------------------------------
109
110# Identifies a phase of building a port.
111class Phase(str):
112	PATCH = 'PATCH'
113	BUILD = 'BUILD'
114	INSTALL = 'INSTALL'
115	TEST = 'TEST'
116
117	@staticmethod
118	def getAllowedValues():
119		return [Phase.PATCH, Phase.BUILD, Phase.TEST, Phase.INSTALL]
120
121
122# -- LinesOfText --------------------------------------------------------------
123
124# Create new type 'LinesOfText', used to handle the description in a recipe
125class LinesOfText(list):
126	pass
127
128
129# -- ProvidesList -------------------------------------------------------------
130
131# Create new type 'ProvidesList', used to handle a list of provides
132# specifications
133class ProvidesList(list):
134	pass
135
136
137# -- RequiresList -------------------------------------------------------------
138
139# Create new type 'RequiresList', used to handle a list of requires
140# specifications
141class RequiresList(list):
142	pass
143
144
145# -- YesNo --------------------------------------------------------------------
146
147# A string representing a boolean value.
148class YesNo(str):
149
150	@staticmethod
151	def getAllowedValues():
152		return ['yes', 'no', 'true', 'false']
153
154	@staticmethod
155	def toBool(value):
156		return value.lower() == 'yes' or value.lower() == 'true'
157
158# -- Extendable ---------------------------------------------------------------
159
160# Defines the possible values for the 'extendable' attribute of recipe
161# attributes:
162#	NO		   -> The attribute is not extendable, i.e. it is per-port.
163#	INHERITED  -> The attribute is extendable (i.e. per-package) and when not
164#				  specified for a package, the attribute value for the main
165#				  package is inherited.
166#	DEFAULT	   -> The attribute is extendable (i.e. per-package) and when not
167#				  specified for a package, the attribute get the default value.
168class Extendable(str):
169	NO = 'no',
170	INHERITED = 'inherited',
171	DEFAULT = 'default'
172
173