jolt 0.9.172__py3-none-any.whl → 0.9.435__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.
Files changed (185) hide show
  1. jolt/__init__.py +80 -7
  2. jolt/__main__.py +9 -1
  3. jolt/bin/fstree-darwin-x86_64 +0 -0
  4. jolt/bin/fstree-linux-x86_64 +0 -0
  5. jolt/cache.py +596 -252
  6. jolt/chroot.py +36 -11
  7. jolt/cli.py +143 -130
  8. jolt/common_pb2.py +45 -45
  9. jolt/config.py +76 -40
  10. jolt/error.py +19 -4
  11. jolt/filesystem.py +2 -6
  12. jolt/graph.py +400 -82
  13. jolt/influence.py +110 -3
  14. jolt/loader.py +338 -174
  15. jolt/log.py +127 -31
  16. jolt/manifest.py +13 -46
  17. jolt/options.py +35 -11
  18. jolt/pkgs/abseil.py +42 -0
  19. jolt/pkgs/asio.py +25 -0
  20. jolt/pkgs/autoconf.py +41 -0
  21. jolt/pkgs/automake.py +41 -0
  22. jolt/pkgs/b2.py +31 -0
  23. jolt/pkgs/boost.py +111 -0
  24. jolt/pkgs/boringssl.py +32 -0
  25. jolt/pkgs/busybox.py +39 -0
  26. jolt/pkgs/bzip2.py +43 -0
  27. jolt/pkgs/cares.py +29 -0
  28. jolt/pkgs/catch2.py +36 -0
  29. jolt/pkgs/cbindgen.py +17 -0
  30. jolt/pkgs/cista.py +19 -0
  31. jolt/pkgs/clang.py +44 -0
  32. jolt/pkgs/cli11.py +24 -0
  33. jolt/pkgs/cmake.py +48 -0
  34. jolt/pkgs/cpython.py +196 -0
  35. jolt/pkgs/crun.py +29 -0
  36. jolt/pkgs/curl.py +38 -0
  37. jolt/pkgs/dbus.py +18 -0
  38. jolt/pkgs/double_conversion.py +24 -0
  39. jolt/pkgs/fastfloat.py +21 -0
  40. jolt/pkgs/ffmpeg.py +28 -0
  41. jolt/pkgs/flatbuffers.py +29 -0
  42. jolt/pkgs/fmt.py +27 -0
  43. jolt/pkgs/fstree.py +20 -0
  44. jolt/pkgs/gflags.py +18 -0
  45. jolt/pkgs/glib.py +18 -0
  46. jolt/pkgs/glog.py +25 -0
  47. jolt/pkgs/glslang.py +21 -0
  48. jolt/pkgs/golang.py +16 -11
  49. jolt/pkgs/googlebenchmark.py +18 -0
  50. jolt/pkgs/googletest.py +46 -0
  51. jolt/pkgs/gperf.py +15 -0
  52. jolt/pkgs/grpc.py +73 -0
  53. jolt/pkgs/hdf5.py +19 -0
  54. jolt/pkgs/help2man.py +14 -0
  55. jolt/pkgs/inja.py +28 -0
  56. jolt/pkgs/jsoncpp.py +31 -0
  57. jolt/pkgs/libarchive.py +43 -0
  58. jolt/pkgs/libcap.py +44 -0
  59. jolt/pkgs/libdrm.py +44 -0
  60. jolt/pkgs/libedit.py +42 -0
  61. jolt/pkgs/libevent.py +31 -0
  62. jolt/pkgs/libexpat.py +27 -0
  63. jolt/pkgs/libfastjson.py +21 -0
  64. jolt/pkgs/libffi.py +16 -0
  65. jolt/pkgs/libglvnd.py +30 -0
  66. jolt/pkgs/libogg.py +28 -0
  67. jolt/pkgs/libpciaccess.py +18 -0
  68. jolt/pkgs/libseccomp.py +21 -0
  69. jolt/pkgs/libtirpc.py +24 -0
  70. jolt/pkgs/libtool.py +42 -0
  71. jolt/pkgs/libunwind.py +35 -0
  72. jolt/pkgs/libva.py +18 -0
  73. jolt/pkgs/libvorbis.py +33 -0
  74. jolt/pkgs/libxml2.py +35 -0
  75. jolt/pkgs/libxslt.py +17 -0
  76. jolt/pkgs/libyajl.py +16 -0
  77. jolt/pkgs/llvm.py +81 -0
  78. jolt/pkgs/lua.py +54 -0
  79. jolt/pkgs/lz4.py +26 -0
  80. jolt/pkgs/m4.py +14 -0
  81. jolt/pkgs/make.py +17 -0
  82. jolt/pkgs/mesa.py +81 -0
  83. jolt/pkgs/meson.py +17 -0
  84. jolt/pkgs/mstch.py +28 -0
  85. jolt/pkgs/mysql.py +60 -0
  86. jolt/pkgs/nasm.py +49 -0
  87. jolt/pkgs/ncurses.py +30 -0
  88. jolt/pkgs/ng_log.py +25 -0
  89. jolt/pkgs/ninja.py +45 -0
  90. jolt/pkgs/nlohmann_json.py +25 -0
  91. jolt/pkgs/nodejs.py +19 -11
  92. jolt/pkgs/opencv.py +24 -0
  93. jolt/pkgs/openjdk.py +26 -0
  94. jolt/pkgs/openssl.py +103 -0
  95. jolt/pkgs/paho.py +76 -0
  96. jolt/pkgs/patchelf.py +16 -0
  97. jolt/pkgs/perl.py +42 -0
  98. jolt/pkgs/pkgconfig.py +64 -0
  99. jolt/pkgs/poco.py +39 -0
  100. jolt/pkgs/protobuf.py +77 -0
  101. jolt/pkgs/pugixml.py +27 -0
  102. jolt/pkgs/python.py +19 -0
  103. jolt/pkgs/qt.py +35 -0
  104. jolt/pkgs/rapidjson.py +26 -0
  105. jolt/pkgs/rapidyaml.py +28 -0
  106. jolt/pkgs/re2.py +30 -0
  107. jolt/pkgs/re2c.py +17 -0
  108. jolt/pkgs/readline.py +15 -0
  109. jolt/pkgs/rust.py +41 -0
  110. jolt/pkgs/sdl.py +28 -0
  111. jolt/pkgs/simdjson.py +27 -0
  112. jolt/pkgs/soci.py +46 -0
  113. jolt/pkgs/spdlog.py +29 -0
  114. jolt/pkgs/spirv_llvm.py +21 -0
  115. jolt/pkgs/spirv_tools.py +24 -0
  116. jolt/pkgs/sqlite.py +83 -0
  117. jolt/pkgs/ssl.py +12 -0
  118. jolt/pkgs/texinfo.py +15 -0
  119. jolt/pkgs/tomlplusplus.py +22 -0
  120. jolt/pkgs/wayland.py +26 -0
  121. jolt/pkgs/x11.py +58 -0
  122. jolt/pkgs/xerces_c.py +20 -0
  123. jolt/pkgs/xorg.py +360 -0
  124. jolt/pkgs/xz.py +29 -0
  125. jolt/pkgs/yamlcpp.py +30 -0
  126. jolt/pkgs/zeromq.py +47 -0
  127. jolt/pkgs/zlib.py +87 -0
  128. jolt/pkgs/zstd.py +33 -0
  129. jolt/plugins/alias.py +3 -0
  130. jolt/plugins/allure.py +2 -2
  131. jolt/plugins/autotools.py +66 -0
  132. jolt/plugins/cache.py +1 -1
  133. jolt/plugins/cmake.py +74 -6
  134. jolt/plugins/conan.py +238 -0
  135. jolt/plugins/cxxinfo.py +7 -0
  136. jolt/plugins/docker.py +76 -19
  137. jolt/plugins/email.xslt +141 -118
  138. jolt/plugins/environ.py +11 -0
  139. jolt/plugins/fetch.py +141 -0
  140. jolt/plugins/gdb.py +33 -14
  141. jolt/plugins/gerrit.py +0 -13
  142. jolt/plugins/git.py +248 -66
  143. jolt/plugins/googletest.py +1 -1
  144. jolt/plugins/http.py +1 -1
  145. jolt/plugins/libtool.py +63 -0
  146. jolt/plugins/linux.py +990 -0
  147. jolt/plugins/logstash.py +4 -4
  148. jolt/plugins/meson.py +61 -0
  149. jolt/plugins/ninja-compdb.py +96 -28
  150. jolt/plugins/ninja.py +424 -150
  151. jolt/plugins/paths.py +11 -1
  152. jolt/plugins/pkgconfig.py +219 -0
  153. jolt/plugins/podman.py +131 -87
  154. jolt/plugins/python.py +137 -0
  155. jolt/plugins/remote_execution/administration_pb2.py +27 -19
  156. jolt/plugins/remote_execution/log_pb2.py +12 -12
  157. jolt/plugins/remote_execution/scheduler_pb2.py +23 -23
  158. jolt/plugins/remote_execution/worker_pb2.py +19 -19
  159. jolt/plugins/report.py +7 -2
  160. jolt/plugins/rust.py +25 -0
  161. jolt/plugins/scheduler.py +135 -86
  162. jolt/plugins/selfdeploy/setup.py +6 -6
  163. jolt/plugins/selfdeploy.py +49 -31
  164. jolt/plugins/strings.py +35 -22
  165. jolt/plugins/symlinks.py +11 -4
  166. jolt/plugins/telemetry.py +1 -2
  167. jolt/plugins/timeline.py +13 -3
  168. jolt/scheduler.py +467 -165
  169. jolt/tasks.py +427 -111
  170. jolt/templates/timeline.html.template +44 -47
  171. jolt/timer.py +22 -0
  172. jolt/tools.py +527 -188
  173. jolt/utils.py +183 -3
  174. jolt/version.py +1 -1
  175. jolt/xmldom.py +12 -2
  176. {jolt-0.9.172.dist-info → jolt-0.9.435.dist-info}/METADATA +97 -41
  177. jolt-0.9.435.dist-info/RECORD +207 -0
  178. {jolt-0.9.172.dist-info → jolt-0.9.435.dist-info}/WHEEL +1 -1
  179. jolt/plugins/amqp.py +0 -855
  180. jolt/plugins/debian.py +0 -338
  181. jolt/plugins/repo.py +0 -253
  182. jolt/plugins/snap.py +0 -122
  183. jolt-0.9.172.dist-info/RECORD +0 -92
  184. {jolt-0.9.172.dist-info → jolt-0.9.435.dist-info}/entry_points.txt +0 -0
  185. {jolt-0.9.172.dist-info → jolt-0.9.435.dist-info}/top_level.txt +0 -0
jolt/plugins/cache.py CHANGED
@@ -85,7 +85,7 @@ class Cache(cache.StorageProvider):
85
85
  except ConnectTimeout:
86
86
  self._disabled = True
87
87
  log.warning(NAME_LOG + " failed to establish server connection, disabled")
88
- return []
88
+ return [], []
89
89
 
90
90
  if response.status_code != 200:
91
91
  log.debug(NAME_LOG + " POST ({}): {}", response.status_code, self._file_uri)
jolt/plugins/cmake.py CHANGED
@@ -1,3 +1,4 @@
1
+ from jolt import attributes
1
2
  from jolt import influence
2
3
  from jolt import Task
3
4
  from jolt import utils
@@ -6,31 +7,98 @@ from jolt.error import raise_task_error_if
6
7
  import os
7
8
 
8
9
 
10
+ def options(attrib):
11
+ """
12
+ Decorates a CMake task with an alternative ``options`` attribute.
13
+
14
+ The new attribute will be concatenated with the regular
15
+ ``options`` attribute.
16
+
17
+ Args:
18
+ attrib (str): Name of alternative attribute.
19
+ Keywords are expanded.
20
+ """
21
+ return utils.concat_attributes("options", attrib)
22
+
23
+
24
+ def requires(version=None):
25
+ """ Decorator to add CMake requirements to a task. """
26
+
27
+ import jolt.pkgs.cmake
28
+
29
+ def decorate(cls):
30
+ cls = attributes.requires("requires_cmake")(cls)
31
+ cls.requires_cmake = ["cmake" + (f":version={version}" if version else "")]
32
+ return cls
33
+
34
+ return decorate
35
+
36
+
37
+ def use_ninja():
38
+ """
39
+ Decorator to add Ninja dependencies to CMake task.
40
+
41
+ It also selects Ninja as the CMake generator and builder.
42
+ """
43
+
44
+ import jolt.pkgs.ninja
45
+
46
+ def decorate(cls):
47
+ cls = attributes.requires("requires_ninja")(cls)
48
+ cls.generator = "Ninja"
49
+ cls.requires_ninja = ["ninja"]
50
+ return cls
51
+
52
+ return decorate
53
+
54
+
55
+ @attributes.common_metadata()
56
+ @options("options")
9
57
  class CMake(Task):
10
58
  """ Builds and publishes a CMake project """
11
-
12
59
  abstract = True
13
60
 
14
61
  cmakelists = "CMakeLists.txt"
15
62
  """ Path to CMakeLists.txt or directory containing CMakelists.txt """
16
63
 
64
+ config = "Release"
65
+ """ The default build configuration to use """
66
+
17
67
  generator = None
68
+ """ The build file generator that CMake should use """
18
69
 
19
70
  incremental = True
71
+ """ Keep build directories between Jolt invocations """
20
72
 
21
73
  options = []
22
74
  """ List of options and their values (``option[:type]=value``) """
23
75
 
76
+ srcdir = None
77
+ """ Source directory. If not specified, the task working directory is used. """
78
+
79
+ install = ["install"]
80
+ """ List of install build targets. If empty, the default install target is used. """
81
+
82
+ def clean(self, tools):
83
+ cmake = tools.cmake(incremental=self.incremental)
84
+ cmake.clean()
85
+
24
86
  def run(self, deps, tools):
87
+ self.deps = deps
25
88
  raise_task_error_if(not self.cmakelists, self, "cmakelists attribute has not been defined")
26
89
 
27
- cmake = tools.cmake(incremental=self.incremental)
28
- cmake.configure(tools.expand(self.cmakelists), *["-D" + tools.expand(option) for option in self.options], generator=self.generator)
29
- cmake.build()
30
- cmake.install()
90
+ config = tools.expand(str(self.config))
91
+ options = self._options()
92
+ options += ["CMAKE_BUILD_TYPE=" + config]
93
+
94
+ with tools.cwd(self.srcdir or self.joltdir):
95
+ cmake = tools.cmake(deps, incremental=self.incremental)
96
+ cmake.configure(tools.expand(self.cmakelists), *["-D" + tools.expand(option) for option in options], generator=self.generator)
97
+ for target in self.install or ["install"]:
98
+ cmake.install(config=config, target=target)
31
99
 
32
100
  def publish(self, artifact, tools):
33
- cmake = tools.cmake()
101
+ cmake = tools.cmake(incremental=self.incremental)
34
102
  cmake.publish(artifact)
35
103
 
36
104
 
jolt/plugins/conan.py CHANGED
@@ -3,6 +3,7 @@ from os import path
3
3
 
4
4
  from jolt import Task
5
5
  from jolt import influence
6
+ from jolt import utils
6
7
  from jolt.error import raise_task_error_if
7
8
 
8
9
 
@@ -239,3 +240,240 @@ class Conan(Task):
239
240
  artifact.cxxinfo.cflags.append(dep["cflags"])
240
241
  artifact.cxxinfo.cxxflags.append(dep["cxxflags"])
241
242
  artifact.cxxinfo.ldflags.append(dep["exelinkflags"])
243
+
244
+
245
+ @influence.attribute("conanfile")
246
+ @influence.attribute("generators")
247
+ @influence.attribute("incremental")
248
+ @influence.attribute("options")
249
+ @influence.attribute("packages")
250
+ class Conan2(Task):
251
+ """
252
+ Conan package installer task.
253
+
254
+ This task base class can be used to fetch, build and publish Conan packages
255
+ as Jolt artifacts. All package metadata is transfered from the Conan package
256
+ manifest to the Jolt artifact so that no manual configuration of include
257
+ paths, library paths, macros, etc is required.
258
+
259
+ An existing installation of Conan is required. Please visit https://conan.io/
260
+ for installation instructions and documentation.
261
+
262
+ A minimal task to download and publish the Boost C++ libraries can look like this:
263
+
264
+ .. code-block:: python
265
+
266
+ from jolt.plugins.conan import Conan
267
+
268
+ class Boost(Conan):
269
+ packages = ["boost/1.74.0"]
270
+
271
+ Boost may then be used from Ninja tasks by declaring a requirement:
272
+
273
+ .. code-block:: python
274
+
275
+ from jolt.plugins.ninja import CXXExecutable
276
+
277
+ class BoostApplication(CXXExecutable):
278
+ requires = ["boost"]
279
+ sources = ["main.cpp"]
280
+
281
+ The task supports using an existing conanfile.txt, but it is not required.
282
+ Packages are installed into and collected from Jolt build directories. The
283
+ user's regular Conan cache will not be affected.
284
+
285
+ """
286
+
287
+ abstract = True
288
+
289
+ conanfile = None
290
+ """
291
+ An existing conanfile.txt file to use.
292
+
293
+ Instead of generating the conanfile.txt file on-demand, an external
294
+ file may be used. If this attribute is set, the ``generators``, ``options``
295
+ and ``packages`` attributes must not be set.
296
+
297
+ See Conan documentation for further details.
298
+ """
299
+
300
+ packages = []
301
+ """
302
+ A list of Conan package references to collect and publish.
303
+
304
+ The reference format is ``PkgName/<version>@user/channel``. See Conan
305
+ documentation for further details.
306
+
307
+ Any {keyword} arguments, or macros, found in the strings are automatically
308
+ expanded to the value of the associated task's parameters and properties.
309
+
310
+ Example:
311
+
312
+ .. code-block:: python
313
+
314
+ sdl_version = Parameter("2.0.12")
315
+
316
+ packages = [
317
+ "boost/1.74.0",
318
+ "sdl2/{sdl_version}@bincrafters/stable",
319
+ ]
320
+
321
+ """
322
+
323
+ options = []
324
+ """
325
+ A list of Conan package options to apply
326
+
327
+ The option format is ``PkgName:Option=Value``. See Conan
328
+ documentation for further details.
329
+
330
+ Any {keyword} arguments, or macros, found in the strings are automatically
331
+ expanded to the value of the associated task's parameters and properties.
332
+
333
+ Example:
334
+
335
+ .. code-block:: python
336
+
337
+ options = [
338
+ "boost:shared=True",
339
+ "zlib:shared=True",
340
+ ]
341
+
342
+ """
343
+
344
+ settings = []
345
+ """
346
+ A list of Conan settings to apply
347
+
348
+ The settings format is ``Option=Value``. See Conan
349
+ documentation for further details.
350
+
351
+ Any {keyword} arguments, or macros, found in the strings are automatically
352
+ expanded to the value of the associated task's parameters and properties.
353
+
354
+ Example:
355
+
356
+ .. code-block:: python
357
+
358
+ settings = [
359
+ "compiler.libcxx=libstdc++11",
360
+ ]
361
+
362
+ """
363
+
364
+ remotes = {}
365
+ """
366
+ A dictionary with Conan remotes to use when fetching packages.
367
+
368
+ The dictionary key is the name of remote and its value is the URL.
369
+
370
+ Example:
371
+
372
+ .. code-block:: python
373
+
374
+ remotes = {
375
+ "bincrafters": "https://api.bintray.com/conan/bincrafters/public-conan"
376
+ }
377
+
378
+ """
379
+
380
+ incremental = True
381
+ """
382
+ Keep installed packages in the Conan cache between Jolt invokations.
383
+
384
+ If incremental build is disabled, the Jolt Conan cache is removed
385
+ before execution begins.
386
+ """
387
+
388
+ def __init__(self, *args, **kwargs):
389
+ super().__init__(*args, **kwargs)
390
+ if self.conanfile:
391
+ self.influence.append(influence.FileInfluence(self.conanfile))
392
+
393
+ def _options(self):
394
+ return [] + self.options
395
+
396
+ def _settings(self):
397
+ return [] + self.settings
398
+
399
+ def _packages(self):
400
+ return [] + self.packages
401
+
402
+ def _remotes(self):
403
+ return self.remotes
404
+
405
+ def run(self, deps, tools):
406
+ raise_task_error_if(
407
+ not tools.which("conan"), self,
408
+ "Conan: Conan is not installed in the PATH")
409
+ raise_task_error_if(
410
+ self.conanfile and (self._packages() or self._options()), self,
411
+ "Conan: 'conanfile' attribute cannot be used with other attributes")
412
+
413
+ conanfile = tools.expand_path(self.conanfile) if self.conanfile else None
414
+
415
+ with tools.cwd(tools.builddir()):
416
+ if conanfile is None or not path.exists(conanfile):
417
+ conanfile = "conanfile.txt"
418
+ self.info("Creating conanfile.txt")
419
+ self.tools.write_file(conanfile, "[requires]\n")
420
+ for pkg in self._packages():
421
+ self.tools.append_file(conanfile, pkg + "\n")
422
+
423
+ with tools.environ(CONAN_USER_HOME=tools.builddir("conan", incremental=self.incremental)):
424
+ for remote, url in self._remotes().items():
425
+ self.info("Registering remote '{}'", remote)
426
+ tools.run("conan remote add -f {} {}", remote, url, output_on_error=True)
427
+
428
+ self.info("Installing packages into the Conan cache")
429
+ options = " ".join(["-o " + opt for opt in self._options()])
430
+ settings = " ".join(["-s " + opt for opt in self._settings()])
431
+ output = tools.run("conan install --build=missing --output-folder . -u --format=json {} {} {}", options, settings, conanfile, output_stdout=False)
432
+
433
+ self.info("Parsing manifest")
434
+ self._manifest = json.loads(output)
435
+
436
+ for dep in self._manifest["graph"]["nodes"].values():
437
+ if dep["package_folder"]:
438
+ self.info("Collecting '{}' files from: {}", dep["name"], dep["package_folder"])
439
+ tools.copy(dep["package_folder"], dep["name"])
440
+
441
+ def publish(self, artifact, tools):
442
+ self.info("Publishing package files")
443
+ with tools.cwd(tools.builddir()):
444
+ artifact.collect("*")
445
+
446
+ self.info("Publishing metadata")
447
+ for dep in self._manifest["graph"]["nodes"].values():
448
+ if not dep["package_folder"]:
449
+ continue
450
+
451
+ for node in dep["cpp_info"]:
452
+ for incpath in dep["cpp_info"][node]["includedirs"]:
453
+ artifact.cxxinfo.incpaths.append(path.join(dep["name"], path.relpath(incpath, dep["package_folder"])))
454
+ for libpath in dep["cpp_info"][node]["libdirs"]:
455
+ artifact.cxxinfo.libpaths.append(path.join(dep["name"], path.relpath(libpath, dep["package_folder"])))
456
+ for binpath in dep["cpp_info"][node]["bindirs"]:
457
+ artifact.environ.PATH.append(path.join(dep["name"], path.relpath(binpath, dep["package_folder"])))
458
+ if dep["cpp_info"][node]["libs"]:
459
+ artifact.cxxinfo.libraries.extend(dep["cpp_info"][node]["libs"])
460
+ if dep["cpp_info"][node]["system_libs"]:
461
+ artifact.cxxinfo.libraries.extend(dep["cpp_info"][node]["system_libs"])
462
+ if dep["cpp_info"][node]["defines"]:
463
+ artifact.cxxinfo.macros.extend(dep["cpp_info"][node]["defines"])
464
+ if dep["cpp_info"][node]["cflags"]:
465
+ artifact.cxxinfo.cflags.extend(dep["cpp_info"][node]["cflags"])
466
+ if dep["cpp_info"][node]["cxxflags"]:
467
+ artifact.cxxinfo.cxxflags.extend(dep["cpp_info"][node]["cxxflags"])
468
+ if dep["cpp_info"][node]["exelinkflags"]:
469
+ artifact.cxxinfo.ldflags.extend(dep["cpp_info"][node]["exelinkflags"])
470
+
471
+ # Make list of unique values
472
+ artifact.cxxinfo.incpaths = utils.unique_list(artifact.cxxinfo.incpaths)
473
+ artifact.cxxinfo.libpaths = utils.unique_list(artifact.cxxinfo.libpaths)
474
+ artifact.cxxinfo.libraries = utils.unique_list(artifact.cxxinfo.libraries)
475
+ artifact.cxxinfo.macros = utils.unique_list(artifact.cxxinfo.macros)
476
+ artifact.cxxinfo.cflags = utils.unique_list(artifact.cxxinfo.cflags)
477
+ artifact.cxxinfo.cxxflags = utils.unique_list(artifact.cxxinfo.cxxflags)
478
+ artifact.cxxinfo.ldflags = utils.unique_list(artifact.cxxinfo.ldflags)
479
+ artifact.environ.PATH = path.pathsep.join(utils.unique_list(str(artifact.environ.PATH).split(path.pathsep)))
jolt/plugins/cxxinfo.py CHANGED
@@ -1,4 +1,5 @@
1
1
  from jolt.cache import ArtifactListAttribute
2
+ from jolt.cache import ArtifactStringAttribute
2
3
  from jolt.cache import ArtifactAttributeSet
3
4
  from jolt.cache import ArtifactAttributeSetProvider
4
5
 
@@ -7,6 +8,10 @@ class CppInfoListVariable(ArtifactListAttribute):
7
8
  pass
8
9
 
9
10
 
11
+ class CppInfoStringVariable(ArtifactStringAttribute):
12
+ pass
13
+
14
+
10
15
  class CppInfoDictVariable(ArtifactListAttribute):
11
16
  def __init__(self, artifact, name):
12
17
  super(CppInfoDictVariable, self).__init__(artifact, name)
@@ -26,6 +31,8 @@ class CppInfo(ArtifactAttributeSet):
26
31
  return CppInfoListVariable(self._artifact, "asflags")
27
32
  if name == "cflags":
28
33
  return CppInfoListVariable(self._artifact, "cflags")
34
+ if name == "msvcrt":
35
+ return CppInfoStringVariable(self._artifact, "msvcrt")
29
36
  if name == "cxxflags":
30
37
  return CppInfoListVariable(self._artifact, "cxxflags")
31
38
  if name == "incpaths":
jolt/plugins/docker.py CHANGED
@@ -25,8 +25,6 @@ class DockerListVariable(ArtifactListAttribute):
25
25
 
26
26
  class DockerLoadListVariable(DockerListVariable):
27
27
  def apply(self, task, artifact):
28
- if isinstance(task, Resource):
29
- return
30
28
  for image in self.items():
31
29
  task.tools.run(
32
30
  "docker load -i {}",
@@ -35,16 +33,12 @@ class DockerLoadListVariable(DockerListVariable):
35
33
 
36
34
  class DockerPullListVariable(DockerListVariable):
37
35
  def apply(self, task, artifact):
38
- if isinstance(task, Resource):
39
- return
40
36
  for image in self.items():
41
37
  task.tools.run("docker pull {}", image, output_on_error=True)
42
38
 
43
39
 
44
40
  class DockerRmiListVariable(DockerListVariable):
45
41
  def unapply(self, task, artifact):
46
- if isinstance(task, Resource):
47
- return
48
42
  for image in self.items():
49
43
  task.tools.run("docker rmi -f {}", image, output_on_error=True)
50
44
 
@@ -109,8 +103,8 @@ class DockerClient(Download):
109
103
  url = "https://download.docker.com/{host}/static/stable/{arch}/docker-{version}.tgz"
110
104
  """ URL of binaries """
111
105
 
112
- version = Parameter("20.10.13", help="Docker version")
113
- """ Docker version [20.10.13] """
106
+ version = Parameter("27.4.1", help="Docker version")
107
+ """ Docker version [27.4.1] """
114
108
 
115
109
  def publish(self, artifact, tools):
116
110
  super().publish(artifact, tools)
@@ -173,6 +167,40 @@ class DockerContainer(Resource):
173
167
  Alternatively, assign ``True`` to publish all exposed ports to random ports.
174
168
  """
175
169
 
170
+ release_on_error = True
171
+ """ Stop and remove container on error to avoid resource leaks. """
172
+
173
+ security_opts = []
174
+ """
175
+ A list of security options.
176
+
177
+ By default, the container is started with the default security profile.
178
+
179
+ Example:
180
+
181
+ .. code-block:: python
182
+
183
+ security_opts = [
184
+ "seccomp:unconfined",
185
+ ]
186
+
187
+ """
188
+
189
+ stop_timeout = 10
190
+ """ Timeout in seconds for stopping the container .
191
+
192
+ When stopping the container, the task will wait for the container to stop
193
+ for the specified number of seconds before forcefully killing it.
194
+
195
+ Default: 10 seconds.
196
+ """
197
+
198
+ stop_signal = "SIGTERM"
199
+ """ Signal to send to the container when stopping it.
200
+
201
+ Default: ``SIGTERM``.
202
+ """
203
+
176
204
  volumes = []
177
205
  """
178
206
  A list of volumes to mount.
@@ -199,6 +227,9 @@ class DockerContainer(Resource):
199
227
  Defaults to the current user.
200
228
  """
201
229
 
230
+ workdir = None
231
+ """ The container working directory. """
232
+
202
233
  @property
203
234
  def _arguments(self):
204
235
  return " ".join(self.arguments)
@@ -223,7 +254,7 @@ class DockerContainer(Resource):
223
254
  def _image(self):
224
255
  registry = TaskRegistry.get()
225
256
  tool = tools.Tools(self)
226
- if registry.get_task_class(tool.expand(self.image)):
257
+ if registry.has_task(tool.expand(self.image)):
227
258
  return [self.image]
228
259
  return []
229
260
 
@@ -248,6 +279,14 @@ class DockerContainer(Resource):
248
279
  return "-P"
249
280
  return " ".join([utils.option("-p ", self.tools.expand(port)) for port in self.ports])
250
281
 
282
+ @property
283
+ def _security_opts(self):
284
+ return " ".join([utils.option("--security-opt ", self.tools.expand(opt)) for opt in self.security_opts])
285
+
286
+ @property
287
+ def _stop_signal(self):
288
+ return f" -s {self.stop_signal}" if self.stop_signal else ""
289
+
251
290
  @property
252
291
  def _user(self):
253
292
  if self.user:
@@ -263,7 +302,13 @@ class DockerContainer(Resource):
263
302
  return " ".join([utils.option("-v ", self.tools.expand(vol))
264
303
  for vol in self.volumes_default + self.volumes])
265
304
 
305
+ @property
306
+ def _workdir(self):
307
+ return "--workdir " + self.tools.expand(self.workdir) if self.workdir else ""
308
+
266
309
  def acquire(self, artifact, deps, tools, owner):
310
+ self._context_stack = None
311
+ self.container = None
267
312
  self.joltcachedir = config.get_cachedir()
268
313
  try:
269
314
  image = deps[self.image]
@@ -272,9 +317,10 @@ class DockerContainer(Resource):
272
317
  image = tools.expand(self.image)
273
318
 
274
319
  self._info(f"Creating container from image '{image}'")
275
- self.container = tools.run(
276
- "docker run -i -d {_cap_adds} {_cap_drops} {_entrypoint} {_labels} {_ports} {_privileged} {_user} {_environment} {_volumes} {image} {_arguments}",
277
- image=image, output_on_error=True)
320
+ with utils.delayed_interrupt():
321
+ self.container = tools.run(
322
+ "docker run -i -d {_cap_adds} {_cap_drops} {_entrypoint} {_labels} {_ports} {_privileged} {_security_opts} {_user} {_environment} {_volumes} {_workdir} {image} {_arguments}",
323
+ image=image, output_on_error=True)
278
324
 
279
325
  self._info("Created container '{container}'")
280
326
  info = tools.run("docker inspect {container}", output_on_error=True)
@@ -287,14 +333,18 @@ class DockerContainer(Resource):
287
333
  owner.tools.runprefix(f"docker exec -i {artifact.container}"))
288
334
 
289
335
  def release(self, artifact, deps, tools, owner):
290
- if self.chroot:
336
+ if self.chroot and self._context_stack:
291
337
  self._context_stack.close()
292
338
 
293
- self._info("Stopping container '{container}'")
294
- tools.run("docker stop {container}", output_on_error=True)
339
+ if not self.container:
340
+ return
295
341
 
296
- self._info("Deleting container '{container}'")
297
- tools.run("docker rm {container}", output_on_error=True)
342
+ try:
343
+ self._info("Stopping container '{container}'")
344
+ tools.run("docker stop{_stop_signal} -t {stop_timeout} {container}", output_on_error=True)
345
+ finally:
346
+ self._info("Deleting container '{container}'")
347
+ tools.run("docker rm -f {container}", output_on_error=True)
298
348
 
299
349
 
300
350
  class DockerLogin(Resource):
@@ -443,6 +493,9 @@ class DockerImage(Task):
443
493
  """
444
494
  abstract = True
445
495
 
496
+ annotations = []
497
+ """ A list of image annotations """
498
+
446
499
  autoload = True
447
500
  """
448
501
  Automatically load image file into local registry when the artifact is
@@ -529,6 +582,10 @@ class DockerImage(Task):
529
582
  with _Tarfile.open(layerpath, 'r') as tar:
530
583
  tar.extractall(targetpath)
531
584
 
585
+ @property
586
+ def _annotations(self):
587
+ return " ".join([utils.option("--annotation ", self.tools.expand(an)) for an in self.annotations])
588
+
532
589
  @property
533
590
  def _buildargs(self):
534
591
  return " ".join([utils.option("--build-arg ", self.tools.expand(ba)) for ba in self.buildargs])
@@ -570,7 +627,7 @@ class DockerImage(Task):
570
627
  tools.expand_relpath(context))
571
628
 
572
629
  with tools.cwd(context):
573
- tools.run("docker build {_platform} . -f {} {_buildargs} {_labels} {_tags} {pull}{squash}",
630
+ tools.run("docker build {_platform} . -f {} {_annotations} {_buildargs} {_labels} {_tags} {pull}{squash}",
574
631
  utils.quote(dockerfile), pull=pull, squash=squash)
575
632
 
576
633
  try:
@@ -620,4 +677,4 @@ class DockerImage(Task):
620
677
  if self._autoload:
621
678
  artifact.docker.load.append("{_imagefile}")
622
679
  if self._autoload:
623
- artifact.docker.rmi.append(artifact.strings.tag.get_value())
680
+ artifact.docker.rmi.append(artifact.strings.tag)