auditwheel-emscripten 0.0.16__py3-none-any.whl → 0.1.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.
@@ -1,12 +1,12 @@
1
1
  from .exports import get_exports
2
2
  from .imports import get_imports
3
- from .repair import copylib, repair, repair_extracted, resolve_sharedlib
3
+ from .repair import copylib, repair, resolve_sharedlib, modify_runtime_path
4
4
  from .show import show, show_dylib, show_wheel
5
5
 
6
6
  __all__ = [
7
7
  "repair",
8
- "repair_extracted",
9
8
  "resolve_sharedlib",
9
+ "modify_runtime_path",
10
10
  "show",
11
11
  "show_wheel",
12
12
  "show_dylib",
@@ -50,7 +50,7 @@ def _repair(
50
50
  wheel_file,
51
51
  libdir,
52
52
  output_dir,
53
- modify_needed_section=False,
53
+ modify_rpath=True,
54
54
  )
55
55
  dependencies = show(repaired_wheel)
56
56
  pprint(dependencies)
@@ -157,6 +157,7 @@ class DylinkType(IntEnum):
157
157
  NEEDED = 2
158
158
  EXPORT_INFO = 3
159
159
  IMPORT_INFO = 4
160
+ RUNTIME_PATH = 5
160
161
 
161
162
 
162
163
  class InvalidWasmError(BaseException):
@@ -178,6 +179,7 @@ Dylink = namedtuple(
178
179
  "needed",
179
180
  "export_info",
180
181
  "import_info",
182
+ "runtime_paths",
181
183
  ],
182
184
  )
183
185
  Table = namedtuple("Table", ["elem_type", "limits"])
@@ -332,6 +334,7 @@ class Module:
332
334
  needed = []
333
335
  export_info = {}
334
336
  import_info = {}
337
+ runtime_paths = []
335
338
  self.read_string() # name
336
339
 
337
340
  if dylink_section.name == "dylink":
@@ -378,6 +381,12 @@ class Module:
378
381
  import_info.setdefault(module, {})
379
382
  import_info[module][field] = flags
380
383
  count -= 1
384
+ elif subsection_type == DylinkType.RUNTIME_PATH:
385
+ count = self.read_uleb()
386
+ while count:
387
+ rpath = self.read_string()
388
+ runtime_paths.append(rpath)
389
+ count -= 1
381
390
  else:
382
391
  print(f"unknown subsection: {subsection_type}")
383
392
  # ignore unknown subsections
@@ -395,6 +404,7 @@ class Module:
395
404
  needed,
396
405
  export_info,
397
406
  import_info,
407
+ runtime_paths,
398
408
  )
399
409
 
400
410
  @memoize
@@ -76,6 +76,17 @@ class ModuleWritable(webassembly.Module):
76
76
  buf.extend(leb128.u.encode(len(subsection_buf)))
77
77
  buf.extend(subsection_buf)
78
78
 
79
+ # 5. RUNTIME_PATH
80
+ subsection_buf = bytearray()
81
+ subsection_buf.extend(leb128.u.encode(len(dylink.runtime_paths)))
82
+ for path in dylink.runtime_paths:
83
+ subsection_buf.extend(leb128.u.encode(len(path.encode())))
84
+ subsection_buf += path.encode()
85
+
86
+ buf.extend(leb128.u.encode(DylinkType.RUNTIME_PATH))
87
+ buf.extend(leb128.u.encode(len(subsection_buf)))
88
+ buf.extend(subsection_buf)
89
+
79
90
  section_buf = bytearray()
80
91
 
81
92
  # custom section
@@ -115,6 +126,29 @@ class ModuleWritable(webassembly.Module):
115
126
 
116
127
  return patched_module
117
128
 
129
+ def patch_runtime_path(self, runtime_path: Path) -> bytes:
130
+ curfile = Path(self.filename).resolve()
131
+
132
+ relpath = os.path.relpath(runtime_path, curfile.parent)
133
+ if relpath == ".":
134
+ realpath_with_prefix = "$ORIGIN"
135
+ else:
136
+ realpath_with_prefix = "$ORIGIN/" + Path(relpath).as_posix()
137
+
138
+ dylink_section: webassembly.Dylink = self.parse_dylink_section()
139
+ runtime_paths = dylink_section.runtime_paths
140
+
141
+ if realpath_with_prefix not in runtime_paths:
142
+ runtime_paths = runtime_paths + [realpath_with_prefix]
143
+
144
+ patched_dylink_section = dylink_section._replace(
145
+ runtime_paths=runtime_paths,
146
+ )
147
+ encoded_dylink_section = self.encode_dylink_section(patched_dylink_section)
148
+ patched_module = self.patch_dylink(encoded_dylink_section)
149
+
150
+ return patched_module
151
+
118
152
 
119
153
  def parse_dylink_section(dylib: Path):
120
154
  """
@@ -126,12 +160,9 @@ def parse_dylink_section(dylib: Path):
126
160
  return dylink
127
161
 
128
162
 
129
- def patch_needed_libs_path(dylib: Path, dep_map: dict[str, Path]):
130
- """
131
- Patch needed path in dylink section
132
- """
163
+ def patch_runtime_path(dylib: Path, runtime_path: Path):
133
164
  with ModuleWritable(dylib) as m:
134
- patched_module = m.patch_needed_path(dep_map)
165
+ patched_module = m.patch_runtime_path(runtime_path)
135
166
 
136
167
  return patched_module
137
168
 
@@ -4,7 +4,7 @@ from collections import deque
4
4
  from pathlib import Path
5
5
 
6
6
  from .lib_utils import get_all_shared_libs_in_dir, libdir_candidates
7
- from .module import patch_needed_libs_path
7
+ from .module import patch_runtime_path
8
8
  from .show import show
9
9
  from .wheel_utils import WHEEL_INFO_RE, is_emscripten_wheel, pack, unpack
10
10
 
@@ -60,27 +60,33 @@ def copylib(
60
60
  return new_dep_map
61
61
 
62
62
 
63
- def repair_extracted(
64
- wheel_extract_dir: str | Path,
65
- dep_map: dict[str, Path],
66
- lib_sdir: str,
67
- ) -> dict[str, Path]:
68
- dep_map_copied = copylib(wheel_extract_dir, dep_map, lib_sdir)
63
+ def modify_runtime_path(wheel_extract_dir: str | Path, runtime_path: str) -> None:
64
+ """
65
+ Patch the runtime path of shared libraries inside the wheel file
66
+
67
+ Parameters
68
+ ----------
69
+ wheel_extract_dir : str | Path
70
+ The directory containing the extracted wheel file
71
+
72
+ runtime_path : str
73
+ The target directory name where the shared libraries are located
74
+ """
75
+ runtime_path_full = Path(wheel_extract_dir) / runtime_path
76
+ assert runtime_path_full.exists(), f"lib directory not found: {runtime_path_full}"
69
77
 
70
78
  shared_libs = get_all_shared_libs_in_dir(wheel_extract_dir)
71
79
  for shared_lib in shared_libs:
72
- patched_module = patch_needed_libs_path(shared_lib, dep_map_copied)
80
+ patched_module = patch_runtime_path(shared_lib, runtime_path_full)
73
81
  shared_lib.write_bytes(patched_module)
74
82
 
75
- return dep_map_copied
76
-
77
83
 
78
84
  def repair(
79
85
  wheel_file: str | Path,
80
86
  libdir: str | Path,
81
87
  outdir: str | Path | None,
82
88
  lib_sdir: str = ".libs",
83
- modify_needed_section: bool = False, # Deprecated
89
+ modify_rpath: bool = True,
84
90
  ) -> Path:
85
91
  file = Path(wheel_file)
86
92
  if not file.exists():
@@ -101,6 +107,8 @@ def repair(
101
107
 
102
108
  extract_dir = unpack(str(wheel_file), str(tmpdir))
103
109
  copylib(extract_dir, dep_map, lib_sdir)
110
+ if modify_rpath:
111
+ modify_runtime_path(extract_dir, lib_sdir)
104
112
  pack(str(extract_dir), str(outdir), None)
105
113
 
106
114
  return outdir / file.name
@@ -21,7 +21,7 @@ def show_wheel_unpacked(wheel_extract_dir: str | Path) -> dict[str, list[str]]:
21
21
  shared_libs = get_all_shared_libs_in_dir(wheel_extract_dir)
22
22
  for shared_lib in shared_libs:
23
23
  deps = show_dylib(shared_lib)
24
- dependencies[str(shared_lib.relative_to(wheel_extract_dir))] = deps
24
+ dependencies[shared_lib.relative_to(wheel_extract_dir).as_posix()] = deps
25
25
 
26
26
  return dependencies
27
27
 
@@ -1,13 +1,11 @@
1
- import io
2
1
  import re
3
- from contextlib import redirect_stdout, contextmanager
4
- from pathlib import Path
2
+ import subprocess
5
3
  import tempfile
4
+ from contextlib import contextmanager
5
+ from pathlib import Path
6
6
  from collections.abc import Generator
7
7
 
8
8
  from packaging.utils import parse_wheel_filename
9
- from wheel.cli.pack import pack as pack_wheel
10
- from wheel.cli.unpack import unpack as unpack_wheel
11
9
 
12
10
  # Copied from auditwheel
13
11
  WHEEL_INFO_RE = re.compile(
@@ -61,8 +59,15 @@ def unpack(path: str | Path, dest: str | Path = ".") -> Path:
61
59
  path = str(path)
62
60
  dest = str(dest)
63
61
 
64
- with io.StringIO() as buf, redirect_stdout(buf):
65
- unpack_wheel(path, dest)
62
+ result = subprocess.run(
63
+ ["wheel", "unpack", path, "--dest", dest],
64
+ check=True,
65
+ encoding="utf-8",
66
+ capture_output=True,
67
+ )
68
+
69
+ if result.returncode != 0:
70
+ raise RuntimeError(f"Failed to unpack wheel: {result.stderr}")
66
71
 
67
72
  return Path(dest) / parse_wheel_extract_dir(path)
68
73
 
@@ -73,9 +78,17 @@ def pack(directory: str | Path, dest_dir: str | Path, build_number: str | None)
73
78
  wheel file name can be determined.
74
79
  :param directory: The unpacked wheel directory
75
80
  :param dest_dir: Destination directory (defaults to the current directory)
81
+ :param build_number: Optional build number for the wheel
76
82
  """
77
83
  directory = str(directory)
78
84
  dest_dir = str(dest_dir)
79
85
 
80
- with io.StringIO() as buf, redirect_stdout(buf):
81
- pack_wheel(directory, dest_dir, build_number)
86
+ cmd = ["wheel", "pack", directory, "--dest-dir", dest_dir]
87
+
88
+ if build_number is not None:
89
+ cmd.extend(["--build-number", build_number])
90
+
91
+ result = subprocess.run(cmd, check=True, encoding="utf-8", capture_output=True)
92
+
93
+ if result.returncode != 0:
94
+ raise RuntimeError(f"Failed to pack wheel: {result.stderr}")
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: auditwheel_emscripten
3
- Version: 0.0.16
3
+ Version: 0.1.0
4
4
  Summary: auditwheel-like tool for Pyodide
5
5
  Project-URL: Home, https://github.com/ryanking13/auditwheel-emscripten
6
6
  Author-email: Gyeongjae Choi <def6488@gmail.com>
@@ -378,7 +378,7 @@ License: Mozilla Public License Version 2.0
378
378
  This Source Code Form is "Incompatible With Secondary Licenses", as
379
379
  defined by the Mozilla Public License, v. 2.0.
380
380
  License-File: LICENSE
381
- Requires-Python: >=3.10
381
+ Requires-Python: >=3.12
382
382
  Requires-Dist: leb128
383
383
  Requires-Dist: packaging
384
384
  Requires-Dist: pyodide-cli
@@ -407,7 +407,7 @@ auditwheel-emscripten is a tiny tool to facilitate the creation of Python wheel
407
407
  Python-in-the-browser using Emscripten.
408
408
 
409
409
  - `pyodide auditwheel show`: shows external shared libraries that the wheel depends on.
410
- - `pyodide auditwheel repair`: copies these external shared libraries into the wheel itself.
410
+ - `pyodide auditwheel repair`: copies these external shared libraries into the wheel itself, and update the RPATH of the WASM module correspondingly.
411
411
 
412
412
  ## Usage (CLI)
413
413
 
@@ -0,0 +1,22 @@
1
+ auditwheel_emscripten/__init__.py,sha256=JAjlFQMSqCJ8k0kuA2DVuxRuPGWMrrP_HRkXXoTuuTs,371
2
+ auditwheel_emscripten/exports.py,sha256=cB-vj6uYJlF9hLHs04SujDI72zkWBcUGZxeTjRWPMDM,1821
3
+ auditwheel_emscripten/function_type.py,sha256=fE-ogFAhS07M-3LM1t5KCRYJtJq570zc898boO4NOYE,831
4
+ auditwheel_emscripten/imports.py,sha256=YI8KItf1qujmycSLb7c7igpCBXNqJAJVUIH3H8HY-Ns,1821
5
+ auditwheel_emscripten/lib_utils.py,sha256=4qodvz1go0tgHZA803Q3vcIR-QQbOdqSR0p2wo7wjrA,682
6
+ auditwheel_emscripten/module.py,sha256=wwLAzlhGKgGojNvUdommO7FGfME49rWVRZOPRp77qjU,6619
7
+ auditwheel_emscripten/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ auditwheel_emscripten/repair.py,sha256=CvTj2SobzAfQjKbXPqvPe7lWRPD9DTHEfJFpHuQD7KY,3755
9
+ auditwheel_emscripten/show.py,sha256=TTulud3juo1QPo7avIa0K_nOR7iYBAVIMpUdXKaLLVI,1714
10
+ auditwheel_emscripten/wasm_utils.py,sha256=-IuAWiPPOkWmPpaW4u3tyxttpP0ZTWeKk0VMh1dj384,220
11
+ auditwheel_emscripten/wheel_utils.py,sha256=_uh8MiKYpjtBcpOE5bG2vEfh9eXlZhz-nMMVo6-Fvl8,2995
12
+ auditwheel_emscripten/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
+ auditwheel_emscripten/cli/main.py,sha256=rhJoQCu8uL_CPevF3vIrZ6c3IsDILTgxW8JNfc5lADY,4043
14
+ auditwheel_emscripten/emscripten_tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
+ auditwheel_emscripten/emscripten_tools/diagnostics.py,sha256=fG8kS7BByJKwC3JJrfJc0TB1EDV4W--LQwcf4fnN0GI,7072
16
+ auditwheel_emscripten/emscripten_tools/utils.py,sha256=sAcW8WaxfN0lNA64y9d0_CsdfYecV_YUcN6nrDrMmMs,3316
17
+ auditwheel_emscripten/emscripten_tools/webassembly.py,sha256=ppyx_lzgtve2hCDn8jQn1Wto_2pGv-Kk-CcOhqUB8NQ,17408
18
+ auditwheel_emscripten-0.1.0.dist-info/METADATA,sha256=6ofoErOVppyKzcdUEdCT_7rftjfEVFSvTjfmY-62o-M,27093
19
+ auditwheel_emscripten-0.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
20
+ auditwheel_emscripten-0.1.0.dist-info/entry_points.txt,sha256=Jok5wALksOWKJv8BRV2Riozxts_stW2n-ud9uHTNCB8,62
21
+ auditwheel_emscripten-0.1.0.dist-info/licenses/LICENSE,sha256=HyVuytGSiAUQ6ErWBHTqt1iSGHhLmlC8fO7jTCuR8dU,16725
22
+ auditwheel_emscripten-0.1.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.25.0
2
+ Generator: hatchling 1.27.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,22 +0,0 @@
1
- auditwheel_emscripten/__init__.py,sha256=wJIPBZjANSL17sOF2-hXWcExAGhGDKPzHHud-yRd-GU,365
2
- auditwheel_emscripten/exports.py,sha256=cB-vj6uYJlF9hLHs04SujDI72zkWBcUGZxeTjRWPMDM,1821
3
- auditwheel_emscripten/function_type.py,sha256=fE-ogFAhS07M-3LM1t5KCRYJtJq570zc898boO4NOYE,831
4
- auditwheel_emscripten/imports.py,sha256=YI8KItf1qujmycSLb7c7igpCBXNqJAJVUIH3H8HY-Ns,1821
5
- auditwheel_emscripten/lib_utils.py,sha256=4qodvz1go0tgHZA803Q3vcIR-QQbOdqSR0p2wo7wjrA,682
6
- auditwheel_emscripten/module.py,sha256=9bZ6eEMB5k7QUyOHWb4ni5m_ROPPieGKulseweCbGOk,5353
7
- auditwheel_emscripten/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- auditwheel_emscripten/repair.py,sha256=rvmsx8pJkRX3yFiePOxUpfGIQ7Y18hLzQ41mXDeHD1w,3387
9
- auditwheel_emscripten/show.py,sha256=x7juLK0AxHZkEpbXIHGK91mC6Z_OFVLcuphBHoW-LHQ,1708
10
- auditwheel_emscripten/wasm_utils.py,sha256=-IuAWiPPOkWmPpaW4u3tyxttpP0ZTWeKk0VMh1dj384,220
11
- auditwheel_emscripten/wheel_utils.py,sha256=pp40x9umTCsSyQHygKvkRMlRm9Sx_1S6zzwvriFXwPI,2634
12
- auditwheel_emscripten/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
- auditwheel_emscripten/cli/main.py,sha256=IsPyZbiEPNXc3pirHtSL2jA4uip8EzYdcRZznfnnx-E,4053
14
- auditwheel_emscripten/emscripten_tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
- auditwheel_emscripten/emscripten_tools/diagnostics.py,sha256=fG8kS7BByJKwC3JJrfJc0TB1EDV4W--LQwcf4fnN0GI,7072
16
- auditwheel_emscripten/emscripten_tools/utils.py,sha256=sAcW8WaxfN0lNA64y9d0_CsdfYecV_YUcN6nrDrMmMs,3316
17
- auditwheel_emscripten/emscripten_tools/webassembly.py,sha256=qFsTPSCrtVdiCISMF-CPyrGGxxKqN4QW4Bn2UsMEaGc,17027
18
- auditwheel_emscripten-0.0.16.dist-info/METADATA,sha256=mefeJkMKxCvio9gXhgHbg1ISPGHvj0eNCzWjuMQn_qc,27037
19
- auditwheel_emscripten-0.0.16.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
20
- auditwheel_emscripten-0.0.16.dist-info/entry_points.txt,sha256=Jok5wALksOWKJv8BRV2Riozxts_stW2n-ud9uHTNCB8,62
21
- auditwheel_emscripten-0.0.16.dist-info/licenses/LICENSE,sha256=HyVuytGSiAUQ6ErWBHTqt1iSGHhLmlC8fO7jTCuR8dU,16725
22
- auditwheel_emscripten-0.0.16.dist-info/RECORD,,