scons-xo-exts-lib 1.3.0__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.
- scons_xo_exts_lib/Actions/Uv.py +48 -0
- scons_xo_exts_lib/Actions/__init__.py +1 -0
- scons_xo_exts_lib/BuildSupport/Make.py +18 -0
- scons_xo_exts_lib/BuildSupport/NodeMangling.py +34 -0
- scons_xo_exts_lib/BuildSupport/__init__.py +1 -0
- scons_xo_exts_lib/Builders/__init__.py +1 -0
- scons_xo_exts_lib/Builders/bazel.py +39 -0
- scons_xo_exts_lib/Builders/cmake.py +39 -0
- scons_xo_exts_lib/Builders/dotnet.py +242 -0
- scons_xo_exts_lib/Builders/dune.py +110 -0
- scons_xo_exts_lib/Builders/elisp.py +128 -0
- scons_xo_exts_lib/Builders/elixir.py +67 -0
- scons_xo_exts_lib/Builders/make.py +39 -0
- scons_xo_exts_lib/Builders/meson.py +44 -0
- scons_xo_exts_lib/Builders/ninja.py +42 -0
- scons_xo_exts_lib/Builders/orgmode.py +109 -0
- scons_xo_exts_lib/Builders/pandoc.py +42 -0
- scons_xo_exts_lib/Builders/racket.py +123 -0
- scons_xo_exts_lib/Builders/tar_image.py +40 -0
- scons_xo_exts_lib/Find.py +32 -0
- scons_xo_exts_lib/GenericExtensions.py +38 -0
- scons_xo_exts_lib/Read.py +53 -0
- scons_xo_exts_lib/__init__.py +8 -0
- scons_xo_exts_lib-1.3.0.dist-info/METADATA +39 -0
- scons_xo_exts_lib-1.3.0.dist-info/RECORD +26 -0
- scons_xo_exts_lib-1.3.0.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
4
|
+
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
5
|
+
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
import os
|
|
9
|
+
|
|
10
|
+
from SCons.Script import Environment
|
|
11
|
+
|
|
12
|
+
from ..GenericExtensions import execute_command
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def uv_venv_action(target, source, env):
|
|
16
|
+
if os.path.exists(".venv"):
|
|
17
|
+
return
|
|
18
|
+
else:
|
|
19
|
+
env.Execute("${UV_EXE} venv")
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def uv_sync_action(target, source, env):
|
|
23
|
+
execute_command(env, "${UV_EXE} sync --all-packages")
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def uv_pip(env, cmd):
|
|
27
|
+
execute_command(env, "${UV_EXE} pip " + cmd)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def uv_pip_freeze_action(target, source, env):
|
|
31
|
+
output_file = str(target[0])
|
|
32
|
+
|
|
33
|
+
uv_pip(env, f"freeze --exclude-editable > {output_file}")
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def uv_build_pkg_action(target, source, env):
|
|
37
|
+
if source:
|
|
38
|
+
flags = " ".join(str(s) for s in source)
|
|
39
|
+
else:
|
|
40
|
+
flags = "--all-packages"
|
|
41
|
+
|
|
42
|
+
execute_command(env, "${UV_EXE} build " + flags)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def uv_pytest_action(target, source, env):
|
|
46
|
+
pytest_exec_flags = env.get("PYTEST_FLAGS", "--capture=no")
|
|
47
|
+
|
|
48
|
+
execute_command(env, f"${{UV_EXE}} run -- pytest {pytest_exec_flags}")
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
4
|
+
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
5
|
+
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
from typing import List
|
|
9
|
+
|
|
10
|
+
from SCons.Script import Environment
|
|
11
|
+
|
|
12
|
+
from .GenericExtensions import execute_command
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def execute_make(env: Environment, args: List[str]) -> None:
|
|
16
|
+
make_cmd = "make" + " ".join(args)
|
|
17
|
+
|
|
18
|
+
execute_command(env, make_cmd)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
4
|
+
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
5
|
+
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
import os
|
|
9
|
+
import re
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def get_first_node(nodes):
|
|
13
|
+
if isinstance(nodes, list):
|
|
14
|
+
return nodes[0]
|
|
15
|
+
|
|
16
|
+
return nodes
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def get_first_directory(nodes):
|
|
20
|
+
node = get_first_node(nodes=nodes)
|
|
21
|
+
path = node.abspath
|
|
22
|
+
|
|
23
|
+
if os.path.isdir(path):
|
|
24
|
+
return path
|
|
25
|
+
|
|
26
|
+
return os.path.dirname(path)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def regex_find_node(regex, nodes):
|
|
30
|
+
for node in nodes:
|
|
31
|
+
if re.match(pattern=regex, string=str(node.abspath)):
|
|
32
|
+
return node
|
|
33
|
+
|
|
34
|
+
raise RuntimeError("No file was matched using the specified regex")
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
4
|
+
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
5
|
+
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
import subprocess
|
|
9
|
+
|
|
10
|
+
from SCons.Script import Builder
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def bazel_action(target, source, env):
|
|
14
|
+
bazel_pkgs = " ".join(str(s) for s in source)
|
|
15
|
+
|
|
16
|
+
bazel_exe = env.get("BAZEL_EXE", "bazelisk")
|
|
17
|
+
bazel_flags = env.get("BAZEL_FLAGS", "")
|
|
18
|
+
|
|
19
|
+
cmd = f"{bazel_exe} build {bazel_flags} {bazel_pkgs}"
|
|
20
|
+
print(cmd)
|
|
21
|
+
|
|
22
|
+
result = subprocess.run(
|
|
23
|
+
args=cmd,
|
|
24
|
+
capture_output=False,
|
|
25
|
+
check=False,
|
|
26
|
+
shell=True,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
return result.returncode
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def generate(env):
|
|
33
|
+
bazel_binary_builder = Builder(action=bazel_action)
|
|
34
|
+
|
|
35
|
+
env.Append(BUILDERS={"BazelBinary": bazel_binary_builder})
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def exists(env):
|
|
39
|
+
return env.Detect("bazel")
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
4
|
+
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
5
|
+
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
import subprocess
|
|
9
|
+
|
|
10
|
+
from SCons.Script import Builder
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def cmake_action(target, source, env):
|
|
14
|
+
cmake_targets = " ".join(str(t) for t in target)
|
|
15
|
+
|
|
16
|
+
cmake_exe = env.get("CMAKE_EXE", "cmake")
|
|
17
|
+
cmake_flags = env.get("CMAKE_FLAGS", "")
|
|
18
|
+
|
|
19
|
+
cmd = f"{cmake_exe} {cmake_flags} {cmake_targets}"
|
|
20
|
+
print(cmd)
|
|
21
|
+
|
|
22
|
+
result = subprocess.run(
|
|
23
|
+
args=cmd,
|
|
24
|
+
capture_output=False,
|
|
25
|
+
check=False,
|
|
26
|
+
shell=True,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
return result.returncode
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def generate(env):
|
|
33
|
+
cmake_binary_builder = Builder(action=cmake_action)
|
|
34
|
+
|
|
35
|
+
env.Append(BUILDERS={"CmakeBinary": cmake_binary_builder})
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def exists(env):
|
|
39
|
+
return env.Detect("cmake")
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
4
|
+
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
5
|
+
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
import os
|
|
9
|
+
import platform
|
|
10
|
+
import subprocess
|
|
11
|
+
|
|
12
|
+
from typing import List
|
|
13
|
+
|
|
14
|
+
from SCons.Script import Builder
|
|
15
|
+
from SCons.Script import Environment
|
|
16
|
+
|
|
17
|
+
from scons_xo_exts_lib.BuildSupport import NodeMangling
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _dotnet_get_dotnet_exe(env: Environment) -> str:
|
|
21
|
+
dotnet_exe = env.get("DOTNET_EXE")
|
|
22
|
+
|
|
23
|
+
if dotnet_exe:
|
|
24
|
+
return dotnet_exe
|
|
25
|
+
|
|
26
|
+
try:
|
|
27
|
+
return os.path.join(env["DOTNET_ROOT"], "dotnet")
|
|
28
|
+
except KeyError:
|
|
29
|
+
return "dotnet"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _dotnet_get_project(source) -> str:
|
|
33
|
+
regex = ".*\\.(cs|fs|vb|)proj$"
|
|
34
|
+
|
|
35
|
+
try:
|
|
36
|
+
node = NodeMangling.regex_find_node(regex=regex, nodes=source)
|
|
37
|
+
|
|
38
|
+
return str(node.abspath)
|
|
39
|
+
except Exception as exception:
|
|
40
|
+
raise RuntimeError("No dotnet project file found", exception)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def _dotnet_command(env: Environment, source, args: List[str]) -> None:
|
|
44
|
+
project_file = _dotnet_get_project(source=source)
|
|
45
|
+
source_directory = os.path.dirname(project_file)
|
|
46
|
+
|
|
47
|
+
extra_variables = {
|
|
48
|
+
"DOTNET_CLI_TELEMETRY_OPTOUT": "1",
|
|
49
|
+
"DOTNET_NOLOGO": "1",
|
|
50
|
+
"DOTNET_SKIP_FIRST_TIME_EXPERIENCE": "1",
|
|
51
|
+
"MSBUILDTERMINALLOGGER": "off",
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
subprocess_env = env.Clone()["ENV"]
|
|
55
|
+
subprocess_env.update(extra_variables)
|
|
56
|
+
|
|
57
|
+
dotnet_exe = _dotnet_get_dotnet_exe(env=env)
|
|
58
|
+
|
|
59
|
+
cmd = [dotnet_exe] + args
|
|
60
|
+
print(cmd)
|
|
61
|
+
|
|
62
|
+
result = subprocess.run(
|
|
63
|
+
args=cmd,
|
|
64
|
+
capture_output=False,
|
|
65
|
+
check=False,
|
|
66
|
+
cwd=source_directory,
|
|
67
|
+
env=subprocess_env,
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
if result.returncode == 0:
|
|
71
|
+
return
|
|
72
|
+
|
|
73
|
+
raise RuntimeError("Dotnet command failed")
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def _dotnet_detect_rid() -> str:
|
|
77
|
+
"""
|
|
78
|
+
Returns a dotnet runtime identifier string in the format "{os}-{arch}".
|
|
79
|
+
|
|
80
|
+
OS values: linux, linux-musl, windows, osx
|
|
81
|
+
Arch values: x64, x86, arm, arm64
|
|
82
|
+
"""
|
|
83
|
+
|
|
84
|
+
os_name = "unknownos"
|
|
85
|
+
os_arch = "unknownarch"
|
|
86
|
+
|
|
87
|
+
py_os_name = platform.system().lower()
|
|
88
|
+
py_os_arch = platform.machine().lower()
|
|
89
|
+
|
|
90
|
+
match py_os_name:
|
|
91
|
+
case "linux":
|
|
92
|
+
if platform.libc_ver()[0] == "glibc":
|
|
93
|
+
os_name = "linux"
|
|
94
|
+
else:
|
|
95
|
+
os_name = "linux-musl"
|
|
96
|
+
case "darwin":
|
|
97
|
+
os_name = "osx"
|
|
98
|
+
case "windows":
|
|
99
|
+
os_name = "win"
|
|
100
|
+
case _:
|
|
101
|
+
os_name = py_os_name
|
|
102
|
+
|
|
103
|
+
match py_os_arch:
|
|
104
|
+
case "x86_64" | "amd64":
|
|
105
|
+
os_arch = "x64"
|
|
106
|
+
case "i386" | "i686":
|
|
107
|
+
os_arch = "x86"
|
|
108
|
+
case "aarch64":
|
|
109
|
+
os_arch = "arm64"
|
|
110
|
+
case _:
|
|
111
|
+
os_arch = py_os_arch
|
|
112
|
+
|
|
113
|
+
return f"{os_name}-{os_arch}"
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def _dotnet_get_rid(env: Environment) -> str:
|
|
117
|
+
key = "DOTNET_RUNTIME"
|
|
118
|
+
|
|
119
|
+
if key in env:
|
|
120
|
+
return env[key]
|
|
121
|
+
|
|
122
|
+
return _dotnet_detect_rid()
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def _dotnet_get_configuration(env: Environment) -> str:
|
|
126
|
+
key = "DOTNET_CONFIGURATION"
|
|
127
|
+
|
|
128
|
+
if key in env:
|
|
129
|
+
return env[key]
|
|
130
|
+
|
|
131
|
+
return "Release"
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def _dotnet_restore(env: Environment, source) -> None:
|
|
135
|
+
runtime = _dotnet_get_rid(env=env)
|
|
136
|
+
|
|
137
|
+
_dotnet_command(
|
|
138
|
+
env=env,
|
|
139
|
+
source=source,
|
|
140
|
+
args=[
|
|
141
|
+
"restore",
|
|
142
|
+
"--force-evaluate",
|
|
143
|
+
f"--runtime={runtime}",
|
|
144
|
+
],
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def _dotnet_build(env: Environment, source) -> None:
|
|
149
|
+
runtime = _dotnet_get_rid(env=env)
|
|
150
|
+
configuration = _dotnet_get_configuration(env=env)
|
|
151
|
+
|
|
152
|
+
_dotnet_command(
|
|
153
|
+
env=env,
|
|
154
|
+
source=source,
|
|
155
|
+
args=[
|
|
156
|
+
"build",
|
|
157
|
+
"--no-restore",
|
|
158
|
+
f"--runtime={runtime}",
|
|
159
|
+
f"--configuration={configuration}",
|
|
160
|
+
],
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def _dotnet_compile(*args, **kwargs) -> None:
|
|
165
|
+
_dotnet_restore(*args, **kwargs)
|
|
166
|
+
_dotnet_build(*args, **kwargs)
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def _dotnet_pack(env: Environment, source, target) -> None:
|
|
170
|
+
runtime = _dotnet_get_rid(env=env)
|
|
171
|
+
configuration = _dotnet_get_configuration(env=env)
|
|
172
|
+
|
|
173
|
+
target_directory = NodeMangling.get_first_directory(nodes=target)
|
|
174
|
+
|
|
175
|
+
_dotnet_command(
|
|
176
|
+
env=env,
|
|
177
|
+
source=source,
|
|
178
|
+
args=[
|
|
179
|
+
"pack",
|
|
180
|
+
"--no-restore",
|
|
181
|
+
f"--runtime={runtime}",
|
|
182
|
+
f"--configuration={configuration}",
|
|
183
|
+
f"--output={target_directory}",
|
|
184
|
+
],
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def _dotnet_compile_binary(env: Environment, source, target) -> None:
|
|
189
|
+
runtime = _dotnet_get_rid(env=env)
|
|
190
|
+
configuration = _dotnet_get_configuration(env=env)
|
|
191
|
+
|
|
192
|
+
target_directory = NodeMangling.get_first_directory(nodes=target)
|
|
193
|
+
|
|
194
|
+
_dotnet_command(
|
|
195
|
+
env=env,
|
|
196
|
+
source=source,
|
|
197
|
+
args=[
|
|
198
|
+
"publish",
|
|
199
|
+
"--no-restore",
|
|
200
|
+
"--self-contained",
|
|
201
|
+
"-p:PublishSingleFile=true",
|
|
202
|
+
f"--runtime={runtime}",
|
|
203
|
+
f"--configuration={configuration}",
|
|
204
|
+
f"--output={target_directory}",
|
|
205
|
+
],
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def dotnet_package_build_action(target, source, env: Environment) -> int:
|
|
210
|
+
try:
|
|
211
|
+
_dotnet_compile(env=env, source=source)
|
|
212
|
+
_dotnet_pack(env=env, source=source, target=target)
|
|
213
|
+
except RuntimeError:
|
|
214
|
+
return 1
|
|
215
|
+
|
|
216
|
+
return 0
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def dotnet_binary_build_action(target, source, env) -> int:
|
|
220
|
+
try:
|
|
221
|
+
_dotnet_compile(env=env, source=source)
|
|
222
|
+
_dotnet_compile_binary(env=env, source=source, target=target)
|
|
223
|
+
except RuntimeError:
|
|
224
|
+
return 1
|
|
225
|
+
|
|
226
|
+
return 0
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
def generate(env: Environment) -> None:
|
|
230
|
+
dotnet_binary_builder = Builder(action=dotnet_binary_build_action)
|
|
231
|
+
dotnet_package_builder = Builder(action=dotnet_package_build_action)
|
|
232
|
+
|
|
233
|
+
env.Append(
|
|
234
|
+
BUILDERS={
|
|
235
|
+
"DotnetBinary": dotnet_binary_builder,
|
|
236
|
+
"DotnetPackage": dotnet_package_builder,
|
|
237
|
+
}
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def exists(env: Environment):
|
|
242
|
+
return env.Detect("dotnet")
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
4
|
+
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
5
|
+
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
import os
|
|
9
|
+
import subprocess
|
|
10
|
+
|
|
11
|
+
from SCons.Script import Builder
|
|
12
|
+
from SCons.Script import Environment
|
|
13
|
+
|
|
14
|
+
from scons_xo_exts_lib.BuildSupport import NodeMangling
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _get_dune_project(source: list):
|
|
18
|
+
for source_node in source:
|
|
19
|
+
path = source_node.abspath
|
|
20
|
+
|
|
21
|
+
if "dune-project" in path:
|
|
22
|
+
return path
|
|
23
|
+
|
|
24
|
+
raise RuntimeError("No dune-project in specified sources")
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _dune_command(env: Environment, args_string: str, cwd: str) -> int:
|
|
28
|
+
dune_exe = env.get("DUNE_EXE", "dune")
|
|
29
|
+
dune_flags = env.get("DUNE_FLAGS", "--display=short")
|
|
30
|
+
|
|
31
|
+
cmd = f"{dune_exe} {args_string} {dune_flags}"
|
|
32
|
+
print(cmd)
|
|
33
|
+
|
|
34
|
+
result = subprocess.run(
|
|
35
|
+
args=cmd,
|
|
36
|
+
capture_output=False,
|
|
37
|
+
check=False,
|
|
38
|
+
cwd=cwd,
|
|
39
|
+
shell=True,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
return result.returncode
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _dune_get_install_prefix(target) -> str:
|
|
46
|
+
"""
|
|
47
|
+
Guess the install prefix for "dune install --prefix=...".
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
separators = ["/bin/", "/lib/"]
|
|
51
|
+
|
|
52
|
+
target_node = NodeMangling.get_first_node(target)
|
|
53
|
+
path = str(target_node)
|
|
54
|
+
|
|
55
|
+
try:
|
|
56
|
+
for separator in separators:
|
|
57
|
+
if separator in path:
|
|
58
|
+
substrings = path.split(sep=separator, maxsplit=1)
|
|
59
|
+
prefix = substrings[0]
|
|
60
|
+
|
|
61
|
+
return os.path.abspath(prefix)
|
|
62
|
+
|
|
63
|
+
raise RuntimeError("Separator not found in target")
|
|
64
|
+
|
|
65
|
+
except Exception:
|
|
66
|
+
raise RuntimeError(f"Could not guess prefix, given: {path}")
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def dune_build_action(target, source, env) -> int:
|
|
70
|
+
dune_project = _get_dune_project(source=source)
|
|
71
|
+
dune_base_dir = os.path.dirname(dune_project)
|
|
72
|
+
|
|
73
|
+
result = _dune_command(
|
|
74
|
+
env=env,
|
|
75
|
+
args_string="build @install",
|
|
76
|
+
cwd=dune_base_dir,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
return result
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def dune_image_action(target, source, env) -> int:
|
|
83
|
+
dune_project = _get_dune_project(source=source)
|
|
84
|
+
dune_base_dir = os.path.dirname(dune_project)
|
|
85
|
+
|
|
86
|
+
install_prefix = _dune_get_install_prefix(target=target)
|
|
87
|
+
|
|
88
|
+
result = _dune_command(
|
|
89
|
+
env=env,
|
|
90
|
+
args_string=f"install --prefix={install_prefix}",
|
|
91
|
+
cwd=dune_base_dir,
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
return result
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def generate(env: Environment) -> None:
|
|
98
|
+
dune_binary_builder = Builder(action=dune_build_action)
|
|
99
|
+
dune_image_builder = Builder(action=dune_image_action)
|
|
100
|
+
|
|
101
|
+
env.Append(
|
|
102
|
+
BUILDERS={
|
|
103
|
+
"DuneBinary": dune_binary_builder,
|
|
104
|
+
"DuneImage": dune_image_builder,
|
|
105
|
+
},
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def exists(env: Environment):
|
|
110
|
+
return env.Detect("dune")
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
4
|
+
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
5
|
+
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
import os
|
|
9
|
+
import subprocess
|
|
10
|
+
|
|
11
|
+
from SCons.Node import FS
|
|
12
|
+
|
|
13
|
+
from SCons.Script import Builder
|
|
14
|
+
from SCons.Script import Environment
|
|
15
|
+
|
|
16
|
+
from scons_xo_exts_lib.BuildSupport import NodeMangling
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _elisp_construct_load_path(sources: list) -> str:
|
|
20
|
+
"""
|
|
21
|
+
:param sources: list of files to construct a load path from
|
|
22
|
+
:returns: Emacs load path command-line options
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
load_path_flags: set[str] = set()
|
|
26
|
+
|
|
27
|
+
for source in sources:
|
|
28
|
+
if isinstance(source, FS.File):
|
|
29
|
+
dir_name = source.get_dir().relpath
|
|
30
|
+
else:
|
|
31
|
+
dir_name = os.path.dirname(str(source))
|
|
32
|
+
|
|
33
|
+
# Then check if the directory **really** exists.
|
|
34
|
+
if dir_name and os.path.exists(dir_name):
|
|
35
|
+
load_flag = f"-L {dir_name}"
|
|
36
|
+
|
|
37
|
+
load_path_flags.add(load_flag)
|
|
38
|
+
|
|
39
|
+
return " ".join(load_path_flags)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _elisp_get_emacs_exe(env: Environment) -> str:
|
|
43
|
+
emacs_exe = env.get("EMACS_EXE")
|
|
44
|
+
emacs_version = env.get("EMACS_VERSION")
|
|
45
|
+
|
|
46
|
+
if not emacs_exe:
|
|
47
|
+
if emacs_version:
|
|
48
|
+
return f"emacs-{emacs_version}"
|
|
49
|
+
|
|
50
|
+
return "emacs"
|
|
51
|
+
|
|
52
|
+
return emacs_exe
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _elisp_get_base_command(env: Environment) -> str:
|
|
56
|
+
exe: str = _elisp_get_emacs_exe(env)
|
|
57
|
+
|
|
58
|
+
exec_flags = env.get("EMACS_EXEC_FLAGS", "-batch -q --no-site-file")
|
|
59
|
+
extra_flags = env.get("EMACS_EXTRA_FLAGS", "")
|
|
60
|
+
|
|
61
|
+
return f"{exe} {exec_flags} {extra_flags}"
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def elisp_autoloads_action(target, source, env) -> int:
|
|
65
|
+
directory = NodeMangling.get_first_directory(source[0])
|
|
66
|
+
out = NodeMangling.get_first_node(target).abspath
|
|
67
|
+
|
|
68
|
+
base_args = _elisp_get_base_command(env)
|
|
69
|
+
|
|
70
|
+
func = f'loaddefs-generate \\"{directory}\\" \\"{out}\\"'
|
|
71
|
+
flags = f'--eval "({func})"'
|
|
72
|
+
|
|
73
|
+
cmd = f"{base_args} {flags}"
|
|
74
|
+
print(cmd)
|
|
75
|
+
|
|
76
|
+
result = subprocess.run(
|
|
77
|
+
args=cmd,
|
|
78
|
+
capture_output=False,
|
|
79
|
+
check=False,
|
|
80
|
+
cwd=directory,
|
|
81
|
+
shell=True,
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
return result.returncode
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def elisp_binary_action(target, source, env) -> int:
|
|
88
|
+
srcs: str = " ".join(str(s) for s in source)
|
|
89
|
+
load_path: str = _elisp_construct_load_path(sources=source)
|
|
90
|
+
|
|
91
|
+
base_args = _elisp_get_base_command(env)
|
|
92
|
+
comp_flags = env.get("EMACS_COMP_FLAGS", "-L .")
|
|
93
|
+
|
|
94
|
+
func = "batch-byte-compile"
|
|
95
|
+
flags = f"{comp_flags} {load_path} -f {func}"
|
|
96
|
+
|
|
97
|
+
cmd = f"{base_args} {flags} {srcs}"
|
|
98
|
+
print(cmd)
|
|
99
|
+
|
|
100
|
+
result = subprocess.run(
|
|
101
|
+
args=cmd,
|
|
102
|
+
capture_output=False,
|
|
103
|
+
check=False,
|
|
104
|
+
shell=True,
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
return result.returncode
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def generate(env: Environment) -> None:
|
|
111
|
+
autoloads_builder = Builder(action=elisp_autoloads_action)
|
|
112
|
+
|
|
113
|
+
binary_builder = Builder(
|
|
114
|
+
action=elisp_binary_action,
|
|
115
|
+
src_suffix=".el",
|
|
116
|
+
suffix=".elc",
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
env.Append(
|
|
120
|
+
BUILDERS={
|
|
121
|
+
"ElispAutoloadsFile": autoloads_builder,
|
|
122
|
+
"ElispBinary": binary_builder,
|
|
123
|
+
}
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def exists(env: Environment):
|
|
128
|
+
return env.Detect(progs="elisp")
|