jolt 0.9.419__py3-none-any.whl → 0.9.430__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/cache.py +19 -0
- jolt/cli.py +3 -2
- jolt/filesystem.py +2 -2
- jolt/log.py +12 -2
- jolt/pkgs/abseil.py +42 -0
- jolt/pkgs/asio.py +25 -0
- jolt/pkgs/autoconf.py +41 -0
- jolt/pkgs/automake.py +41 -0
- jolt/pkgs/b2.py +31 -0
- jolt/pkgs/boost.py +111 -0
- jolt/pkgs/boringssl.py +32 -0
- jolt/pkgs/busybox.py +39 -0
- jolt/pkgs/bzip2.py +43 -0
- jolt/pkgs/cares.py +29 -0
- jolt/pkgs/catch2.py +36 -0
- jolt/pkgs/cbindgen.py +17 -0
- jolt/pkgs/cista.py +19 -0
- jolt/pkgs/clang.py +44 -0
- jolt/pkgs/cli11.py +23 -0
- jolt/pkgs/cmake.py +48 -0
- jolt/pkgs/cpython.py +196 -0
- jolt/pkgs/crun.py +29 -0
- jolt/pkgs/curl.py +38 -0
- jolt/pkgs/dbus.py +18 -0
- jolt/pkgs/double_conversion.py +24 -0
- jolt/pkgs/fastfloat.py +21 -0
- jolt/pkgs/ffmpeg.py +28 -0
- jolt/pkgs/flatbuffers.py +29 -0
- jolt/pkgs/fmt.py +27 -0
- jolt/pkgs/fstree.py +20 -0
- jolt/pkgs/gflags.py +18 -0
- jolt/pkgs/glib.py +18 -0
- jolt/pkgs/glog.py +25 -0
- jolt/pkgs/glslang.py +21 -0
- jolt/pkgs/golang.py +16 -11
- jolt/pkgs/googlebenchmark.py +18 -0
- jolt/pkgs/googletest.py +46 -0
- jolt/pkgs/gperf.py +15 -0
- jolt/pkgs/grpc.py +73 -0
- jolt/pkgs/hdf5.py +19 -0
- jolt/pkgs/help2man.py +14 -0
- jolt/pkgs/inja.py +28 -0
- jolt/pkgs/jsoncpp.py +31 -0
- jolt/pkgs/libarchive.py +43 -0
- jolt/pkgs/libcap.py +44 -0
- jolt/pkgs/libdrm.py +44 -0
- jolt/pkgs/libedit.py +42 -0
- jolt/pkgs/libevent.py +31 -0
- jolt/pkgs/libexpat.py +27 -0
- jolt/pkgs/libfastjson.py +21 -0
- jolt/pkgs/libffi.py +16 -0
- jolt/pkgs/libglvnd.py +30 -0
- jolt/pkgs/libogg.py +28 -0
- jolt/pkgs/libpciaccess.py +18 -0
- jolt/pkgs/libseccomp.py +21 -0
- jolt/pkgs/libtirpc.py +24 -0
- jolt/pkgs/libtool.py +42 -0
- jolt/pkgs/libunwind.py +35 -0
- jolt/pkgs/libva.py +18 -0
- jolt/pkgs/libvorbis.py +33 -0
- jolt/pkgs/libxml2.py +35 -0
- jolt/pkgs/libxslt.py +17 -0
- jolt/pkgs/libyajl.py +16 -0
- jolt/pkgs/llvm.py +81 -0
- jolt/pkgs/lua.py +54 -0
- jolt/pkgs/lz4.py +26 -0
- jolt/pkgs/m4.py +14 -0
- jolt/pkgs/make.py +17 -0
- jolt/pkgs/mesa.py +81 -0
- jolt/pkgs/meson.py +17 -0
- jolt/pkgs/mstch.py +28 -0
- jolt/pkgs/mysql.py +60 -0
- jolt/pkgs/nasm.py +49 -0
- jolt/pkgs/ncurses.py +30 -0
- jolt/pkgs/ng_log.py +25 -0
- jolt/pkgs/ninja.py +45 -0
- jolt/pkgs/nlohmann_json.py +25 -0
- jolt/pkgs/nodejs.py +19 -11
- jolt/pkgs/opencv.py +24 -0
- jolt/pkgs/openjdk.py +26 -0
- jolt/pkgs/openssl.py +103 -0
- jolt/pkgs/paho.py +76 -0
- jolt/pkgs/patchelf.py +16 -0
- jolt/pkgs/perl.py +42 -0
- jolt/pkgs/pkgconfig.py +64 -0
- jolt/pkgs/poco.py +39 -0
- jolt/pkgs/protobuf.py +77 -0
- jolt/pkgs/pugixml.py +27 -0
- jolt/pkgs/python.py +19 -0
- jolt/pkgs/qt.py +35 -0
- jolt/pkgs/rapidjson.py +26 -0
- jolt/pkgs/rapidyaml.py +28 -0
- jolt/pkgs/re2.py +30 -0
- jolt/pkgs/re2c.py +17 -0
- jolt/pkgs/readline.py +15 -0
- jolt/pkgs/rust.py +41 -0
- jolt/pkgs/sdl.py +28 -0
- jolt/pkgs/simdjson.py +27 -0
- jolt/pkgs/soci.py +46 -0
- jolt/pkgs/spdlog.py +29 -0
- jolt/pkgs/spirv_llvm.py +21 -0
- jolt/pkgs/spirv_tools.py +24 -0
- jolt/pkgs/sqlite.py +83 -0
- jolt/pkgs/ssl.py +12 -0
- jolt/pkgs/texinfo.py +15 -0
- jolt/pkgs/tomlplusplus.py +22 -0
- jolt/pkgs/wayland.py +26 -0
- jolt/pkgs/x11.py +58 -0
- jolt/pkgs/xerces_c.py +20 -0
- jolt/pkgs/xorg.py +360 -0
- jolt/pkgs/xz.py +29 -0
- jolt/pkgs/yamlcpp.py +30 -0
- jolt/pkgs/zeromq.py +47 -0
- jolt/pkgs/zlib.py +69 -0
- jolt/pkgs/zstd.py +33 -0
- jolt/plugins/autotools.py +66 -0
- jolt/plugins/cmake.py +74 -6
- jolt/plugins/cxxinfo.py +7 -0
- jolt/plugins/fetch.py +141 -0
- jolt/plugins/git.py +33 -11
- jolt/plugins/libtool.py +63 -0
- jolt/plugins/meson.py +61 -0
- jolt/plugins/ninja.py +236 -17
- jolt/plugins/pkgconfig.py +219 -0
- jolt/plugins/python.py +137 -0
- jolt/plugins/rust.py +25 -0
- jolt/plugins/selfdeploy/setup.py +1 -0
- jolt/tasks.py +79 -14
- jolt/tools.py +86 -42
- jolt/utils.py +6 -0
- jolt/version.py +1 -1
- {jolt-0.9.419.dist-info → jolt-0.9.430.dist-info}/METADATA +19 -2
- jolt-0.9.430.dist-info/RECORD +207 -0
- jolt-0.9.419.dist-info/RECORD +0 -92
- {jolt-0.9.419.dist-info → jolt-0.9.430.dist-info}/WHEEL +0 -0
- {jolt-0.9.419.dist-info → jolt-0.9.430.dist-info}/entry_points.txt +0 -0
- {jolt-0.9.419.dist-info → jolt-0.9.430.dist-info}/top_level.txt +0 -0
jolt/plugins/python.py
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import sys
|
|
2
2
|
|
|
3
|
+
from jolt import Task
|
|
4
|
+
from jolt import attributes
|
|
3
5
|
from jolt import filesystem as fs
|
|
4
6
|
from jolt.cache import ArtifactStringAttribute
|
|
5
7
|
from jolt.cache import ArtifactAttributeSet
|
|
6
8
|
from jolt.cache import ArtifactAttributeSetProvider
|
|
9
|
+
from jolt.error import raise_task_error_if
|
|
7
10
|
|
|
8
11
|
|
|
9
12
|
class PythonVariable(ArtifactStringAttribute):
|
|
@@ -98,3 +101,137 @@ class PythonProvider(ArtifactAttributeSetProvider):
|
|
|
98
101
|
|
|
99
102
|
def unapply(self, task, artifact):
|
|
100
103
|
artifact.python.unapply(task, artifact)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
@attributes.system
|
|
107
|
+
@attributes.requires("requires_python")
|
|
108
|
+
class PythonEnv(Task):
|
|
109
|
+
"""
|
|
110
|
+
Base class for Python virtual environment tasks.
|
|
111
|
+
|
|
112
|
+
Builds a Python virtual environment and installs specified packages.
|
|
113
|
+
|
|
114
|
+
The venv module from the Python standard library must be available in the
|
|
115
|
+
Python installation used to run the task.
|
|
116
|
+
"""
|
|
117
|
+
|
|
118
|
+
abstract = True
|
|
119
|
+
""" This is an abstract base class that should be inherited by concrete tasks. """
|
|
120
|
+
|
|
121
|
+
executable = "python3"
|
|
122
|
+
""" Python executable to use for creating the virtual environment. """
|
|
123
|
+
|
|
124
|
+
requirements = []
|
|
125
|
+
"""
|
|
126
|
+
List of Python packages to install in the virtual environment.
|
|
127
|
+
|
|
128
|
+
Each entry should be a string suitable for pip, e.g., "package==version".
|
|
129
|
+
"""
|
|
130
|
+
|
|
131
|
+
def _verify_influence(self, deps, artifact, tools, sources=None):
|
|
132
|
+
# No influence to verify
|
|
133
|
+
return
|
|
134
|
+
|
|
135
|
+
def relocate_scripts(self, artifact, tools, frompath, topath):
|
|
136
|
+
bindir = "Scripts" if self.system == "windows" else "bin"
|
|
137
|
+
|
|
138
|
+
with tools.cwd(artifact.path, bindir):
|
|
139
|
+
for script in tools.glob("*"):
|
|
140
|
+
if script.startswith("python"):
|
|
141
|
+
continue
|
|
142
|
+
tools.replace_in_file(script, frompath, topath)
|
|
143
|
+
|
|
144
|
+
with tools.cwd(artifact.path):
|
|
145
|
+
if not tools.exists("local/bin"):
|
|
146
|
+
return
|
|
147
|
+
with tools.cwd("local", "bin"):
|
|
148
|
+
for script in tools.glob("*"):
|
|
149
|
+
tools.replace_in_file(script, frompath, topath)
|
|
150
|
+
|
|
151
|
+
def publish(self, artifact, tools):
|
|
152
|
+
# Create a parallel installation by copying a Python installation
|
|
153
|
+
|
|
154
|
+
# First locate the Python executable to copy
|
|
155
|
+
py_exe = tools.which(self.executable)
|
|
156
|
+
raise_task_error_if(
|
|
157
|
+
py_exe is None, self,
|
|
158
|
+
f"Python executable '{self.executable}' not found in PATH.",
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
# Follow symlinks to get the real executable
|
|
162
|
+
py_exe = fs.path.realpath(py_exe)
|
|
163
|
+
|
|
164
|
+
# Determine the Python home directory
|
|
165
|
+
py_home = fs.path.dirname(fs.path.dirname(py_exe))
|
|
166
|
+
|
|
167
|
+
# Determine the Python version
|
|
168
|
+
self.version_major = tools.run(
|
|
169
|
+
[py_exe, "-c", "import sys; print(\"{{}}.{{}}\".format(sys.version_info[0], sys.version_info[1]))"],
|
|
170
|
+
shell=False,
|
|
171
|
+
output_on_error=True).strip()
|
|
172
|
+
|
|
173
|
+
self.info("Python executable: {0}", py_exe)
|
|
174
|
+
self.info("Python home: {0}", py_home)
|
|
175
|
+
self.info("Python version: {0}", self.version_major)
|
|
176
|
+
|
|
177
|
+
# Copy the Python installation to the artifact path
|
|
178
|
+
with tools.cwd(py_home):
|
|
179
|
+
artifact.collect(py_exe, "bin/python3")
|
|
180
|
+
artifact.collect("lib/python3")
|
|
181
|
+
artifact.collect("lib/python{version_major}")
|
|
182
|
+
artifact.collect("lib/libpython{version_major}.*")
|
|
183
|
+
|
|
184
|
+
# Create common symlinks
|
|
185
|
+
if self.system != "windows":
|
|
186
|
+
with tools.cwd(artifact.path, "bin"):
|
|
187
|
+
tools.symlink("python3", "python")
|
|
188
|
+
tools.symlink("python3", "python{version_major}")
|
|
189
|
+
|
|
190
|
+
# Install required packages into the artifact using pip
|
|
191
|
+
with tools.environ(PYTHONHOME=artifact.path):
|
|
192
|
+
py_exe = fs.path.join(artifact.path, "bin", "python3")
|
|
193
|
+
with tools.tmpdir() as tmp, tools.cwd(tmp):
|
|
194
|
+
tools.write_file(
|
|
195
|
+
"requirements.txt",
|
|
196
|
+
"\n".join(self.requirements) + "\n"
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
pip_cmd = [
|
|
200
|
+
py_exe,
|
|
201
|
+
"-m",
|
|
202
|
+
"pip",
|
|
203
|
+
"--isolated",
|
|
204
|
+
"--no-cache-dir",
|
|
205
|
+
"install",
|
|
206
|
+
"-r",
|
|
207
|
+
"requirements.txt",
|
|
208
|
+
"--break-system-packages",
|
|
209
|
+
]
|
|
210
|
+
tools.run(pip_cmd, shell=False)
|
|
211
|
+
|
|
212
|
+
artifact.environ.PATH.append("bin")
|
|
213
|
+
artifact.environ.PATH.append("local/bin")
|
|
214
|
+
artifact.strings.install_prefix = artifact.path
|
|
215
|
+
|
|
216
|
+
def unpack(self, artifact, tools):
|
|
217
|
+
# Relocate the virtual environment by adjusting script paths
|
|
218
|
+
frompath = artifact.strings.install_prefix
|
|
219
|
+
topath = artifact.final_path
|
|
220
|
+
self.relocate_scripts(artifact, tools, frompath, topath)
|
|
221
|
+
|
|
222
|
+
artifact.strings.install_prefix = artifact.final_path
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def requires(python=True):
|
|
226
|
+
""" Decorator to add Python requirements to a task. """
|
|
227
|
+
|
|
228
|
+
import jolt.pkgs.cpython
|
|
229
|
+
|
|
230
|
+
def decorate(cls):
|
|
231
|
+
if python:
|
|
232
|
+
cls = attributes.requires("requires_python")(cls)
|
|
233
|
+
cls.requires_python = ["cpython"]
|
|
234
|
+
|
|
235
|
+
return cls
|
|
236
|
+
|
|
237
|
+
return decorate
|
jolt/plugins/rust.py
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from jolt import attributes, Task
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
@attributes.common_metadata()
|
|
5
|
+
class Rust(Task):
|
|
6
|
+
""" Base class for Rust-based build tasks. """
|
|
7
|
+
|
|
8
|
+
abstract = True
|
|
9
|
+
|
|
10
|
+
srcdir = None
|
|
11
|
+
"""
|
|
12
|
+
Source directory for the Rust project.
|
|
13
|
+
|
|
14
|
+
If None, defaults to the task work directory (joltdir).
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
def run(self, deps, tools):
|
|
18
|
+
self.builddir = tools.builddir(incremental=True)
|
|
19
|
+
self.installdir = tools.builddir("install")
|
|
20
|
+
with tools.cwd(self.srcdir or self.joltdir):
|
|
21
|
+
tools.run("cargo install --path . --target-dir={builddir} --root={installdir}")
|
|
22
|
+
|
|
23
|
+
def publish(self, artifact, tools):
|
|
24
|
+
with tools.cwd(self.installdir):
|
|
25
|
+
artifact.collect("*", symlinks=True)
|
jolt/plugins/selfdeploy/setup.py
CHANGED
jolt/tasks.py
CHANGED
|
@@ -197,7 +197,7 @@ class Parameter(object):
|
|
|
197
197
|
def highlight(value):
|
|
198
198
|
return colors.bright(value) if self._is_default(value) else colors.dim(value)
|
|
199
199
|
|
|
200
|
-
return "[{}]".format(", ".join([highlight(value) for value in accepted])) if accepted else ""
|
|
200
|
+
return "[{}]".format(", ".join([highlight(str(value)) for value in accepted])) if accepted else ""
|
|
201
201
|
|
|
202
202
|
def __str__(self):
|
|
203
203
|
""" Returns the parameter value as a string """
|
|
@@ -923,6 +923,14 @@ class TaskGenerator(object):
|
|
|
923
923
|
|
|
924
924
|
|
|
925
925
|
class attributes:
|
|
926
|
+
@staticmethod
|
|
927
|
+
def arch(cls):
|
|
928
|
+
""" Return the architecture name (x86_64, arm64, etc.). """
|
|
929
|
+
|
|
930
|
+
cls._arch = Export(lambda t: platform.machine().lower().replace("amd64", "x86_64"))
|
|
931
|
+
cls.arch = property(lambda t: t._arch.value)
|
|
932
|
+
return cls
|
|
933
|
+
|
|
926
934
|
@staticmethod
|
|
927
935
|
def artifact(name, session=False):
|
|
928
936
|
"""Decorator adding an additional artifact to a task.
|
|
@@ -1208,6 +1216,65 @@ class attributes:
|
|
|
1208
1216
|
return utils.concat_attributes("_publish_files", attrib)(cls)
|
|
1209
1217
|
return decorate
|
|
1210
1218
|
|
|
1219
|
+
@staticmethod
|
|
1220
|
+
def common_metadata(aclocal=True, cmake=True, cxxinfo=True, path=True, pkgconfig=True):
|
|
1221
|
+
"""
|
|
1222
|
+
Decorator adding common metadata to published artifacts.
|
|
1223
|
+
|
|
1224
|
+
The decorator adds common environment variables and C/C++ build information
|
|
1225
|
+
to the published artifact:
|
|
1226
|
+
|
|
1227
|
+
- Adds `bin/` to `PATH` environment variable if it exists.
|
|
1228
|
+
- Adds `lib/` and `lib64/` to C++ library paths if they exist.
|
|
1229
|
+
- Adds `include/` to C++ include paths if it exists.
|
|
1230
|
+
- Adds `lib/pkgconfig/`, `lib64/pkgconfig/` and `share/pkgconfig/` to
|
|
1231
|
+
`PKG_CONFIG_PATH` environment variable if `.pc` files are found.
|
|
1232
|
+
The `prefix` variable in `.pc` files is relocated to allow
|
|
1233
|
+
installation in arbitrary locations.
|
|
1234
|
+
- Adds `lib/cmake/`, `lib64/cmake/` and `share/cmake/` to
|
|
1235
|
+
`CMAKE_PREFIX_PATH` environment variable if they exist.
|
|
1236
|
+
- Adds `share/aclocal/` to `ACLOCAL_PATH` environment variable if it exists.
|
|
1237
|
+
|
|
1238
|
+
"""
|
|
1239
|
+
def decorate(cls):
|
|
1240
|
+
_old_publish = cls.publish
|
|
1241
|
+
|
|
1242
|
+
@functools.wraps(cls.publish)
|
|
1243
|
+
def publish(self, artifact, tools):
|
|
1244
|
+
_old_publish(self, artifact, tools)
|
|
1245
|
+
|
|
1246
|
+
with tools.cwd(artifact.path):
|
|
1247
|
+
if path and tools.exists("bin"):
|
|
1248
|
+
artifact.environ.PATH.append("bin")
|
|
1249
|
+
|
|
1250
|
+
pcdirs = set()
|
|
1251
|
+
|
|
1252
|
+
for pcpath in tools.glob("lib/pkgconfig/*.pc") + tools.glob("lib64/pkgconfig/*.pc") + tools.glob("share/pkgconfig/*.pc"):
|
|
1253
|
+
pcdirs.add(fs.path.dirname(pcpath))
|
|
1254
|
+
tools.replace_in_file(pcpath, artifact.strings.install_prefix, "${{pcfiledir}}/../..")
|
|
1255
|
+
for pcpath in tools.glob("lib/*/pkgconfig/*.pc") + tools.glob("lib64/*/pkgconfig/*.pc"):
|
|
1256
|
+
pcdirs.add(fs.path.dirname(pcpath))
|
|
1257
|
+
tools.replace_in_file(pcpath, artifact.strings.install_prefix, "${{pcfiledir}}/../../..")
|
|
1258
|
+
|
|
1259
|
+
for pcdir in pcdirs:
|
|
1260
|
+
artifact.environ.PKG_CONFIG_PATH.append(pcdir)
|
|
1261
|
+
|
|
1262
|
+
if cmake and tools.exists("lib/cmake"):
|
|
1263
|
+
artifact.environ.CMAKE_PREFIX_PATH.append(".")
|
|
1264
|
+
if cmake and tools.exists("lib64/cmake"):
|
|
1265
|
+
artifact.environ.CMAKE_PREFIX_PATH.append(".")
|
|
1266
|
+
if cmake and tools.exists("share/cmake"):
|
|
1267
|
+
artifact.environ.CMAKE_PREFIX_PATH.append(".")
|
|
1268
|
+
|
|
1269
|
+
if aclocal and tools.exists("share/aclocal"):
|
|
1270
|
+
artifact.environ.ACLOCAL_PATH.append("share/aclocal")
|
|
1271
|
+
|
|
1272
|
+
cls.publish = publish
|
|
1273
|
+
|
|
1274
|
+
return cls
|
|
1275
|
+
|
|
1276
|
+
return decorate
|
|
1277
|
+
|
|
1211
1278
|
@staticmethod
|
|
1212
1279
|
def requires(attrib):
|
|
1213
1280
|
"""
|
|
@@ -2689,7 +2756,7 @@ class ReportProxy(object):
|
|
|
2689
2756
|
if not filterfn(error):
|
|
2690
2757
|
continue
|
|
2691
2758
|
if error["location"] not in errors_by_location:
|
|
2692
|
-
errors_by_location[error["location"]] = (error, [error["message"]], error
|
|
2759
|
+
errors_by_location[error["location"]] = (error, [error["message"]], error.get("details", ""))
|
|
2693
2760
|
else:
|
|
2694
2761
|
errors_by_location[error["location"]][1].append(error["message"])
|
|
2695
2762
|
|
|
@@ -2976,6 +3043,7 @@ class Download(Task):
|
|
|
2976
3043
|
Once downloaded, archives are extracted and all of their files are published.
|
|
2977
3044
|
If the file is not an archive it is published as is. Recognized archive extensions are:
|
|
2978
3045
|
|
|
3046
|
+
- .7z
|
|
2979
3047
|
- .tar
|
|
2980
3048
|
- .tar.bz2
|
|
2981
3049
|
- .tar.gz
|
|
@@ -3038,7 +3106,7 @@ class Download(Task):
|
|
|
3038
3106
|
return fs.posixpath.basename(url.path) or "file"
|
|
3039
3107
|
|
|
3040
3108
|
def run(self, deps, tools):
|
|
3041
|
-
supported_formats = [".tar", ".tar.bz2", ".tar.gz", ".tar.xz", ".tgz", ".zip"]
|
|
3109
|
+
supported_formats = [".7z", ".tar", ".tar.bz2", ".tar.gz", ".tar.xz", ".tgz", ".zip"]
|
|
3042
3110
|
|
|
3043
3111
|
raise_task_error_if(not self.url, self, "No URL(s) specified")
|
|
3044
3112
|
|
|
@@ -3292,24 +3360,21 @@ class Test(Task):
|
|
|
3292
3360
|
"""
|
|
3293
3361
|
raise_error_if(type(args) is not list, "Test.parameterized() expects a list as argument")
|
|
3294
3362
|
|
|
3295
|
-
|
|
3296
|
-
def
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
retval = super().__get__(obj, cls)
|
|
3302
|
-
retval.__name__ = f"{self.func.__name__}[{self.__index}]"
|
|
3303
|
-
retval.__doc__ = self.func.__doc__
|
|
3304
|
-
return retval
|
|
3363
|
+
def make_method(index, func, *args):
|
|
3364
|
+
def testmethod(self):
|
|
3365
|
+
return func(self, *args)
|
|
3366
|
+
testmethod.__name__ = f"{func.__name__}[{index}]"
|
|
3367
|
+
testmethod.__doc__ = func.__doc__
|
|
3368
|
+
return testmethod
|
|
3305
3369
|
|
|
3306
3370
|
def decorate(method):
|
|
3307
3371
|
frame = sys._getframe().f_back.f_locals
|
|
3308
3372
|
for index, arg in enumerate(args):
|
|
3309
|
-
testmethod =
|
|
3373
|
+
testmethod = make_method(index, method, *utils.as_list(arg))
|
|
3310
3374
|
name = f"{method.__name__}[{index}]"
|
|
3311
3375
|
frame[name] = testmethod
|
|
3312
3376
|
return None
|
|
3377
|
+
|
|
3313
3378
|
return decorate
|
|
3314
3379
|
|
|
3315
3380
|
def setup(self, deps, tools):
|
jolt/tools.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import py7zr
|
|
1
2
|
import bz2
|
|
2
3
|
import copy
|
|
3
4
|
import getpass
|
|
@@ -42,6 +43,9 @@ from jolt.error import raise_error_if
|
|
|
42
43
|
from jolt.error import raise_task_error, raise_task_error_if
|
|
43
44
|
|
|
44
45
|
|
|
46
|
+
SUPPORTED_ARCHIVE_TYPES = [".tar", ".tar.bz2", ".tar.gz", ".tgz", ".tar.xz", ".tar.zst", ".zip"]
|
|
47
|
+
|
|
48
|
+
|
|
45
49
|
http_session = Session()
|
|
46
50
|
|
|
47
51
|
|
|
@@ -257,6 +261,10 @@ class _CMake(object):
|
|
|
257
261
|
self.builddir = self.tools.builddir(incremental=incremental)
|
|
258
262
|
self.installdir = self.tools.builddir("install", incremental=False)
|
|
259
263
|
|
|
264
|
+
def clean(self):
|
|
265
|
+
self.tools.rmtree(self.builddir, ignore_errors=True)
|
|
266
|
+
self.tools.rmtree(self.installdir, ignore_errors=True)
|
|
267
|
+
|
|
260
268
|
def configure(self, sourcedir, *args, generator=None, **kwargs):
|
|
261
269
|
sourcedir = self.tools.expand_path(sourcedir)
|
|
262
270
|
|
|
@@ -267,74 +275,85 @@ class _CMake(object):
|
|
|
267
275
|
|
|
268
276
|
with self.tools.cwd(self.builddir):
|
|
269
277
|
self.tools.run(
|
|
270
|
-
"cmake {0}
|
|
278
|
+
"cmake {0} {1} -DCMAKE_INSTALL_PREFIX=/jolt-prefix {1} {2} {3}",
|
|
271
279
|
sourcedir,
|
|
272
|
-
self.builddir,
|
|
273
|
-
self.installdir,
|
|
280
|
+
utils.option("-B", self.builddir),
|
|
274
281
|
utils.option("-G", generator),
|
|
275
282
|
extra_args,
|
|
276
283
|
output=True)
|
|
277
284
|
|
|
278
|
-
def build(self,
|
|
285
|
+
def build(self, *args, config="Release", **kwargs):
|
|
279
286
|
threading_args = ' -j {}'.format(kwargs.get("threads", self.tools.thread_count()))
|
|
280
287
|
with self.tools.cwd(self.builddir):
|
|
281
|
-
|
|
282
|
-
self.tools.run("cmake --build . {0}{1}", release, threading_args, output=True)
|
|
288
|
+
self.tools.run("cmake --build . --config {0} {1}", config, threading_args, output=True)
|
|
283
289
|
|
|
284
|
-
def install(self,
|
|
285
|
-
with self.tools.cwd(self.builddir):
|
|
286
|
-
|
|
287
|
-
self.tools.run("cmake --build . --target install {0}", release, output=True)
|
|
290
|
+
def install(self, target="install", config="Release", **kwargs):
|
|
291
|
+
with self.tools.cwd(self.builddir), self.tools.environ(DESTDIR=self.installdir):
|
|
292
|
+
self.tools.run("cmake --build . --config {0} --target {1}", config, target, output=True)
|
|
288
293
|
|
|
289
|
-
def publish(self, artifact, files='*', *args, **kwargs):
|
|
290
|
-
with self.tools.cwd(self.installdir):
|
|
291
|
-
artifact.collect(files, *args, **kwargs)
|
|
294
|
+
def publish(self, artifact, files='*', symlinks=True, *args, **kwargs):
|
|
295
|
+
with self.tools.cwd(self.installdir, "jolt-prefix"):
|
|
296
|
+
artifact.collect(files, *args, symlinks=symlinks, **kwargs)
|
|
297
|
+
artifact.strings.install_prefix = "/jolt-prefix"
|
|
292
298
|
|
|
293
299
|
|
|
294
300
|
class _Meson(object):
|
|
295
|
-
def __init__(self, deps, tools):
|
|
301
|
+
def __init__(self, deps, tools, incremental=False):
|
|
296
302
|
self.deps = deps
|
|
297
303
|
self.tools = tools
|
|
298
|
-
self.builddir = self.tools.builddir()
|
|
299
|
-
self.installdir = self.tools.builddir("install")
|
|
304
|
+
self.builddir = self.tools.builddir(incremental=incremental)
|
|
305
|
+
self.installdir = self.tools.builddir("install", incremental=False)
|
|
306
|
+
self.prefix = "/jolt-prefix" if os.name != "nt" else "C:\\jolt-prefix"
|
|
307
|
+
|
|
308
|
+
def clean(self):
|
|
309
|
+
self.tools.rmtree(self.builddir, ignore_errors=True)
|
|
310
|
+
self.tools.rmtree(self.installdir, ignore_errors=True)
|
|
300
311
|
|
|
301
312
|
def configure(self, sourcedir, *args, **kwargs):
|
|
302
313
|
sourcedir = self.tools.expand_path(sourcedir)
|
|
303
|
-
|
|
314
|
+
options = " ".join([f"-D{arg}" for arg in args]) + " "
|
|
315
|
+
options += " ".join(["-D{0}={1}".format(key, self.tools.expand(val)) for key, val in kwargs.items()])
|
|
316
|
+
self.tools.run("meson setup --prefix={0} {1} {2} {3}", self.prefix, sourcedir, self.builddir, options,
|
|
304
317
|
output=True)
|
|
305
318
|
|
|
306
319
|
def build(self, *args, **kwargs):
|
|
307
320
|
self.tools.run("ninja -C {0} ", self.builddir, output=True)
|
|
308
321
|
|
|
309
322
|
def install(self, *args, **kwargs):
|
|
310
|
-
self.tools.
|
|
311
|
-
|
|
312
|
-
output=True)
|
|
323
|
+
with self.tools.environ(DESTDIR=self.installdir):
|
|
324
|
+
self.tools.run("ninja -C {0} install", self.builddir, output=True)
|
|
313
325
|
|
|
314
|
-
def publish(self, artifact, files='*', *args, **kwargs):
|
|
315
|
-
with self.tools.cwd(self.installdir):
|
|
316
|
-
artifact.collect(files, *args, **kwargs)
|
|
326
|
+
def publish(self, artifact, files='*', symlinks=True, *args, **kwargs):
|
|
327
|
+
with self.tools.cwd(self.installdir, "jolt-prefix"):
|
|
328
|
+
artifact.collect(files, *args, symlinks=symlinks, **kwargs)
|
|
329
|
+
artifact.strings.install_prefix = self.prefix
|
|
317
330
|
|
|
318
331
|
|
|
319
332
|
class _AutoTools(object):
|
|
320
|
-
def __init__(self, deps, tools):
|
|
333
|
+
def __init__(self, deps, tools, incremental=False):
|
|
321
334
|
self.deps = deps
|
|
322
335
|
self.tools = tools
|
|
323
|
-
self.builddir = self.tools.builddir()
|
|
324
|
-
self.installdir = self.tools.builddir("install")
|
|
336
|
+
self.builddir = self.tools.builddir(incremental=incremental)
|
|
337
|
+
self.installdir = self.tools.builddir("install", incremental=False)
|
|
338
|
+
self.prefix = "jolt-prefix"
|
|
325
339
|
|
|
326
|
-
def
|
|
340
|
+
def clean(self):
|
|
341
|
+
self.tools.rmtree(self.builddir, ignore_errors=True)
|
|
342
|
+
self.tools.rmtree(self.installdir, ignore_errors=True)
|
|
343
|
+
|
|
344
|
+
def configure(self, sourcedir, *args):
|
|
327
345
|
sourcedir = self.tools.expand_path(sourcedir)
|
|
328
|
-
prefix = kwargs.get("prefix", "/")
|
|
329
346
|
|
|
330
347
|
if not fs.path.exists(fs.path.join(sourcedir, "configure")):
|
|
331
348
|
with self.tools.cwd(sourcedir):
|
|
332
349
|
self.tools.run("autoreconf -visf", output=True)
|
|
333
350
|
|
|
334
351
|
with self.tools.cwd(self.builddir), self.tools.environ(DESTDIR=self.installdir):
|
|
335
|
-
self.tools.run("{0}/configure --prefix
|
|
336
|
-
sourcedir,
|
|
352
|
+
self.tools.run("{0}/configure --prefix=/{1} {2} {3}",
|
|
353
|
+
sourcedir,
|
|
354
|
+
self.prefix,
|
|
337
355
|
self.tools.getenv("CONFIGURE_FLAGS", ""),
|
|
356
|
+
" ".join(args),
|
|
338
357
|
output=True)
|
|
339
358
|
|
|
340
359
|
def build(self, *args, **kwargs):
|
|
@@ -342,13 +361,14 @@ class _AutoTools(object):
|
|
|
342
361
|
self.tools.run("make VERBOSE=yes Q= V=1 -j{0}",
|
|
343
362
|
self.tools.cpu_count(), output=True)
|
|
344
363
|
|
|
345
|
-
def install(self, target="install"
|
|
346
|
-
with self.tools.cwd(self.builddir)
|
|
347
|
-
self.tools.run("make {}", target, output=True)
|
|
364
|
+
def install(self, target="install"):
|
|
365
|
+
with self.tools.cwd(self.builddir):
|
|
366
|
+
self.tools.run("make DESTDIR={} {}", self.installdir, target, output=True)
|
|
348
367
|
|
|
349
|
-
def publish(self, artifact, files='*', *args, **kwargs):
|
|
350
|
-
with self.tools.cwd(self.installdir):
|
|
351
|
-
artifact.collect(files, *args, **kwargs)
|
|
368
|
+
def publish(self, artifact, files='*', symlinks=True, *args, **kwargs):
|
|
369
|
+
with self.tools.cwd(self.installdir, self.prefix):
|
|
370
|
+
artifact.collect(files, *args, symlinks=symlinks, **kwargs)
|
|
371
|
+
artifact.strings.install_prefix = "/" + self.prefix
|
|
352
372
|
|
|
353
373
|
|
|
354
374
|
class ZipFile(zipfile.ZipFile):
|
|
@@ -527,6 +547,12 @@ class Tools(object):
|
|
|
527
547
|
zf.write(path, zippath)
|
|
528
548
|
return filename
|
|
529
549
|
|
|
550
|
+
def _make_7zfile(self, filename, fmt, rootdir):
|
|
551
|
+
self.mkdirname(filename)
|
|
552
|
+
with py7zr.SevenZipFile(filename, 'w') as archive:
|
|
553
|
+
archive.writeall(rootdir, ".")
|
|
554
|
+
return filename
|
|
555
|
+
|
|
530
556
|
def _make_tarfile(self, filename, fmt, rootdir):
|
|
531
557
|
self.mkdirname(filename)
|
|
532
558
|
with tarfile.open(filename, 'w|%s' % fmt) as tar:
|
|
@@ -559,6 +585,7 @@ class Tools(object):
|
|
|
559
585
|
The type of archive to create is determined by the filename extension.
|
|
560
586
|
Supported formats are:
|
|
561
587
|
|
|
588
|
+
- 7z
|
|
562
589
|
- tar
|
|
563
590
|
- tar.bz2
|
|
564
591
|
- tar.gz
|
|
@@ -594,12 +621,16 @@ class Tools(object):
|
|
|
594
621
|
fmt = "tarbz2"
|
|
595
622
|
elif filename.endswith(".tar.xz"):
|
|
596
623
|
fmt = "tarxz"
|
|
624
|
+
elif filename.endswith(".7z"):
|
|
625
|
+
fmt = "7z"
|
|
597
626
|
raise_task_error_if(
|
|
598
627
|
not fmt, self._task,
|
|
599
628
|
"unknown archive type '{0}'", fs.path.basename(filename))
|
|
600
629
|
try:
|
|
601
630
|
if fmt == "zip":
|
|
602
631
|
outfile = self._make_zipfile(filename, fmt, rootdir=pathname)
|
|
632
|
+
elif fmt == "7z":
|
|
633
|
+
outfile = self._make_7zfile(filename, fmt, rootdir=pathname)
|
|
603
634
|
else:
|
|
604
635
|
outfile = self._make_tarfile(filename, fmt[3:], rootdir=pathname)
|
|
605
636
|
if outfile != filename:
|
|
@@ -608,9 +639,9 @@ class Tools(object):
|
|
|
608
639
|
except Exception:
|
|
609
640
|
raise_task_error(self._task, "failed to create archive from directory '{0}'", pathname)
|
|
610
641
|
|
|
611
|
-
def autotools(self, deps=None):
|
|
642
|
+
def autotools(self, deps=None, incremental=False):
|
|
612
643
|
""" Creates an AutoTools invokation helper """
|
|
613
|
-
return _AutoTools(deps, self)
|
|
644
|
+
return _AutoTools(deps, self, incremental=incremental)
|
|
614
645
|
|
|
615
646
|
@utils.locked(lock='_builddir_lock')
|
|
616
647
|
def builddir(self, name=None, incremental=False, unique=True):
|
|
@@ -895,7 +926,7 @@ class Tools(object):
|
|
|
895
926
|
pbar.update(len(data))
|
|
896
927
|
actual_size = self.file_size(pathname)
|
|
897
928
|
raise_error_if(
|
|
898
|
-
size != 0 and size
|
|
929
|
+
size != 0 and size > actual_size,
|
|
899
930
|
f"Downloaded file was truncated to {actual_size}/{size} bytes: {name}")
|
|
900
931
|
|
|
901
932
|
return response.status_code == 200
|
|
@@ -1054,6 +1085,7 @@ class Tools(object):
|
|
|
1054
1085
|
|
|
1055
1086
|
Supported formats are:
|
|
1056
1087
|
|
|
1088
|
+
- 7z
|
|
1057
1089
|
- tar
|
|
1058
1090
|
- tar.bz2
|
|
1059
1091
|
- tar.gz
|
|
@@ -1117,6 +1149,13 @@ class Tools(object):
|
|
|
1117
1149
|
self._extract_tarzstd(filename, filepath, files)
|
|
1118
1150
|
except tarfile.StreamError as e:
|
|
1119
1151
|
raise_task_error(self._task, "failed to extract archive '{0}': {1}", filename, str(e))
|
|
1152
|
+
elif filename.endswith(".7z"):
|
|
1153
|
+
with py7zr.SevenZipFile(filename, 'r') as archive:
|
|
1154
|
+
if files:
|
|
1155
|
+
for file in files:
|
|
1156
|
+
archive.extract(file, filepath)
|
|
1157
|
+
else:
|
|
1158
|
+
archive.extractall(filepath)
|
|
1120
1159
|
else:
|
|
1121
1160
|
raise_task_error(self._task, "unknown archive type '{0}'", fs.path.basename(filename))
|
|
1122
1161
|
except Exception:
|
|
@@ -1268,9 +1307,9 @@ class Tools(object):
|
|
|
1268
1307
|
"""
|
|
1269
1308
|
return utils.map_concurrent(callable, iterable, max_workers)
|
|
1270
1309
|
|
|
1271
|
-
def meson(self, deps=None):
|
|
1310
|
+
def meson(self, deps=None, incremental=False):
|
|
1272
1311
|
""" Creates a Meson invokation helper """
|
|
1273
|
-
return _Meson(deps, self)
|
|
1312
|
+
return _Meson(deps, self, incremental=incremental)
|
|
1274
1313
|
|
|
1275
1314
|
@contextmanager
|
|
1276
1315
|
def nixpkgs(self, nixfile=None, packages=None, pure=False, path=None, options=None):
|
|
@@ -1702,11 +1741,15 @@ class Tools(object):
|
|
|
1702
1741
|
fs.makedirs(path)
|
|
1703
1742
|
for relsrcpath, reldstpath in artifact.files.items():
|
|
1704
1743
|
srcpath = fs.path.normpath(fs.path.join(artifact.task.joltdir, relsrcpath))
|
|
1744
|
+
srcpath = self.expand_path(srcpath)
|
|
1705
1745
|
dstpath = fs.path.normpath(fs.path.join(path, reldstpath))
|
|
1746
|
+
dstpath = self.expand_path(dstpath)
|
|
1747
|
+
|
|
1706
1748
|
if dstpath != fs.path.realpath(dstpath):
|
|
1707
1749
|
log.debug("Cannot symlink '{} -> {}', parent directory already symlinked",
|
|
1708
1750
|
srcpath, dstpath)
|
|
1709
1751
|
continue
|
|
1752
|
+
|
|
1710
1753
|
if fs.path.isdir(dstpath):
|
|
1711
1754
|
files = fs.scandir(srcpath)
|
|
1712
1755
|
for file in files:
|
|
@@ -1716,7 +1759,8 @@ class Tools(object):
|
|
|
1716
1759
|
self.symlink(srcpath, dstpath)
|
|
1717
1760
|
|
|
1718
1761
|
# Restore missing srcfiles if they resided in a build directory
|
|
1719
|
-
|
|
1762
|
+
buildroot_abs = self.expand_path(artifact.tools.buildroot)
|
|
1763
|
+
if srcpath.startswith(buildroot_abs) and \
|
|
1720
1764
|
not fs.path.exists(srcpath):
|
|
1721
1765
|
fs.copy(fs.path.join(artifact.path, reldstpath), srcpath, symlinks=True)
|
|
1722
1766
|
self.write_file(meta, artifact.path)
|
jolt/utils.py
CHANGED
|
@@ -219,6 +219,10 @@ class _SafeDict(object):
|
|
|
219
219
|
value = self.values.get(key)
|
|
220
220
|
if value is None:
|
|
221
221
|
value = call_and_catch(getattr, self.values.get("_instance", object()), key)
|
|
222
|
+
if value is None and key == "buildroot":
|
|
223
|
+
tools = getattr(self.values.get("_instance", object()), "tools", None)
|
|
224
|
+
if tools:
|
|
225
|
+
value = tools.buildroot
|
|
222
226
|
if value is None:
|
|
223
227
|
value = self._envget(key)
|
|
224
228
|
if type(value) is list:
|
|
@@ -238,6 +242,8 @@ class JoltFormatter(Formatter):
|
|
|
238
242
|
return str(value).lower()
|
|
239
243
|
elif conversion == "c":
|
|
240
244
|
return value()
|
|
245
|
+
elif conversion == "t":
|
|
246
|
+
return str(value).title()
|
|
241
247
|
elif conversion == "j":
|
|
242
248
|
return " ".join(value)
|
|
243
249
|
return super().convert_field(value, conversion)
|
jolt/version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.9.
|
|
1
|
+
__version__ = "0.9.430"
|