jolt 0.9.355__py3-none-any.whl → 0.9.371__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- jolt/__init__.py +47 -0
- jolt/cache.py +339 -159
- jolt/cli.py +29 -98
- jolt/config.py +14 -26
- jolt/graph.py +27 -15
- jolt/loader.py +141 -180
- jolt/manifest.py +0 -46
- jolt/options.py +35 -12
- jolt/plugins/conan.py +238 -0
- jolt/plugins/docker.py +1 -1
- jolt/plugins/environ.py +11 -0
- jolt/plugins/gdb.py +6 -5
- jolt/plugins/linux.py +943 -0
- jolt/plugins/ninja-compdb.py +7 -6
- jolt/plugins/podman.py +4 -4
- jolt/plugins/scheduler.py +18 -14
- jolt/plugins/selfdeploy/setup.py +1 -1
- jolt/plugins/selfdeploy.py +1 -22
- jolt/plugins/strings.py +16 -6
- jolt/scheduler.py +428 -138
- jolt/tasks.py +27 -0
- jolt/tools.py +15 -8
- jolt/version.py +1 -1
- {jolt-0.9.355.dist-info → jolt-0.9.371.dist-info}/METADATA +2 -2
- {jolt-0.9.355.dist-info → jolt-0.9.371.dist-info}/RECORD +28 -29
- jolt/plugins/debian.py +0 -338
- jolt/plugins/repo.py +0 -253
- {jolt-0.9.355.dist-info → jolt-0.9.371.dist-info}/WHEEL +0 -0
- {jolt-0.9.355.dist-info → jolt-0.9.371.dist-info}/entry_points.txt +0 -0
- {jolt-0.9.355.dist-info → jolt-0.9.371.dist-info}/top_level.txt +0 -0
jolt/plugins/linux.py
ADDED
|
@@ -0,0 +1,943 @@
|
|
|
1
|
+
|
|
2
|
+
from jolt import Task, Parameter, ListParameter
|
|
3
|
+
from jolt import attributes
|
|
4
|
+
from jolt import log
|
|
5
|
+
from jolt import utils
|
|
6
|
+
from jolt.error import raise_task_error_if
|
|
7
|
+
from jolt.plugins import podman
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
import os
|
|
11
|
+
import shutil
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def linux_arch_to_container_platform(arch):
|
|
15
|
+
"""
|
|
16
|
+
Convert Linux architecture to Podman platform.
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
arch: Linux architecture.
|
|
20
|
+
|
|
21
|
+
Returns:
|
|
22
|
+
- linux/amd64
|
|
23
|
+
- linux/arm
|
|
24
|
+
- linux/arm64
|
|
25
|
+
- linux/mips
|
|
26
|
+
- linux/ppc64
|
|
27
|
+
- linux/riscv64
|
|
28
|
+
- linux/s390x
|
|
29
|
+
"""
|
|
30
|
+
platforms = {
|
|
31
|
+
"arm": "linux/arm",
|
|
32
|
+
"arm64": "linux/arm64",
|
|
33
|
+
"mips": "linux/mips64le",
|
|
34
|
+
"powerpc": "linux/ppc64le",
|
|
35
|
+
"riscv": "linux/riscv64",
|
|
36
|
+
"s390": "linux/s390x",
|
|
37
|
+
"x86": "linux/amd64",
|
|
38
|
+
}
|
|
39
|
+
arch = str(arch)
|
|
40
|
+
try:
|
|
41
|
+
return platforms[arch]
|
|
42
|
+
except KeyError:
|
|
43
|
+
raise ValueError(f"Unsupported architecture {arch}")
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def linux_arch_to_debian_arch(arch):
|
|
47
|
+
"""
|
|
48
|
+
Convert Linux architecture to Debian architecture.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
arch: Linux architecture.
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
- amd64
|
|
55
|
+
- armhf
|
|
56
|
+
- arm64
|
|
57
|
+
- mips
|
|
58
|
+
- ppc64el
|
|
59
|
+
- riscv64
|
|
60
|
+
- s390x
|
|
61
|
+
"""
|
|
62
|
+
debian_arch = {
|
|
63
|
+
"amd64": "amd64",
|
|
64
|
+
"arm": "armhf",
|
|
65
|
+
"arm64": "arm64",
|
|
66
|
+
"mips": "mips",
|
|
67
|
+
"powerpc": "ppc64el",
|
|
68
|
+
"riscv": "riscv64",
|
|
69
|
+
"s390": "s390x",
|
|
70
|
+
"x86": "i386",
|
|
71
|
+
}
|
|
72
|
+
return debian_arch[str(arch)]
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class ArchParameter(Parameter):
|
|
76
|
+
"""
|
|
77
|
+
Linux target architecture parameter.
|
|
78
|
+
|
|
79
|
+
Supported values:
|
|
80
|
+
|
|
81
|
+
- amd64
|
|
82
|
+
- arm
|
|
83
|
+
- arm64
|
|
84
|
+
- mips
|
|
85
|
+
- powerpc
|
|
86
|
+
- riscv
|
|
87
|
+
- s390
|
|
88
|
+
- x86
|
|
89
|
+
|
|
90
|
+
"""
|
|
91
|
+
|
|
92
|
+
def __init__(self, *args, **kwargs):
|
|
93
|
+
kwargs["values"] = [
|
|
94
|
+
"amd64",
|
|
95
|
+
"arm",
|
|
96
|
+
"arm64",
|
|
97
|
+
"mips",
|
|
98
|
+
"powerpc",
|
|
99
|
+
"riscv",
|
|
100
|
+
"s390",
|
|
101
|
+
"x86",
|
|
102
|
+
]
|
|
103
|
+
kwargs["help"] = "Target architecture."
|
|
104
|
+
super().__init__(*args, **kwargs)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
class _ContainerImageBase(podman.ContainerImage):
|
|
108
|
+
""" Builds a container image from external source tree """
|
|
109
|
+
|
|
110
|
+
abstract = True
|
|
111
|
+
""" Must be subclassed """
|
|
112
|
+
|
|
113
|
+
arch = ArchParameter()
|
|
114
|
+
""" Target architecture [amd64, arm, arm64, mips, powerpc, riscv, s390, x86] """
|
|
115
|
+
|
|
116
|
+
@property
|
|
117
|
+
def target(self):
|
|
118
|
+
return linux_arch_to_container_platform(self.arch)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
class _DebianSdkImage(podman.ContainerImage):
|
|
122
|
+
""" Provides a Debian SDK for building Linux kernel and U-Boot """
|
|
123
|
+
|
|
124
|
+
abstract = True
|
|
125
|
+
""" Must be subclassed """
|
|
126
|
+
|
|
127
|
+
arch = ArchParameter()
|
|
128
|
+
""" Target architecture """
|
|
129
|
+
|
|
130
|
+
dockerfile = """
|
|
131
|
+
FROM debian:{version}-slim
|
|
132
|
+
ARG DEBIAN_FRONTEND=noninteractive
|
|
133
|
+
RUN apt-get update && apt-get install -y crossbuild-essential-{debian_arch}
|
|
134
|
+
"""
|
|
135
|
+
|
|
136
|
+
version = "stable"
|
|
137
|
+
""" Debian codename/version """
|
|
138
|
+
|
|
139
|
+
@property
|
|
140
|
+
def debian_arch(self):
|
|
141
|
+
return {
|
|
142
|
+
"amd64": "amd64",
|
|
143
|
+
"arm": "armhf",
|
|
144
|
+
"arm64": "arm64",
|
|
145
|
+
"mips": "mips",
|
|
146
|
+
"powerpc": "ppc64el",
|
|
147
|
+
"riscv": "riscv64",
|
|
148
|
+
"s390": "s390x",
|
|
149
|
+
"x86": "i386",
|
|
150
|
+
}[str(self.arch)]
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
class DebianHostSdk(Task):
|
|
154
|
+
"""
|
|
155
|
+
Helper task that exports a Debian host's cross-compiler toolchains to consumers.
|
|
156
|
+
|
|
157
|
+
The task verifies that the cross-compiler toolchains are installed on the host.
|
|
158
|
+
If not, the task will raise an error with instructions.
|
|
159
|
+
|
|
160
|
+
Exported environment variables:
|
|
161
|
+
|
|
162
|
+
- ``CC``: Cross-compiler
|
|
163
|
+
- ``CPP``: Cross-preprocessor
|
|
164
|
+
- ``CXX``: Cross-C++ compiler
|
|
165
|
+
- ``CROSS_COMPILE``: Cross-compile prefix
|
|
166
|
+
|
|
167
|
+
"""
|
|
168
|
+
abstract = True
|
|
169
|
+
""" Must be subclassed """
|
|
170
|
+
|
|
171
|
+
arch = ArchParameter()
|
|
172
|
+
""" Target architecture [amd64, arm, arm64, mips, powerpc, riscv, s390, x86] """
|
|
173
|
+
|
|
174
|
+
def publish(self, artifact, tools):
|
|
175
|
+
arch_to_cross_compile = {
|
|
176
|
+
"amd64": "x86_64-linux-gnu-",
|
|
177
|
+
"arm": "arm-linux-gnueabihf-",
|
|
178
|
+
"arm64": "aarch64-linux-gnu-",
|
|
179
|
+
"mips": "mips-linux-gnu-",
|
|
180
|
+
"powerpc": "powerpc64-linux-gnu-",
|
|
181
|
+
"riscv": "riscv64-linux-gnu-",
|
|
182
|
+
"s390": "s390x-linux-gnu-",
|
|
183
|
+
"x86": "i686-linux-gnu-",
|
|
184
|
+
}
|
|
185
|
+
debian_arch = linux_arch_to_debian_arch(self.arch)
|
|
186
|
+
debian_cross = arch_to_cross_compile[str(self.arch)]
|
|
187
|
+
raise_task_error_if(
|
|
188
|
+
not tools.which(arch_to_cross_compile[str(self.arch)] + "gcc"),
|
|
189
|
+
self, f"Cross compiler not found. Please install crossbuild-essential-{debian_arch} package.")
|
|
190
|
+
artifact.environ.CC = f"{debian_cross}gcc"
|
|
191
|
+
artifact.environ.CPP = f"{debian_cross}cpp"
|
|
192
|
+
artifact.environ.CXX = f"{debian_cross}g++"
|
|
193
|
+
artifact.environ.CROSS_COMPILE = debian_cross
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
class Initramfs(_ContainerImageBase):
|
|
197
|
+
"""
|
|
198
|
+
Builds an initramfs image using Podman.
|
|
199
|
+
|
|
200
|
+
The task builds the initramfs image using the given Dockerfile and
|
|
201
|
+
publishes the resulting cpio archive. The task requires the following
|
|
202
|
+
attributes to be set:
|
|
203
|
+
|
|
204
|
+
- arch: Target architecture
|
|
205
|
+
- dockerfile: Path to Dockerfile, or Dockerfile content.
|
|
206
|
+
|
|
207
|
+
When building images for an architecture other than the host, the
|
|
208
|
+
binfmt-support package must be installed and configured to support the
|
|
209
|
+
target architecture. The package is available in most Linux distributions.
|
|
210
|
+
|
|
211
|
+
The location of the resulting cpio archive is stored in the
|
|
212
|
+
'artifact.paths.cpio' attribute.
|
|
213
|
+
|
|
214
|
+
"""
|
|
215
|
+
abstract = True
|
|
216
|
+
""" Must be subclassed """
|
|
217
|
+
|
|
218
|
+
output = ["cpio"]
|
|
219
|
+
|
|
220
|
+
def publish(self, artifact, tools):
|
|
221
|
+
super().publish(artifact, tools)
|
|
222
|
+
artifact.strings.arch = str(self.arch)
|
|
223
|
+
artifact.paths.cpio = "cpio/{_imagefile}.cpio"
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
class Squashfs(_ContainerImageBase):
|
|
227
|
+
"""
|
|
228
|
+
Builds a squashfs image using Podman.
|
|
229
|
+
|
|
230
|
+
The task builds a container image using the given Dockerfile and converts
|
|
231
|
+
the resulting container filesystem to a squashfs image which is published.
|
|
232
|
+
|
|
233
|
+
When building images for an architecture other than the host, the
|
|
234
|
+
binfmt-support package must be installed and configured to support running
|
|
235
|
+
applications for the target architecture. The package is available in most
|
|
236
|
+
Linux distributions.
|
|
237
|
+
|
|
238
|
+
The location of the resulting squashfs image is stored in the
|
|
239
|
+
``artifact.paths.squashfs`` artifact attribute.
|
|
240
|
+
"""
|
|
241
|
+
abstract = True
|
|
242
|
+
""" Must be subclassed """
|
|
243
|
+
|
|
244
|
+
output = ["squashfs"]
|
|
245
|
+
|
|
246
|
+
size = None
|
|
247
|
+
"""
|
|
248
|
+
Size of the squashfs image.
|
|
249
|
+
|
|
250
|
+
Typically used to align the image size to a supported SD card size (power of two).
|
|
251
|
+
|
|
252
|
+
Supported units are 'K', 'M', 'G', 'T'.
|
|
253
|
+
"""
|
|
254
|
+
|
|
255
|
+
def run(self, deps, tools):
|
|
256
|
+
super().run(deps, tools)
|
|
257
|
+
if self.size:
|
|
258
|
+
with tools.cwd(tools.builddir("squashfs")):
|
|
259
|
+
tools.run("fallocate -l {size} image.squashfs")
|
|
260
|
+
|
|
261
|
+
def publish(self, artifact, tools):
|
|
262
|
+
super().publish(artifact, tools)
|
|
263
|
+
artifact.strings.arch = str(self.arch)
|
|
264
|
+
artifact.paths.squashfs = "squashfs/{_imagefile}.squashfs"
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
class _KernelBase(Task):
|
|
268
|
+
abstract = True
|
|
269
|
+
""" Must be subclassed """
|
|
270
|
+
|
|
271
|
+
arch = ArchParameter()
|
|
272
|
+
""" Linux target architecture [amd64, arm, arm64, mips, powerpc, riscv, s390, x86] """
|
|
273
|
+
|
|
274
|
+
defconfig = Parameter("allnoconfig", help="Name of kernel defconfig")
|
|
275
|
+
""" Default configuration """
|
|
276
|
+
|
|
277
|
+
features = ListParameter([], help="List of feature configs to apply")
|
|
278
|
+
"""
|
|
279
|
+
List of feature configuration snippets to apply.
|
|
280
|
+
|
|
281
|
+
If used, the task will search for feature configuration snippets in the
|
|
282
|
+
configured paths and merge them into the selected defconfig.
|
|
283
|
+
"""
|
|
284
|
+
|
|
285
|
+
configpaths = [
|
|
286
|
+
"{srcdir}/arch/{arch}/configs",
|
|
287
|
+
]
|
|
288
|
+
"""
|
|
289
|
+
Paths to configuration file snippets.
|
|
290
|
+
|
|
291
|
+
When building the kernel with features, the task will search for
|
|
292
|
+
feature configuration snippets in these directories. The snippets
|
|
293
|
+
are applied and merged with the selected defconfig.
|
|
294
|
+
"""
|
|
295
|
+
|
|
296
|
+
defconfigpath = "arch/{arch}/configs/{defconfig}_defconfig"
|
|
297
|
+
""" Path to defconfig file. """
|
|
298
|
+
|
|
299
|
+
srcdir = None
|
|
300
|
+
""" Location of Linux kernel source tree """
|
|
301
|
+
|
|
302
|
+
targets = ListParameter(help="Targets to build and publish")
|
|
303
|
+
""" Override and set accepted values """
|
|
304
|
+
|
|
305
|
+
def clean(self, tools):
|
|
306
|
+
self.moddir = tools.builddir("modules")
|
|
307
|
+
self.objdir = tools.builddir("objects", incremental=True)
|
|
308
|
+
tools.rmtree(self.moddir)
|
|
309
|
+
tools.rmtree(self.objdir)
|
|
310
|
+
|
|
311
|
+
def run(self, deps, tools):
|
|
312
|
+
raise_task_error_if(not tools.which("bison"), self, "bison is required to build the kernel")
|
|
313
|
+
raise_task_error_if(not tools.which("flex"), self, "flex is required to build the kernel")
|
|
314
|
+
raise_task_error_if(not tools.which("make"), self, "make is required to build the kernel")
|
|
315
|
+
|
|
316
|
+
self.objdir = tools.builddir("objects", incremental=True)
|
|
317
|
+
|
|
318
|
+
config = tools.expand_path("{objdir}/.config")
|
|
319
|
+
tools.unlink(config, ignore_errors=True)
|
|
320
|
+
|
|
321
|
+
arch = f"ARCH={self.arch}" if self.arch else ""
|
|
322
|
+
verbose = "V=1" if log.is_verbose() else ""
|
|
323
|
+
defconf_conf = self.run_find_defconfig_configs(deps, tools)
|
|
324
|
+
feature_confs = self.run_find_feature_configs(deps, tools)
|
|
325
|
+
defconfigpath = tools.expand(self.defconfigpath)
|
|
326
|
+
if self.defconfig in ["defconfig"]:
|
|
327
|
+
defconfigpath = os.path.join(os.path.dirname(defconfigpath), "defconfig")
|
|
328
|
+
|
|
329
|
+
with tools.cwd(self.srcdir):
|
|
330
|
+
if self.defconfig in ["allnoconfig"]:
|
|
331
|
+
self.info("Generating allnoconfig configuration")
|
|
332
|
+
tools.run("{} make allnoconfig O={objdir}", arch)
|
|
333
|
+
tools.run("{} scripts/kconfig/merge_config.sh -O {objdir} {objdir}/.config {} {}", arch, defconf_conf, " ".join(feature_confs))
|
|
334
|
+
else:
|
|
335
|
+
self.info("Generating {defconfig} configuration")
|
|
336
|
+
tools.run("{} scripts/kconfig/merge_config.sh -O {objdir} {} {} {}", arch, defconfigpath, defconf_conf, " ".join(feature_confs))
|
|
337
|
+
|
|
338
|
+
# Run build for each requested target
|
|
339
|
+
for target in self.targets:
|
|
340
|
+
fn = getattr(self, f"run_{target}", None)
|
|
341
|
+
assert fn, f"Dont know how to build {target}"
|
|
342
|
+
with tools.runprefix("{} make {} O={objdir} -j{}", arch, verbose, tools.thread_count()):
|
|
343
|
+
fn(deps, tools)
|
|
344
|
+
|
|
345
|
+
def run_find_defconfig_configs(self, deps, tools):
|
|
346
|
+
""" Finds local overrides for the chosen defconfig """
|
|
347
|
+
configpaths = [tools.expand_path(tools.expand(path)) for path in getattr(self, "configpaths", [])]
|
|
348
|
+
return shutil.which(tools.expand("{defconfig}.config"), os.F_OK, os.pathsep.join(configpaths)) or ""
|
|
349
|
+
|
|
350
|
+
def run_find_feature_configs(self, deps, tools):
|
|
351
|
+
""" Finds local overrides for chosen features """
|
|
352
|
+
configpaths = [tools.expand_path(tools.expand(path)) for path in getattr(self, "configpaths", [])]
|
|
353
|
+
return [shutil.which(feature + ".config", os.F_OK, os.pathsep.join(configpaths)) or "" for feature in self.features]
|
|
354
|
+
|
|
355
|
+
def publish(self, artifact, tools):
|
|
356
|
+
artifact.strings.arch = str(self.arch)
|
|
357
|
+
|
|
358
|
+
for target in self.targets:
|
|
359
|
+
fn = getattr(self, f"publish_{target}", None)
|
|
360
|
+
assert fn, f"Dont know how to publish {target}"
|
|
361
|
+
fn(artifact, tools)
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
class UBoot(_KernelBase):
|
|
365
|
+
"""
|
|
366
|
+
Builds u-boot makefile target(s) and publishes the result.
|
|
367
|
+
|
|
368
|
+
An implementor must subclass this task and set the following attributes:
|
|
369
|
+
|
|
370
|
+
- srcdir: Path to U-boot source tree
|
|
371
|
+
|
|
372
|
+
It is recommended to use a task dependency to setup the
|
|
373
|
+
required tools by adding them to ``PATH`` and/or setting the ``CROSS_COMPILE``
|
|
374
|
+
environment variable. When building on a Debian host, the
|
|
375
|
+
:class:`jolt.plugins.linux.DebianHostSdk` helper task can be used to export
|
|
376
|
+
the cross-compiler tools.
|
|
377
|
+
|
|
378
|
+
"""
|
|
379
|
+
abstract = True
|
|
380
|
+
|
|
381
|
+
defconfig = Parameter("allnoconfig", help="Name of u-boot defconfig")
|
|
382
|
+
""" Default configuration """
|
|
383
|
+
|
|
384
|
+
targets = ListParameter(
|
|
385
|
+
["uboot"],
|
|
386
|
+
values=["tools", "uboot"],
|
|
387
|
+
help="Targets to build and publish",
|
|
388
|
+
)
|
|
389
|
+
""" Build targets [tools, uboot] """
|
|
390
|
+
|
|
391
|
+
def run_tools(self, deps, tools):
|
|
392
|
+
self.info("Building tools ...")
|
|
393
|
+
tools.run("tools")
|
|
394
|
+
|
|
395
|
+
def run_uboot(self, deps, tools):
|
|
396
|
+
self.info("Building u-boot ...")
|
|
397
|
+
tools.run("u-boot.bin")
|
|
398
|
+
|
|
399
|
+
def publish_tools(self, artifact, tools):
|
|
400
|
+
self.info("Publishing tools ...")
|
|
401
|
+
with tools.cwd(self.objdir):
|
|
402
|
+
artifact.collect("tools/mkimage")
|
|
403
|
+
artifact.environ.PATH.append("tools")
|
|
404
|
+
|
|
405
|
+
def publish_uboot(self, artifact, tools):
|
|
406
|
+
self.info("Publishing u-boot ...")
|
|
407
|
+
with tools.cwd(self.objdir):
|
|
408
|
+
artifact.collect("*.bin")
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
@utils.concat_attributes("dtbs", "dtbs_{defconfig}")
|
|
412
|
+
class Kernel(_KernelBase):
|
|
413
|
+
"""
|
|
414
|
+
Builds kernel makefile target(s) and publishes the result.
|
|
415
|
+
|
|
416
|
+
Targets are selected by assigning the ``targets`` parameter. The following
|
|
417
|
+
values are supported:
|
|
418
|
+
|
|
419
|
+
- ``binary``: Build kernel binary
|
|
420
|
+
- ``dtbs``: Build device trees
|
|
421
|
+
- ``dtc``: Build device tree compiler
|
|
422
|
+
- ``gzimage``: Build gzipped kernel image
|
|
423
|
+
- ``image``: Build kernel image
|
|
424
|
+
- ``modules``: Build kernel modules
|
|
425
|
+
- ``uimage``: Build uImage
|
|
426
|
+
- ``vmlinux``: Build vmlinux
|
|
427
|
+
- ``zimage``: Build zImage
|
|
428
|
+
|
|
429
|
+
Mutliple targets can be selected at once, such as ``vmlinux+dtbs+modules``.
|
|
430
|
+
The resulting artifacts are published into different directories
|
|
431
|
+
based on the target name.
|
|
432
|
+
|
|
433
|
+
It is recommended to use a task dependency to setup the
|
|
434
|
+
required tools by adding them to ``PATH`` and/or setting the ``CROSS_COMPILE``
|
|
435
|
+
environment variable. When building on a Debian host, the
|
|
436
|
+
:class:`jolt.plugins.linux.DebianHostSdk` helper task can be used to export
|
|
437
|
+
the cross-compiler tools.
|
|
438
|
+
|
|
439
|
+
The following tools are required to be available in PATH:
|
|
440
|
+
|
|
441
|
+
- bison
|
|
442
|
+
- flex
|
|
443
|
+
- make
|
|
444
|
+
- gcc
|
|
445
|
+
|
|
446
|
+
Artifact path attributes are created to point to the published files.
|
|
447
|
+
|
|
448
|
+
"""
|
|
449
|
+
|
|
450
|
+
abstract = True
|
|
451
|
+
""" Must be subclassed """
|
|
452
|
+
|
|
453
|
+
dtbs = []
|
|
454
|
+
"""
|
|
455
|
+
List of device trees to build when the 'dtbs' target is requested.
|
|
456
|
+
|
|
457
|
+
If empty, all device trees associated with the target architecture are built.
|
|
458
|
+
"""
|
|
459
|
+
|
|
460
|
+
loadaddr = 0
|
|
461
|
+
"""
|
|
462
|
+
Kernel load address.
|
|
463
|
+
"""
|
|
464
|
+
|
|
465
|
+
loadaddr_fdt = 0
|
|
466
|
+
"""
|
|
467
|
+
Device-tree load address.
|
|
468
|
+
"""
|
|
469
|
+
|
|
470
|
+
targets = ListParameter(
|
|
471
|
+
["vmlinux"],
|
|
472
|
+
values=["binary", "dtbs", "dtc", "gzimage", "image", "modules", "uimage", "vmlinux", "zimage"],
|
|
473
|
+
help="Targets to build and publish",
|
|
474
|
+
)
|
|
475
|
+
""" Build targets [binary, dtbs, dtc, gzimage, image, modules, uimage, vmlinux, zimage] """
|
|
476
|
+
|
|
477
|
+
def run_binary(self, deps, tools):
|
|
478
|
+
self.info("Building binary kernel ...")
|
|
479
|
+
tools.run("LOADADDR={loadaddr} vmlinux")
|
|
480
|
+
objcopy = tools.getenv("OBJCOPY", tools.getenv("CROSS_COMPILE", "") + "objcopy")
|
|
481
|
+
tools._run_prefix = [] # Hack to cancel previous prefix
|
|
482
|
+
tools.run("{} -O binary -R .note -R .comment -S {objdir}/vmlinux {objdir}/vmlinux.bin", objcopy)
|
|
483
|
+
|
|
484
|
+
def run_dtbs(self, deps, tools):
|
|
485
|
+
self.info("Building device trees ...")
|
|
486
|
+
if not self._dtbs():
|
|
487
|
+
tools.run("dtbs")
|
|
488
|
+
else:
|
|
489
|
+
tools.run(" ".join(self._dtbs()))
|
|
490
|
+
|
|
491
|
+
def run_dtc(self, deps, tools):
|
|
492
|
+
self.info("Building device tree compiler ...")
|
|
493
|
+
tools.run("CONFIG_DTC=y scripts")
|
|
494
|
+
|
|
495
|
+
def run_modules(self, deps, tools):
|
|
496
|
+
self.info("Building modules ...")
|
|
497
|
+
self.moddir = tools.builddir("modules")
|
|
498
|
+
tools.run("INSTALL_MOD_PATH={moddir} modules")
|
|
499
|
+
tools.run("INSTALL_MOD_PATH={moddir} modules_install")
|
|
500
|
+
|
|
501
|
+
def run_image(self, deps, tools):
|
|
502
|
+
self.info("Building Image ...")
|
|
503
|
+
tools.run("LOADADDR={loadaddr} Image")
|
|
504
|
+
|
|
505
|
+
def run_gzimage(self, deps, tools):
|
|
506
|
+
self.info("Building Image.gz ...")
|
|
507
|
+
tools.run("LOADADDR={loadaddr} Image.gz")
|
|
508
|
+
|
|
509
|
+
def run_uimage(self, deps, tools):
|
|
510
|
+
self.info("Building uImage ...")
|
|
511
|
+
tools.run("LOADADDR={loadaddr} uImage")
|
|
512
|
+
|
|
513
|
+
def run_vmlinux(self, deps, tools):
|
|
514
|
+
self.info("Building vmlinux ...")
|
|
515
|
+
tools.run("vmlinux")
|
|
516
|
+
|
|
517
|
+
def run_zimage(self, deps, tools):
|
|
518
|
+
self.info("Building zImage ...")
|
|
519
|
+
tools.run("zImage")
|
|
520
|
+
|
|
521
|
+
def publish(self, artifact, tools):
|
|
522
|
+
super().publish(artifact, tools)
|
|
523
|
+
|
|
524
|
+
if self.loadaddr != 0:
|
|
525
|
+
artifact.strings.loadaddr = str(self.loadaddr)
|
|
526
|
+
if self.loadaddr_fdt != 0:
|
|
527
|
+
artifact.strings.loadaddr_fdt = str(self.loadaddr_fdt)
|
|
528
|
+
|
|
529
|
+
def publish_binary(self, artifact, tools):
|
|
530
|
+
self.info("Publishing binary ...")
|
|
531
|
+
with tools.cwd(self.objdir):
|
|
532
|
+
artifact.collect("vmlinux.bin", "binary/")
|
|
533
|
+
artifact.paths.binary = "binary/vmlinux.bin"
|
|
534
|
+
|
|
535
|
+
def publish_dtbs(self, artifact, tools):
|
|
536
|
+
self.info("Publishing device trees ...")
|
|
537
|
+
with tools.cwd(self.objdir, "arch/{arch}/boot/dts"):
|
|
538
|
+
if not self._dtbs():
|
|
539
|
+
artifact.collect("**/*.dtb", "dtbs/")
|
|
540
|
+
else:
|
|
541
|
+
for dtb in self._dtbs():
|
|
542
|
+
artifact.collect(dtb, "dtbs/")
|
|
543
|
+
artifact.paths.dtbs = "dtbs"
|
|
544
|
+
|
|
545
|
+
def publish_dtc(self, artifact, tools):
|
|
546
|
+
self.info("Publishing device tree compiler ...")
|
|
547
|
+
with tools.cwd(self.objdir, "scripts/dtc"):
|
|
548
|
+
artifact.collect("dtc", "bin/")
|
|
549
|
+
artifact.environ.PATH.append("bin")
|
|
550
|
+
|
|
551
|
+
def publish_modules(self, artifact, tools):
|
|
552
|
+
self.info("Publishing modules ...")
|
|
553
|
+
with tools.cwd(self.moddir):
|
|
554
|
+
artifact.collect(".", "modules/", symlinks=True)
|
|
555
|
+
artifact.paths.modules = "modules"
|
|
556
|
+
|
|
557
|
+
with tools.cwd(self.objdir):
|
|
558
|
+
if os.path.exists(tools.expand_path("Module.symvers")):
|
|
559
|
+
artifact.collect("Module.symvers")
|
|
560
|
+
artifact.paths.symvers = "Module.symvers"
|
|
561
|
+
|
|
562
|
+
def publish_image(self, artifact, tools):
|
|
563
|
+
self.info("Publishing Image ...")
|
|
564
|
+
with tools.cwd(self.objdir, "arch/{arch}/boot"):
|
|
565
|
+
artifact.collect("Image", "image/")
|
|
566
|
+
artifact.paths.image = "image/Image"
|
|
567
|
+
|
|
568
|
+
def publish_gzimage(self, artifact, tools):
|
|
569
|
+
self.info("Publishing Image.gz ...")
|
|
570
|
+
with tools.cwd(self.objdir, "arch/{arch}/boot"):
|
|
571
|
+
artifact.collect("Image.gz", "gzimage/")
|
|
572
|
+
artifact.paths.gzimage = "gzimage/Image.gz"
|
|
573
|
+
|
|
574
|
+
def publish_uimage(self, artifact, tools):
|
|
575
|
+
self.info("Publishing uImage ...")
|
|
576
|
+
with tools.cwd(self.objdir, "arch/{arch}/boot"):
|
|
577
|
+
artifact.collect("uImage", "uimage/")
|
|
578
|
+
artifact.paths.uimage = "uimage/uImage"
|
|
579
|
+
|
|
580
|
+
def publish_vmlinux(self, artifact, tools):
|
|
581
|
+
self.info("Publishing vmlinux ...")
|
|
582
|
+
with tools.cwd(self.objdir):
|
|
583
|
+
artifact.collect("vmlinux", "vmlinux/")
|
|
584
|
+
artifact.paths.vmlinux = "vmlinux/vmlinux"
|
|
585
|
+
|
|
586
|
+
def publish_zimage(self, artifact, tools):
|
|
587
|
+
self.info("Publishing zImage ...")
|
|
588
|
+
with tools.cwd(self.objdir, "arch/{arch}/boot"):
|
|
589
|
+
artifact.collect("zImage", "zimage/")
|
|
590
|
+
artifact.paths.zimage = "zimage/zImage"
|
|
591
|
+
|
|
592
|
+
|
|
593
|
+
class Module(Kernel):
|
|
594
|
+
"""
|
|
595
|
+
Builds a kernel module from external source tree.
|
|
596
|
+
|
|
597
|
+
The task is based on the :class:`Kernel` task and builds a kernel module
|
|
598
|
+
from the given source tree specified by the ``srcdir_module`` attribute.
|
|
599
|
+
The ``targets`` attribute is set to ``modules`` by default.
|
|
600
|
+
|
|
601
|
+
See :class:`Kernel` for additional information on building kernel targets.
|
|
602
|
+
In particular, the ``srcdir`` attribute must be set to the kernel source tree
|
|
603
|
+
to build the modules against.
|
|
604
|
+
"""
|
|
605
|
+
|
|
606
|
+
abstract = True
|
|
607
|
+
""" Must be subclassed """
|
|
608
|
+
|
|
609
|
+
srcdir_module = None
|
|
610
|
+
""" Path to kernel module source tree """
|
|
611
|
+
|
|
612
|
+
targets = ["modules"]
|
|
613
|
+
""" Build targets [modules] """
|
|
614
|
+
|
|
615
|
+
def run(self, deps, tools):
|
|
616
|
+
self.targets = ["modules"]
|
|
617
|
+
super().run(deps, tools)
|
|
618
|
+
|
|
619
|
+
def run_modules(self, deps, tools):
|
|
620
|
+
with tools.cwd(self.objdir):
|
|
621
|
+
for _, artifact in deps.items():
|
|
622
|
+
if str(artifact.paths.symvers):
|
|
623
|
+
self.info("Copying Module.symvers")
|
|
624
|
+
tools.copy(str(artifact.paths.symvers), ".")
|
|
625
|
+
|
|
626
|
+
self.info("Building modules ...")
|
|
627
|
+
self.moddir = tools.builddir("modules")
|
|
628
|
+
tools.run("INSTALL_MOD_PATH={moddir} modules_prepare")
|
|
629
|
+
tools.run("INSTALL_MOD_PATH={moddir} M={joltdir}/{srcdir_module} modules")
|
|
630
|
+
tools.run("INSTALL_MOD_PATH={moddir} M={joltdir}/{srcdir_module} modules_install")
|
|
631
|
+
|
|
632
|
+
|
|
633
|
+
@utils.concat_attributes("configs", "configs")
|
|
634
|
+
class FIT(Task):
|
|
635
|
+
"""
|
|
636
|
+
Builds and publishes a FIT Image.
|
|
637
|
+
|
|
638
|
+
The task builds a FIT image using the given kernel, device tree and ramdisk
|
|
639
|
+
tasks and publishes the resulting image. Multiple FIT configurations can be
|
|
640
|
+
created by defining the ``configs`` attribute. The image is optinally signed
|
|
641
|
+
using the provided key.
|
|
642
|
+
|
|
643
|
+
The task requires the ``mkimage`` tool to be available in PATH.
|
|
644
|
+
"""
|
|
645
|
+
|
|
646
|
+
abstract = True
|
|
647
|
+
""" Must be subclassed """
|
|
648
|
+
|
|
649
|
+
configs = {}
|
|
650
|
+
"""
|
|
651
|
+
FIT configurations to create.
|
|
652
|
+
|
|
653
|
+
Dictionary of 2 or 3 element tuples according to this format:
|
|
654
|
+
|
|
655
|
+
.. code-block:: python
|
|
656
|
+
|
|
657
|
+
configs = {
|
|
658
|
+
"<name of config>": ("<name of kernel task>", "<name of dtb>"),
|
|
659
|
+
"<name of config with ramdisk>": ("<name of kernel task>", "<name of dtb>", "<name of ramdisk task>"),
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
Example:
|
|
663
|
+
|
|
664
|
+
.. code-block:: python
|
|
665
|
+
|
|
666
|
+
requires = [
|
|
667
|
+
"kernel=linux/kernel:arch=arm,targets=dtbs+binary_gz,defconfig=bcm2835",
|
|
668
|
+
"ramdisk=busybox/irfs:arch=armv7"
|
|
669
|
+
]
|
|
670
|
+
|
|
671
|
+
configs = {
|
|
672
|
+
"conf-rpi0w": ("kernel", "bcm2835-rpi-zero-w.dtb"),
|
|
673
|
+
"conf-rpi0w-irfs": ("kernel", "bcm2835-rpi-zero-w.dtb", "ramdisk"),
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
Loaded from defs/{defconfig}.py
|
|
677
|
+
"""
|
|
678
|
+
|
|
679
|
+
config_default = None
|
|
680
|
+
""" Default FIT configuration """
|
|
681
|
+
|
|
682
|
+
_template = """/dts-v1/;
|
|
683
|
+
|
|
684
|
+
/ {
|
|
685
|
+
description = "U-Boot fitImage";
|
|
686
|
+
|
|
687
|
+
images {
|
|
688
|
+
{% for i, kernel in enumerate(_kernels) %}
|
|
689
|
+
kernel@{{kernel}} {
|
|
690
|
+
description = "Linux kernel";
|
|
691
|
+
{% if str(deps[kernel].paths.zimage) %}
|
|
692
|
+
data = /incbin/("{{deps[kernel].paths.zimage}}");
|
|
693
|
+
compression = "none";
|
|
694
|
+
{% elif str(deps[kernel].paths.gzimage) %}
|
|
695
|
+
data = /incbin/("{{deps[kernel].paths.gzimage}}");
|
|
696
|
+
compression = "gzip";
|
|
697
|
+
{% elif str(deps[kernel].paths.image) %}
|
|
698
|
+
data = /incbin/("{{deps[kernel].paths.image}}");
|
|
699
|
+
compression = "none";
|
|
700
|
+
{% else %}
|
|
701
|
+
#error "Kernel type not supported."
|
|
702
|
+
{% endif %}
|
|
703
|
+
type = "kernel";
|
|
704
|
+
arch = "{{deps[kernel].strings.arch}}";
|
|
705
|
+
os = "linux";
|
|
706
|
+
{% if deps[kernel].strings.loadaddr %}
|
|
707
|
+
load = <{{deps[kernel].strings.loadaddr}}>;
|
|
708
|
+
entry = <{{deps[kernel].strings.loadaddr}}>;
|
|
709
|
+
{% endif %}
|
|
710
|
+
hash {
|
|
711
|
+
algo = "sha256";
|
|
712
|
+
};
|
|
713
|
+
};
|
|
714
|
+
|
|
715
|
+
{% endfor %}
|
|
716
|
+
{% for kernel, dtb in _dtbs %}
|
|
717
|
+
fdt@{{path.basename(dtb)}} {
|
|
718
|
+
description = "Flattened Device Tree blob";
|
|
719
|
+
data = /incbin/("{{deps[kernel].paths.dtbs}}/{{dtb}}");
|
|
720
|
+
type = "flat_dt";
|
|
721
|
+
arch = "{{deps[kernel].strings.arch}}";
|
|
722
|
+
compression = "none";
|
|
723
|
+
os = "linux";
|
|
724
|
+
{% if deps[kernel].strings.loadaddr_fdt %}
|
|
725
|
+
load = <{{deps[kernel].strings.loadaddr_fdt}}>;
|
|
726
|
+
{% endif %}
|
|
727
|
+
hash {
|
|
728
|
+
algo = "sha256";
|
|
729
|
+
};
|
|
730
|
+
};
|
|
731
|
+
|
|
732
|
+
{% endfor %}
|
|
733
|
+
{% for ramdisk in _ramdisks %}
|
|
734
|
+
ramdisk@{{ramdisk}} {
|
|
735
|
+
description = "Ramdisk";
|
|
736
|
+
data = /incbin/("{{deps[ramdisk].paths.cpio}}");
|
|
737
|
+
type = "ramdisk";
|
|
738
|
+
arch = "{{deps[ramdisk].strings.arch}}";
|
|
739
|
+
os = "linux";
|
|
740
|
+
{% if deps[ramdisk].strings.compression %}
|
|
741
|
+
compression = "{{deps[ramdisk].strings.compression}}";
|
|
742
|
+
{% else %}
|
|
743
|
+
compression = "none";
|
|
744
|
+
{% endif %}
|
|
745
|
+
hash {
|
|
746
|
+
algo = "sha256";
|
|
747
|
+
};
|
|
748
|
+
};
|
|
749
|
+
|
|
750
|
+
{% endfor %}
|
|
751
|
+
};
|
|
752
|
+
|
|
753
|
+
configurations {
|
|
754
|
+
{% if config_default %}
|
|
755
|
+
default = "conf@{{config_default}}";
|
|
756
|
+
{% endif %}
|
|
757
|
+
|
|
758
|
+
{% for name, config in _configs().items() %}
|
|
759
|
+
conf@{{name}} {
|
|
760
|
+
{% if len(config) > 2 %}
|
|
761
|
+
description = "Linux kernel, FDT blob, Ramdisk";
|
|
762
|
+
{% else %}
|
|
763
|
+
description = "Linux kernel, FDT blob";
|
|
764
|
+
{% endif %}
|
|
765
|
+
kernel = "kernel@{{config[0]}}";
|
|
766
|
+
os = "linux";
|
|
767
|
+
fdt = "fdt@{{path.basename(config[1])}}";
|
|
768
|
+
{% if len(config) > 2 %}
|
|
769
|
+
ramdisk = "ramdisk@{{config[2]}}";
|
|
770
|
+
{% endif %}
|
|
771
|
+
|
|
772
|
+
hash {
|
|
773
|
+
algo = "sha256";
|
|
774
|
+
};
|
|
775
|
+
signature {
|
|
776
|
+
algo = "sha256,rsa2048";
|
|
777
|
+
{% if signature_key_name %}
|
|
778
|
+
key-name-hint = "{{signature_key_name}}";
|
|
779
|
+
{% endif %}
|
|
780
|
+
{% if len(config) > 2 %}
|
|
781
|
+
sign-images = "kernel", "fdt", "ramdisk";
|
|
782
|
+
{% else %}
|
|
783
|
+
sign-images = "kernel", "fdt";
|
|
784
|
+
{% endif %}
|
|
785
|
+
};
|
|
786
|
+
};
|
|
787
|
+
|
|
788
|
+
{% endfor %}
|
|
789
|
+
};
|
|
790
|
+
};
|
|
791
|
+
"""
|
|
792
|
+
|
|
793
|
+
signature_key_name = None
|
|
794
|
+
""" Name of key used to sign image. If None, image won't be signed. """
|
|
795
|
+
|
|
796
|
+
signature_key_path = None
|
|
797
|
+
""" Directory path to signature key """
|
|
798
|
+
|
|
799
|
+
def run(self, deps, tools):
|
|
800
|
+
assert tools.which("mkimage"), "mkimage is required to build the FIT image"
|
|
801
|
+
|
|
802
|
+
kernels = []
|
|
803
|
+
dtbs = []
|
|
804
|
+
ramdisks = []
|
|
805
|
+
|
|
806
|
+
# Add kernels and dtbs to individual lists
|
|
807
|
+
for name, config in self._configs().items():
|
|
808
|
+
kernels.append(config[0])
|
|
809
|
+
dtbs.append((config[0], config[1]))
|
|
810
|
+
try:
|
|
811
|
+
ramdisks.append(config[2])
|
|
812
|
+
except IndexError:
|
|
813
|
+
pass
|
|
814
|
+
dtbs = list(set(dtbs))
|
|
815
|
+
kernels = list(set(kernels))
|
|
816
|
+
|
|
817
|
+
# Render image device tree source template
|
|
818
|
+
self.info("Rendering FIT image source file")
|
|
819
|
+
its = tools.render(
|
|
820
|
+
self._template,
|
|
821
|
+
enumerate=enumerate,
|
|
822
|
+
len=len,
|
|
823
|
+
path=os.path,
|
|
824
|
+
print=print,
|
|
825
|
+
str=str,
|
|
826
|
+
deps=deps,
|
|
827
|
+
_dtbs=list(set(dtbs)),
|
|
828
|
+
_kernels=list(set(kernels)),
|
|
829
|
+
_ramdisks=list(set(ramdisks)))
|
|
830
|
+
|
|
831
|
+
with tools.cwd(tools.builddir()):
|
|
832
|
+
tools.write_file("fitImage.its", its, expand=False)
|
|
833
|
+
print(its)
|
|
834
|
+
|
|
835
|
+
self.info("Building FIT image")
|
|
836
|
+
tools.run(["mkimage", "-V"], shell=False)
|
|
837
|
+
tools.run(["mkimage", "-D", "-I dts -O dtb -p 2000", "-f", "fitImage.its", "fitImage"], shell=False)
|
|
838
|
+
|
|
839
|
+
# Optionally sign the image
|
|
840
|
+
if self.signature_key_name:
|
|
841
|
+
self.info("Signing FIT image")
|
|
842
|
+
signature_key_path = tools.expand_path(self.signature_key_path)
|
|
843
|
+
tools.copy("fitImage", "fitImage.unsigned")
|
|
844
|
+
tools.run(["mkimage", "-D", "-I dts -O dtb -p 2000", "-F", "-k", signature_key_path, "-r", "fitImage"], shell=False)
|
|
845
|
+
|
|
846
|
+
def publish(self, artifact, tools):
|
|
847
|
+
with tools.cwd(tools.builddir()):
|
|
848
|
+
artifact.collect("fitImage")
|
|
849
|
+
artifact.collect("fitImage.unsigned")
|
|
850
|
+
artifact.collect("fitImage.its")
|
|
851
|
+
artifact.paths.fitimage = "fitImage"
|
|
852
|
+
|
|
853
|
+
|
|
854
|
+
@attributes.attribute("binary", "binary_{arch}")
|
|
855
|
+
class Qemu(Task):
|
|
856
|
+
"""
|
|
857
|
+
Runs Qemu with the given kernel, initramfs and rootfs.
|
|
858
|
+
|
|
859
|
+
The task automatically selects the correct Qemu binary for the architecture
|
|
860
|
+
and builds the command line arguments based on the provided kernel, initramfs
|
|
861
|
+
and rootfs tasks.
|
|
862
|
+
|
|
863
|
+
Additional arguments can be passed to QEMU by setting the ``arguments``
|
|
864
|
+
attribute.
|
|
865
|
+
|
|
866
|
+
The selected Qemu binary must be available in PATH.
|
|
867
|
+
"""
|
|
868
|
+
|
|
869
|
+
abstract = True
|
|
870
|
+
""" Must be subclassed """
|
|
871
|
+
|
|
872
|
+
arch = ArchParameter()
|
|
873
|
+
""" Target architecture [amd64, arm, arm64, mips, powerpc, riscv, s390, x86] """
|
|
874
|
+
|
|
875
|
+
arguments = []
|
|
876
|
+
""" Additional arguments to pass to QEMU """
|
|
877
|
+
|
|
878
|
+
binary = None
|
|
879
|
+
""" Name of QEMU binary """
|
|
880
|
+
|
|
881
|
+
binary_arm = "qemu-system-arm"
|
|
882
|
+
binary_arm64 = "qemu-system-aarch64"
|
|
883
|
+
binary_mips = "qemu-system-mips"
|
|
884
|
+
binary_powerpc = "qemu-system-ppc"
|
|
885
|
+
binary_riscv = "qemu-system-riscv64"
|
|
886
|
+
binary_s390 = "qemu-system-s390x"
|
|
887
|
+
binary_x86 = "qemu-system-x86_64"
|
|
888
|
+
|
|
889
|
+
cacheable = False
|
|
890
|
+
""" Task is not cacheable """
|
|
891
|
+
|
|
892
|
+
dtb = None
|
|
893
|
+
""" Path to device tree in kernel artifact """
|
|
894
|
+
|
|
895
|
+
initrd = None
|
|
896
|
+
""" Name of initrd/ramfs task, if any """
|
|
897
|
+
|
|
898
|
+
kernel = None
|
|
899
|
+
""" Name of kernel task """
|
|
900
|
+
|
|
901
|
+
machine = None
|
|
902
|
+
""" Target machine """
|
|
903
|
+
|
|
904
|
+
memory = None
|
|
905
|
+
""" Memory size. Example: 512M """
|
|
906
|
+
|
|
907
|
+
rootfs = None
|
|
908
|
+
""" Name of rootfs task, if any """
|
|
909
|
+
|
|
910
|
+
def requires(self):
|
|
911
|
+
r = []
|
|
912
|
+
if self.kernel:
|
|
913
|
+
r.append("kernel=" + self.kernel)
|
|
914
|
+
if self.initrd:
|
|
915
|
+
r.append("initrd=" + self.initrd)
|
|
916
|
+
if self.rootfs:
|
|
917
|
+
r.append("rootfs=" + self.rootfs)
|
|
918
|
+
return r
|
|
919
|
+
|
|
920
|
+
def run(self, deps, tools):
|
|
921
|
+
assert tools.which(self.binary), "{binary} is required to run QEMU"
|
|
922
|
+
assert self.machine, "Machine type is required to run QEMU"
|
|
923
|
+
|
|
924
|
+
self.deps = deps
|
|
925
|
+
|
|
926
|
+
# Get kernel and initrd paths
|
|
927
|
+
arguments = self.expand(self.arguments)
|
|
928
|
+
dtb = ["-dtb", os.path.join(str(deps[self.kernel].paths.dtbs), self.dtb)] if self.dtb else []
|
|
929
|
+
initrd = ["-initrd", str(deps[self.initrd].paths.cpio)] if self.initrd else []
|
|
930
|
+
kernel = ["-kernel", str(deps[self.kernel].paths.zimage)] if self.kernel else []
|
|
931
|
+
memory = ["-m", self.memory] if self.memory else []
|
|
932
|
+
|
|
933
|
+
# Run QEMU
|
|
934
|
+
binary = tools.which(self.binary)
|
|
935
|
+
|
|
936
|
+
cmdline = [
|
|
937
|
+
binary,
|
|
938
|
+
"-M", self.machine,
|
|
939
|
+
] + kernel + dtb + initrd + memory + arguments
|
|
940
|
+
|
|
941
|
+
self.info("Running QEMU with command: {}", cmdline)
|
|
942
|
+
|
|
943
|
+
os.execv(binary, cmdline)
|