relenv 0.21.2__py3-none-any.whl → 0.22.1__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 (49) hide show
  1. relenv/__init__.py +14 -2
  2. relenv/__main__.py +12 -6
  3. relenv/_resources/xz/config.h +148 -0
  4. relenv/_resources/xz/readme.md +4 -0
  5. relenv/build/__init__.py +28 -30
  6. relenv/build/common/__init__.py +50 -0
  7. relenv/build/common/_sysconfigdata_template.py +72 -0
  8. relenv/build/common/builder.py +907 -0
  9. relenv/build/common/builders.py +163 -0
  10. relenv/build/common/download.py +324 -0
  11. relenv/build/common/install.py +609 -0
  12. relenv/build/common/ui.py +432 -0
  13. relenv/build/darwin.py +128 -14
  14. relenv/build/linux.py +292 -74
  15. relenv/build/windows.py +123 -169
  16. relenv/buildenv.py +48 -17
  17. relenv/check.py +10 -5
  18. relenv/common.py +492 -165
  19. relenv/create.py +147 -7
  20. relenv/fetch.py +16 -4
  21. relenv/manifest.py +15 -7
  22. relenv/python-versions.json +350 -0
  23. relenv/pyversions.py +817 -30
  24. relenv/relocate.py +101 -55
  25. relenv/runtime.py +457 -282
  26. relenv/toolchain.py +9 -3
  27. {relenv-0.21.2.dist-info → relenv-0.22.1.dist-info}/METADATA +1 -1
  28. relenv-0.22.1.dist-info/RECORD +48 -0
  29. tests/__init__.py +2 -0
  30. tests/_pytest_typing.py +45 -0
  31. tests/conftest.py +42 -36
  32. tests/test_build.py +426 -9
  33. tests/test_common.py +373 -48
  34. tests/test_create.py +149 -6
  35. tests/test_downloads.py +19 -15
  36. tests/test_fips_photon.py +6 -3
  37. tests/test_module_imports.py +44 -0
  38. tests/test_pyversions_runtime.py +177 -0
  39. tests/test_relocate.py +45 -39
  40. tests/test_relocate_module.py +257 -0
  41. tests/test_runtime.py +1968 -6
  42. tests/test_verify_build.py +477 -34
  43. relenv/build/common.py +0 -1707
  44. relenv-0.21.2.dist-info/RECORD +0 -35
  45. {relenv-0.21.2.dist-info → relenv-0.22.1.dist-info}/WHEEL +0 -0
  46. {relenv-0.21.2.dist-info → relenv-0.22.1.dist-info}/entry_points.txt +0 -0
  47. {relenv-0.21.2.dist-info → relenv-0.22.1.dist-info}/licenses/LICENSE.md +0 -0
  48. {relenv-0.21.2.dist-info → relenv-0.22.1.dist-info}/licenses/NOTICE +0 -0
  49. {relenv-0.21.2.dist-info → relenv-0.22.1.dist-info}/top_level.txt +0 -0
relenv/build/windows.py CHANGED
@@ -1,8 +1,11 @@
1
1
  # Copyright 2022-2025 Broadcom.
2
2
  # SPDX-License-Identifier: Apache-2
3
+ # mypy: ignore-errors
3
4
  """
4
5
  The windows build process.
5
6
  """
7
+ from __future__ import annotations
8
+
6
9
  import glob
7
10
  import json
8
11
  import logging
@@ -11,24 +14,34 @@ import pathlib
11
14
  import shutil
12
15
  import sys
13
16
  import tarfile
17
+ import time
18
+ from typing import IO, MutableMapping, Union
14
19
 
15
20
  from .common import (
21
+ Dirs,
16
22
  builds,
17
23
  create_archive,
18
- download_url,
19
- extract_archive,
24
+ get_dependency_version,
20
25
  install_runtime,
21
- MODULE_DIR,
22
26
  patch_file,
23
- runcmd,
24
27
  update_ensurepip,
28
+ update_sbom_checksums,
29
+ )
30
+ from ..common import (
31
+ WIN32,
32
+ arches,
33
+ MODULE_DIR,
34
+ download_url,
35
+ extract_archive,
36
+ runcmd,
25
37
  )
26
- from ..common import arches, WIN32, Version
27
38
 
28
39
  log = logging.getLogger(__name__)
29
40
 
30
41
  ARCHES = arches[WIN32]
31
42
 
43
+ EnvMapping = MutableMapping[str, str]
44
+
32
45
  if sys.platform == WIN32:
33
46
  import ctypes
34
47
 
@@ -36,7 +49,7 @@ if sys.platform == WIN32:
36
49
  kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 7)
37
50
 
38
51
 
39
- def populate_env(env, dirs):
52
+ def populate_env(env: EnvMapping, dirs: Dirs) -> None:
40
53
  """
41
54
  Make sure we have the correct environment variables set.
42
55
 
@@ -48,7 +61,7 @@ def populate_env(env, dirs):
48
61
  env["MSBUILDDISABLENODEREUSE"] = "1"
49
62
 
50
63
 
51
- def update_props(source, old, new):
64
+ def update_props(source: pathlib.Path, old: str, new: str) -> None:
52
65
  """
53
66
  Overwrite a dependency string for Windows PCBuild.
54
67
 
@@ -63,7 +76,7 @@ def update_props(source, old, new):
63
76
  patch_file(source / "PCbuild" / "get_externals.bat", old, new)
64
77
 
65
78
 
66
- def get_externals_source(externals_dir, url):
79
+ def get_externals_source(externals_dir: pathlib.Path, url: str) -> None:
67
80
  """
68
81
  Download external source code dependency.
69
82
 
@@ -80,7 +93,7 @@ def get_externals_source(externals_dir, url):
80
93
  log.exception("Failed to remove temporary file")
81
94
 
82
95
 
83
- def get_externals_bin(source_root, url):
96
+ def get_externals_bin(source_root: pathlib.Path, url: str) -> None:
84
97
  """
85
98
  Download external binary dependency.
86
99
 
@@ -90,13 +103,25 @@ def get_externals_bin(source_root, url):
90
103
  pass
91
104
 
92
105
 
93
- def update_sqlite(dirs, env):
106
+ def update_sqlite(dirs: Dirs, env: EnvMapping) -> None:
94
107
  """
95
108
  Update the SQLITE library.
96
109
  """
97
- version = "3.50.4.0"
98
- url = "https://sqlite.org/2025/sqlite-autoconf-3500400.tar.gz"
99
- sha256 = "a3db587a1b92ee5ddac2f66b3edb41b26f9c867275782d46c3a088977d6a5b18"
110
+ # Try to get version from JSON
111
+ sqlite_info = get_dependency_version("sqlite", "win32")
112
+ if sqlite_info:
113
+ version = sqlite_info["version"]
114
+ url_template = sqlite_info["url"]
115
+ sha256 = sqlite_info["sha256"]
116
+ sqliteversion = sqlite_info.get("sqliteversion", "3500400")
117
+ # Format the URL with sqliteversion (the 7-digit version number)
118
+ url = url_template.format(version=sqliteversion)
119
+ else:
120
+ # Fallback to hardcoded values
121
+ version = "3.50.4.0"
122
+ url = "https://sqlite.org/2025/sqlite-autoconf-3500400.tar.gz"
123
+ sha256 = "a3db587a1b92ee5ddac2f66b3edb41b26f9c867275782d46c3a088977d6a5b18"
124
+ sqliteversion = "3500400"
100
125
  ref_loc = f"cpe:2.3:a:sqlite:sqlite:{version}:*:*:*:*:*:*:*"
101
126
  target_dir = dirs.source / "externals" / f"sqlite-{version}"
102
127
  target_dir.parent.mkdir(parents=True, exist_ok=True)
@@ -104,7 +129,7 @@ def update_sqlite(dirs, env):
104
129
  update_props(dirs.source, r"sqlite-\d+.\d+.\d+.\d+", f"sqlite-{version}")
105
130
  get_externals_source(externals_dir=dirs.source / "externals", url=url)
106
131
  # # we need to fix the name of the extracted directory
107
- extracted_dir = dirs.source / "externals" / "sqlite-autoconf-3500400"
132
+ extracted_dir = dirs.source / "externals" / f"sqlite-autoconf-{sqliteversion}"
108
133
  shutil.move(str(extracted_dir), str(target_dir))
109
134
  # Update externals.spdx.json with the correct version, url, and hash
110
135
  # This became a thing in 3.12
@@ -122,13 +147,43 @@ def update_sqlite(dirs, env):
122
147
  json.dump(data, f, indent=2)
123
148
 
124
149
 
125
- def update_xz(dirs, env):
150
+ def update_xz(dirs: Dirs, env: EnvMapping) -> None:
126
151
  """
127
152
  Update the XZ library.
153
+
154
+ COMPATIBILITY NOTE: We use config.h from XZ 5.4.7 for all XZ versions.
155
+ Starting with XZ 5.5.0, the project removed Visual Studio .vcxproj files
156
+ and switched to CMake. Python's build system (PCbuild/liblzma.vcxproj)
157
+ still expects MSBuild-compatible builds, so we maintain a compatibility
158
+ shim at relenv/_resources/xz/config.h.
159
+
160
+ When updating XZ versions, verify compatibility by checking:
161
+ 1. Build completes without compiler errors
162
+ 2. test_xz_lzma_functionality passes
163
+ 3. No new HAVE_* defines required in src/liblzma source files
164
+ 4. No removed HAVE_* defines that config.h references
165
+
166
+ If compatibility breaks, you have two options:
167
+ - Use CMake to generate new config.h for Windows (see discussion at
168
+ https://discuss.python.org/t/building-python-from-source-on-windows-using-a-custom-version-of-xz/74717)
169
+ - Update relenv/_resources/xz/config.h manually from newer XZ source
170
+
171
+ See also: relenv/_resources/xz/readme.md
128
172
  """
129
- version = "5.6.2"
130
- url = f"https://github.com/tukaani-project/xz/releases/download/v{version}/xz-{version}.tar.xz"
131
- sha256 = "8bfd20c0e1d86f0402f2497cfa71c6ab62d4cd35fd704276e3140bfb71414519"
173
+ # Try to get version from JSON
174
+ # Note: Windows may use a different XZ version than Linux/Darwin due to MSBuild compatibility
175
+ xz_info = get_dependency_version("xz", "win32")
176
+ if xz_info:
177
+ version = xz_info["version"]
178
+ url_template = xz_info["url"]
179
+ sha256 = xz_info["sha256"]
180
+ url = url_template.format(version=version)
181
+ else:
182
+ # Fallback to hardcoded values
183
+ # Note: Using 5.6.2 for MSBuild compatibility (5.5.0+ removed MSBuild support)
184
+ version = "5.6.2"
185
+ url = f"https://github.com/tukaani-project/xz/releases/download/v{version}/xz-{version}.tar.xz"
186
+ sha256 = "8bfd20c0e1d86f0402f2497cfa71c6ab62d4cd35fd704276e3140bfb71414519"
132
187
  ref_loc = f"cpe:2.3:a:tukaani:xz:{version}:*:*:*:*:*:*:*"
133
188
  target_dir = dirs.source / "externals" / f"xz-{version}"
134
189
  target_dir.parent.mkdir(parents=True, exist_ok=True)
@@ -158,14 +213,23 @@ def update_xz(dirs, env):
158
213
  json.dump(data, f, indent=2)
159
214
 
160
215
 
161
- def update_expat(dirs, env):
216
+ def update_expat(dirs: Dirs, env: EnvMapping) -> None:
162
217
  """
163
218
  Update the EXPAT library.
164
219
  """
165
220
  # Patch <src>/Modules/expat/refresh.sh. When the SBOM is created, refresh.sh
166
221
  # is scanned for the expat version, even though it doesn't run on Windows.
167
- version = "2.7.3"
168
- hash = "821ac9710d2c073eaf13e1b1895a9c9aa66c1157a99635c639fbff65cdbdd732"
222
+
223
+ # Try to get version from JSON
224
+ expat_info = get_dependency_version("expat", "win32")
225
+ if expat_info:
226
+ version = expat_info["version"]
227
+ hash = expat_info["sha256"]
228
+ else:
229
+ # Fallback to hardcoded values
230
+ version = "2.7.3"
231
+ hash = "821ac9710d2c073eaf13e1b1895a9c9aa66c1157a99635c639fbff65cdbdd732"
232
+
169
233
  url = f'https://github.com/libexpat/libexpat/releases/download/R_{version.replace(".", "_")}/expat-{version}.tar.xz'
170
234
  bash_refresh = dirs.source / "Modules" / "expat" / "refresh.sh"
171
235
  old = r'expected_libexpat_tag="R_\d+_\d+_\d"'
@@ -181,137 +245,43 @@ def update_expat(dirs, env):
181
245
  # Copy *.h and *.c to expat directory
182
246
  expat_lib_dir = dirs.source / "Modules" / "expat" / f"expat-{version}" / "lib"
183
247
  expat_dir = dirs.source / "Modules" / "expat"
248
+ updated_files = []
184
249
  for file in glob.glob(str(expat_lib_dir / "*.h")):
185
- if expat_dir / os.path.basename(file):
186
- (expat_dir / os.path.basename(file)).unlink()
250
+ target = expat_dir / os.path.basename(file)
251
+ if target.exists():
252
+ target.unlink()
187
253
  shutil.move(file, str(expat_dir))
254
+ updated_files.append(target)
188
255
  for file in glob.glob(str(expat_lib_dir / "*.c")):
189
- if expat_dir / os.path.basename(file):
190
- (expat_dir / os.path.basename(file)).unlink()
256
+ target = expat_dir / os.path.basename(file)
257
+ if target.exists():
258
+ target.unlink()
191
259
  shutil.move(file, str(expat_dir))
192
- # Update sbom.spdx.json with the correct hashes. This became a thing in 3.12
193
- # python Tools/build/generate_sbom.py doesn't work because it requires a git
194
- # repository, so we have to do it manually.
195
- if env["RELENV_PY_MAJOR_VERSION"] in ["3.12", "3.13", "3.14"]:
196
- checksums = {
197
- "Modules/expat/expat.h": [
198
- {
199
- "algorithm": "SHA1",
200
- "checksumValue": "a4395dd0589a97aab0904f7a5f5dc5781a086aa2",
201
- },
202
- {
203
- "algorithm": "SHA256",
204
- "checksumValue": "610b844bbfa3ec955772cc825db4d4db470827d57adcb214ad372d0eaf00e591",
205
- },
206
- ],
207
- "Modules/expat/expat_external.h": [
208
- {
209
- "algorithm": "SHA1",
210
- "checksumValue": "8fdf2e79a7ab46a3c76c74ed7e5fe641cbef308d",
211
- },
212
- {
213
- "algorithm": "SHA256",
214
- "checksumValue": "ffb960af48b80935f3856a16e87023524b104f7fc1e58104f01db88ba7bfbcc9",
215
- },
216
- ],
217
- "Modules/expat/internal.h": [
218
- {
219
- "algorithm": "SHA1",
220
- "checksumValue": "7dce7d98943c5db33ae05e54801dcafb4547b9dd",
221
- },
222
- {
223
- "algorithm": "SHA256",
224
- "checksumValue": "6bfe307d52e7e4c71dbc30d3bd902a4905cdd83bbe4226a7e8dfa8e4c462a157",
225
- },
226
- ],
227
- "Modules/expat/refresh.sh": [
228
- {
229
- "algorithm": "SHA1",
230
- "checksumValue": "71812ca27328697a8dcae1949cd638717538321a",
231
- },
232
- {
233
- "algorithm": "SHA256",
234
- "checksumValue": "64fd1368de41e4ebc14593c65f5a676558aed44bd7d71c43ae05d06f9086d3b0",
235
- },
236
- ],
237
- "Modules/expat/xmlparse.c": [
238
- {
239
- "algorithm": "SHA1",
240
- "checksumValue": "4c81a1f04fc653877c63c834145c18f93cd95f3e",
241
- },
242
- {
243
- "algorithm": "SHA256",
244
- "checksumValue": "04a379615f476d55f95ca1853107e20627b48ca4afe8d0fd5981ac77188bf0a6",
245
- },
246
- ],
247
- "Modules/expat/xmlrole.h": [
248
- {
249
- "algorithm": "SHA1",
250
- "checksumValue": "ac2964cca107f62dd133bfd4736a9a17defbc401",
251
- },
252
- {
253
- "algorithm": "SHA256",
254
- "checksumValue": "92e41f373b67f6e0dcd7735faef3c3f1e2c17fe59e007e6b74beef6a2e70fa88",
255
- },
256
- ],
257
- "Modules/expat/xmltok.c": [
258
- {
259
- "algorithm": "SHA1",
260
- "checksumValue": "1e2d35d90a1c269217f83d3bdf3c71cc22cb4c3f",
261
- },
262
- {
263
- "algorithm": "SHA256",
264
- "checksumValue": "98d0fc735041956cc2e7bbbe2fb8f03130859410e0aee5e8015f406a37c02a3c",
265
- },
266
- ],
267
- "Modules/expat/xmltok.h": [
268
- {
269
- "algorithm": "SHA1",
270
- "checksumValue": "d126831eaa5158cff187a8c93f4bc1c8118f3b17",
271
- },
272
- {
273
- "algorithm": "SHA256",
274
- "checksumValue": "91bf003a725a675761ea8d92cebc299a76fd28c3a950572f41bc7ce5327ee7b5",
275
- },
276
- ],
277
- }
278
- spdx_json = dirs.source / "Misc" / "sbom.spdx.json"
279
- with open(str(spdx_json), "r") as f:
280
- data = json.load(f)
281
- for file in data["files"]:
282
- if file["fileName"] in checksums.keys():
283
- print(file["fileName"])
284
- file["checksums"] = checksums[file["fileName"]]
285
- with open(str(spdx_json), "w") as f:
286
- json.dump(data, f, indent=2)
260
+ updated_files.append(target)
261
+
262
+ # Touch all updated files to ensure MSBuild rebuilds them
263
+ # (The original files may have newer timestamps)
264
+ now = time.time()
265
+ for target_file in updated_files:
266
+ os.utime(target_file, (now, now))
267
+
268
+ # Update SBOM with correct checksums for updated expat files
269
+ # Map SBOM file names to actual file paths
270
+ files_to_update = {}
271
+ for target_file in updated_files:
272
+ # SBOM uses relative paths from Python source root
273
+ relative_path = f"Modules/expat/{target_file.name}"
274
+ files_to_update[relative_path] = target_file
275
+
276
+ # Also include refresh.sh which was patched
277
+ bash_refresh = dirs.source / "Modules" / "expat" / "refresh.sh"
278
+ if bash_refresh.exists():
279
+ files_to_update["Modules/expat/refresh.sh"] = bash_refresh
287
280
 
281
+ update_sbom_checksums(dirs.source, files_to_update)
288
282
 
289
- def update_expat_check(env):
290
- """
291
- Check if the given python version should get an updated libexpat.
292
-
293
- Patch libexpat on these versions and below:
294
- - 3.9.23
295
- - 3.10.18
296
- - 3.11.13
297
- - 3.12.11
298
- - 3.13.7
299
- """
300
- relenv_version = Version(env["RELENV_PY_VERSION"])
301
- if relenv_version.minor == 9 and relenv_version.micro <= 23:
302
- return True
303
- elif relenv_version.minor == 10 and relenv_version.micro <= 18:
304
- return True
305
- elif relenv_version.minor == 11 and relenv_version.micro <= 13:
306
- return True
307
- elif relenv_version.minor == 12 and relenv_version.micro <= 11:
308
- return True
309
- elif relenv_version.minor == 13 and relenv_version.micro <= 7:
310
- return True
311
- return False
312
-
313
-
314
- def build_python(env, dirs, logfp):
283
+
284
+ def build_python(env: EnvMapping, dirs: Dirs, logfp: IO[str]) -> None:
315
285
  """
316
286
  Run the commands to build Python.
317
287
 
@@ -328,27 +298,11 @@ def build_python(env, dirs, logfp):
328
298
  externals_dir = dirs.source / "externals"
329
299
  externals_dir.mkdir(parents=True, exist_ok=True)
330
300
 
331
- # SQLITE
332
- # TODO: Python 3.12 started creating an SBOM. We're doing something wrong
333
- # TODO: updating sqlite so SBOM creation is failing. Gating here until we
334
- # TODO: fix this. Here's the original gate:
335
- # if env["RELENV_PY_MAJOR_VERSION"] in ["3.10", "3.11", "3.12"]:
336
- if env["RELENV_PY_MAJOR_VERSION"] in ["3.10", "3.11"]:
337
- update_sqlite(dirs=dirs, env=env)
338
-
339
- # XZ-Utils
340
- # TODO: Python 3.12 started creating an SBOM. We're doing something wrong
341
- # TODO: updating XZ so SBOM creation is failing. Gating here until we fix
342
- # TODO: this. Here's the original gate:
343
- # if env["RELENV_PY_MAJOR_VERSION"] in ["3.10", "3.11", "3.12", "3.13", "3.14"]:
344
- if env["RELENV_PY_MAJOR_VERSION"] in ["3.10", "3.11"]:
345
- update_xz(dirs=dirs, env=env)
346
-
347
- # TODO: This was my attempt to fix the expat error during build... it failed
348
- # TODO: so we're just skipping for now.
349
- if env["RELENV_PY_MAJOR_VERSION"] in ["3.10", "3.11"]:
350
- if update_expat_check(env=env):
351
- update_expat(dirs=dirs, env=env)
301
+ update_sqlite(dirs=dirs, env=env)
302
+
303
+ update_xz(dirs=dirs, env=env)
304
+
305
+ update_expat(dirs=dirs, env=env)
352
306
 
353
307
  arch_to_plat = {
354
308
  "amd64": "x64",
@@ -447,7 +401,7 @@ build.add(
447
401
  )
448
402
 
449
403
 
450
- def finalize(env, dirs, logfp):
404
+ def finalize(env: EnvMapping, dirs: Dirs, logfp: IO[str]) -> None:
451
405
  """
452
406
  Finalize sitecustomize, relenv runtime, and pip for Windows.
453
407
 
@@ -469,7 +423,7 @@ def finalize(env, dirs, logfp):
469
423
  python = dirs.prefix / "Scripts" / "python.exe"
470
424
  runcmd([str(python), "-m", "ensurepip"], env=env, stderr=logfp, stdout=logfp)
471
425
 
472
- def runpip(pkg):
426
+ def runpip(pkg: Union[str, os.PathLike[str]]) -> None:
473
427
  # XXX Support cross pip installs on windows
474
428
  env = os.environ.copy()
475
429
  target = None
relenv/buildenv.py CHANGED
@@ -1,15 +1,21 @@
1
- # Copyright 2023-2025 Broadcom.
1
+ # Copyright 2022-2025 Broadcom.
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
  """
4
4
  Helper for building libraries to install into a relenv environment.
5
5
  """
6
+ from __future__ import annotations
7
+
8
+ import argparse
6
9
  import json
7
10
  import logging
11
+ import os
8
12
  import sys
13
+ from typing import Any, cast
9
14
 
10
15
  from .common import (
11
16
  MACOS_DEVELOPMENT_TARGET,
12
- RelenvException,
17
+ PlatformError,
18
+ RelenvEnvironmentError,
13
19
  get_toolchain,
14
20
  get_triplet,
15
21
  )
@@ -17,7 +23,9 @@ from .common import (
17
23
  log = logging.getLogger()
18
24
 
19
25
 
20
- def setup_parser(subparsers):
26
+ def setup_parser(
27
+ subparsers: argparse._SubParsersAction[argparse.ArgumentParser],
28
+ ) -> None:
21
29
  """
22
30
  Setup the subparser for the ``relenv buildenv`` command.
23
31
 
@@ -36,30 +44,33 @@ def setup_parser(subparsers):
36
44
  )
37
45
 
38
46
 
39
- def is_relenv():
47
+ def is_relenv() -> bool:
40
48
  """
41
49
  True when we are in a relenv environment.
42
50
  """
43
51
  return hasattr(sys, "RELENV")
44
52
 
45
53
 
46
- def buildenv(relenv_path=None):
54
+ def buildenv(
55
+ relenv_path: str | os.PathLike[str] | None = None,
56
+ ) -> dict[str, str]:
47
57
  """
48
58
  Relenv build environment variable mapping.
49
59
  """
50
60
  if not relenv_path:
51
61
  if not is_relenv():
52
- raise RelenvException("Not in a relenv environment")
53
- relenv_path = sys.RELENV
62
+ raise RelenvEnvironmentError("Not in a relenv environment")
63
+ relenv_path = cast(str | os.PathLike[str], cast(Any, sys).RELENV)
54
64
 
55
65
  if sys.platform != "linux":
56
- raise RelenvException("buildenv is only supported on Linux")
66
+ raise PlatformError("buildenv is only supported on Linux")
57
67
 
58
68
  toolchain = get_toolchain()
59
69
  if not toolchain:
60
- raise RelenvException("buildenv is only supported on Linux")
70
+ raise PlatformError("buildenv is only supported on Linux")
61
71
 
62
72
  triplet = get_triplet()
73
+ sysroot = f"{toolchain}/{triplet}/sysroot"
63
74
  env = {
64
75
  "RELENV_BUILDENV": "1",
65
76
  "TOOLCHAIN_PATH": f"{toolchain}",
@@ -67,30 +78,50 @@ def buildenv(relenv_path=None):
67
78
  "RELENV_PATH": f"{relenv_path}",
68
79
  "CC": f"{toolchain}/bin/{triplet}-gcc",
69
80
  "CXX": f"{toolchain}/bin/{triplet}-g++",
70
- "CFLAGS": f"-I{relenv_path}/include -I{toolchain}/sysroot/usr/include",
81
+ "CFLAGS": (
82
+ f"--sysroot={sysroot} "
83
+ f"-fPIC "
84
+ f"-I{relenv_path}/include "
85
+ f"-I{sysroot}/usr/include"
86
+ ),
71
87
  "CXXFLAGS": (
88
+ f"--sysroot={sysroot} "
89
+ f"-fPIC "
72
90
  f"-I{relenv_path}/include "
73
- f"-I{toolchain}/{triplet}/sysroot/usr/include "
74
- f"-L{relenv_path}/lib -L{toolchain}/{triplet}/sysroot/lib "
91
+ f"-I{sysroot}/usr/include "
92
+ f"-L{relenv_path}/lib -L{sysroot}/lib "
75
93
  f"-Wl,-rpath,{relenv_path}/lib"
76
94
  ),
77
95
  "CPPFLAGS": (
78
- f"-I{relenv_path}/include " f"-I{toolchain}/{triplet}/sysroot/usr/include"
96
+ f"--sysroot={sysroot} "
97
+ f"-fPIC "
98
+ f"-I{relenv_path}/include "
99
+ f"-I{sysroot}/usr/include"
79
100
  ),
80
101
  "CMAKE_CFLAGS": (
81
- f"-I{relenv_path}/include " f"-I{toolchain}/{triplet}/sysroot/usr/include"
102
+ f"--sysroot={sysroot} "
103
+ f"-fPIC "
104
+ f"-I{relenv_path}/include "
105
+ f"-I{sysroot}/usr/include"
82
106
  ),
83
107
  "LDFLAGS": (
84
- f"-L{relenv_path}/lib -L{toolchain}/{triplet}/sysroot/lib "
108
+ f"--sysroot={sysroot} "
109
+ f"-L{relenv_path}/lib -L{sysroot}/lib "
85
110
  f"-Wl,-rpath,{relenv_path}/lib"
86
111
  ),
112
+ "CRATE_CC_NO_DEFAULTS": "1",
113
+ "OPENSSL_DIR": f"{relenv_path}",
114
+ "OPENSSL_INCLUDE_DIR": f"{relenv_path}/include",
115
+ "OPENSSL_LIB_DIR": f"{relenv_path}/lib",
116
+ "PKG_CONFIG_PATH": f"{relenv_path}/lib/pkgconfig",
117
+ "RUSTFLAGS": f"-L {relenv_path}/lib -C link-arg=-Wl,-rpath,{relenv_path}/lib",
87
118
  }
88
- if sys.platform == "dawin":
119
+ if sys.platform == "darwin":
89
120
  env["MACOS_DEVELOPMENT_TARGET"] = MACOS_DEVELOPMENT_TARGET
90
121
  return env
91
122
 
92
123
 
93
- def main(args):
124
+ def main(args: argparse.Namespace) -> None:
94
125
  """
95
126
  The entrypoint into the ``relenv buildenv`` command.
96
127
 
relenv/check.py CHANGED
@@ -1,18 +1,23 @@
1
- # Copyright 2025 Broadcom.
1
+ # Copyright 2022-2025 Broadcom.
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
  """
4
4
  Check the integrety of a relenv environment.
5
5
  """
6
+ from __future__ import annotations
7
+
8
+ import argparse
6
9
  import logging
7
10
  import pathlib
8
11
  import sys
9
12
 
10
- from . import relocate
13
+ from relenv import relocate
11
14
 
12
- log = logging.getLogger()
15
+ log: logging.Logger = logging.getLogger(__name__)
13
16
 
14
17
 
15
- def setup_parser(subparsers):
18
+ def setup_parser(
19
+ subparsers: argparse._SubParsersAction[argparse.ArgumentParser],
20
+ ) -> None:
16
21
  """
17
22
  Setup the subparser for the ``relenv check`` command.
18
23
 
@@ -23,7 +28,7 @@ def setup_parser(subparsers):
23
28
  subparser.set_defaults(func=main)
24
29
 
25
30
 
26
- def main(args):
31
+ def main(args: argparse.Namespace) -> None:
27
32
  """
28
33
  The entrypoint into the ``relenv check`` command.
29
34