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
jolt/plugins/cxx.py ADDED
@@ -0,0 +1,698 @@
1
+ from jolt import MultiTask, attributes
2
+ from jolt import utils
3
+ from jolt.error import raise_task_error, raise_task_error_if
4
+ from jolt.influence import FileInfluence
5
+ from jolt.plugins import ninja
6
+
7
+ from copy import copy
8
+ import os
9
+
10
+
11
+ class GnuToolchain(object):
12
+ gnu_ar = "ar"
13
+ gnu_as = "as"
14
+ gnu_cc = "gcc"
15
+ gnu_cxx = "g++"
16
+ gnu_ld = "g++"
17
+
18
+ def _gnu_tool(self, env, default):
19
+ cmd = self.tools.getenv(env, default).split()
20
+ tool = self.tools.which(cmd[0])
21
+ raise_task_error_if(not tool, self, f"Tool '{default}' not found in PATH")
22
+ cmd[0] = tool
23
+ return " ".join(cmd)
24
+
25
+ gnu_archive_cmd = "{gnu_ar} -M <{inputs}"
26
+ gnu_compile_asm_cmd = "{gnu_cc} -x assembler -MMD -MF {outputs}.d {asflags} -c {inputs} -o {outputs}"
27
+ gnu_compile_asm_cpp_cmd = "{gnu_cc} -x assembler-with-cpp -MMD -MF {outputs}.d {% if shared %}-fPIC {% endif %}{asflags_imported} {asflags_environ} {asflags} {{(macros_imported+macros)|prefix('-D')|join(' ')}} {{(incpaths+incpaths_imported)|prefix('-I')|join(' ')}} -c {inputs} -o {outputs}"
28
+ gnu_compile_c_cmd = "{gnu_cc} -x c -MMD -MF {outputs}.d {% if shared %}-fPIC {% endif %}{cflags_imported} {cflags_environ} {cflags} {{(macros_imported+macros)|prefix('-D')|join(' ')}} {{(incpaths+incpaths_imported)|prefix('-I')|join(' ')}} -c {inputs} -o {outputs}"
29
+ gnu_compile_cxx_cmd = "{gnu_cxx} -x c++ -MMD -MF {outputs}.d {% if shared %}-fPIC {% endif %}{cxxflags_imported} {cxxflags_environ} {cxxflags} {{(macros_imported+macros)|prefix('-D')|join(' ')}} {{(incpaths+incpaths_imported)|prefix('-I')|join(' ')}} -c {inputs} -o {outputs}"
30
+ gnu_compile_pch_cmd = "{gnu_cxx} -x c++-header -MMD -MF {outputs}.d {% if shared %}-fPIC {% endif %}{cxxflags_imported} {cxxflags_environ} {cxxflags} {{(macros_imported+macros)|prefix('-D')|join(' ')}} {{(incpaths+incpaths_imported)|prefix('-I')|join(' ')}} -c {inputs} -o {outputs}"
31
+ gnu_link_cmd = "{gnu_ld} {% if shared %}-shared {% endif %}{ldflags_imported} {ldflags_environ} {ldflags} -Wl,--start-group @{inputs} -Wl,--end-group {{(libpaths+libpaths_imported)|prefix('-L')|join(' ')}} -o {outputs} -Wl,--start-group {{(libraries+libraries_imported)|prefix('-l')|join(' ')}} -Wl,--end-group"
32
+
33
+ def gnu_archive(self, binary, objects, **kwargs):
34
+ command = kwargs.pop("command", self.gnu_archive_cmd)
35
+
36
+ kwargs["gnu_ar"] = self._gnu_tool("AR", self.gnu_ar)
37
+
38
+ outputs = ["{outdir_rel}/lib{binary}.a"]
39
+ objlist = self.gnu_mrilist(objects, outputs[0], "{outdir_rel}/objects.mri")
40
+ command = self.tools.render(command, inputs=objlist, outputs=outputs, **kwargs)
41
+
42
+ binary = self.command(
43
+ command,
44
+ inputs=objlist,
45
+ outputs=outputs,
46
+ message="{binary}",
47
+ **kwargs)
48
+ binary.add_dependency(objects)
49
+ return binary
50
+
51
+ def gnu_compile_generic(self, cmd, sources=[], **kwargs):
52
+ objects = []
53
+
54
+ for srcfile in utils.as_list(sources):
55
+ srcfile = self.tools.expand_relpath(srcfile, self.joltdir)
56
+ objfile = self.tools.expand_relpath(os.path.join(self.outdir, srcfile + ".o"), self.joltdir)
57
+ cmd = self.tools.render(cmd, inputs=srcfile, outputs=objfile, **kwargs)
58
+ obj = self.command(
59
+ cmd,
60
+ srcfile, objfile,
61
+ message="{inputs}",
62
+ **kwargs)
63
+ obj.add_influence_depfile(objfile + ".d")
64
+ if hasattr(self, "_pch_objects"):
65
+ obj.add_dependency(self._pch_objects)
66
+ objects.append(obj)
67
+
68
+ return objects
69
+
70
+ def gnu_compile_asm(self, sources, **kwargs):
71
+ kwargs["gnu_as"] = self._gnu_tool("AS", self.gnu_as)
72
+
73
+ kwargs["asflags"] = kwargs.pop("asflags", self._asflags())
74
+ kwargs["asflags_environ"] = kwargs.pop("asflags_environ", self.tools.getenv("ASFLAGS"))
75
+ kwargs["asflags_imported"] = kwargs.pop("asflags_imported", self._import_listattr("asflags"))
76
+ return self.gnu_compile_generic(self.gnu_compile_asm_cmd, sources, **kwargs)
77
+
78
+ def gnu_compile_asm_cpp(self, sources, **kwargs):
79
+ kwargs["gnu_as"] = self._gnu_tool("AS", self.gnu_as)
80
+
81
+ kwargs["asflags"] = kwargs.pop("asflags", self._asflags())
82
+ kwargs["asflags_environ"] = kwargs.pop("asflags_environ", self.tools.getenv("ASFLAGS"))
83
+ kwargs["asflags_imported"] = kwargs.pop("asflags_imported", self._import_listattr("asflags"))
84
+ kwargs["incpaths"] = ["{outdir_rel}"] + kwargs.pop("incpaths", self._task_incpaths())
85
+ kwargs["incpaths_imported"] = kwargs.pop("incpaths_imported", self._imported_incpaths())
86
+ kwargs["macros"] = kwargs.pop("macros", self._macros())
87
+ kwargs["macros_imported"] = kwargs.pop("macros_imported", self._import_listattr("macros"))
88
+ return self.gnu_compile_generic(self.gnu_compile_asm_cpp_cmd, sources, **kwargs)
89
+
90
+ def gnu_compile_c(self, sources, **kwargs):
91
+ kwargs["gnu_cc"] = self._gnu_tool("CC", self.gnu_cc)
92
+
93
+ kwargs["cflags"] = kwargs.pop("cflags", self._cflags())
94
+ kwargs["cflags_environ"] = kwargs.pop("cflags_environ", self.tools.getenv("CFLAGS"))
95
+ kwargs["cflags_imported"] = kwargs.pop("cflags_imported", self._import_listattr("cflags"))
96
+ kwargs["incpaths"] = ["{outdir_rel}"] + kwargs.pop("incpaths", self._task_incpaths())
97
+ kwargs["incpaths_imported"] = kwargs.pop("incpaths_imported", self._imported_incpaths())
98
+ kwargs["macros"] = kwargs.pop("macros", self._macros())
99
+ kwargs["macros_imported"] = kwargs.pop("macros_imported", self._import_listattr("macros"))
100
+ return self.gnu_compile_generic(self.gnu_compile_c_cmd, sources, **kwargs)
101
+
102
+ def gnu_compile_cxx(self, sources, **kwargs):
103
+ kwargs["gnu_cxx"] = self._gnu_tool("CXX", self.gnu_cxx)
104
+
105
+ kwargs["cxxflags"] = kwargs.pop("cxxflags", self._cxxflags())
106
+ kwargs["cxxflags_environ"] = kwargs.pop("cxxflags_environ", self.tools.getenv("CXXFLAGS"))
107
+ kwargs["cxxflags_imported"] = kwargs.pop("cxxflags_imported", self._import_listattr("cxxflags"))
108
+ kwargs["incpaths"] = ["{outdir_rel}"] + kwargs.pop("incpaths", self._task_incpaths())
109
+ kwargs["incpaths_imported"] = kwargs.pop("incpaths_imported", self._imported_incpaths())
110
+ kwargs["macros"] = kwargs.pop("macros", self._macros())
111
+ kwargs["macros_imported"] = kwargs.pop("macros_imported", self._import_listattr("macros"))
112
+
113
+ return self.gnu_compile_generic(self.gnu_compile_cxx_cmd, sources, **kwargs)
114
+
115
+ def gnu_compile_h(self, sources, **kwargs):
116
+ return []
117
+
118
+ def gnu_compile_pch(self, sources, **kwargs):
119
+ raise_task_error_if(hasattr(self, "_pch_objects"), self, "Multiple precompiled headers found, only one allowed")
120
+
121
+ kwargs["gnu_cxx"] = self._gnu_tool("CXX", self.gnu_cxx)
122
+ kwargs["cxxflags"] = kwargs.pop("cxxflags", self._cxxflags())
123
+ kwargs["cxxflags_environ"] = kwargs.pop("cxxflags_environ", self.tools.getenv("CXXFLAGS"))
124
+ kwargs["cxxflags_imported"] = kwargs.pop("cxxflags_imported", self._import_listattr("cxxflags"))
125
+ kwargs["incpaths"] = ["{outdir_rel}"] + kwargs.pop("incpaths", self._task_incpaths())
126
+ kwargs["incpaths_imported"] = kwargs.pop("incpaths_imported", self._imported_incpaths())
127
+ kwargs["macros"] = kwargs.pop("macros", self._macros())
128
+ kwargs["macros_imported"] = kwargs.pop("macros_imported", self._import_listattr("macros"))
129
+
130
+ sources = self._to_subtask_list(sources)
131
+ objects = []
132
+
133
+ for srcsubtask in sources:
134
+ for srcfile in srcsubtask.outputs:
135
+ srcfile = os.path.relpath(srcfile, self.joltdir)
136
+ objfile = os.path.basename(srcfile)
137
+ objfile = os.path.relpath(os.path.join(self.outdir, objfile + ".gch"), self.joltdir)
138
+ cmd = self.tools.render(self.gnu_compile_pch_cmd, inputs=srcfile, outputs=objfile, **kwargs)
139
+ obj = self.command(
140
+ cmd,
141
+ srcfile, objfile,
142
+ message="{inputs}",
143
+ **kwargs)
144
+ obj.add_influence_depfile(objfile + ".d")
145
+ objects.append(obj)
146
+
147
+ self._pch_objects = objects
148
+
149
+ return objects
150
+
151
+ def gnu_link(self, binary, objects, **kwargs):
152
+ command = kwargs.pop("command", self.gnu_link_cmd)
153
+
154
+ kwargs["gnu_ld"] = self._gnu_tool("CXX", self.gnu_ld)
155
+
156
+ kwargs["ldflags"] = kwargs.pop("ldflags", self._ldflags())
157
+ kwargs["ldflags_environ"] = kwargs.pop("ldflags_environ", self.tools.getenv("LDFLAGS"))
158
+ kwargs["ldflags_imported"] = kwargs.pop("ldflags_imported", self._import_listattr("ldflags"))
159
+
160
+ kwargs["libpaths"] = kwargs.pop("libpaths", self._libpaths())
161
+ kwargs["libpaths_imported"] = kwargs.pop("libpaths_imported", self._import_pathlistattr("libpaths"))
162
+
163
+ kwargs["libraries"] = kwargs.pop("libraries", self._libraries())
164
+ kwargs["libraries_imported"] = kwargs.pop("libraries_imported", self._import_listattr("libraries"))
165
+
166
+ objlist = self.filelist(objects, "{outdir}/objects.list")
167
+ if getattr(self, "shared", False):
168
+ outputs = ["{outdir_rel}/lib{binary}.so"]
169
+ else:
170
+ outputs = ["{outdir_rel}/{binary}"]
171
+ command = self.tools.render(command, inputs=objlist, outputs=outputs, **kwargs)
172
+
173
+ binary = self.command(
174
+ command,
175
+ inputs=objlist,
176
+ outputs=outputs,
177
+ message="{binary}",
178
+ **kwargs)
179
+ binary.add_dependency(objects)
180
+ return binary
181
+
182
+ def gnu_mrilist(self, inputs, target, outputs):
183
+ inputs = self._to_subtask_list(inputs)
184
+ inputs = self._to_output_files(inputs)
185
+ target = self.tools.expand(target)
186
+ mrilist = self.render(
187
+ "create {{target}}\n{% for input in inputs %}{% if input[-2:] == '.a' %}addlib {{input}}\n{% else %}addmod {{ input }}\n{% endif %}{% endfor %}save\nend\n",
188
+ outputs, target=target, inputs=inputs)
189
+
190
+ return mrilist
191
+
192
+ def gnu_import_libraries(self, deps):
193
+ archives = []
194
+ for name, artifact in deps.items():
195
+ for lib in artifact.cxxinfo.libraries.items():
196
+ name = f"lib{lib}.a"
197
+ for path in artifact.cxxinfo.libpaths.items():
198
+ archive = os.path.join(artifact.path, path, name)
199
+ if os.path.exists(archive):
200
+ sandbox = self.tools.sandbox(artifact, self.incremental)
201
+ archive = os.path.join(sandbox, path, name)
202
+ archives.append(archive)
203
+ return archives
204
+
205
+
206
+ def flatbuffer():
207
+ def decorate(cls):
208
+ class WithFlatbufferCompilation(cls):
209
+ abstract = True
210
+
211
+ flatc = "flatc"
212
+ flatbuffer_cmd = "{{flatc}} --{{generator}} {fbflags} {{incpaths|prefix('-I ')|join(' ')}} -o {{outdir}} {inputs} && {{flatc}} -M --{{generator}} {fbflags} {{incpaths|prefix('-I ')|join(' ')}} -o {{outdir}} {inputs} > {depfile}"
213
+ fbflags = []
214
+
215
+ def run(self, deps, tools):
216
+ super().run(deps, tools)
217
+
218
+ def compile_flatbuffer(self, inputs, **kwargs):
219
+ kwargs["flatc"] = self._gnu_tool("FLATC", self.flatc)
220
+
221
+ jobs = []
222
+
223
+ for input in inputs:
224
+ context = self.context(input, **kwargs)
225
+ context["generator"] = kwargs.pop("generator", "cpp")
226
+
227
+ command = self.tools.render(self.flatbuffer_cmd, **context)
228
+ depfile = self.tools.expand("{outdir}/{input}.d", input=input, **context)
229
+ outputs = []
230
+
231
+ depfiledir = self.mkdirname(depfile)
232
+
233
+ flatbuffer_job = self.command(
234
+ command,
235
+ inputs=input,
236
+ outputs=self.tools.expand(outputs, **context),
237
+ message="{inputs} [{generator}]",
238
+ depfile=depfile,
239
+ **context)
240
+
241
+ flatbuffer_job.add_dependency(depfiledir)
242
+ flatbuffer_job.add_influence_depfile(depfile)
243
+ jobs.append(flatbuffer_job)
244
+
245
+ return jobs
246
+
247
+ def compile(self, sources, **kwargs):
248
+ flatbuffers, sources = self.filter_by_ext(sources, ".fbs")
249
+ if not flatbuffers:
250
+ return super().compile(sources, **kwargs)
251
+
252
+ flatbuffer_job = self.compile_flatbuffer(flatbuffers, **kwargs)
253
+ flatbuffer_sources = self._to_output_files(flatbuffer_job)
254
+ flatbuffer_outputs = self.compile(flatbuffer_sources, **kwargs)
255
+
256
+ outputs = self.compile(sources, **kwargs)
257
+ for output in outputs:
258
+ output.add_dependency(flatbuffer_outputs)
259
+
260
+ return outputs + flatbuffer_outputs
261
+
262
+ return WithFlatbufferCompilation
263
+
264
+ return decorate
265
+
266
+
267
+ def protobuf():
268
+ def decorate(cls):
269
+ class WithProtobufCompilation(cls):
270
+ abstract = True
271
+
272
+ protoc = "protoc"
273
+ proto_cmd = "{protoc} {{(incpaths_imported+incpaths)|prefix('-I')|join(' ')}} {protoflags} --dependency_out={depfile} --{generator}_out={outdir_rel}{% if generator_plugin %} --plugin=protoc-gen-{generator}={generator_plugin}{% endif %} {inputs}"
274
+ protoflags = []
275
+ protogenerator = "cpp"
276
+
277
+ def run(self, deps, tools):
278
+ self.protoc = self._gnu_tool("PROTOC", self.protoc)
279
+ super().run(deps, tools)
280
+
281
+ def context(self, input=None, **kwargs):
282
+ kwargs = copy(kwargs)
283
+
284
+ kwargs["asflags"] = kwargs.pop("cflags", self._cflags())
285
+ kwargs["asflags_imported"] = kwargs.pop("asflags_imported", self._import_listattr("asflags"))
286
+
287
+ kwargs["cflags"] = kwargs.pop("cflags", self._cflags())
288
+ kwargs["cflags_imported"] = kwargs.pop("cflags_imported", self._import_listattr("cflags"))
289
+
290
+ kwargs["cxxflags"] = kwargs.pop("cxxflags", self._cxxflags())
291
+ kwargs["cxxflags_imported"] = kwargs.pop("cxxflags_imported", self._import_listattr("cxxflags"))
292
+
293
+ kwargs["incpaths"] = ["{outdir_rel}"] + kwargs.pop("incpaths", self._task_incpaths())
294
+ kwargs["incpaths_imported"] = kwargs.pop("incpaths_imported", self._imported_incpaths())
295
+
296
+ if hasattr(self, "_ldflags"):
297
+ kwargs["ldflags"] = kwargs.pop("ldflags", self._ldflags())
298
+ kwargs["ldflags_imported"] = kwargs.pop("ldflags_imported", self._import_listattr("ldflags"))
299
+
300
+ if hasattr(self, "_libpaths"):
301
+ kwargs["libpaths"] = kwargs.pop("libpaths", self._libpaths())
302
+ kwargs["libpaths_imported"] = kwargs.pop("libpaths_imported", self._import_pathlistattr("libpaths"))
303
+
304
+ if hasattr(self, "_libraries"):
305
+ kwargs["libraries"] = kwargs.pop("libraries", self._libraries())
306
+ kwargs["libraries_imported"] = kwargs.pop("libraries_imported", self._import_listattr("libraries"))
307
+
308
+ kwargs["macros"] = kwargs.pop("macros", self._macros())
309
+ kwargs["macros_imported"] = kwargs.pop("macros_imported", self._import_listattr("macros"))
310
+
311
+ if input:
312
+ kwargs["in_path"] = os.path.dirname(input) or "."
313
+ kwargs["in_base"], kwargs["in_ext"] = os.path.splitext(os.path.basename(input))
314
+
315
+ return kwargs
316
+
317
+ def compile_proto_cpp(self, inputs, **kwargs):
318
+ depfile = "{outdir_rel}/{in_base}.pb.d"
319
+ outputs = [
320
+ "{outdir_rel}/{in_base}.pb.h",
321
+ "{outdir_rel}/{in_base}.pb.cc",
322
+ ]
323
+ kwargs["depfile"] = kwargs.pop("depfile", depfile)
324
+ kwargs["generator"] = kwargs.pop("generator", "cpp")
325
+ kwargs["outputs"] = kwargs.pop("outputs", outputs)
326
+
327
+ return self._compile_proto(inputs, **kwargs)
328
+
329
+ def compile_proto_cpp_grpc(self, inputs, **kwargs):
330
+ return self.compile_proto_cpp(inputs, **kwargs) + \
331
+ self.compile_proto_grpc(inputs, generator_plugin="grpc_cpp_plugin", **kwargs)
332
+
333
+ def compile_proto_grpc(self, inputs, **kwargs):
334
+ depfile = "{outdir_rel}/{in_base}.grpc.pb.d"
335
+ outputs = [
336
+ "{outdir_rel}/{in_base}.grpc.pb.h",
337
+ "{outdir_rel}/{in_base}.grpc.pb.cc",
338
+ ]
339
+ kwargs["depfile"] = kwargs.pop("depfile", depfile)
340
+ kwargs["generator"] = kwargs.pop("generator", "grpc")
341
+ kwargs["generator_plugin"] = self.tools.which(kwargs.pop("generator_plugin", "grpc_cpp_plugin"))
342
+ kwargs["outputs"] = kwargs.pop("outputs", outputs)
343
+ return self._compile_proto(inputs, **kwargs)
344
+
345
+ def compile_proto_python(self, inputs, **kwargs):
346
+ depfile = "{outdir_rel}/{in_base}_pb2.py.d"
347
+ outputs = [
348
+ "{outdir_rel}/{in_base}_pb2.py",
349
+ ]
350
+ kwargs["command"] = kwargs.pop("command", self.proto_cmd)
351
+ kwargs["depfile"] = kwargs.pop("depfile", depfile)
352
+ kwargs["generator"] = kwargs.pop("generator", "python")
353
+ kwargs["outputs"] = kwargs.pop("outputs", outputs)
354
+ return self._compile_proto(inputs, **kwargs)
355
+
356
+ def compile_proto_python_grpc(self, inputs, **kwargs):
357
+ depfile = "{outdir_rel}/{in_base}_pb2_grpc.py.d"
358
+ outputs = [
359
+ "{outdir_rel}/{in_base}_pb2_grpc.py",
360
+ ]
361
+ kwargs["protoc"] = kwargs.pop("protoc", "python -m grpc_tools.protoc")
362
+ kwargs["command"] = kwargs.pop("command", self.proto_cmd)
363
+ kwargs["depfile"] = kwargs.pop("depfile", depfile)
364
+ kwargs["generator"] = kwargs.pop("generator", "grpc_python")
365
+ kwargs["outputs"] = kwargs.pop("outputs", outputs)
366
+ return self._compile_proto(inputs, **kwargs)
367
+
368
+ def _compile_proto(self, inputs, **kwargs):
369
+ jobs = []
370
+
371
+ for input in inputs:
372
+ context = self.context(input, **kwargs)
373
+
374
+ command = self.tools.render(context.pop("command", self.proto_cmd), **context)
375
+ depfile = context.pop("depfile")
376
+ depfile = self.tools.expand(depfile, **context)
377
+ outputs = context.pop("outputs")
378
+
379
+ proto_job = self.command(
380
+ command,
381
+ inputs=input,
382
+ outputs=self.tools.expand(outputs, **context),
383
+ message="{inputs} [{generator}]",
384
+ depfile=depfile,
385
+ **context)
386
+
387
+ proto_job.add_influence_depfile(depfile)
388
+ jobs.append(proto_job)
389
+
390
+ return jobs
391
+
392
+ def compile(self, sources, **kwargs):
393
+ protobufs, sources = self.filter_by_ext(sources, ".proto")
394
+ if not protobufs:
395
+ return super().compile(sources, **kwargs)
396
+
397
+ proto_sources = []
398
+ generators = utils.as_list(kwargs.get("protogenerator", getattr(self, "protogenerator", [])))
399
+ for generator in generators:
400
+ proto_fn = getattr(self, "compile_proto_" + generator, None)
401
+ raise_task_error_if(not proto_fn, self, "Protobuf generator '{}' is not supported", generator)
402
+ proto_job = proto_fn(protobufs, **kwargs)
403
+ proto_sources += self._to_output_files(proto_job)
404
+ proto_outputs = self.compile(proto_sources, **kwargs)
405
+
406
+ outputs = self.compile(sources, **kwargs)
407
+ for output in outputs:
408
+ output.add_dependency(proto_job)
409
+
410
+ return outputs + proto_outputs
411
+
412
+ WithProtobufCompilation.__doc__ = cls.__doc__
413
+ WithProtobufCompilation.__name__ = cls.__name__
414
+ return WithProtobufCompilation
415
+
416
+ return decorate
417
+
418
+
419
+ @attributes.method("archive", "{toolchain}_archive")
420
+ @attributes.method("compile_asm", "{toolchain}_compile_asm")
421
+ @attributes.method("compile_asm_cpp", "{toolchain}_compile_asm_cpp")
422
+ @attributes.method("compile_c", "{toolchain}_compile_c")
423
+ @attributes.method("compile_cxx", "{toolchain}_compile_cxx")
424
+ @attributes.method("compile_h", "{toolchain}_compile_h")
425
+ @attributes.method("compile_pch", "{toolchain}_compile_pch")
426
+ @attributes.method("import_libraries", "{toolchain}_import_libraries")
427
+ @attributes.method("link", "{toolchain}_link")
428
+ @ninja.attributes.asflags("asflags")
429
+ @ninja.attributes.cflags("cflags")
430
+ @ninja.attributes.cxxflags("cxxflags")
431
+ @ninja.attributes.incpaths("incpaths")
432
+ @ninja.attributes.ldflags("ldflags")
433
+ @ninja.attributes.libpaths("libpaths")
434
+ @ninja.attributes.libraries("libraries")
435
+ @ninja.attributes.macros("macros")
436
+ @ninja.attributes.sources("sources")
437
+ @flatbuffer()
438
+ @protobuf()
439
+ class Compilation(GnuToolchain, MultiTask):
440
+ abstract = True
441
+
442
+ binary = "{canonical_name}"
443
+
444
+ incremental = True
445
+
446
+ source_influence = True
447
+ """ Let the contents of source files influence the identity of the task artifact.
448
+
449
+ When ``True``, a source file listed in the ``sources`` attribute will
450
+ cause a rebuild of the task if modified.
451
+
452
+ Source influence can hurt performance since every files needs to be hashed.
453
+ It is safe to set this flag to ``False`` if all source files reside in a
454
+ ``git`` repository listed as a dependency with the ``requires`` attribute or
455
+ if the task uses the ``git.influence`` decorator.
456
+
457
+ Always use ``source_influence`` if you are unsure whether it is needed or not.
458
+ """
459
+
460
+ toolchain = "gnu"
461
+
462
+ def __init__(self, *args, **kwargs):
463
+ super().__init__(*args, **kwargs)
464
+ self.binary = self.expand(utils.call_or_return(self, self.__class__.binary))
465
+ if self.source_influence:
466
+ for source in self._sources():
467
+ self.influence.append(FileInfluence(source))
468
+
469
+ def _import_listattr(self, attribute):
470
+ result = []
471
+ for _, artifact in self.deps.items():
472
+ result.extend(list(getattr(artifact.cxxinfo, attribute, []).items()))
473
+ return result
474
+
475
+ def _import_pathlistattr(self, attribute):
476
+ result = []
477
+ for _, artifact in self.deps.items():
478
+ result.extend([os.path.join(artifact.path, path) for path in list(getattr(artifact.cxxinfo, attribute, []).items())])
479
+ return result
480
+
481
+ @utils.cached.instance
482
+ def _task_incpaths(self):
483
+ result = []
484
+
485
+ for path in self._incpaths():
486
+ if path[0] in ['=', os.sep]:
487
+ path = self.tools.expand(path)
488
+ if path[0] in ['-']:
489
+ path = self.tools.expand_relpath(path[1:], self.joltdir)
490
+ result.append(path)
491
+
492
+ return result
493
+
494
+ @utils.cached.instance
495
+ def _imported_incpaths(self):
496
+ self.depsdir = self.tools.builddir("deps", incremental=self.incremental)
497
+
498
+ result = []
499
+ for _, artifact in self.deps.items():
500
+ symlink = os.path.join(self.depsdir, utils.canonical(artifact.task.short_qualified_name), artifact.name)
501
+ self.tools.symlink(artifact.path, symlink, replace=True)
502
+
503
+ for path in list(getattr(artifact.cxxinfo, "incpaths", []).items()):
504
+ if path[0] in ['=', os.sep]:
505
+ path = self.tools.expand(path)
506
+ result.append(path)
507
+ elif path[0] in ['-']:
508
+ path = self.tools.expand_relpath(path[1:], self.joltdir)
509
+ result.append(path)
510
+ else:
511
+ path = os.path.join(symlink, path)
512
+ path = os.path.relpath(path, self.joltdir)
513
+ result.append(path)
514
+ return result
515
+
516
+ def filelist(self, inputs, outputs):
517
+ inputs = self._to_subtask_list(inputs)
518
+ inputs = self._to_output_files(inputs)
519
+ objlist = self.render(
520
+ "{% for input in inputs %}{{ input }}\n{% endfor %}",
521
+ outputs, inputs=inputs)
522
+
523
+ return objlist
524
+
525
+ def filter_by_ext(self, inputs, exts):
526
+ exts = utils.as_list(exts)
527
+ inputs = self._to_subtask_list(inputs)
528
+ inputs = self._to_output_files(inputs)
529
+
530
+ matches = []
531
+ mismatches = []
532
+ for input in inputs:
533
+ _, ext = os.path.splitext(input)
534
+ if ext in exts:
535
+ matches.append(input)
536
+ else:
537
+ mismatches.append(input)
538
+
539
+ return matches, mismatches
540
+
541
+ def glob(self, paths):
542
+ result = []
543
+ for path in paths:
544
+ found = self.tools.glob(path)
545
+ raise_task_error_if(
546
+ not found and not ('*' in path or '?' in path), self,
547
+ "Listed source file '{0}' not found in workspace", os.path.basename(path))
548
+ result += found
549
+ return result
550
+
551
+ def glob_headers(self):
552
+ return self.glob(self._headers())
553
+
554
+ def glob_sources(self, deps=None):
555
+ sources_imported = self._import_pathlistattr("sources") if deps else []
556
+ return self.glob(self._sources() + sources_imported)
557
+
558
+ def compile(self, sources):
559
+ outputs = []
560
+ newsources = []
561
+
562
+ for source in utils.as_list(sources):
563
+ _, ext = os.path.splitext(source)
564
+ if ext in [".pch"]:
565
+ self.compile_pch(source)
566
+ else:
567
+ pass
568
+
569
+ sources += newsources
570
+
571
+ for source in utils.as_list(sources):
572
+ _, ext = os.path.splitext(source)
573
+ if ext in [".a"]:
574
+ outputs.extend(self.compile_lib(source))
575
+ elif ext in [".c"]:
576
+ outputs.extend(self.compile_c(source))
577
+ elif ext in [".cc", ".cpp", ".cxx"]:
578
+ outputs.extend(self.compile_cxx(source))
579
+ elif ext in [".h"]:
580
+ outputs.extend(self.compile_h(source))
581
+ elif ext in [".pch"]:
582
+ pass
583
+ elif ext in [".py"]:
584
+ pass
585
+ elif ext in [".s"]:
586
+ outputs.extend(self.compile_asm(source))
587
+ elif ext in [".S"]:
588
+ outputs.extend(self.compile_asm_cpp(source))
589
+ else:
590
+ raise_task_error(self, "Unknown file extension: {}", source)
591
+
592
+ return outputs
593
+
594
+ def compile_lib(self, sources):
595
+ return self._to_subtask_list(sources)
596
+
597
+ def generate(self, deps, tools):
598
+ self.deps = deps
599
+ self.outdir = self.tools.builddir("outputs", incremental=True)
600
+ self.outdir_rel = self.tools.expand_relpath(self.outdir, self.joltdir)
601
+
602
+ sources = self.glob_sources(deps)
603
+ return self.compile(sources)
604
+
605
+
606
+ @ninja.attributes.headers("headers")
607
+ class Library(Compilation):
608
+ abstract = True
609
+
610
+ headers = []
611
+
612
+ publishapi = "include/"
613
+ """ The artifact path where the library is published. """
614
+
615
+ publishdir = "lib/"
616
+ """ The artifact path where the library is published. """
617
+
618
+ shared = False
619
+
620
+ def __init__(self, *args, **kwargs):
621
+ super().__init__(*args, **kwargs)
622
+ if self.source_influence:
623
+ for header in self._headers():
624
+ self.influence.append(FileInfluence(header))
625
+
626
+ def generate(self, deps, tools):
627
+ self.deps = deps
628
+ self.outdir = self.tools.builddir("outputs", incremental=True)
629
+ self.outdir_rel = self.tools.expand_relpath(self.outdir, self.joltdir)
630
+
631
+ sources = self.glob_sources(deps)
632
+ if self.selfsustained:
633
+ sources += self.import_libraries(deps)
634
+ objects = self.compile(sources)
635
+ if self.shared:
636
+ binary = self.link(self.binary, objects)
637
+ else:
638
+ binary = self.archive(self.binary, objects)
639
+ return binary
640
+
641
+ def publish(self, artifact, tools):
642
+ for header in self._headers():
643
+ artifact.collect(header, self.publishapi)
644
+
645
+ with tools.cwd(self.outdir):
646
+ if not self.shared:
647
+ if artifact.collect("lib{binary}.a", self.publishdir):
648
+ artifact.cxxinfo.libpaths.append(self.publishdir)
649
+ artifact.cxxinfo.libraries.append("{binary}")
650
+ else:
651
+ if artifact.collect("lib{binary}.so", self.publishdir):
652
+ artifact.cxxinfo.libpaths.append(self.publishdir)
653
+ artifact.cxxinfo.libraries.append("{binary}")
654
+ artifact.collect("{binary}.dll", self.publishdir)
655
+ if artifact.collect("{binary}.lib", self.publishdir):
656
+ artifact.cxxinfo.libpaths.append(self.publishdir)
657
+ artifact.cxxinfo.libraries.append("{binary}")
658
+
659
+
660
+ class Executable(Compilation):
661
+ abstract = True
662
+
663
+ publishdir = "bin/"
664
+ """ The artifact path where the binary is published. """
665
+
666
+ strip = True
667
+ """
668
+ Remove debug information from binary.
669
+
670
+ When using the GNU toolchain, debug information is kept in a separate binary
671
+ which is either published or not depending on the value of this attribute.
672
+ It's found in a .debug directory if present.
673
+
674
+ Only applicable to shared libraries.
675
+ """
676
+
677
+ def generate(self, deps, tools):
678
+ self.deps = deps
679
+ self.outdir = self.tools.builddir("outputs", incremental=True)
680
+ self.outdir_rel = self.tools.expand_relpath(self.outdir, self.joltdir)
681
+
682
+ sources = self.glob_sources(deps)
683
+ objects = self.compile(sources)
684
+ binary = self.link(self.binary, objects)
685
+ return binary
686
+
687
+ def publish(self, artifact, tools):
688
+ with tools.cwd(self.outdir):
689
+ if os.name == "nt":
690
+ binary = artifact.collect(self.binary + '.exe', self.publishdir)
691
+ else:
692
+ binary = artifact.collect(self.binary, self.publishdir)
693
+ if not self.strip:
694
+ artifact.collect(".debug", self.publishdir)
695
+ if binary:
696
+ artifact.environ.PATH.append(self.publishdir)
697
+ artifact.strings.executable = os.path.join(
698
+ self.publishdir, self.binary)