jolt 0.9.123__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 (196) 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 +832 -362
  6. jolt/chroot.py +156 -0
  7. jolt/cli.py +281 -162
  8. jolt/common_pb2.py +63 -0
  9. jolt/common_pb2_grpc.py +4 -0
  10. jolt/config.py +98 -41
  11. jolt/error.py +19 -4
  12. jolt/filesystem.py +2 -6
  13. jolt/graph.py +705 -117
  14. jolt/hooks.py +43 -0
  15. jolt/influence.py +122 -3
  16. jolt/loader.py +369 -121
  17. jolt/log.py +225 -63
  18. jolt/manifest.py +28 -38
  19. jolt/options.py +35 -10
  20. jolt/pkgs/abseil.py +42 -0
  21. jolt/pkgs/asio.py +25 -0
  22. jolt/pkgs/autoconf.py +41 -0
  23. jolt/pkgs/automake.py +41 -0
  24. jolt/pkgs/b2.py +31 -0
  25. jolt/pkgs/boost.py +111 -0
  26. jolt/pkgs/boringssl.py +32 -0
  27. jolt/pkgs/busybox.py +39 -0
  28. jolt/pkgs/bzip2.py +43 -0
  29. jolt/pkgs/cares.py +29 -0
  30. jolt/pkgs/catch2.py +36 -0
  31. jolt/pkgs/cbindgen.py +17 -0
  32. jolt/pkgs/cista.py +19 -0
  33. jolt/pkgs/clang.py +44 -0
  34. jolt/pkgs/cli11.py +24 -0
  35. jolt/pkgs/cmake.py +48 -0
  36. jolt/pkgs/cpython.py +196 -0
  37. jolt/pkgs/crun.py +29 -0
  38. jolt/pkgs/curl.py +38 -0
  39. jolt/pkgs/dbus.py +18 -0
  40. jolt/pkgs/double_conversion.py +24 -0
  41. jolt/pkgs/fastfloat.py +21 -0
  42. jolt/pkgs/ffmpeg.py +28 -0
  43. jolt/pkgs/flatbuffers.py +29 -0
  44. jolt/pkgs/fmt.py +27 -0
  45. jolt/pkgs/fstree.py +20 -0
  46. jolt/pkgs/gflags.py +18 -0
  47. jolt/pkgs/glib.py +18 -0
  48. jolt/pkgs/glog.py +25 -0
  49. jolt/pkgs/glslang.py +21 -0
  50. jolt/pkgs/golang.py +16 -11
  51. jolt/pkgs/googlebenchmark.py +18 -0
  52. jolt/pkgs/googletest.py +46 -0
  53. jolt/pkgs/gperf.py +15 -0
  54. jolt/pkgs/grpc.py +73 -0
  55. jolt/pkgs/hdf5.py +19 -0
  56. jolt/pkgs/help2man.py +14 -0
  57. jolt/pkgs/inja.py +28 -0
  58. jolt/pkgs/jsoncpp.py +31 -0
  59. jolt/pkgs/libarchive.py +43 -0
  60. jolt/pkgs/libcap.py +44 -0
  61. jolt/pkgs/libdrm.py +44 -0
  62. jolt/pkgs/libedit.py +42 -0
  63. jolt/pkgs/libevent.py +31 -0
  64. jolt/pkgs/libexpat.py +27 -0
  65. jolt/pkgs/libfastjson.py +21 -0
  66. jolt/pkgs/libffi.py +16 -0
  67. jolt/pkgs/libglvnd.py +30 -0
  68. jolt/pkgs/libogg.py +28 -0
  69. jolt/pkgs/libpciaccess.py +18 -0
  70. jolt/pkgs/libseccomp.py +21 -0
  71. jolt/pkgs/libtirpc.py +24 -0
  72. jolt/pkgs/libtool.py +42 -0
  73. jolt/pkgs/libunwind.py +35 -0
  74. jolt/pkgs/libva.py +18 -0
  75. jolt/pkgs/libvorbis.py +33 -0
  76. jolt/pkgs/libxml2.py +35 -0
  77. jolt/pkgs/libxslt.py +17 -0
  78. jolt/pkgs/libyajl.py +16 -0
  79. jolt/pkgs/llvm.py +81 -0
  80. jolt/pkgs/lua.py +54 -0
  81. jolt/pkgs/lz4.py +26 -0
  82. jolt/pkgs/m4.py +14 -0
  83. jolt/pkgs/make.py +17 -0
  84. jolt/pkgs/mesa.py +81 -0
  85. jolt/pkgs/meson.py +17 -0
  86. jolt/pkgs/mstch.py +28 -0
  87. jolt/pkgs/mysql.py +60 -0
  88. jolt/pkgs/nasm.py +49 -0
  89. jolt/pkgs/ncurses.py +30 -0
  90. jolt/pkgs/ng_log.py +25 -0
  91. jolt/pkgs/ninja.py +45 -0
  92. jolt/pkgs/nlohmann_json.py +25 -0
  93. jolt/pkgs/nodejs.py +19 -11
  94. jolt/pkgs/opencv.py +24 -0
  95. jolt/pkgs/openjdk.py +26 -0
  96. jolt/pkgs/openssl.py +103 -0
  97. jolt/pkgs/paho.py +76 -0
  98. jolt/pkgs/patchelf.py +16 -0
  99. jolt/pkgs/perl.py +42 -0
  100. jolt/pkgs/pkgconfig.py +64 -0
  101. jolt/pkgs/poco.py +39 -0
  102. jolt/pkgs/protobuf.py +77 -0
  103. jolt/pkgs/pugixml.py +27 -0
  104. jolt/pkgs/python.py +19 -0
  105. jolt/pkgs/qt.py +35 -0
  106. jolt/pkgs/rapidjson.py +26 -0
  107. jolt/pkgs/rapidyaml.py +28 -0
  108. jolt/pkgs/re2.py +30 -0
  109. jolt/pkgs/re2c.py +17 -0
  110. jolt/pkgs/readline.py +15 -0
  111. jolt/pkgs/rust.py +41 -0
  112. jolt/pkgs/sdl.py +28 -0
  113. jolt/pkgs/simdjson.py +27 -0
  114. jolt/pkgs/soci.py +46 -0
  115. jolt/pkgs/spdlog.py +29 -0
  116. jolt/pkgs/spirv_llvm.py +21 -0
  117. jolt/pkgs/spirv_tools.py +24 -0
  118. jolt/pkgs/sqlite.py +83 -0
  119. jolt/pkgs/ssl.py +12 -0
  120. jolt/pkgs/texinfo.py +15 -0
  121. jolt/pkgs/tomlplusplus.py +22 -0
  122. jolt/pkgs/wayland.py +26 -0
  123. jolt/pkgs/x11.py +58 -0
  124. jolt/pkgs/xerces_c.py +20 -0
  125. jolt/pkgs/xorg.py +360 -0
  126. jolt/pkgs/xz.py +29 -0
  127. jolt/pkgs/yamlcpp.py +30 -0
  128. jolt/pkgs/zeromq.py +47 -0
  129. jolt/pkgs/zlib.py +87 -0
  130. jolt/pkgs/zstd.py +33 -0
  131. jolt/plugins/alias.py +3 -0
  132. jolt/plugins/allure.py +5 -2
  133. jolt/plugins/autotools.py +66 -0
  134. jolt/plugins/cache.py +133 -0
  135. jolt/plugins/cmake.py +74 -6
  136. jolt/plugins/conan.py +238 -0
  137. jolt/plugins/cxx.py +698 -0
  138. jolt/plugins/cxxinfo.py +7 -0
  139. jolt/plugins/dashboard.py +1 -1
  140. jolt/plugins/docker.py +80 -23
  141. jolt/plugins/email.py +2 -2
  142. jolt/plugins/email.xslt +144 -101
  143. jolt/plugins/environ.py +11 -0
  144. jolt/plugins/fetch.py +141 -0
  145. jolt/plugins/gdb.py +39 -19
  146. jolt/plugins/gerrit.py +1 -14
  147. jolt/plugins/git.py +283 -85
  148. jolt/plugins/googletest.py +2 -1
  149. jolt/plugins/http.py +36 -38
  150. jolt/plugins/libtool.py +63 -0
  151. jolt/plugins/linux.py +990 -0
  152. jolt/plugins/logstash.py +4 -4
  153. jolt/plugins/meson.py +61 -0
  154. jolt/plugins/ninja-compdb.py +99 -30
  155. jolt/plugins/ninja.py +468 -166
  156. jolt/plugins/paths.py +11 -1
  157. jolt/plugins/pkgconfig.py +219 -0
  158. jolt/plugins/podman.py +136 -92
  159. jolt/plugins/python.py +137 -0
  160. jolt/plugins/remote_execution/__init__.py +0 -0
  161. jolt/plugins/remote_execution/administration_pb2.py +46 -0
  162. jolt/plugins/remote_execution/administration_pb2_grpc.py +170 -0
  163. jolt/plugins/remote_execution/log_pb2.py +32 -0
  164. jolt/plugins/remote_execution/log_pb2_grpc.py +68 -0
  165. jolt/plugins/remote_execution/scheduler_pb2.py +41 -0
  166. jolt/plugins/remote_execution/scheduler_pb2_grpc.py +141 -0
  167. jolt/plugins/remote_execution/worker_pb2.py +38 -0
  168. jolt/plugins/remote_execution/worker_pb2_grpc.py +112 -0
  169. jolt/plugins/report.py +12 -2
  170. jolt/plugins/rust.py +25 -0
  171. jolt/plugins/scheduler.py +710 -0
  172. jolt/plugins/selfdeploy/setup.py +8 -4
  173. jolt/plugins/selfdeploy.py +138 -88
  174. jolt/plugins/strings.py +35 -22
  175. jolt/plugins/symlinks.py +26 -11
  176. jolt/plugins/telemetry.py +5 -2
  177. jolt/plugins/timeline.py +13 -3
  178. jolt/plugins/volume.py +46 -48
  179. jolt/scheduler.py +589 -192
  180. jolt/tasks.py +625 -121
  181. jolt/templates/timeline.html.template +44 -47
  182. jolt/timer.py +22 -0
  183. jolt/tools.py +638 -282
  184. jolt/utils.py +211 -7
  185. jolt/version.py +1 -1
  186. jolt/xmldom.py +12 -2
  187. {jolt-0.9.123.dist-info → jolt-0.9.435.dist-info}/METADATA +97 -38
  188. jolt-0.9.435.dist-info/RECORD +207 -0
  189. {jolt-0.9.123.dist-info → jolt-0.9.435.dist-info}/WHEEL +1 -1
  190. jolt/plugins/amqp.py +0 -834
  191. jolt/plugins/debian.py +0 -338
  192. jolt/plugins/ftp.py +0 -181
  193. jolt/plugins/repo.py +0 -253
  194. jolt-0.9.123.dist-info/RECORD +0 -77
  195. {jolt-0.9.123.dist-info → jolt-0.9.435.dist-info}/entry_points.txt +0 -0
  196. {jolt-0.9.123.dist-info → jolt-0.9.435.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,66 @@
1
+ from jolt import Task, attributes
2
+
3
+
4
+ @attributes.common_metadata()
5
+ class Autotools(Task):
6
+ """ Base class for Autotools-based build tasks. """
7
+
8
+ abstract = True
9
+ """ This is an abstract base class that should be inherited by concrete tasks. """
10
+
11
+ incremental = True
12
+ """
13
+ Whether to use incremental builds.
14
+ If True, the build directories are preserved between runs.
15
+ """
16
+
17
+ options = []
18
+ """
19
+ Additional options to pass to the `./configure` script.
20
+ """
21
+
22
+ srcdir = None
23
+ """
24
+ Source directory for the Autotools project.
25
+
26
+ If None, defaults to the task work directory (joltdir).
27
+ """
28
+
29
+ def clean(self, tools):
30
+ at = tools.autotools(incremental=self.incremental)
31
+ at.clean()
32
+
33
+ def run(self, deps, tools):
34
+ self.deps = deps
35
+ options = tools.expand(self.options)
36
+ at = tools.autotools(deps, incremental=self.incremental)
37
+ at.configure(self.srcdir or self.joltdir, *options)
38
+ at.build()
39
+ at.install()
40
+
41
+ def publish(self, artifact, tools):
42
+ at = tools.autotools(incremental=self.incremental)
43
+ at.publish(artifact)
44
+
45
+
46
+ def requires(autoconf=True, automake=True, libtool=True):
47
+ """ Decorator to add Autotools requirements to a task. """
48
+
49
+ import jolt.pkgs.autoconf
50
+ import jolt.pkgs.automake
51
+ import jolt.pkgs.libtool
52
+
53
+ def decorate(cls):
54
+ if autoconf:
55
+ cls = attributes.requires("requires_autoconf")(cls)
56
+ cls.requires_autoconf = ["autoconf"]
57
+ if automake:
58
+ cls = attributes.requires("requires_automake")(cls)
59
+ cls.requires_automake = ["automake"]
60
+ if libtool:
61
+ cls = attributes.requires("requires_libtool")(cls)
62
+ cls.requires_libtool = ["libtool"]
63
+
64
+ return cls
65
+
66
+ return decorate
jolt/plugins/cache.py ADDED
@@ -0,0 +1,133 @@
1
+ from requests.exceptions import ConnectTimeout, RequestException
2
+ from urllib.parse import urlparse, urlunparse
3
+
4
+ from jolt import utils
5
+ from jolt import cache
6
+ from jolt import log
7
+ from jolt import config
8
+ from jolt import filesystem as fs
9
+ from jolt import tools
10
+ from jolt.error import raise_error_if, JoltError
11
+
12
+
13
+ NAME = "cache"
14
+ NAME_LOG = "Cache Service"
15
+ TIMEOUT = (3.5, 27)
16
+ TIMEOUT_HEAD = (27, 27)
17
+
18
+
19
+ class Cache(cache.StorageProvider):
20
+ def __init__(self, cache):
21
+ super().__init__()
22
+ self._cache = cache
23
+ self._uri = config.get(NAME, "uri", "http://cache")
24
+ self._uri = self._uri.rstrip("/")
25
+ raise_error_if(not self._uri, "Cache Service URI not configured")
26
+ self._file_uri = self._uri + "/files"
27
+ self._upload = config.getboolean(NAME, "upload", True)
28
+ self._download = config.getboolean(NAME, "download", True)
29
+ self._disabled = False
30
+
31
+ def _get_path(self, artifact):
32
+ return artifact.tools.expand(
33
+ "{name}/{file}",
34
+ name=artifact.task.name,
35
+ file=fs.path.basename(artifact.get_archive_path()))
36
+
37
+ def _get_url(self, artifact):
38
+ return artifact.tools.expand(
39
+ "{uri}/{name}/{file}",
40
+ uri=self._file_uri,
41
+ name=artifact.task.name,
42
+ file=fs.path.basename(artifact.get_archive_path()))
43
+
44
+ @utils.retried.on_exception((RequestException, JoltError))
45
+ def download(self, artifact, force=False):
46
+ if self._disabled:
47
+ return False
48
+ if not self._download and not force:
49
+ return False
50
+ url = self._get_url(artifact)
51
+ return artifact.tools.download(
52
+ url,
53
+ artifact.get_archive_path(),
54
+ exceptions=False,
55
+ timeout=TIMEOUT)
56
+
57
+ def download_enabled(self):
58
+ return not self._disabled and self._download
59
+
60
+ @utils.retried.on_exception((RequestException))
61
+ def upload(self, artifact, force=False):
62
+ if self._disabled:
63
+ return True
64
+ if not self._upload and not force:
65
+ return True
66
+ url = self._get_url(artifact)
67
+ archive = artifact.get_archive()
68
+ return artifact.tools.upload(
69
+ archive, url,
70
+ exceptions=False,
71
+ timeout=TIMEOUT)
72
+
73
+ def upload_enabled(self):
74
+ return not self._disabled and self._upload
75
+
76
+ @utils.retried.on_exception((RequestException))
77
+ def availability(self, artifacts):
78
+ if self._disabled:
79
+ return [], artifacts
80
+
81
+ file_map = {self._get_path(artifact): artifact for artifact in artifacts}
82
+ try:
83
+ data = {"files": list(file_map.keys())}
84
+ response = tools.http_session.post(self._file_uri, json=data, stream=True, timeout=TIMEOUT_HEAD)
85
+ except ConnectTimeout:
86
+ self._disabled = True
87
+ log.warning(NAME_LOG + " failed to establish server connection, disabled")
88
+ return [], []
89
+
90
+ if response.status_code != 200:
91
+ log.debug(NAME_LOG + " POST ({}): {}", response.status_code, self._file_uri)
92
+ return [], artifacts
93
+
94
+ present = []
95
+ missing = []
96
+ data = response.json()
97
+
98
+ for file in data.get("present", []):
99
+ present.append(file_map[file])
100
+
101
+ for file in data.get("missing", []):
102
+ missing.append(file_map[file])
103
+
104
+ return present, missing
105
+
106
+ @utils.retried.on_exception((RequestException))
107
+ def location(self, artifact):
108
+ if self._disabled:
109
+ return False
110
+
111
+ url = self._get_url(artifact)
112
+ try:
113
+ response = tools.http_session.head(url, stream=True, timeout=TIMEOUT_HEAD)
114
+
115
+ except ConnectTimeout:
116
+ self._disabled = True
117
+ log.warning(NAME_LOG + " failed to establish server connection, disabled")
118
+ return False
119
+
120
+ if response.status_code != 200:
121
+ log.debug(NAME_LOG + " HEAD ({}): {}", response.status_code, url)
122
+ return None
123
+
124
+ url = urlunparse(urlparse(url))
125
+ return url
126
+
127
+
128
+ @cache.RegisterStorage
129
+ class HttpFactory(cache.StorageProviderFactory):
130
+ @staticmethod
131
+ def create(cache):
132
+ log.verbose(NAME_LOG + " Loaded")
133
+ return Cache(cache)
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)))