clang-tool-chain 1.1.5__py3-none-any.whl → 1.1.7__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.
- clang_tool_chain/__init__.py +7 -1
- clang_tool_chain/__version__.py +1 -1
- clang_tool_chain/execution/sanitizer_env.py +203 -4
- {clang_tool_chain-1.1.5.dist-info → clang_tool_chain-1.1.7.dist-info}/METADATA +1 -1
- {clang_tool_chain-1.1.5.dist-info → clang_tool_chain-1.1.7.dist-info}/RECORD +8 -8
- {clang_tool_chain-1.1.5.dist-info → clang_tool_chain-1.1.7.dist-info}/WHEEL +0 -0
- {clang_tool_chain-1.1.5.dist-info → clang_tool_chain-1.1.7.dist-info}/entry_points.txt +0 -0
- {clang_tool_chain-1.1.5.dist-info → clang_tool_chain-1.1.7.dist-info}/licenses/LICENSE +0 -0
clang_tool_chain/__init__.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
__version__ = "1.
|
|
1
|
+
__version__ = "1.1.7"
|
|
2
2
|
|
|
3
3
|
# Re-export commonly used functions for convenient access
|
|
4
4
|
from clang_tool_chain.env_utils import (
|
|
@@ -9,6 +9,9 @@ from clang_tool_chain.env_utils import (
|
|
|
9
9
|
)
|
|
10
10
|
from clang_tool_chain.execution.sanitizer_env import (
|
|
11
11
|
detect_sanitizers_from_flags,
|
|
12
|
+
get_all_sanitizer_runtime_dlls,
|
|
13
|
+
get_asan_runtime_dll,
|
|
14
|
+
get_default_asan_options,
|
|
12
15
|
get_runtime_dll_paths,
|
|
13
16
|
get_symbolizer_path,
|
|
14
17
|
prepare_sanitizer_environment,
|
|
@@ -31,4 +34,7 @@ __all__ = [
|
|
|
31
34
|
"get_runtime_dll_paths",
|
|
32
35
|
"get_symbolizer_path",
|
|
33
36
|
"detect_sanitizers_from_flags",
|
|
37
|
+
"get_asan_runtime_dll",
|
|
38
|
+
"get_all_sanitizer_runtime_dlls",
|
|
39
|
+
"get_default_asan_options",
|
|
34
40
|
]
|
clang_tool_chain/__version__.py
CHANGED
|
@@ -30,11 +30,47 @@ logger = logging.getLogger(__name__)
|
|
|
30
30
|
# Default options to inject for optimal stack traces
|
|
31
31
|
# fast_unwind_on_malloc=0: Use slow but accurate unwinding (fixes <unknown module>)
|
|
32
32
|
# symbolize=1: Enable symbolization for readable stack traces
|
|
33
|
-
# detect_leaks=1: Enable leak detection (ASAN only)
|
|
34
|
-
|
|
33
|
+
# detect_leaks=1: Enable leak detection (ASAN only, NOT on Windows - LSAN unsupported)
|
|
34
|
+
#
|
|
35
|
+
# LeakSanitizer (LSAN) is NOT supported on Windows. Only Linux, macOS, Android,
|
|
36
|
+
# Fuchsia, and NetBSD are supported. See: https://clang.llvm.org/docs/LeakSanitizer.html
|
|
37
|
+
#
|
|
38
|
+
# On Windows, setting detect_leaks=1 causes immediate failure with:
|
|
39
|
+
# "AddressSanitizer: detect_leaks is not supported on this platform."
|
|
40
|
+
_BASE_ASAN_OPTIONS = "fast_unwind_on_malloc=0:symbolize=1"
|
|
35
41
|
DEFAULT_LSAN_OPTIONS = "fast_unwind_on_malloc=0:symbolize=1"
|
|
36
42
|
|
|
37
43
|
|
|
44
|
+
def get_default_asan_options() -> str:
|
|
45
|
+
"""
|
|
46
|
+
Get platform-appropriate default ASAN options.
|
|
47
|
+
|
|
48
|
+
Returns options string with detect_leaks=1 only on platforms where
|
|
49
|
+
LeakSanitizer is supported (Linux, macOS). Windows does not support
|
|
50
|
+
LSAN, so detect_leaks is omitted to prevent runtime failures.
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
ASAN options string appropriate for the current platform.
|
|
54
|
+
|
|
55
|
+
Example:
|
|
56
|
+
>>> get_default_asan_options() # On Linux/macOS
|
|
57
|
+
'fast_unwind_on_malloc=0:symbolize=1:detect_leaks=1'
|
|
58
|
+
>>> get_default_asan_options() # On Windows
|
|
59
|
+
'fast_unwind_on_malloc=0:symbolize=1'
|
|
60
|
+
"""
|
|
61
|
+
if platform.system() == "Windows":
|
|
62
|
+
# LSAN (LeakSanitizer) is not supported on Windows
|
|
63
|
+
# See: https://clang.llvm.org/docs/LeakSanitizer.html
|
|
64
|
+
return _BASE_ASAN_OPTIONS
|
|
65
|
+
# Linux, macOS, and other platforms support LSAN
|
|
66
|
+
return f"{_BASE_ASAN_OPTIONS}:detect_leaks=1"
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
# For backward compatibility - this is now dynamically computed
|
|
70
|
+
# Code that imports DEFAULT_ASAN_OPTIONS directly will get the platform-appropriate value
|
|
71
|
+
DEFAULT_ASAN_OPTIONS = get_default_asan_options()
|
|
72
|
+
|
|
73
|
+
|
|
38
74
|
def get_symbolizer_path() -> str | None:
|
|
39
75
|
"""
|
|
40
76
|
Get the path to llvm-symbolizer from the clang-tool-chain installation.
|
|
@@ -131,6 +167,168 @@ def get_runtime_dll_paths() -> list[str]:
|
|
|
131
167
|
return paths
|
|
132
168
|
|
|
133
169
|
|
|
170
|
+
def get_asan_runtime_dll() -> Path | None:
|
|
171
|
+
"""
|
|
172
|
+
Get the full path to the ASAN runtime DLL (Windows only).
|
|
173
|
+
|
|
174
|
+
This function locates the shared ASAN runtime DLL used when compiling
|
|
175
|
+
with -fsanitize=address -shared-libasan. The DLL must be accessible
|
|
176
|
+
at runtime for ASAN-instrumented executables to run.
|
|
177
|
+
|
|
178
|
+
This is particularly useful when running tests via build systems like
|
|
179
|
+
Meson that reset PATH and don't inherit ASAN DLL directories. By getting
|
|
180
|
+
the DLL path, consuming projects can copy it to their build directory
|
|
181
|
+
where the build system will automatically discover it.
|
|
182
|
+
|
|
183
|
+
Returns:
|
|
184
|
+
Path to libclang_rt.asan_dynamic-x86_64.dll (or ARM64 equivalent),
|
|
185
|
+
or None if not found or not on Windows.
|
|
186
|
+
|
|
187
|
+
Example:
|
|
188
|
+
>>> dll_path = get_asan_runtime_dll()
|
|
189
|
+
>>> if dll_path:
|
|
190
|
+
... shutil.copy(dll_path, build_dir / dll_path.name)
|
|
191
|
+
... # Now Meson tests will find the ASAN DLL in build_dir
|
|
192
|
+
|
|
193
|
+
Note:
|
|
194
|
+
This function ensures the toolchain is downloaded before searching.
|
|
195
|
+
The DLL is typically located in the MinGW sysroot bin directory:
|
|
196
|
+
~/.clang-tool-chain/clang/win/x86_64/x86_64-w64-mingw32/bin/
|
|
197
|
+
|
|
198
|
+
See Also:
|
|
199
|
+
get_runtime_dll_paths: Returns directories containing runtime DLLs
|
|
200
|
+
prepare_sanitizer_environment: Adds DLL paths to PATH
|
|
201
|
+
"""
|
|
202
|
+
if platform.system() != "Windows":
|
|
203
|
+
logger.debug("get_asan_runtime_dll: Not on Windows, returning None")
|
|
204
|
+
return None
|
|
205
|
+
|
|
206
|
+
try:
|
|
207
|
+
from clang_tool_chain.platform.detection import get_platform_binary_dir, get_platform_info
|
|
208
|
+
|
|
209
|
+
# Get platform info for sysroot lookup
|
|
210
|
+
_platform_name, arch = get_platform_info()
|
|
211
|
+
|
|
212
|
+
# Get the clang root directory
|
|
213
|
+
clang_bin_dir = get_platform_binary_dir()
|
|
214
|
+
clang_root = clang_bin_dir.parent
|
|
215
|
+
|
|
216
|
+
# Determine sysroot and DLL name based on architecture
|
|
217
|
+
if arch == "x86_64":
|
|
218
|
+
sysroot_name = "x86_64-w64-mingw32"
|
|
219
|
+
dll_name = "libclang_rt.asan_dynamic-x86_64.dll"
|
|
220
|
+
elif arch == "arm64":
|
|
221
|
+
sysroot_name = "aarch64-w64-mingw32"
|
|
222
|
+
dll_name = "libclang_rt.asan_dynamic-aarch64.dll"
|
|
223
|
+
else:
|
|
224
|
+
logger.debug(f"get_asan_runtime_dll: Unsupported architecture {arch}")
|
|
225
|
+
return None
|
|
226
|
+
|
|
227
|
+
# Check MinGW sysroot bin directory first (primary location)
|
|
228
|
+
sysroot_bin = clang_root / sysroot_name / "bin"
|
|
229
|
+
dll_path = sysroot_bin / dll_name
|
|
230
|
+
if dll_path.exists():
|
|
231
|
+
logger.debug(f"Found ASAN runtime DLL: {dll_path}")
|
|
232
|
+
return dll_path
|
|
233
|
+
|
|
234
|
+
# Fallback: check clang bin directory
|
|
235
|
+
dll_path = clang_bin_dir / dll_name
|
|
236
|
+
if dll_path.exists():
|
|
237
|
+
logger.debug(f"Found ASAN runtime DLL (fallback): {dll_path}")
|
|
238
|
+
return dll_path
|
|
239
|
+
|
|
240
|
+
# Try glob pattern for any ASAN DLL (version may vary)
|
|
241
|
+
for search_dir in [sysroot_bin, clang_bin_dir]:
|
|
242
|
+
if search_dir.exists():
|
|
243
|
+
for dll_file in search_dir.glob("libclang_rt.asan*.dll"):
|
|
244
|
+
logger.debug(f"Found ASAN runtime DLL (glob): {dll_file}")
|
|
245
|
+
return dll_file
|
|
246
|
+
|
|
247
|
+
logger.debug(f"ASAN runtime DLL not found in {sysroot_bin} or {clang_bin_dir}")
|
|
248
|
+
return None
|
|
249
|
+
|
|
250
|
+
except (ImportError, RuntimeError) as e:
|
|
251
|
+
logger.debug(f"Could not get ASAN runtime DLL path: {e}")
|
|
252
|
+
return None
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
def get_all_sanitizer_runtime_dlls() -> list[Path]:
|
|
256
|
+
"""
|
|
257
|
+
Get all sanitizer runtime DLLs (Windows only).
|
|
258
|
+
|
|
259
|
+
This function locates all shared sanitizer runtime DLLs, including:
|
|
260
|
+
- Address Sanitizer (ASAN)
|
|
261
|
+
- Undefined Behavior Sanitizer (UBSAN)
|
|
262
|
+
- Thread Sanitizer (TSAN) - if available
|
|
263
|
+
|
|
264
|
+
This is useful for projects that want to copy all sanitizer DLLs to
|
|
265
|
+
their build directory to ensure all instrumented code can run.
|
|
266
|
+
|
|
267
|
+
Returns:
|
|
268
|
+
List of Paths to sanitizer runtime DLLs, or empty list if not
|
|
269
|
+
found or not on Windows.
|
|
270
|
+
|
|
271
|
+
Example:
|
|
272
|
+
>>> dlls = get_all_sanitizer_runtime_dlls()
|
|
273
|
+
>>> for dll in dlls:
|
|
274
|
+
... shutil.copy(dll, build_dir / dll.name)
|
|
275
|
+
|
|
276
|
+
See Also:
|
|
277
|
+
get_asan_runtime_dll: Returns just the ASAN DLL path
|
|
278
|
+
"""
|
|
279
|
+
if platform.system() != "Windows":
|
|
280
|
+
return []
|
|
281
|
+
|
|
282
|
+
dlls: list[Path] = []
|
|
283
|
+
|
|
284
|
+
try:
|
|
285
|
+
from clang_tool_chain.platform.detection import get_platform_binary_dir, get_platform_info
|
|
286
|
+
|
|
287
|
+
# Get platform info for sysroot lookup
|
|
288
|
+
_platform_name, arch = get_platform_info()
|
|
289
|
+
|
|
290
|
+
# Get the clang root directory
|
|
291
|
+
clang_bin_dir = get_platform_binary_dir()
|
|
292
|
+
clang_root = clang_bin_dir.parent
|
|
293
|
+
|
|
294
|
+
# Determine sysroot based on architecture
|
|
295
|
+
if arch == "x86_64":
|
|
296
|
+
sysroot_name = "x86_64-w64-mingw32"
|
|
297
|
+
elif arch == "arm64":
|
|
298
|
+
sysroot_name = "aarch64-w64-mingw32"
|
|
299
|
+
else:
|
|
300
|
+
return []
|
|
301
|
+
|
|
302
|
+
# Search directories
|
|
303
|
+
search_dirs = [
|
|
304
|
+
clang_root / sysroot_name / "bin",
|
|
305
|
+
clang_bin_dir,
|
|
306
|
+
]
|
|
307
|
+
|
|
308
|
+
# Patterns for sanitizer DLLs
|
|
309
|
+
patterns = [
|
|
310
|
+
"libclang_rt.asan*.dll", # Address Sanitizer
|
|
311
|
+
"libclang_rt.ubsan*.dll", # Undefined Behavior Sanitizer
|
|
312
|
+
"libclang_rt.tsan*.dll", # Thread Sanitizer
|
|
313
|
+
"libclang_rt.lsan*.dll", # Leak Sanitizer (standalone)
|
|
314
|
+
]
|
|
315
|
+
|
|
316
|
+
seen_names: set[str] = set()
|
|
317
|
+
for search_dir in search_dirs:
|
|
318
|
+
if search_dir.exists():
|
|
319
|
+
for pattern in patterns:
|
|
320
|
+
for dll_file in search_dir.glob(pattern):
|
|
321
|
+
if dll_file.name not in seen_names:
|
|
322
|
+
dlls.append(dll_file)
|
|
323
|
+
seen_names.add(dll_file.name)
|
|
324
|
+
logger.debug(f"Found sanitizer DLL: {dll_file}")
|
|
325
|
+
|
|
326
|
+
except (ImportError, RuntimeError) as e:
|
|
327
|
+
logger.debug(f"Could not get sanitizer runtime DLLs: {e}")
|
|
328
|
+
|
|
329
|
+
return dlls
|
|
330
|
+
|
|
331
|
+
|
|
134
332
|
def detect_sanitizers_from_flags(compiler_flags: list[str]) -> tuple[bool, bool]:
|
|
135
333
|
"""
|
|
136
334
|
Detect which sanitizers are enabled from compiler flags.
|
|
@@ -263,8 +461,9 @@ def prepare_sanitizer_environment(
|
|
|
263
461
|
|
|
264
462
|
# Inject ASAN_OPTIONS if ASAN is enabled and not already set by user
|
|
265
463
|
if asan_enabled and "ASAN_OPTIONS" not in env:
|
|
266
|
-
|
|
267
|
-
|
|
464
|
+
asan_options = get_default_asan_options()
|
|
465
|
+
env["ASAN_OPTIONS"] = asan_options
|
|
466
|
+
logger.info(f"Injecting ASAN_OPTIONS={asan_options}")
|
|
268
467
|
|
|
269
468
|
# Inject LSAN_OPTIONS if LSAN is enabled and not already set by user
|
|
270
469
|
if lsan_enabled and "LSAN_OPTIONS" not in env:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: clang-tool-chain
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.7
|
|
4
4
|
Summary: Clang Tool Chain - C/C++ compilation toolchain utilities
|
|
5
5
|
Project-URL: Homepage, https://github.com/zackees/clang-tool-chain
|
|
6
6
|
Project-URL: Repository, https://github.com/zackees/clang-tool-chain
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
clang_tool_chain/__init__.py,sha256=
|
|
2
|
-
clang_tool_chain/__version__.py,sha256=
|
|
1
|
+
clang_tool_chain/__init__.py,sha256=Ac2qUqz9rzFHvXLkH6kqf63m-1JywYcJckKrbLft2ag,1125
|
|
2
|
+
clang_tool_chain/__version__.py,sha256=gVI5QWADLkUhsYHs8TuVovVei5SJ_bx5saZRIWgkOTU,71
|
|
3
3
|
clang_tool_chain/archive.py,sha256=t3reh7cm5XP2rhTqfRIDAQZv5XQq7SsstyiROYg8wFA,27697
|
|
4
4
|
clang_tool_chain/archive_cache.py,sha256=5ZmlwXIJZDcrDFkTbdgBQYN9sulGn0WyI6qwWqC4HEU,6806
|
|
5
5
|
clang_tool_chain/checksums.py,sha256=KFXeAeDz5ZlcZVOxsHDpNDCrm9UDoJ8bMA4PeNhuzdA,9868
|
|
@@ -49,7 +49,7 @@ clang_tool_chain/execution/iwyu.py,sha256=bmP0d_PZObA1JfmFYp3qIOKCb7y32AWPm2_ReF
|
|
|
49
49
|
clang_tool_chain/execution/lldb.py,sha256=VpxkWTPS6PsyskaKTALeziR5Z5NLwarW174Fm1SMX9k,20718
|
|
50
50
|
clang_tool_chain/execution/nodejs_resolver.py,sha256=8QsJWvIfmt5mBDV7n0ypSjsPyXS-eZTizhBli937I-g,11172
|
|
51
51
|
clang_tool_chain/execution/platform_executor.py,sha256=sF4GyW0ujy2EewG8y2Eo1gUWGzss5G5iIkv02w7-2_o,14362
|
|
52
|
-
clang_tool_chain/execution/sanitizer_env.py,sha256=
|
|
52
|
+
clang_tool_chain/execution/sanitizer_env.py,sha256=IHxmeAzbbdrIAz38c2U3erunTVjHjePx7BytVBzluB4,20766
|
|
53
53
|
clang_tool_chain/installers/__init__.py,sha256=NAV5woPCEDKSbFr1UmfQsrg4Ua5UdghN4q7H3ymvRsg,279
|
|
54
54
|
clang_tool_chain/installers/base.py,sha256=OS78bau9zoYPitmhla7pKsfCPEj-zLY0DkvVzjE31Tw,15437
|
|
55
55
|
clang_tool_chain/installers/clang.py,sha256=rUtheVRF7mq_1YdmQ3XzIybrJqsHbm2Xf0cbhRbH7RQ,16994
|
|
@@ -71,8 +71,8 @@ clang_tool_chain/symbolizer/unwind_windows.h,sha256=XTWhJDv13AAMUPAzWCfRN7tO6EbN
|
|
|
71
71
|
clang_tool_chain/testing/__init__.py,sha256=-sYqOOCuTV_u-MkmExrD4uKdTHG4RmMwR3D1kIG281Q,208
|
|
72
72
|
clang_tool_chain/testing/diagnostic_runner.py,sha256=mnmFUEOQulY3-Ggu6hKVGZwjrKQNmV6kY80PRTUu2qU,5293
|
|
73
73
|
clang_tool_chain/testing/diagnostic_tests.py,sha256=GmtKWrDcddZTpx9_yIKfhRAy6YOde8dj7SksCWVEME4,6019
|
|
74
|
-
clang_tool_chain-1.1.
|
|
75
|
-
clang_tool_chain-1.1.
|
|
76
|
-
clang_tool_chain-1.1.
|
|
77
|
-
clang_tool_chain-1.1.
|
|
78
|
-
clang_tool_chain-1.1.
|
|
74
|
+
clang_tool_chain-1.1.7.dist-info/METADATA,sha256=m33JQp6EzIWtJsAFjwat9lcI-kGIXmh902VQZ2IQwb8,60267
|
|
75
|
+
clang_tool_chain-1.1.7.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
76
|
+
clang_tool_chain-1.1.7.dist-info/entry_points.txt,sha256=N0a0OVPkCFbf6BisRkHj-m2TcZ-f1mqxfXxAHQxfrQg,2800
|
|
77
|
+
clang_tool_chain-1.1.7.dist-info/licenses/LICENSE,sha256=51FO1oc2pZbQNI0v0_THnznnZIF4iFgawG1xnQ58kKo,10997
|
|
78
|
+
clang_tool_chain-1.1.7.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|