node-liblzma 1.1.9 → 2.0.3
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.
- package/.gitattributes +3 -0
- package/.release-it.json +7 -0
- package/.release-it.manual.json +7 -0
- package/.release-it.retry.json +3 -0
- package/CHANGELOG.md +271 -0
- package/History.md +20 -0
- package/README.md +750 -30
- package/RELEASING.md +131 -0
- package/binding.gyp +162 -436
- package/biome.json +81 -0
- package/index.d.ts +254 -0
- package/lib/errors.d.ts +72 -0
- package/lib/errors.d.ts.map +1 -0
- package/lib/errors.js +153 -0
- package/lib/errors.js.map +1 -0
- package/lib/lzma.d.ts +245 -0
- package/lib/lzma.d.ts.map +1 -0
- package/lib/lzma.js +626 -345
- package/lib/lzma.js.map +1 -0
- package/lib/pool.d.ts +123 -0
- package/lib/pool.d.ts.map +1 -0
- package/lib/pool.js +188 -0
- package/lib/pool.js.map +1 -0
- package/lib/types.d.ts +27 -0
- package/lib/types.d.ts.map +1 -0
- package/lib/types.js +5 -0
- package/lib/types.js.map +1 -0
- package/package.json +61 -22
- package/pnpm-workspace.yaml +3 -0
- package/prebuilds/darwin-x64/node-liblzma.node +0 -0
- package/prebuilds/linux-x64/node-liblzma.node +0 -0
- package/prebuilds/win32-x64/node-liblzma.node +0 -0
- package/scripts/analyze-coverage.js +132 -0
- package/scripts/build_xz_with_cmake.py +390 -0
- package/scripts/compare-coverage-tools.js +93 -0
- package/scripts/copy_dll.py +51 -0
- package/scripts/download_xz_from_github.py +376 -0
- package/src/bindings/node-liblzma.cpp +411 -229
- package/src/bindings/node-liblzma.hpp +101 -48
- package/src/errors.ts +167 -0
- package/src/lzma.ts +839 -0
- package/src/pool.ts +228 -0
- package/src/types.ts +30 -0
- package/tsconfig.json +50 -0
- package/vitest.config.istanbul.ts +29 -0
- package/vitest.config.monocart.ts +44 -0
- package/vitest.config.ts +52 -0
- package/xz-version.json +8 -0
- package/prebuilds/darwin-x64/node.napi.node +0 -0
- package/prebuilds/linux-x64/node.napi.node +0 -0
- package/prebuilds/win32-x64/node.napi.node +0 -0
- package/scripts/download_extract_deps.py +0 -29
- package/scripts/prebuildify.py +0 -13
- package/src/lzma.coffee +0 -344
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Build XZ Utils using CMake from GitHub sources.
|
|
4
|
+
|
|
5
|
+
This script compiles liblzma from XZ sources using CMake, which works
|
|
6
|
+
with raw Git sources without needing autogen.sh or pre-built config files.
|
|
7
|
+
|
|
8
|
+
Usage:
|
|
9
|
+
python3 build_xz_with_cmake.py <xz_source_dir> <install_prefix> [runtime_link] [enable_threads]
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import os
|
|
13
|
+
import sys
|
|
14
|
+
import subprocess
|
|
15
|
+
import platform
|
|
16
|
+
import argparse
|
|
17
|
+
import shutil
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
|
|
20
|
+
def detect_cmake():
|
|
21
|
+
"""Check if CMake is available"""
|
|
22
|
+
try:
|
|
23
|
+
result = subprocess.run(['cmake', '--version'],
|
|
24
|
+
capture_output=True, text=True, check=True)
|
|
25
|
+
version_line = result.stdout.split('\n')[0]
|
|
26
|
+
print(f"[PACKAGE] Found {version_line}")
|
|
27
|
+
return True
|
|
28
|
+
except (subprocess.CalledProcessError, FileNotFoundError):
|
|
29
|
+
return False
|
|
30
|
+
|
|
31
|
+
def get_cmake_generator():
|
|
32
|
+
"""Get appropriate CMake generator for the current platform"""
|
|
33
|
+
system = platform.system()
|
|
34
|
+
if system == "Windows":
|
|
35
|
+
# Use Ninja or Unix Makefiles for better CI compatibility
|
|
36
|
+
# Visual Studio generator can be problematic in CI environments
|
|
37
|
+
return "Ninja" if shutil.which('ninja') else "Unix Makefiles"
|
|
38
|
+
else:
|
|
39
|
+
# Use Unix Makefiles on Linux/macOS (works with make, ninja, etc.)
|
|
40
|
+
return "Unix Makefiles"
|
|
41
|
+
|
|
42
|
+
def configure_cmake(source_dir, build_dir, install_dir, runtime_link="static", enable_threads="no"):
|
|
43
|
+
"""Configure XZ build with CMake"""
|
|
44
|
+
generator = get_cmake_generator()
|
|
45
|
+
cmake_args = [
|
|
46
|
+
'cmake',
|
|
47
|
+
f'-G{generator}',
|
|
48
|
+
f'-B{build_dir}',
|
|
49
|
+
f'-DCMAKE_INSTALL_PREFIX={install_dir}',
|
|
50
|
+
'-DCMAKE_BUILD_TYPE=Release',
|
|
51
|
+
'-DBUILD_SHARED_LIBS=OFF' if runtime_link == 'static' else '-DBUILD_SHARED_LIBS=ON',
|
|
52
|
+
# Build only liblzma, not the command-line tools
|
|
53
|
+
'-DCREATE_XZ_SYMLINKS=OFF',
|
|
54
|
+
'-DCREATE_LZMA_SYMLINKS=OFF',
|
|
55
|
+
# Disable CLI tools completely (they have libintl dependency issues on macOS)
|
|
56
|
+
'-DXZ_TOOL_XZ=OFF',
|
|
57
|
+
'-DXZ_TOOL_LZMAINFO=OFF',
|
|
58
|
+
'-DXZ_TOOL_XZDEC=OFF',
|
|
59
|
+
'-DXZ_TOOL_LZMADEC=OFF',
|
|
60
|
+
# Enable Position Independent Code for use in shared libraries
|
|
61
|
+
'-DCMAKE_POSITION_INDEPENDENT_CODE=ON',
|
|
62
|
+
# Disable compiler warnings that might cause issues in CI
|
|
63
|
+
'-DCMAKE_C_FLAGS=-w',
|
|
64
|
+
]
|
|
65
|
+
|
|
66
|
+
# Platform-specific configuration
|
|
67
|
+
system = platform.system()
|
|
68
|
+
|
|
69
|
+
# Threading support - XZ 5.8+ has full XZ_THREADS support
|
|
70
|
+
if enable_threads.lower() in ['yes', 'true', '1']:
|
|
71
|
+
cmake_args.append('-DXZ_THREADS=yes')
|
|
72
|
+
print("[THREAD] Threading support: enabled (XZ_THREADS=yes)")
|
|
73
|
+
else:
|
|
74
|
+
cmake_args.append('-DXZ_THREADS=no')
|
|
75
|
+
print("[THREAD] Threading support: disabled (XZ_THREADS=no)")
|
|
76
|
+
|
|
77
|
+
if system == "Windows":
|
|
78
|
+
# Use Visual Studio generator for Windows builds (supports -A x64)
|
|
79
|
+
cmake_args.extend(['-G', 'Visual Studio 17 2022', '-A', 'x64'])
|
|
80
|
+
print("[BUILD] Windows x64 build configuration")
|
|
81
|
+
elif system == "Darwin":
|
|
82
|
+
# macOS specific optimizations
|
|
83
|
+
cmake_args.extend([
|
|
84
|
+
'-DCMAKE_OSX_DEPLOYMENT_TARGET=10.15'
|
|
85
|
+
])
|
|
86
|
+
|
|
87
|
+
# For shared libraries on macOS, configure proper install_name
|
|
88
|
+
if runtime_link == "shared":
|
|
89
|
+
cmake_args.extend([
|
|
90
|
+
'-DCMAKE_INSTALL_NAME_DIR=@rpath',
|
|
91
|
+
'-DCMAKE_BUILD_WITH_INSTALL_RPATH=ON',
|
|
92
|
+
'-DCMAKE_INSTALL_RPATH=@loader_path;@loader_path/../lib',
|
|
93
|
+
'-DCMAKE_MACOSX_RPATH=ON'
|
|
94
|
+
])
|
|
95
|
+
print("[BUILD] macOS shared library: configured @rpath install_name")
|
|
96
|
+
|
|
97
|
+
print("[BUILD] macOS build configuration")
|
|
98
|
+
else:
|
|
99
|
+
# Linux and other Unix systems
|
|
100
|
+
print("[BUILD] Linux/Unix build configuration")
|
|
101
|
+
|
|
102
|
+
cmake_args.append(source_dir)
|
|
103
|
+
|
|
104
|
+
print(f"[CONFIG] Configuring CMake build...")
|
|
105
|
+
print(f" Source: {source_dir}")
|
|
106
|
+
print(f" Build: {build_dir}")
|
|
107
|
+
print(f" Install: {install_dir}")
|
|
108
|
+
print(f" Runtime: {runtime_link}")
|
|
109
|
+
|
|
110
|
+
try:
|
|
111
|
+
result = subprocess.run(cmake_args, check=True, cwd=source_dir, capture_output=True, text=True)
|
|
112
|
+
print("[SUCCESS] CMake configuration successful")
|
|
113
|
+
|
|
114
|
+
# Log all CMake output for threading diagnostics
|
|
115
|
+
print(f"[DEBUG] Full CMake configuration output:")
|
|
116
|
+
for line in result.stdout.split('\n'):
|
|
117
|
+
if line.strip():
|
|
118
|
+
print(f"[DEBUG] {line.strip()}")
|
|
119
|
+
|
|
120
|
+
if result.stderr.strip():
|
|
121
|
+
print(f"[DEBUG] CMake stderr:")
|
|
122
|
+
for line in result.stderr.split('\n'):
|
|
123
|
+
if line.strip():
|
|
124
|
+
print(f"[DEBUG] {line.strip()}")
|
|
125
|
+
|
|
126
|
+
return True
|
|
127
|
+
except subprocess.CalledProcessError as e:
|
|
128
|
+
print(f"[ERROR] CMake configuration failed with exit code {e.returncode}")
|
|
129
|
+
if e.stdout:
|
|
130
|
+
print(f"[ERROR] stdout: {e.stdout}")
|
|
131
|
+
if e.stderr:
|
|
132
|
+
print(f"[ERROR] stderr: {e.stderr}")
|
|
133
|
+
return False
|
|
134
|
+
|
|
135
|
+
def build_cmake(build_dir):
|
|
136
|
+
"""Build the configured CMake project"""
|
|
137
|
+
cmake_args = [
|
|
138
|
+
'cmake',
|
|
139
|
+
'--build', build_dir,
|
|
140
|
+
'--config', 'Release',
|
|
141
|
+
'--parallel'
|
|
142
|
+
]
|
|
143
|
+
|
|
144
|
+
print("[BUILD] Building XZ with CMake...")
|
|
145
|
+
|
|
146
|
+
try:
|
|
147
|
+
result = subprocess.run(cmake_args, check=True)
|
|
148
|
+
print("[SUCCESS] CMake build successful")
|
|
149
|
+
return True
|
|
150
|
+
except subprocess.CalledProcessError as e:
|
|
151
|
+
print(f"[ERROR] CMake build failed with exit code {e.returncode}")
|
|
152
|
+
return False
|
|
153
|
+
|
|
154
|
+
def install_cmake(build_dir, install_dir):
|
|
155
|
+
"""Install the built libraries to the target directory"""
|
|
156
|
+
cmake_args = [
|
|
157
|
+
'cmake',
|
|
158
|
+
'--install', build_dir,
|
|
159
|
+
'--prefix', install_dir,
|
|
160
|
+
'--config', 'Release'
|
|
161
|
+
]
|
|
162
|
+
|
|
163
|
+
print(f"[INSTALL] Installing to {install_dir}...")
|
|
164
|
+
|
|
165
|
+
# Ensure install directory exists
|
|
166
|
+
os.makedirs(install_dir, exist_ok=True)
|
|
167
|
+
|
|
168
|
+
try:
|
|
169
|
+
result = subprocess.run(cmake_args, check=True)
|
|
170
|
+
print("[SUCCESS] CMake install successful")
|
|
171
|
+
return True
|
|
172
|
+
except subprocess.CalledProcessError as e:
|
|
173
|
+
print(f"[ERROR] CMake install failed with exit code {e.returncode}")
|
|
174
|
+
return False
|
|
175
|
+
|
|
176
|
+
def fix_windows_lib_names(install_dir):
|
|
177
|
+
"""Fix Windows library naming: CMake creates lzma.lib but binding.gyp expects liblzma.lib"""
|
|
178
|
+
if platform.system() != "Windows":
|
|
179
|
+
return True
|
|
180
|
+
|
|
181
|
+
import shutil
|
|
182
|
+
lib_dir = os.path.join(install_dir, 'lib')
|
|
183
|
+
source_lib = os.path.join(lib_dir, 'lzma.lib')
|
|
184
|
+
target_lib = os.path.join(lib_dir, 'liblzma.lib')
|
|
185
|
+
|
|
186
|
+
if os.path.exists(source_lib) and not os.path.exists(target_lib):
|
|
187
|
+
try:
|
|
188
|
+
shutil.copy2(source_lib, target_lib)
|
|
189
|
+
print(f"[FIX] Created {target_lib} from {source_lib}")
|
|
190
|
+
return True
|
|
191
|
+
except Exception as e:
|
|
192
|
+
print(f"[WARNING] Could not create liblzma.lib: {e}")
|
|
193
|
+
return False
|
|
194
|
+
elif os.path.exists(target_lib):
|
|
195
|
+
print(f"[OK] {target_lib} already exists")
|
|
196
|
+
return True
|
|
197
|
+
else:
|
|
198
|
+
print(f"[WARNING] Source file {source_lib} not found")
|
|
199
|
+
return False
|
|
200
|
+
|
|
201
|
+
def verify_and_fix_dylib_install_name(install_dir, runtime_link="static"):
|
|
202
|
+
"""Verify and fix macOS dylib install_name to use @rpath"""
|
|
203
|
+
# Only relevant for macOS shared library builds
|
|
204
|
+
if platform.system() != "Darwin" or runtime_link != "shared":
|
|
205
|
+
return True
|
|
206
|
+
|
|
207
|
+
dylib_path = os.path.join(install_dir, 'lib', 'liblzma.dylib')
|
|
208
|
+
if not os.path.exists(dylib_path):
|
|
209
|
+
print(f"[WARNING] Dylib not found at {dylib_path}")
|
|
210
|
+
return False
|
|
211
|
+
|
|
212
|
+
try:
|
|
213
|
+
# Check current install_name using otool
|
|
214
|
+
result = subprocess.run(['otool', '-D', dylib_path],
|
|
215
|
+
capture_output=True, text=True, check=True)
|
|
216
|
+
current_install_name = result.stdout.strip().split('\n')[-1]
|
|
217
|
+
|
|
218
|
+
print(f"[VERIFY] Current install_name: {current_install_name}")
|
|
219
|
+
|
|
220
|
+
# If install_name doesn't start with @rpath, fix it
|
|
221
|
+
if not current_install_name.startswith('@rpath'):
|
|
222
|
+
print(f"[FIX] Fixing install_name to use @rpath")
|
|
223
|
+
subprocess.run(['install_name_tool', '-id', '@rpath/liblzma.dylib', dylib_path],
|
|
224
|
+
check=True)
|
|
225
|
+
|
|
226
|
+
# Verify the fix
|
|
227
|
+
result = subprocess.run(['otool', '-D', dylib_path],
|
|
228
|
+
capture_output=True, text=True, check=True)
|
|
229
|
+
new_install_name = result.stdout.strip().split('\n')[-1]
|
|
230
|
+
print(f"[SUCCESS] Updated install_name: {new_install_name}")
|
|
231
|
+
|
|
232
|
+
if not new_install_name.startswith('@rpath'):
|
|
233
|
+
print(f"[ERROR] Failed to update install_name")
|
|
234
|
+
return False
|
|
235
|
+
else:
|
|
236
|
+
print(f"[OK] install_name already uses @rpath")
|
|
237
|
+
|
|
238
|
+
return True
|
|
239
|
+
|
|
240
|
+
except subprocess.CalledProcessError as e:
|
|
241
|
+
print(f"[ERROR] Failed to verify/fix install_name: {e}")
|
|
242
|
+
return False
|
|
243
|
+
except Exception as e:
|
|
244
|
+
print(f"[ERROR] Unexpected error in install_name verification: {e}")
|
|
245
|
+
return False
|
|
246
|
+
|
|
247
|
+
def verify_build(install_dir, runtime_link="static"):
|
|
248
|
+
"""Verify that the build produced the expected files"""
|
|
249
|
+
expected_files = ['include/lzma.h'] # Common file for all builds
|
|
250
|
+
|
|
251
|
+
system = platform.system()
|
|
252
|
+
if system == "Windows":
|
|
253
|
+
if runtime_link == "static":
|
|
254
|
+
expected_files.append('lib/liblzma.lib')
|
|
255
|
+
else:
|
|
256
|
+
# For shared builds on Windows, expect both import lib and DLL
|
|
257
|
+
expected_files.extend(['lib/liblzma.lib', 'bin/liblzma.dll'])
|
|
258
|
+
else:
|
|
259
|
+
if runtime_link == "static":
|
|
260
|
+
expected_files.append('lib/liblzma.a')
|
|
261
|
+
else:
|
|
262
|
+
# For shared builds, look for .so files (or .dylib on macOS)
|
|
263
|
+
if system == "Darwin":
|
|
264
|
+
expected_files.append('lib/liblzma.dylib')
|
|
265
|
+
else:
|
|
266
|
+
expected_files.append('lib/liblzma.so')
|
|
267
|
+
|
|
268
|
+
missing_files = []
|
|
269
|
+
for file_path in expected_files:
|
|
270
|
+
full_path = os.path.join(install_dir, file_path)
|
|
271
|
+
if not os.path.exists(full_path):
|
|
272
|
+
missing_files.append(file_path)
|
|
273
|
+
|
|
274
|
+
if missing_files:
|
|
275
|
+
print(f"[WARNING] Missing expected files: {', '.join(missing_files)}")
|
|
276
|
+
return False
|
|
277
|
+
else:
|
|
278
|
+
print("[SUCCESS] Build verification successful - all expected files present")
|
|
279
|
+
return True
|
|
280
|
+
|
|
281
|
+
def main():
|
|
282
|
+
parser = argparse.ArgumentParser(
|
|
283
|
+
description='Build XZ Utils using CMake',
|
|
284
|
+
epilog='''
|
|
285
|
+
Required environment variables (strict validation):
|
|
286
|
+
RUNTIME_LINK: 'static' or 'shared' (REQUIRED)
|
|
287
|
+
ENABLE_THREAD_SUPPORT: 'yes' or 'no' (REQUIRED)
|
|
288
|
+
USE_GLOBAL: 'true' or 'false' (REQUIRED)
|
|
289
|
+
|
|
290
|
+
Examples:
|
|
291
|
+
RUNTIME_LINK=static ENABLE_THREAD_SUPPORT=yes USE_GLOBAL=false \\
|
|
292
|
+
python3 build_xz_with_cmake.py deps/xz build/liblzma
|
|
293
|
+
|
|
294
|
+
RUNTIME_LINK=shared ENABLE_THREAD_SUPPORT=no USE_GLOBAL=true \\
|
|
295
|
+
python3 build_xz_with_cmake.py deps/xz build/liblzma
|
|
296
|
+
''',
|
|
297
|
+
formatter_class=argparse.RawDescriptionHelpFormatter
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
parser.add_argument('source_dir', help='XZ source directory')
|
|
301
|
+
parser.add_argument('install_dir', help='Installation directory')
|
|
302
|
+
parser.add_argument('--verbose', '-v', action='store_true',
|
|
303
|
+
help='Verbose output')
|
|
304
|
+
|
|
305
|
+
args = parser.parse_args()
|
|
306
|
+
|
|
307
|
+
# Get configuration from environment variables with strict validation
|
|
308
|
+
runtime_link = os.environ.get('RUNTIME_LINK')
|
|
309
|
+
enable_threads = os.environ.get('ENABLE_THREAD_SUPPORT')
|
|
310
|
+
use_global = os.environ.get('USE_GLOBAL')
|
|
311
|
+
|
|
312
|
+
# Strict validation - fail if critical variables are not explicitly set
|
|
313
|
+
if runtime_link is None:
|
|
314
|
+
print("[ERROR] RUNTIME_LINK environment variable must be explicitly set ('static' or 'shared')")
|
|
315
|
+
return 1
|
|
316
|
+
|
|
317
|
+
if enable_threads is None:
|
|
318
|
+
print("[ERROR] ENABLE_THREAD_SUPPORT environment variable must be explicitly set ('yes' or 'no')")
|
|
319
|
+
return 1
|
|
320
|
+
|
|
321
|
+
if use_global is None:
|
|
322
|
+
print("[ERROR] USE_GLOBAL environment variable must be explicitly set ('true' or 'false')")
|
|
323
|
+
return 1
|
|
324
|
+
|
|
325
|
+
# Validate values
|
|
326
|
+
if runtime_link not in ['static', 'shared']:
|
|
327
|
+
print(f"[ERROR] Invalid RUNTIME_LINK: {runtime_link}. Must be 'static' or 'shared'")
|
|
328
|
+
return 1
|
|
329
|
+
|
|
330
|
+
if enable_threads.lower() not in ['yes', 'no', 'true', 'false', '1', '0']:
|
|
331
|
+
print(f"[ERROR] Invalid ENABLE_THREAD_SUPPORT: {enable_threads}. Must be yes/no/true/false/1/0")
|
|
332
|
+
return 1
|
|
333
|
+
|
|
334
|
+
if use_global.lower() not in ['true', 'false']:
|
|
335
|
+
print(f"[ERROR] Invalid USE_GLOBAL: {use_global}. Must be 'true' or 'false'")
|
|
336
|
+
return 1
|
|
337
|
+
|
|
338
|
+
# Convert to absolute paths
|
|
339
|
+
source_dir = os.path.abspath(args.source_dir)
|
|
340
|
+
install_dir = os.path.abspath(args.install_dir)
|
|
341
|
+
build_dir = os.path.join(source_dir, 'build-cmake')
|
|
342
|
+
|
|
343
|
+
if args.verbose:
|
|
344
|
+
print("[VERBOSE] Verbose mode enabled")
|
|
345
|
+
|
|
346
|
+
# Validate source directory
|
|
347
|
+
cmake_file = os.path.join(source_dir, 'CMakeLists.txt')
|
|
348
|
+
if not os.path.exists(cmake_file):
|
|
349
|
+
print(f"[ERROR] CMakeLists.txt not found in {source_dir}")
|
|
350
|
+
return 1
|
|
351
|
+
|
|
352
|
+
# Check CMake availability
|
|
353
|
+
if not detect_cmake():
|
|
354
|
+
print("[ERROR] CMake not found. Please install CMake to continue.")
|
|
355
|
+
return 1
|
|
356
|
+
|
|
357
|
+
# Clean build directory if it exists
|
|
358
|
+
if os.path.exists(build_dir):
|
|
359
|
+
import shutil
|
|
360
|
+
print(f"[CLEAN] Cleaning existing build directory: {build_dir}")
|
|
361
|
+
shutil.rmtree(build_dir)
|
|
362
|
+
|
|
363
|
+
# Build process
|
|
364
|
+
success = (
|
|
365
|
+
configure_cmake(source_dir, build_dir, install_dir,
|
|
366
|
+
runtime_link, enable_threads) and
|
|
367
|
+
build_cmake(build_dir) and
|
|
368
|
+
install_cmake(build_dir, install_dir) and
|
|
369
|
+
fix_windows_lib_names(install_dir) and
|
|
370
|
+
verify_and_fix_dylib_install_name(install_dir, runtime_link) and
|
|
371
|
+
verify_build(install_dir, runtime_link)
|
|
372
|
+
)
|
|
373
|
+
|
|
374
|
+
if success:
|
|
375
|
+
print(f"[DONE] XZ build completed successfully!")
|
|
376
|
+
print(f" Libraries installed in: {install_dir}")
|
|
377
|
+
return 0
|
|
378
|
+
else:
|
|
379
|
+
print("[ERROR] Build failed")
|
|
380
|
+
return 1
|
|
381
|
+
|
|
382
|
+
if __name__ == '__main__':
|
|
383
|
+
try:
|
|
384
|
+
sys.exit(main())
|
|
385
|
+
except KeyboardInterrupt:
|
|
386
|
+
print("\n[ERROR] Interrupted by user")
|
|
387
|
+
sys.exit(1)
|
|
388
|
+
except Exception as e:
|
|
389
|
+
print(f"[ERROR] Unexpected error: {e}")
|
|
390
|
+
sys.exit(1)
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
|
|
6
|
+
const V8_COVERAGE = './coverage/coverage-final.json';
|
|
7
|
+
const MONOCART_DATA = './coverage-reports/coverage-data.js';
|
|
8
|
+
const SOURCE_FILE = './src/lzma.ts';
|
|
9
|
+
|
|
10
|
+
console.log('🔍 COMPARAISON V8 vs MONOCART\n');
|
|
11
|
+
|
|
12
|
+
// Lire V8
|
|
13
|
+
if (!fs.existsSync(V8_COVERAGE)) {
|
|
14
|
+
console.log('❌ V8 coverage manquant');
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
|
17
|
+
const v8Coverage = JSON.parse(fs.readFileSync(V8_COVERAGE, 'utf8'));
|
|
18
|
+
const sourceLines = fs.readFileSync(SOURCE_FILE, 'utf8').split('\n');
|
|
19
|
+
const filePath = path.resolve(SOURCE_FILE);
|
|
20
|
+
const v8Data = v8Coverage[filePath] || v8Coverage[Object.keys(v8Coverage)[0]];
|
|
21
|
+
|
|
22
|
+
// Lire Monocart
|
|
23
|
+
if (!fs.existsSync(MONOCART_DATA)) {
|
|
24
|
+
console.log('❌ Monocart data manquant');
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Extraire les données Monocart du fichier JS
|
|
29
|
+
const monocartContent = fs.readFileSync(MONOCART_DATA, 'utf8');
|
|
30
|
+
const monocartMatch = monocartContent.match(/window\.reportData\s*=\s*'([^']+)'/);
|
|
31
|
+
if (!monocartMatch) {
|
|
32
|
+
console.log('❌ Format Monocart non reconnu');
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Monocart utilise un format compressé, on doit le décoder
|
|
37
|
+
console.log('⚠️ Monocart utilise un format de données compressé, analyse simplifiée...');
|
|
38
|
+
const monocartData = { summary: null };
|
|
39
|
+
const summaryData = monocartData.summary;
|
|
40
|
+
|
|
41
|
+
console.log('📊 COMPARAISON GLOBALE:');
|
|
42
|
+
console.log(
|
|
43
|
+
`V8 : ${v8Data.s ? Object.values(v8Data.s).filter((x) => x > 0).length : 0} statements couverts / ${v8Data.s ? Object.keys(v8Data.s).length : 0} total`
|
|
44
|
+
);
|
|
45
|
+
console.log(
|
|
46
|
+
`Monocart : ${summaryData.statements.covered} statements couverts / ${summaryData.statements.total} total`
|
|
47
|
+
);
|
|
48
|
+
console.log('');
|
|
49
|
+
|
|
50
|
+
console.log(
|
|
51
|
+
`V8 : ${v8Data.b ? Object.values(v8Data.b).filter((arr) => arr.every((x) => x > 0)).length : 0} branches couvertes / ${v8Data.b ? Object.keys(v8Data.b).length : 0} total`
|
|
52
|
+
);
|
|
53
|
+
console.log(
|
|
54
|
+
`Monocart : ${summaryData.branches.covered} branches couvertes / ${summaryData.branches.total} total`
|
|
55
|
+
);
|
|
56
|
+
console.log('');
|
|
57
|
+
|
|
58
|
+
console.log(
|
|
59
|
+
`V8 : ${v8Data.f ? Object.values(v8Data.f).filter((x) => x > 0).length : 0} fonctions couvertes / ${v8Data.f ? Object.keys(v8Data.f).length : 0} total`
|
|
60
|
+
);
|
|
61
|
+
console.log(
|
|
62
|
+
`Monocart : ${summaryData.functions.covered} fonctions couvertes / ${summaryData.functions.total} total`
|
|
63
|
+
);
|
|
64
|
+
console.log('');
|
|
65
|
+
|
|
66
|
+
// Analyse des statements non couverts
|
|
67
|
+
const v8UncoveredStmts = Object.entries(v8Data.s || {}).filter(([, count]) => count === 0);
|
|
68
|
+
console.log(`🎯 V8 STATEMENTS NON COUVERTS: ${v8UncoveredStmts.length}`);
|
|
69
|
+
v8UncoveredStmts.slice(0, 5).forEach(([key]) => {
|
|
70
|
+
const stmt = v8Data.statementMap[key];
|
|
71
|
+
const line = stmt.start.line;
|
|
72
|
+
console.log(` Ligne ${line}: ${sourceLines[line - 1]?.trim() || 'N/A'}`);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
console.log('\n💡 VERDICT:');
|
|
76
|
+
if (summaryData.statements.total !== Object.keys(v8Data.s || {}).length) {
|
|
77
|
+
console.log('⚠️ Monocart détecte un nombre différent de statements');
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const v8Pct = (
|
|
81
|
+
(Object.values(v8Data.s || {}).filter((x) => x > 0).length / Object.keys(v8Data.s || {}).length) *
|
|
82
|
+
100
|
|
83
|
+
).toFixed(2);
|
|
84
|
+
const monocartPct = summaryData.statements.pct;
|
|
85
|
+
|
|
86
|
+
console.log(`V8 : ${v8Pct}% statements coverage`);
|
|
87
|
+
console.log(`Monocart : ${monocartPct}% statements coverage`);
|
|
88
|
+
|
|
89
|
+
if (Math.abs(parseFloat(monocartPct) - parseFloat(v8Pct)) > 1) {
|
|
90
|
+
console.log('✨ Monocart montre une différence significative !');
|
|
91
|
+
} else {
|
|
92
|
+
console.log('📊 Résultats similaires entre V8 et Monocart');
|
|
93
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Copy DLL file for Windows shared builds.
|
|
4
|
+
|
|
5
|
+
This script copies the liblzma.dll from the install directory to the build
|
|
6
|
+
directory so it can be found at runtime.
|
|
7
|
+
|
|
8
|
+
Usage:
|
|
9
|
+
python3 copy_dll.py <source_dll> <target_directory>
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import os
|
|
13
|
+
import sys
|
|
14
|
+
import shutil
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
|
|
17
|
+
def main():
|
|
18
|
+
if len(sys.argv) != 3:
|
|
19
|
+
print("[ERROR] Usage: python3 copy_dll.py <source_dll> <target_directory>")
|
|
20
|
+
return 1
|
|
21
|
+
|
|
22
|
+
source_dll = sys.argv[1]
|
|
23
|
+
target_dir = sys.argv[2]
|
|
24
|
+
|
|
25
|
+
# Convert to absolute paths
|
|
26
|
+
source_dll = os.path.abspath(source_dll)
|
|
27
|
+
target_dir = os.path.abspath(target_dir)
|
|
28
|
+
|
|
29
|
+
# Validate source file exists
|
|
30
|
+
if not os.path.exists(source_dll):
|
|
31
|
+
print(f"[ERROR] Source DLL not found: {source_dll}")
|
|
32
|
+
return 1
|
|
33
|
+
|
|
34
|
+
# Ensure target directory exists
|
|
35
|
+
os.makedirs(target_dir, exist_ok=True)
|
|
36
|
+
|
|
37
|
+
# Get filename and create target path
|
|
38
|
+
dll_name = os.path.basename(source_dll)
|
|
39
|
+
target_path = os.path.join(target_dir, dll_name)
|
|
40
|
+
|
|
41
|
+
try:
|
|
42
|
+
print(f"[COPY] Copying DLL from {source_dll} to {target_path}")
|
|
43
|
+
shutil.copy2(source_dll, target_path)
|
|
44
|
+
print(f"[SUCCESS] DLL copied successfully")
|
|
45
|
+
return 0
|
|
46
|
+
except Exception as e:
|
|
47
|
+
print(f"[ERROR] Failed to copy DLL: {e}")
|
|
48
|
+
return 1
|
|
49
|
+
|
|
50
|
+
if __name__ == '__main__':
|
|
51
|
+
sys.exit(main())
|