clang-tool-chain 1.0.42__py3-none-any.whl → 1.0.44__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/__version__.py +1 -1
- clang_tool_chain/execution/__init__.py +5 -0
- clang_tool_chain/execution/arg_transformers.py +43 -13
- clang_tool_chain/execution/build_pipeline.py +8 -2
- clang_tool_chain/execution/sanitizer_env.py +120 -0
- clang_tool_chain/linker/lld.py +76 -121
- clang_tool_chain/llvm_versions.py +101 -0
- {clang_tool_chain-1.0.42.dist-info → clang_tool_chain-1.0.44.dist-info}/METADATA +53 -1
- {clang_tool_chain-1.0.42.dist-info → clang_tool_chain-1.0.44.dist-info}/RECORD +12 -10
- {clang_tool_chain-1.0.42.dist-info → clang_tool_chain-1.0.44.dist-info}/WHEEL +0 -0
- {clang_tool_chain-1.0.42.dist-info → clang_tool_chain-1.0.44.dist-info}/entry_points.txt +0 -0
- {clang_tool_chain-1.0.42.dist-info → clang_tool_chain-1.0.44.dist-info}/licenses/LICENSE +0 -0
clang_tool_chain/__version__.py
CHANGED
|
@@ -5,10 +5,12 @@ This package provides:
|
|
|
5
5
|
- Core tool execution: execute_tool, run_tool
|
|
6
6
|
- Build utilities: build_main, build_run_main
|
|
7
7
|
- sccache wrappers for compilation caching
|
|
8
|
+
- Sanitizer environment configuration
|
|
8
9
|
"""
|
|
9
10
|
|
|
10
11
|
from clang_tool_chain.execution.build import build_main, build_run_main
|
|
11
12
|
from clang_tool_chain.execution.core import execute_tool, run_tool, sccache_clang_cpp_main, sccache_clang_main
|
|
13
|
+
from clang_tool_chain.execution.sanitizer_env import detect_sanitizers_from_flags, prepare_sanitizer_environment
|
|
12
14
|
|
|
13
15
|
__all__ = [
|
|
14
16
|
# Core execution
|
|
@@ -20,4 +22,7 @@ __all__ = [
|
|
|
20
22
|
# sccache wrappers
|
|
21
23
|
"sccache_clang_main",
|
|
22
24
|
"sccache_clang_cpp_main",
|
|
25
|
+
# Sanitizer utilities
|
|
26
|
+
"prepare_sanitizer_environment",
|
|
27
|
+
"detect_sanitizers_from_flags",
|
|
23
28
|
]
|
|
@@ -209,9 +209,10 @@ class LLDLinkerTransformer(ArgumentTransformer):
|
|
|
209
209
|
|
|
210
210
|
Priority: 200 (runs after SDK but before ABI)
|
|
211
211
|
|
|
212
|
-
This transformer adds
|
|
213
|
-
|
|
214
|
-
-
|
|
212
|
+
This transformer adds -fuse-ld=lld linker flag. The clang driver
|
|
213
|
+
automatically dispatches to the correct linker binary:
|
|
214
|
+
- macOS: ld64.lld (Mach-O linker)
|
|
215
|
+
- Linux: ld.lld (ELF linker)
|
|
215
216
|
|
|
216
217
|
It also translates GNU ld flags to ld64.lld equivalents on macOS:
|
|
217
218
|
- --no-undefined -> -undefined error
|
|
@@ -293,11 +294,16 @@ class ASANRuntimeTransformer(ArgumentTransformer):
|
|
|
293
294
|
This transformer ensures proper ASAN runtime linking on Linux:
|
|
294
295
|
- Detects -fsanitize=address flag
|
|
295
296
|
- Adds -shared-libasan to use shared runtime library
|
|
297
|
+
- Adds -Wl,--allow-shlib-undefined when building shared libraries with ASAN
|
|
296
298
|
- Prevents undefined symbol errors during linking
|
|
297
299
|
|
|
298
300
|
The shared runtime library (libclang_rt.asan.so) contains the full
|
|
299
301
|
ASAN implementation, while the static wrapper library only contains stubs.
|
|
300
302
|
|
|
303
|
+
When building shared libraries with sanitizers, the library may have undefined
|
|
304
|
+
symbols that will be provided by the sanitizer runtime when loaded. LLD by
|
|
305
|
+
default enforces no undefined symbols, so we need to allow them explicitly.
|
|
306
|
+
|
|
301
307
|
Environment Variables:
|
|
302
308
|
CLANG_TOOL_CHAIN_NO_SHARED_ASAN: Set to '1' to disable shared ASAN
|
|
303
309
|
"""
|
|
@@ -306,7 +312,9 @@ class ASANRuntimeTransformer(ArgumentTransformer):
|
|
|
306
312
|
return 250
|
|
307
313
|
|
|
308
314
|
def transform(self, args: list[str], context: ToolContext) -> list[str]:
|
|
309
|
-
"""Add -shared-libasan when using ASAN on Linux."""
|
|
315
|
+
"""Add -shared-libasan and --allow-shlib-undefined when using ASAN on Linux."""
|
|
316
|
+
import sys
|
|
317
|
+
|
|
310
318
|
# Only applies to Linux clang/clang++
|
|
311
319
|
if context.platform_name != "linux" or context.tool_name not in ("clang", "clang++"):
|
|
312
320
|
return args
|
|
@@ -316,19 +324,41 @@ class ASANRuntimeTransformer(ArgumentTransformer):
|
|
|
316
324
|
if not has_asan:
|
|
317
325
|
return args
|
|
318
326
|
|
|
327
|
+
result = list(args)
|
|
328
|
+
injected_flags = []
|
|
329
|
+
|
|
319
330
|
# Check if user disabled shared ASAN
|
|
320
|
-
if os.environ.get("CLANG_TOOL_CHAIN_NO_SHARED_ASAN")
|
|
331
|
+
if os.environ.get("CLANG_TOOL_CHAIN_NO_SHARED_ASAN") != "1":
|
|
332
|
+
# Check if -shared-libasan already present
|
|
333
|
+
if "-shared-libasan" not in args:
|
|
334
|
+
# Add -shared-libasan to use shared runtime library
|
|
335
|
+
# This prevents undefined symbol errors during linking
|
|
336
|
+
logger.info("Adding -shared-libasan for ASAN runtime linking on Linux")
|
|
337
|
+
result = ["-shared-libasan"] + result
|
|
338
|
+
injected_flags.append("-shared-libasan")
|
|
339
|
+
else:
|
|
321
340
|
logger.debug("Shared ASAN disabled via CLANG_TOOL_CHAIN_NO_SHARED_ASAN=1")
|
|
322
|
-
return args
|
|
323
341
|
|
|
324
|
-
# Check if
|
|
325
|
-
|
|
326
|
-
|
|
342
|
+
# Check if building a shared library with ASAN
|
|
343
|
+
# Shared libraries need to allow undefined symbols that will be provided
|
|
344
|
+
# by the sanitizer runtime when the runner loads them
|
|
345
|
+
is_shared_lib = "-shared" in args
|
|
346
|
+
if is_shared_lib:
|
|
347
|
+
# Check if --allow-shlib-undefined already present
|
|
348
|
+
has_allow_shlib_undefined = any("--allow-shlib-undefined" in arg for arg in args)
|
|
349
|
+
if not has_allow_shlib_undefined:
|
|
350
|
+
logger.info("Adding -Wl,--allow-shlib-undefined for shared library with ASAN")
|
|
351
|
+
result = ["-Wl,--allow-shlib-undefined"] + result
|
|
352
|
+
injected_flags.append("-Wl,--allow-shlib-undefined")
|
|
353
|
+
|
|
354
|
+
# Warn on stderr if we injected flags
|
|
355
|
+
if injected_flags:
|
|
356
|
+
print(
|
|
357
|
+
f"clang-tool-chain: note: automatically injected sanitizer flags: {' '.join(injected_flags)}",
|
|
358
|
+
file=sys.stderr,
|
|
359
|
+
)
|
|
327
360
|
|
|
328
|
-
|
|
329
|
-
# This prevents undefined symbol errors during linking
|
|
330
|
-
logger.info("Adding -shared-libasan for ASAN runtime linking on Linux")
|
|
331
|
-
return ["-shared-libasan"] + args
|
|
361
|
+
return result
|
|
332
362
|
|
|
333
363
|
|
|
334
364
|
class RPathTransformer(ArgumentTransformer):
|
|
@@ -137,7 +137,7 @@ def _get_directive_args(source_path: Path) -> list[str]:
|
|
|
137
137
|
print(f" Effective args: {' '.join(all_args)}", file=sys.stderr)
|
|
138
138
|
|
|
139
139
|
return all_args
|
|
140
|
-
except KeyboardInterrupt:
|
|
140
|
+
except KeyboardInterrupt:
|
|
141
141
|
# Re-raise KeyboardInterrupt to allow clean exit
|
|
142
142
|
raise
|
|
143
143
|
except Exception as e:
|
|
@@ -249,6 +249,8 @@ class BuildPipeline(ABC):
|
|
|
249
249
|
Raises:
|
|
250
250
|
SystemExit: Always exits with the executable's return code
|
|
251
251
|
"""
|
|
252
|
+
from clang_tool_chain.execution.sanitizer_env import prepare_sanitizer_environment
|
|
253
|
+
|
|
252
254
|
program_args = self.config.program_args or []
|
|
253
255
|
|
|
254
256
|
print(f"\nRunning: {self.config.output_file}", file=sys.stderr)
|
|
@@ -256,11 +258,15 @@ class BuildPipeline(ABC):
|
|
|
256
258
|
print(f"Program arguments: {' '.join(program_args)}", file=sys.stderr)
|
|
257
259
|
print("=" * 60, file=sys.stderr)
|
|
258
260
|
|
|
261
|
+
# Prepare environment with sanitizer options for better stack traces
|
|
262
|
+
# Only inject options if the corresponding sanitizer was used during compilation
|
|
263
|
+
env = prepare_sanitizer_environment(compiler_flags=self.config.compiler_flags)
|
|
264
|
+
|
|
259
265
|
# Run the compiled executable
|
|
260
266
|
try:
|
|
261
267
|
# Use absolute path for Windows compatibility
|
|
262
268
|
abs_output = self.output_path.absolute()
|
|
263
|
-
result = subprocess.run([str(abs_output)] + program_args)
|
|
269
|
+
result = subprocess.run([str(abs_output)] + program_args, env=env)
|
|
264
270
|
sys.exit(result.returncode)
|
|
265
271
|
except FileNotFoundError:
|
|
266
272
|
print(f"\n{'=' * 60}", file=sys.stderr)
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Sanitizer runtime environment configuration.
|
|
3
|
+
|
|
4
|
+
This module provides automatic injection of ASAN_OPTIONS and LSAN_OPTIONS
|
|
5
|
+
environment variables to improve stack trace quality when running executables
|
|
6
|
+
compiled with Address Sanitizer or Leak Sanitizer.
|
|
7
|
+
|
|
8
|
+
The default options fix <unknown module> entries in stack traces from
|
|
9
|
+
dlopen()'d shared libraries by enabling slow unwinding and symbolization.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import logging
|
|
13
|
+
import os
|
|
14
|
+
|
|
15
|
+
logger = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
# Default options to inject for optimal stack traces
|
|
18
|
+
# fast_unwind_on_malloc=0: Use slow but accurate unwinding (fixes <unknown module>)
|
|
19
|
+
# symbolize=1: Enable symbolization for readable stack traces
|
|
20
|
+
# detect_leaks=1: Enable leak detection (ASAN only)
|
|
21
|
+
DEFAULT_ASAN_OPTIONS = "fast_unwind_on_malloc=0:symbolize=1:detect_leaks=1"
|
|
22
|
+
DEFAULT_LSAN_OPTIONS = "fast_unwind_on_malloc=0:symbolize=1"
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def detect_sanitizers_from_flags(compiler_flags: list[str]) -> tuple[bool, bool]:
|
|
26
|
+
"""
|
|
27
|
+
Detect which sanitizers are enabled from compiler flags.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
compiler_flags: List of compiler flags passed to clang.
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
Tuple of (asan_enabled, lsan_enabled).
|
|
34
|
+
|
|
35
|
+
Example:
|
|
36
|
+
>>> detect_sanitizers_from_flags(["-fsanitize=address", "-O2"])
|
|
37
|
+
(True, True) # ASAN implies LSAN by default
|
|
38
|
+
>>> detect_sanitizers_from_flags(["-fsanitize=leak"])
|
|
39
|
+
(False, True)
|
|
40
|
+
>>> detect_sanitizers_from_flags(["-O2", "-Wall"])
|
|
41
|
+
(False, False)
|
|
42
|
+
"""
|
|
43
|
+
asan_enabled = False
|
|
44
|
+
lsan_enabled = False
|
|
45
|
+
|
|
46
|
+
for flag in compiler_flags:
|
|
47
|
+
if flag.startswith("-fsanitize="):
|
|
48
|
+
# Extract sanitizer list (e.g., "-fsanitize=address,undefined" -> "address,undefined")
|
|
49
|
+
sanitizers = flag.split("=", 1)[1].split(",")
|
|
50
|
+
for sanitizer in sanitizers:
|
|
51
|
+
sanitizer = sanitizer.strip()
|
|
52
|
+
if sanitizer == "address":
|
|
53
|
+
asan_enabled = True
|
|
54
|
+
# ASAN includes LSAN by default (unless detect_leaks=0)
|
|
55
|
+
lsan_enabled = True
|
|
56
|
+
elif sanitizer == "leak":
|
|
57
|
+
lsan_enabled = True
|
|
58
|
+
|
|
59
|
+
return asan_enabled, lsan_enabled
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def prepare_sanitizer_environment(
|
|
63
|
+
base_env: dict[str, str] | None = None,
|
|
64
|
+
compiler_flags: list[str] | None = None,
|
|
65
|
+
) -> dict[str, str]:
|
|
66
|
+
"""
|
|
67
|
+
Prepare environment with optimal sanitizer options.
|
|
68
|
+
|
|
69
|
+
This function injects ASAN_OPTIONS and/or LSAN_OPTIONS environment variables
|
|
70
|
+
if they are not already set by the user AND the corresponding sanitizer was
|
|
71
|
+
enabled during compilation. The injected options improve stack trace quality
|
|
72
|
+
for executables using dlopen()'d shared libraries.
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
base_env: Base environment dictionary to modify. If None, uses os.environ.
|
|
76
|
+
compiler_flags: List of compiler flags used to build the executable.
|
|
77
|
+
Used to detect which sanitizers are enabled. If None, no options
|
|
78
|
+
are injected (safe default).
|
|
79
|
+
|
|
80
|
+
Returns:
|
|
81
|
+
Environment dictionary with sanitizer options injected as appropriate.
|
|
82
|
+
|
|
83
|
+
Environment Variables:
|
|
84
|
+
CLANG_TOOL_CHAIN_NO_SANITIZER_ENV: Set to "1", "true", or "yes" to
|
|
85
|
+
disable automatic injection of sanitizer options.
|
|
86
|
+
ASAN_OPTIONS: If already set, preserved as-is (user config takes priority).
|
|
87
|
+
LSAN_OPTIONS: If already set, preserved as-is (user config takes priority).
|
|
88
|
+
|
|
89
|
+
Example:
|
|
90
|
+
>>> env = prepare_sanitizer_environment(compiler_flags=["-fsanitize=address"])
|
|
91
|
+
>>> # env now contains ASAN_OPTIONS and LSAN_OPTIONS
|
|
92
|
+
>>> env = prepare_sanitizer_environment(compiler_flags=["-O2"])
|
|
93
|
+
>>> # env unchanged - no sanitizers enabled
|
|
94
|
+
"""
|
|
95
|
+
env = base_env.copy() if base_env is not None else os.environ.copy()
|
|
96
|
+
|
|
97
|
+
# Check if disabled via environment variable
|
|
98
|
+
if os.environ.get("CLANG_TOOL_CHAIN_NO_SANITIZER_ENV", "").lower() in ("1", "true", "yes"):
|
|
99
|
+
logger.debug("Sanitizer environment injection disabled via CLANG_TOOL_CHAIN_NO_SANITIZER_ENV")
|
|
100
|
+
return env
|
|
101
|
+
|
|
102
|
+
# If no compiler flags provided, don't inject anything (safe default)
|
|
103
|
+
if compiler_flags is None:
|
|
104
|
+
logger.debug("No compiler flags provided, skipping sanitizer environment injection")
|
|
105
|
+
return env
|
|
106
|
+
|
|
107
|
+
# Detect which sanitizers are enabled
|
|
108
|
+
asan_enabled, lsan_enabled = detect_sanitizers_from_flags(compiler_flags)
|
|
109
|
+
|
|
110
|
+
# Inject ASAN_OPTIONS if ASAN is enabled and not already set by user
|
|
111
|
+
if asan_enabled and "ASAN_OPTIONS" not in env:
|
|
112
|
+
env["ASAN_OPTIONS"] = DEFAULT_ASAN_OPTIONS
|
|
113
|
+
logger.info(f"Injecting ASAN_OPTIONS={DEFAULT_ASAN_OPTIONS}")
|
|
114
|
+
|
|
115
|
+
# Inject LSAN_OPTIONS if LSAN is enabled and not already set by user
|
|
116
|
+
if lsan_enabled and "LSAN_OPTIONS" not in env:
|
|
117
|
+
env["LSAN_OPTIONS"] = DEFAULT_LSAN_OPTIONS
|
|
118
|
+
logger.info(f"Injecting LSAN_OPTIONS={DEFAULT_LSAN_OPTIONS}")
|
|
119
|
+
|
|
120
|
+
return env
|
clang_tool_chain/linker/lld.py
CHANGED
|
@@ -6,129 +6,48 @@ This module provides functions for:
|
|
|
6
6
|
- Translating GNU ld flags to ld64.lld equivalents on macOS
|
|
7
7
|
- Managing linker selection based on platform and user preferences
|
|
8
8
|
- Ensuring ld64.lld symlink exists on macOS (runtime fallback)
|
|
9
|
-
- LLVM version detection with caching for compatibility decisions
|
|
10
9
|
"""
|
|
11
10
|
|
|
12
11
|
import logging
|
|
13
12
|
import os
|
|
14
|
-
import re
|
|
15
|
-
import subprocess
|
|
16
13
|
import sys
|
|
17
14
|
|
|
18
15
|
from clang_tool_chain.interrupt_utils import handle_keyboard_interrupt_properly
|
|
16
|
+
from clang_tool_chain.llvm_versions import get_llvm_version_tuple, supports_ld64_lld_flag
|
|
19
17
|
|
|
20
18
|
logger = logging.getLogger(__name__)
|
|
21
19
|
|
|
22
|
-
# Module-level cache for LLVM version (avoids repeated subprocess calls)
|
|
23
|
-
_cached_llvm_version: tuple[int, int, int] | None = None
|
|
24
20
|
|
|
25
|
-
|
|
26
|
-
def _get_llvm_version() -> tuple[int, int, int] | None:
|
|
21
|
+
def _get_llvm_version_for_platform() -> tuple[int, int, int]:
|
|
27
22
|
"""
|
|
28
|
-
Get the LLVM version
|
|
29
|
-
|
|
30
|
-
This runs `clang --version` and parses the version number. The result
|
|
31
|
-
is cached in memory for the duration of the process, and also cached
|
|
32
|
-
to a file in the install directory for persistence across invocations.
|
|
23
|
+
Get the LLVM version for the current platform from centralized configuration.
|
|
33
24
|
|
|
34
25
|
Returns:
|
|
35
|
-
Tuple of (major, minor, patch) version numbers
|
|
26
|
+
Tuple of (major, minor, patch) version numbers.
|
|
36
27
|
"""
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
# Return memory-cached version if available
|
|
40
|
-
if _cached_llvm_version is not None:
|
|
41
|
-
return _cached_llvm_version
|
|
42
|
-
|
|
43
|
-
# Try to read from file cache
|
|
44
|
-
try:
|
|
45
|
-
from ..platform.detection import get_platform_binary_dir
|
|
46
|
-
|
|
47
|
-
bin_dir = get_platform_binary_dir()
|
|
48
|
-
cache_file = bin_dir.parent / ".llvm_version_cache"
|
|
49
|
-
|
|
50
|
-
if cache_file.exists():
|
|
51
|
-
cached = cache_file.read_text().strip()
|
|
52
|
-
parts = cached.split(".")
|
|
53
|
-
if len(parts) >= 3:
|
|
54
|
-
_cached_llvm_version = (int(parts[0]), int(parts[1]), int(parts[2]))
|
|
55
|
-
logger.debug(f"Loaded LLVM version from cache: {_cached_llvm_version}")
|
|
56
|
-
return _cached_llvm_version
|
|
57
|
-
except KeyboardInterrupt as ke:
|
|
58
|
-
handle_keyboard_interrupt_properly(ke)
|
|
59
|
-
except Exception as e:
|
|
60
|
-
logger.debug(f"Could not read LLVM version cache: {e}")
|
|
28
|
+
from ..platform.detection import get_platform_info
|
|
61
29
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
from ..platform.detection import get_platform_binary_dir
|
|
65
|
-
|
|
66
|
-
bin_dir = get_platform_binary_dir()
|
|
67
|
-
clang_path = bin_dir / "clang"
|
|
68
|
-
|
|
69
|
-
if not clang_path.exists():
|
|
70
|
-
logger.debug(f"Clang binary not found at {clang_path}")
|
|
71
|
-
return None
|
|
72
|
-
|
|
73
|
-
result = subprocess.run(
|
|
74
|
-
[str(clang_path), "--version"],
|
|
75
|
-
capture_output=True,
|
|
76
|
-
text=True,
|
|
77
|
-
timeout=10,
|
|
78
|
-
)
|
|
79
|
-
|
|
80
|
-
if result.returncode != 0:
|
|
81
|
-
logger.debug(f"clang --version failed: {result.stderr}")
|
|
82
|
-
return None
|
|
83
|
-
|
|
84
|
-
# Parse version from output like "clang version 19.1.7 (...)"
|
|
85
|
-
version_match = re.search(r"clang version (\d+)\.(\d+)\.(\d+)", result.stdout)
|
|
86
|
-
if version_match:
|
|
87
|
-
major, minor, patch = int(version_match.group(1)), int(version_match.group(2)), int(version_match.group(3))
|
|
88
|
-
_cached_llvm_version = (major, minor, patch)
|
|
89
|
-
logger.debug(f"Detected LLVM version: {_cached_llvm_version}")
|
|
90
|
-
|
|
91
|
-
# Save to file cache for persistence
|
|
92
|
-
try:
|
|
93
|
-
cache_file = bin_dir.parent / ".llvm_version_cache"
|
|
94
|
-
cache_file.write_text(f"{major}.{minor}.{patch}")
|
|
95
|
-
logger.debug(f"Saved LLVM version to cache: {cache_file}")
|
|
96
|
-
except KeyboardInterrupt as ke:
|
|
97
|
-
handle_keyboard_interrupt_properly(ke)
|
|
98
|
-
except Exception as e:
|
|
99
|
-
logger.debug(f"Could not write LLVM version cache: {e}")
|
|
100
|
-
|
|
101
|
-
return _cached_llvm_version
|
|
102
|
-
|
|
103
|
-
logger.debug(f"Could not parse LLVM version from: {result.stdout[:200]}")
|
|
104
|
-
return None
|
|
105
|
-
|
|
106
|
-
except KeyboardInterrupt as ke:
|
|
107
|
-
handle_keyboard_interrupt_properly(ke)
|
|
108
|
-
except Exception as e:
|
|
109
|
-
logger.debug(f"LLVM version detection failed: {e}")
|
|
110
|
-
return None
|
|
30
|
+
platform_name, _ = get_platform_info()
|
|
31
|
+
return get_llvm_version_tuple(platform_name)
|
|
111
32
|
|
|
112
33
|
|
|
113
34
|
def _llvm_supports_ld64_lld_flag() -> bool:
|
|
114
35
|
"""
|
|
115
|
-
Check if the
|
|
36
|
+
Check if the current platform's LLVM version supports -fuse-ld=ld64.lld.
|
|
116
37
|
|
|
117
|
-
The -fuse-ld=ld64.lld
|
|
118
|
-
|
|
38
|
+
Note: The clang driver does NOT recognize -fuse-ld=ld64.lld as a valid option.
|
|
39
|
+
This function exists for backward compatibility but always returns False in practice
|
|
40
|
+
because -fuse-ld=lld should be used instead (clang auto-dispatches to ld64.lld on Darwin).
|
|
119
41
|
|
|
120
42
|
Returns:
|
|
121
|
-
True if LLVM >= 21.x
|
|
43
|
+
True if LLVM >= 21.x (but we always fall back to -fuse-ld=lld anyway)
|
|
122
44
|
"""
|
|
123
|
-
|
|
124
|
-
if version is None:
|
|
125
|
-
# If we can't detect version, assume older LLVM for safety
|
|
126
|
-
logger.debug("Could not detect LLVM version, assuming < 21.x for ld64.lld compatibility")
|
|
127
|
-
return False
|
|
45
|
+
from ..platform.detection import get_platform_info
|
|
128
46
|
|
|
129
|
-
|
|
130
|
-
supports =
|
|
131
|
-
|
|
47
|
+
platform_name, _ = get_platform_info()
|
|
48
|
+
supports = supports_ld64_lld_flag(platform_name)
|
|
49
|
+
version = get_llvm_version_tuple(platform_name)
|
|
50
|
+
logger.debug(f"LLVM {version[0]}.x {'supports' if supports else 'does not support'} -fuse-ld=ld64.lld")
|
|
132
51
|
return supports
|
|
133
52
|
|
|
134
53
|
|
|
@@ -354,6 +273,39 @@ def _user_specified_lld_on_macos(args: list[str]) -> bool:
|
|
|
354
273
|
return "-fuse-ld=lld" in args_str or "-fuse-ld=ld64.lld" in args_str
|
|
355
274
|
|
|
356
275
|
|
|
276
|
+
def _user_specified_ld64_lld(args: list[str]) -> bool:
|
|
277
|
+
"""
|
|
278
|
+
Check if the user explicitly specified -fuse-ld=ld64.lld.
|
|
279
|
+
|
|
280
|
+
This is used to emit a warning that the flag will be auto-converted
|
|
281
|
+
to -fuse-ld=lld since clang driver doesn't recognize ld64.lld.
|
|
282
|
+
|
|
283
|
+
Args:
|
|
284
|
+
args: Command-line arguments
|
|
285
|
+
|
|
286
|
+
Returns:
|
|
287
|
+
True if user specified -fuse-ld=ld64.lld
|
|
288
|
+
"""
|
|
289
|
+
return any("-fuse-ld=ld64.lld" in arg for arg in args)
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
def _convert_ld64_lld_to_lld(args: list[str]) -> list[str]:
|
|
293
|
+
"""
|
|
294
|
+
Convert -fuse-ld=ld64.lld to -fuse-ld=lld in arguments.
|
|
295
|
+
|
|
296
|
+
The clang driver does not recognize -fuse-ld=ld64.lld as a valid option.
|
|
297
|
+
This function converts it to -fuse-ld=lld which the driver recognizes
|
|
298
|
+
and automatically dispatches to ld64.lld on Darwin targets.
|
|
299
|
+
|
|
300
|
+
Args:
|
|
301
|
+
args: Original compiler arguments
|
|
302
|
+
|
|
303
|
+
Returns:
|
|
304
|
+
Modified arguments with -fuse-ld=ld64.lld replaced by -fuse-ld=lld
|
|
305
|
+
"""
|
|
306
|
+
return [arg.replace("-fuse-ld=ld64.lld", "-fuse-ld=lld") for arg in args]
|
|
307
|
+
|
|
308
|
+
|
|
357
309
|
# pyright: reportUnusedFunction=false
|
|
358
310
|
def _add_lld_linker_if_needed(platform_name: str, args: list[str]) -> list[str]:
|
|
359
311
|
"""
|
|
@@ -366,9 +318,10 @@ def _add_lld_linker_if_needed(platform_name: str, args: list[str]) -> list[str]:
|
|
|
366
318
|
- Faster linking performance
|
|
367
319
|
- Uniform toolchain across all platforms
|
|
368
320
|
|
|
369
|
-
Platform-specific
|
|
370
|
-
-
|
|
371
|
-
-
|
|
321
|
+
Platform-specific behavior:
|
|
322
|
+
- Uses -fuse-ld=lld on all platforms (clang driver auto-dispatches)
|
|
323
|
+
- macOS: Clang driver finds ld64.lld (Mach-O linker)
|
|
324
|
+
- Linux: Clang driver finds ld.lld (ELF linker)
|
|
372
325
|
|
|
373
326
|
The function is skipped when:
|
|
374
327
|
- User sets CLANG_TOOL_CHAIN_USE_SYSTEM_LD=1
|
|
@@ -384,14 +337,25 @@ def _add_lld_linker_if_needed(platform_name: str, args: list[str]) -> list[str]:
|
|
|
384
337
|
args: Original compiler arguments
|
|
385
338
|
|
|
386
339
|
Returns:
|
|
387
|
-
Modified arguments with
|
|
340
|
+
Modified arguments with -fuse-ld=lld flag prepended if needed
|
|
388
341
|
"""
|
|
389
342
|
# On macOS, if user explicitly specified LLD, we still need to translate flags
|
|
390
343
|
# and ensure ld64.lld symlink exists, even though we don't inject the -fuse-ld flag ourselves
|
|
391
344
|
if platform_name == "darwin" and _user_specified_lld_on_macos(args):
|
|
392
345
|
logger.debug("User specified LLD on macOS, translating GNU ld flags to ld64.lld equivalents")
|
|
393
|
-
# Ensure ld64.lld symlink exists for
|
|
346
|
+
# Ensure ld64.lld symlink exists for lld to dispatch to Mach-O mode
|
|
394
347
|
_ensure_ld64_lld_symlink()
|
|
348
|
+
|
|
349
|
+
# Check if user specified -fuse-ld=ld64.lld (which is not a valid clang driver option)
|
|
350
|
+
# and emit a warning about the auto-conversion to -fuse-ld=lld
|
|
351
|
+
if _user_specified_ld64_lld(args):
|
|
352
|
+
print(
|
|
353
|
+
"[clang-tool-chain] Warning: -fuse-ld=ld64.lld is not a valid clang driver option. "
|
|
354
|
+
"Auto-converting to -fuse-ld=lld (clang driver auto-dispatches to ld64.lld on Darwin).",
|
|
355
|
+
file=sys.stderr,
|
|
356
|
+
)
|
|
357
|
+
args = _convert_ld64_lld_to_lld(args)
|
|
358
|
+
|
|
395
359
|
return _translate_linker_flags_for_macos_lld(args)
|
|
396
360
|
|
|
397
361
|
if not _should_force_lld(platform_name, args):
|
|
@@ -402,22 +366,13 @@ def _add_lld_linker_if_needed(platform_name: str, args: list[str]) -> list[str]:
|
|
|
402
366
|
# On macOS, translate GNU ld flags to ld64.lld equivalents
|
|
403
367
|
if platform_name == "darwin":
|
|
404
368
|
args = _translate_linker_flags_for_macos_lld(args)
|
|
369
|
+
# Ensure ld64.lld symlink exists for lld to dispatch to Mach-O mode
|
|
370
|
+
_ensure_ld64_lld_symlink()
|
|
405
371
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
version = _get_llvm_version()
|
|
414
|
-
version_str = f"{version[0]}.{version[1]}.{version[2]}" if version else "unknown"
|
|
415
|
-
print(
|
|
416
|
-
f"[clang-tool-chain] LLVM {version_str} does not support -fuse-ld=ld64.lld, "
|
|
417
|
-
f"using -fuse-ld=lld instead (lld auto-detects Mach-O from target)",
|
|
418
|
-
file=sys.stderr,
|
|
419
|
-
)
|
|
420
|
-
return ["-fuse-ld=lld"] + args
|
|
421
|
-
else:
|
|
422
|
-
# Linux uses standard lld
|
|
423
|
-
return ["-fuse-ld=lld"] + args
|
|
372
|
+
# Always use -fuse-ld=lld on all platforms.
|
|
373
|
+
# Note: -fuse-ld=ld64.lld is NOT a valid clang driver option.
|
|
374
|
+
# The clang driver only recognizes generic names like "lld", "gold", "bfd".
|
|
375
|
+
# When -fuse-ld=lld is used, clang automatically dispatches to:
|
|
376
|
+
# - Darwin: ld64.lld (Mach-O linker)
|
|
377
|
+
# - Linux: ld.lld (ELF linker)
|
|
378
|
+
return ["-fuse-ld=lld"] + args
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Centralized LLVM version configuration for clang-tool-chain.
|
|
3
|
+
|
|
4
|
+
This module provides a single source of truth for LLVM versions used by the toolchain.
|
|
5
|
+
When updating LLVM versions, only this file needs to be modified.
|
|
6
|
+
|
|
7
|
+
Version history:
|
|
8
|
+
- 21.1.6: macOS (darwin) x86_64 and arm64
|
|
9
|
+
- 21.1.5: Windows x86_64, Linux x86_64 and arm64
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from typing import NamedTuple
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class LLVMVersion(NamedTuple):
|
|
16
|
+
"""LLVM version as a tuple of (major, minor, patch)."""
|
|
17
|
+
|
|
18
|
+
major: int
|
|
19
|
+
minor: int
|
|
20
|
+
patch: int
|
|
21
|
+
|
|
22
|
+
def __str__(self) -> str:
|
|
23
|
+
return f"{self.major}.{self.minor}.{self.patch}"
|
|
24
|
+
|
|
25
|
+
@classmethod
|
|
26
|
+
def from_string(cls, version_str: str) -> "LLVMVersion":
|
|
27
|
+
"""Parse a version string like '21.1.6' into an LLVMVersion."""
|
|
28
|
+
parts = version_str.split(".")
|
|
29
|
+
if len(parts) != 3:
|
|
30
|
+
raise ValueError(f"Invalid version string: {version_str}")
|
|
31
|
+
return cls(int(parts[0]), int(parts[1]), int(parts[2]))
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
# Centralized LLVM version configuration by platform
|
|
35
|
+
# Format: {platform_name: LLVMVersion}
|
|
36
|
+
# Platform names match detection.py: "darwin", "linux", "win"
|
|
37
|
+
LLVM_VERSIONS: dict[str, LLVMVersion] = {
|
|
38
|
+
"darwin": LLVMVersion(21, 1, 6), # macOS x86_64 and arm64
|
|
39
|
+
"linux": LLVMVersion(21, 1, 5), # Linux x86_64 and arm64
|
|
40
|
+
"win": LLVMVersion(21, 1, 5), # Windows x86_64
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
# Default version when platform is unknown (should not happen in practice)
|
|
44
|
+
DEFAULT_LLVM_VERSION = LLVMVersion(21, 1, 5)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def get_llvm_version(platform_name: str) -> LLVMVersion:
|
|
48
|
+
"""
|
|
49
|
+
Get the LLVM version for a specific platform.
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
platform_name: Platform name ("darwin", "linux", "win")
|
|
53
|
+
|
|
54
|
+
Returns:
|
|
55
|
+
LLVMVersion tuple for the platform
|
|
56
|
+
"""
|
|
57
|
+
return LLVM_VERSIONS.get(platform_name, DEFAULT_LLVM_VERSION)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def get_llvm_version_string(platform_name: str) -> str:
|
|
61
|
+
"""
|
|
62
|
+
Get the LLVM version string for a specific platform.
|
|
63
|
+
|
|
64
|
+
Args:
|
|
65
|
+
platform_name: Platform name ("darwin", "linux", "win")
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
Version string like "21.1.6"
|
|
69
|
+
"""
|
|
70
|
+
return str(get_llvm_version(platform_name))
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def get_llvm_version_tuple(platform_name: str) -> tuple[int, int, int]:
|
|
74
|
+
"""
|
|
75
|
+
Get the LLVM version as a tuple for a specific platform.
|
|
76
|
+
|
|
77
|
+
Args:
|
|
78
|
+
platform_name: Platform name ("darwin", "linux", "win")
|
|
79
|
+
|
|
80
|
+
Returns:
|
|
81
|
+
Version tuple like (21, 1, 6)
|
|
82
|
+
"""
|
|
83
|
+
version = get_llvm_version(platform_name)
|
|
84
|
+
return (version.major, version.minor, version.patch)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def supports_ld64_lld_flag(platform_name: str) -> bool:
|
|
88
|
+
"""
|
|
89
|
+
Check if the platform's LLVM version supports -fuse-ld=ld64.lld.
|
|
90
|
+
|
|
91
|
+
The -fuse-ld=ld64.lld flag is only recognized by LLVM 21.x and later.
|
|
92
|
+
Earlier versions require -fuse-ld=lld (which auto-detects Mach-O from target).
|
|
93
|
+
|
|
94
|
+
Args:
|
|
95
|
+
platform_name: Platform name ("darwin", "linux", "win")
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
True if LLVM >= 21.x, False otherwise
|
|
99
|
+
"""
|
|
100
|
+
version = get_llvm_version(platform_name)
|
|
101
|
+
return version.major >= 21
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: clang-tool-chain
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.44
|
|
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
|
|
@@ -240,6 +240,7 @@ Comprehensive reference of all available commands organized by category.
|
|
|
240
240
|
- [Inlined Build Directives](#-inlined-build-directives)
|
|
241
241
|
- [Executable C++ Scripts](#-executable-c-scripts-shebang-support)
|
|
242
242
|
- [Windows DLL Deployment](#-windows-dll-deployment)
|
|
243
|
+
- [Address Sanitizer (ASAN)](#️-address-sanitizer-asan-support)
|
|
243
244
|
- [sccache Integration](#-sccache-integration)
|
|
244
245
|
|
|
245
246
|
### Platform & Configuration
|
|
@@ -794,6 +795,7 @@ jobs:
|
|
|
794
795
|
- `CLANG_TOOL_CHAIN_LIB_DEPLOY_VERBOSE` - Enable verbose library deployment logging
|
|
795
796
|
- `CLANG_TOOL_CHAIN_USE_SYSTEM_LD` - Use system linker instead of LLD
|
|
796
797
|
- `CLANG_TOOL_CHAIN_NO_DIRECTIVES` - Disable inlined build directives
|
|
798
|
+
- `CLANG_TOOL_CHAIN_NO_SANITIZER_ENV` - Disable automatic ASAN/LSAN options injection at runtime
|
|
797
799
|
- `SDKROOT` - Custom macOS SDK path (auto-detected by default)
|
|
798
800
|
|
|
799
801
|
**📖 [Complete Documentation](docs/CONFIGURATION.md)** - All environment variables, macOS SDK, Windows DLL settings, sccache backends.
|
|
@@ -838,6 +840,56 @@ Automatic MinGW runtime DLL deployment for Windows executables (GNU ABI). Progra
|
|
|
838
840
|
|
|
839
841
|
---
|
|
840
842
|
|
|
843
|
+
## 🛡️ Address Sanitizer (ASAN) Support
|
|
844
|
+
|
|
845
|
+
Full ASAN support with automatic runtime configuration for better stack traces.
|
|
846
|
+
|
|
847
|
+
### Compilation
|
|
848
|
+
|
|
849
|
+
```bash
|
|
850
|
+
# Compile with ASAN
|
|
851
|
+
clang-tool-chain-cpp -fsanitize=address test.cpp -o test
|
|
852
|
+
|
|
853
|
+
# With automatic library deployment (recommended)
|
|
854
|
+
clang-tool-chain-cpp -fsanitize=address test.cpp -o test --deploy-dependencies
|
|
855
|
+
|
|
856
|
+
# Run - ASAN errors will be detected
|
|
857
|
+
./test
|
|
858
|
+
```
|
|
859
|
+
|
|
860
|
+
### Runtime Environment (Automatic)
|
|
861
|
+
|
|
862
|
+
When running executables via `clang-tool-chain-build-run`, optimal sanitizer options are **automatically injected** to improve stack trace quality - but **only when the corresponding sanitizer was used during compilation**:
|
|
863
|
+
|
|
864
|
+
- `ASAN_OPTIONS=fast_unwind_on_malloc=0:symbolize=1:detect_leaks=1` (when `-fsanitize=address` is used)
|
|
865
|
+
- `LSAN_OPTIONS=fast_unwind_on_malloc=0:symbolize=1` (when `-fsanitize=address` or `-fsanitize=leak` is used)
|
|
866
|
+
|
|
867
|
+
**What these options fix:**
|
|
868
|
+
- `<unknown module>` entries in stack traces from `dlopen()`'d shared libraries
|
|
869
|
+
- Missing function names in crash reports
|
|
870
|
+
- Incomplete leak detection
|
|
871
|
+
|
|
872
|
+
**Your options are always preserved** - if you set `ASAN_OPTIONS` or `LSAN_OPTIONS` yourself, clang-tool-chain won't override them.
|
|
873
|
+
|
|
874
|
+
**Regular builds are unaffected** - sanitizer options are only injected when the compiler flags indicate sanitizers are being used.
|
|
875
|
+
|
|
876
|
+
### Configuration
|
|
877
|
+
|
|
878
|
+
```bash
|
|
879
|
+
# Disable automatic sanitizer environment injection
|
|
880
|
+
export CLANG_TOOL_CHAIN_NO_SANITIZER_ENV=1
|
|
881
|
+
|
|
882
|
+
# Disable automatic -shared-libasan on Linux (use static ASAN)
|
|
883
|
+
export CLANG_TOOL_CHAIN_NO_SHARED_ASAN=1
|
|
884
|
+
```
|
|
885
|
+
|
|
886
|
+
**Platform Notes:**
|
|
887
|
+
- **Linux**: Automatically uses `-shared-libasan` for proper runtime linking
|
|
888
|
+
- **Windows**: Works with both GNU and MSVC ABIs
|
|
889
|
+
- **macOS**: Uses bundled LLVM ASAN runtime
|
|
890
|
+
|
|
891
|
+
---
|
|
892
|
+
|
|
841
893
|
## 🔧 How It Works
|
|
842
894
|
|
|
843
895
|
Auto-downloads on first use (~71-91 MB, 10-60 seconds). Subsequent uses are instant.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
clang_tool_chain/__init__.py,sha256=w3f1hdA72SH-WsfwesNTQbTeiXIlhV8ignySXrV3SfU,23
|
|
2
|
-
clang_tool_chain/__version__.py,sha256=
|
|
2
|
+
clang_tool_chain/__version__.py,sha256=VyBCcvXR6mMibUFhauoR0iyFq2jth9ReImF-qE_frUY,72
|
|
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
|
|
@@ -12,6 +12,7 @@ clang_tool_chain/env_breadcrumbs.py,sha256=bvPTz8xABILhzrXTEBzdGrSbpEXLf2YVgcYEe
|
|
|
12
12
|
clang_tool_chain/fetch.py,sha256=DwsNl5DZkNqEYXL-FbCTnp6IA2iCAa9pMl5oPjyuOS4,4696
|
|
13
13
|
clang_tool_chain/installer.py,sha256=GuGeUvVcAw4HMj9jrub-I11ixmksw-vgtSOFrlupmPA,3323
|
|
14
14
|
clang_tool_chain/interrupt_utils.py,sha256=7YvazvGzyItRVDZ_pzUSK6at8PCw-Dgih69HLSz0tT4,1153
|
|
15
|
+
clang_tool_chain/llvm_versions.py,sha256=lJuMmrRwOpXJxkrNL6HPbZOCemhZA88t0O0SET3VASo,2963
|
|
15
16
|
clang_tool_chain/logging_config.py,sha256=HS0AMgIiyx2fwdl24mZ1oJDCW_MD5VeLxkTwT3d3v9o,2059
|
|
16
17
|
clang_tool_chain/manifest.py,sha256=kYtUDQLY8RHpKeKRoIlzzA52bDnTG0Thx1rp19LvdNg,22138
|
|
17
18
|
clang_tool_chain/parallel_download.py,sha256=nIyiTzSO8c3NA787TQztHRKko2GtQrZbiNbQiepjbDk,19144
|
|
@@ -35,10 +36,10 @@ clang_tool_chain/deployment/factory.py,sha256=Mq6cMMUctoYBZ81I16_hXUmDLQGSAngCmB
|
|
|
35
36
|
clang_tool_chain/deployment/so_deployer.py,sha256=9mRKcJUXKV-8vXWJGdsUkB5cTPWjmToFUcHTVTCHdVk,11527
|
|
36
37
|
clang_tool_chain/directives/__init__.py,sha256=MJDNYL_MD2MF0HFsrTsSTX645bYo6vtjq2pOTtfykaU,198
|
|
37
38
|
clang_tool_chain/directives/parser.py,sha256=6J7mO1JtvuHkkKS0Xges5b_jT9b3uTF6ULI0ZiwGAdw,11179
|
|
38
|
-
clang_tool_chain/execution/__init__.py,sha256=
|
|
39
|
-
clang_tool_chain/execution/arg_transformers.py,sha256=
|
|
39
|
+
clang_tool_chain/execution/__init__.py,sha256=wSYnlGmfTlaUPEKwW6PgwlxKTti6Wa5yyVjXVipdpcY,875
|
|
40
|
+
clang_tool_chain/execution/arg_transformers.py,sha256=vN-1T1mfD61Mg-P2B6hOQeLdD1RZA3l1pmNBbJSzo-g,19750
|
|
40
41
|
clang_tool_chain/execution/build.py,sha256=PCtHw31WXbjCp2K_qaf1liaCiIjD49036cknqdQyhJM,13040
|
|
41
|
-
clang_tool_chain/execution/build_pipeline.py,sha256=
|
|
42
|
+
clang_tool_chain/execution/build_pipeline.py,sha256=piqh7P2-GR0mVOik3OUGRFqWFIRr8LQM3PU7TcBsujk,17622
|
|
42
43
|
clang_tool_chain/execution/core.py,sha256=7CJ0azznC5lq5bw8amk2kwCIN2I_OnDiKytpapkvrdY,25273
|
|
43
44
|
clang_tool_chain/execution/cosmocc.py,sha256=oGlaPK6Jpz3FaohEkWpRz8sRNu2sT-HYCoIf9xBxJHk,13319
|
|
44
45
|
clang_tool_chain/execution/emscripten.py,sha256=lgxPQpeB1_wWxNILgeyyrW5lEn117dHS9dQ3ikHRn1w,44235
|
|
@@ -46,6 +47,7 @@ clang_tool_chain/execution/iwyu.py,sha256=bmP0d_PZObA1JfmFYp3qIOKCb7y32AWPm2_ReF
|
|
|
46
47
|
clang_tool_chain/execution/lldb.py,sha256=VpxkWTPS6PsyskaKTALeziR5Z5NLwarW174Fm1SMX9k,20718
|
|
47
48
|
clang_tool_chain/execution/nodejs_resolver.py,sha256=8QsJWvIfmt5mBDV7n0ypSjsPyXS-eZTizhBli937I-g,11172
|
|
48
49
|
clang_tool_chain/execution/platform_executor.py,sha256=sF4GyW0ujy2EewG8y2Eo1gUWGzss5G5iIkv02w7-2_o,14362
|
|
50
|
+
clang_tool_chain/execution/sanitizer_env.py,sha256=lrGX17BriqYPsHCCrQnwjw0ttnp9mezsq0eYAOLfBag,4853
|
|
49
51
|
clang_tool_chain/installers/__init__.py,sha256=NAV5woPCEDKSbFr1UmfQsrg4Ua5UdghN4q7H3ymvRsg,279
|
|
50
52
|
clang_tool_chain/installers/base.py,sha256=OS78bau9zoYPitmhla7pKsfCPEj-zLY0DkvVzjE31Tw,15437
|
|
51
53
|
clang_tool_chain/installers/clang.py,sha256=rUtheVRF7mq_1YdmQ3XzIybrJqsHbm2Xf0cbhRbH7RQ,16994
|
|
@@ -55,7 +57,7 @@ clang_tool_chain/installers/iwyu.py,sha256=9aAhdGtOTY6BrLuPtladY8Y2mz1i7FjgbMxZf
|
|
|
55
57
|
clang_tool_chain/installers/lldb.py,sha256=FpG8NMNQk8PoNfg6aeU_plmSQrVET7zo-pTvoK8z838,2261
|
|
56
58
|
clang_tool_chain/installers/nodejs.py,sha256=5N07rotgmCfUaDm1uJfBlIAFKC1iTpgZT0HBRuoYwKI,9343
|
|
57
59
|
clang_tool_chain/linker/__init__.py,sha256=ghzDFpZ2-gPmdDO6K05C7yNbY6pZLANPuUks9TaQwVY,537
|
|
58
|
-
clang_tool_chain/linker/lld.py,sha256=
|
|
60
|
+
clang_tool_chain/linker/lld.py,sha256=08qkvoK4-8yACm34GfZzp3vM8rZYHCv_M9fjUeSetd0,13826
|
|
59
61
|
clang_tool_chain/platform/__init__.py,sha256=WkV9Y25ua0mtzEGcsIxF-qExtroSTAMKkcElWuQF2BE,342
|
|
60
62
|
clang_tool_chain/platform/detection.py,sha256=PLHyUfmQ5xuohhpz0KSXJWK3d0u0fCsjx1DbM8f1CxQ,5470
|
|
61
63
|
clang_tool_chain/platform/paths.py,sha256=K0IjeVwbmgPlAWQO8mS3r1WS4C2dN6IYrSqPpckeT5c,6088
|
|
@@ -65,8 +67,8 @@ clang_tool_chain/sdk/windows.py,sha256=8zMLAoFz2OKMz-w6Kqxr3A-6Cofto2VWZvCvRi7kn
|
|
|
65
67
|
clang_tool_chain/testing/__init__.py,sha256=-sYqOOCuTV_u-MkmExrD4uKdTHG4RmMwR3D1kIG281Q,208
|
|
66
68
|
clang_tool_chain/testing/diagnostic_runner.py,sha256=mnmFUEOQulY3-Ggu6hKVGZwjrKQNmV6kY80PRTUu2qU,5293
|
|
67
69
|
clang_tool_chain/testing/diagnostic_tests.py,sha256=GmtKWrDcddZTpx9_yIKfhRAy6YOde8dj7SksCWVEME4,6019
|
|
68
|
-
clang_tool_chain-1.0.
|
|
69
|
-
clang_tool_chain-1.0.
|
|
70
|
-
clang_tool_chain-1.0.
|
|
71
|
-
clang_tool_chain-1.0.
|
|
72
|
-
clang_tool_chain-1.0.
|
|
70
|
+
clang_tool_chain-1.0.44.dist-info/METADATA,sha256=SjvdkUZlqBEHGRSpfaWoAys6sGSSOkH3_b9BdvKFOd0,50425
|
|
71
|
+
clang_tool_chain-1.0.44.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
72
|
+
clang_tool_chain-1.0.44.dist-info/entry_points.txt,sha256=DBfnqZJzHFoO6rldGY3ESaX-z2ydAvIueUPM9ss9M-w,2728
|
|
73
|
+
clang_tool_chain-1.0.44.dist-info/licenses/LICENSE,sha256=51FO1oc2pZbQNI0v0_THnznnZIF4iFgawG1xnQ58kKo,10997
|
|
74
|
+
clang_tool_chain-1.0.44.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|