clang-tool-chain 1.0.44__py3-none-any.whl → 1.0.45__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 +1,32 @@
1
1
  __version__ = "1.0.30"
2
+
3
+ # Re-export commonly used functions for convenient access
4
+ from clang_tool_chain.env_utils import (
5
+ CONTROLLABLE_FEATURES,
6
+ get_disabled_features,
7
+ is_auto_disabled,
8
+ is_feature_disabled,
9
+ )
10
+ from clang_tool_chain.execution.sanitizer_env import (
11
+ detect_sanitizers_from_flags,
12
+ get_symbolizer_path,
13
+ prepare_sanitizer_environment,
14
+ )
15
+ from clang_tool_chain.platform import find_tool_binary, get_platform_binary_dir, get_platform_info
16
+
17
+ __all__ = [
18
+ "__version__",
19
+ # Platform utilities
20
+ "get_platform_info",
21
+ "get_platform_binary_dir",
22
+ "find_tool_binary",
23
+ # Environment utilities
24
+ "is_feature_disabled",
25
+ "is_auto_disabled",
26
+ "get_disabled_features",
27
+ "CONTROLLABLE_FEATURES",
28
+ # Sanitizer environment
29
+ "prepare_sanitizer_environment",
30
+ "get_symbolizer_path",
31
+ "detect_sanitizers_from_flags",
32
+ ]
@@ -1,3 +1,3 @@
1
1
  """Version information for clang-tool-chain."""
2
2
 
3
- __version__ = "1.0.44"
3
+ __version__ = "1.0.45"
@@ -12,6 +12,7 @@ import re
12
12
  import subprocess
13
13
  from pathlib import Path
14
14
 
15
+ from clang_tool_chain.env_utils import is_feature_disabled
15
16
  from clang_tool_chain.interrupt_utils import handle_keyboard_interrupt_properly
16
17
 
17
18
  from .base_deployer import BaseLibraryDeployer
@@ -510,9 +511,10 @@ def post_link_dll_deployment(output_exe_path: Path, platform_name: str, use_gnu_
510
511
  None
511
512
 
512
513
  Environment Variables:
513
- CLANG_TOOL_CHAIN_NO_DEPLOY_DLLS: Set to "1" to disable all DLL deployment
514
- CLANG_TOOL_CHAIN_NO_DEPLOY_DLLS_FOR_DLLS: Set to "1" to disable deployment for .dll outputs only
515
- CLANG_TOOL_CHAIN_DLL_DEPLOY_VERBOSE: Set to "1" for verbose logging
514
+ CLANG_TOOL_CHAIN_NO_DEPLOY_LIBS: Set to "1" to disable all library deployment
515
+ CLANG_TOOL_CHAIN_NO_DEPLOY_SHARED_LIB: Set to "1" to disable deployment for shared library outputs only
516
+ CLANG_TOOL_CHAIN_NO_AUTO: Set to "1" to disable all automatic features
517
+ CLANG_TOOL_CHAIN_LIB_DEPLOY_VERBOSE: Set to "1" for verbose logging
516
518
 
517
519
  Examples:
518
520
  >>> post_link_dll_deployment(Path("test.exe"), "win", True)
@@ -520,13 +522,12 @@ def post_link_dll_deployment(output_exe_path: Path, platform_name: str, use_gnu_
520
522
  >>> post_link_dll_deployment(Path("mylib.dll"), "win", True)
521
523
  # Deploys runtime DLLs alongside the shared library
522
524
  """
523
- # Check opt-out environment variable
524
- if os.environ.get("CLANG_TOOL_CHAIN_NO_DEPLOY_DLLS") == "1":
525
- logger.debug("DLL deployment disabled via CLANG_TOOL_CHAIN_NO_DEPLOY_DLLS")
525
+ # Check opt-out environment variable (via NO_DEPLOY_LIBS or NO_AUTO)
526
+ if is_feature_disabled("DEPLOY_LIBS"):
526
527
  return
527
528
 
528
529
  # Enable verbose logging if requested
529
- if os.environ.get("CLANG_TOOL_CHAIN_DLL_DEPLOY_VERBOSE") == "1":
530
+ if os.environ.get("CLANG_TOOL_CHAIN_LIB_DEPLOY_VERBOSE") == "1":
530
531
  logger.setLevel(logging.DEBUG)
531
532
 
532
533
  # Guard: only deploy on Windows
@@ -542,9 +543,8 @@ def post_link_dll_deployment(output_exe_path: Path, platform_name: str, use_gnu_
542
543
  # Guard: only deploy for .exe and .dll files
543
544
  suffix = output_exe_path.suffix.lower()
544
545
  if suffix == ".dll":
545
- # Check for DLL-specific opt-out
546
- if os.environ.get("CLANG_TOOL_CHAIN_NO_DEPLOY_DLLS_FOR_DLLS") == "1":
547
- logger.debug("DLL deployment for .dll outputs disabled via CLANG_TOOL_CHAIN_NO_DEPLOY_DLLS_FOR_DLLS")
546
+ # Check for shared library-specific opt-out (via NO_DEPLOY_SHARED_LIB or NO_AUTO)
547
+ if is_feature_disabled("DEPLOY_SHARED_LIB"):
548
548
  return
549
549
  elif suffix != ".exe":
550
550
  logger.debug(f"DLL deployment skipped: not .exe or .dll file (suffix={output_exe_path.suffix})")
@@ -596,10 +596,9 @@ def post_link_dependency_deployment(output_path: Path, platform_name: str, use_g
596
596
  None
597
597
 
598
598
  Environment Variables:
599
- CLANG_TOOL_CHAIN_NO_DEPLOY_DLLS: Set to "1" to disable deployment (all platforms)
600
- CLANG_TOOL_CHAIN_NO_DEPLOY_LIBS: Set to "1" to disable deployment (alias)
601
- CLANG_TOOL_CHAIN_DLL_DEPLOY_VERBOSE: Set to "1" for verbose logging (all platforms)
602
- CLANG_TOOL_CHAIN_LIB_DEPLOY_VERBOSE: Set to "1" for verbose logging (alias)
599
+ CLANG_TOOL_CHAIN_NO_DEPLOY_LIBS: Set to "1" to disable all library deployment
600
+ CLANG_TOOL_CHAIN_NO_AUTO: Set to "1" to disable all automatic features
601
+ CLANG_TOOL_CHAIN_LIB_DEPLOY_VERBOSE: Set to "1" for verbose logging
603
602
 
604
603
  Examples:
605
604
  >>> post_link_dependency_deployment(Path("mylib.dll"), "win", True)
@@ -609,17 +608,11 @@ def post_link_dependency_deployment(output_path: Path, platform_name: str, use_g
609
608
  >>> post_link_dependency_deployment(Path("mylib.dylib"), "darwin", False)
610
609
  # Deploys libunwind.1.dylib, libc++.1.dylib, etc. to mylib.dylib directory
611
610
  """
612
- # Check opt-out environment variables (either DLL-specific or generic)
613
- if os.environ.get("CLANG_TOOL_CHAIN_NO_DEPLOY_DLLS") == "1":
614
- logger.debug("Dependency deployment disabled via CLANG_TOOL_CHAIN_NO_DEPLOY_DLLS")
615
- return
616
- if os.environ.get("CLANG_TOOL_CHAIN_NO_DEPLOY_LIBS") == "1":
617
- logger.debug("Dependency deployment disabled via CLANG_TOOL_CHAIN_NO_DEPLOY_LIBS")
611
+ # Check opt-out environment variables (NO_DEPLOY_LIBS or NO_AUTO)
612
+ if is_feature_disabled("DEPLOY_LIBS"):
618
613
  return
619
614
 
620
- # Enable verbose logging if requested (either DLL-specific or generic)
621
- if os.environ.get("CLANG_TOOL_CHAIN_DLL_DEPLOY_VERBOSE") == "1":
622
- logger.setLevel(logging.DEBUG)
615
+ # Enable verbose logging if requested
623
616
  if os.environ.get("CLANG_TOOL_CHAIN_LIB_DEPLOY_VERBOSE") == "1":
624
617
  logger.setLevel(logging.DEBUG)
625
618
 
@@ -18,11 +18,12 @@ Example:
18
18
  """
19
19
 
20
20
  import logging
21
- import os
22
21
  import re
23
22
  import subprocess
24
23
  from pathlib import Path
25
24
 
25
+ from clang_tool_chain.env_utils import is_feature_disabled
26
+
26
27
  from .base_deployer import BaseLibraryDeployer
27
28
 
28
29
  logger = logging.getLogger(__name__)
@@ -499,7 +500,8 @@ def post_link_dylib_deployment(output_path: Path, arch: str = "x86_64") -> int:
499
500
 
500
501
  Environment variables:
501
502
  - CLANG_TOOL_CHAIN_NO_DEPLOY_LIBS=1 - Disable all library deployment
502
- - CLANG_TOOL_CHAIN_NO_DEPLOY_DYLIBS=1 - Disable macOS-specific deployment
503
+ - CLANG_TOOL_CHAIN_NO_DEPLOY_SHARED_LIB=1 - Disable deployment for shared library outputs
504
+ - CLANG_TOOL_CHAIN_NO_AUTO=1 - Disable all automatic features
503
505
 
504
506
  Args:
505
507
  output_path: Path to executable or shared library
@@ -512,14 +514,12 @@ def post_link_dylib_deployment(output_path: Path, arch: str = "x86_64") -> int:
512
514
  >>> # Called automatically after linking
513
515
  >>> count = post_link_dylib_deployment(Path("program"), arch="arm64")
514
516
  """
515
- # Check global disable
516
- if os.getenv("CLANG_TOOL_CHAIN_NO_DEPLOY_LIBS") == "1":
517
- logger.debug("dylib deployment disabled (CLANG_TOOL_CHAIN_NO_DEPLOY_LIBS=1)")
517
+ # Check environment variables (NO_DEPLOY_LIBS or NO_AUTO)
518
+ if is_feature_disabled("DEPLOY_LIBS"):
518
519
  return 0
519
520
 
520
- # Check macOS-specific disable
521
- if os.getenv("CLANG_TOOL_CHAIN_NO_DEPLOY_DYLIBS") == "1":
522
- logger.debug("dylib deployment disabled (CLANG_TOOL_CHAIN_NO_DEPLOY_DYLIBS=1)")
521
+ # Check if output is a shared library (.dylib) - if so, check NO_DEPLOY_SHARED_LIB
522
+ if output_path.suffix == ".dylib" and is_feature_disabled("DEPLOY_SHARED_LIB"):
523
523
  return 0
524
524
 
525
525
  # Check if output is executable or .dylib
@@ -12,6 +12,7 @@ import re
12
12
  import subprocess
13
13
  from pathlib import Path
14
14
 
15
+ from clang_tool_chain.env_utils import is_feature_disabled
15
16
  from clang_tool_chain.interrupt_utils import handle_keyboard_interrupt_properly
16
17
 
17
18
  from .base_deployer import BaseLibraryDeployer
@@ -309,14 +310,19 @@ def post_link_so_deployment(
309
310
 
310
311
  Returns:
311
312
  Number of .so files deployed
313
+
314
+ Environment Variables:
315
+ CLANG_TOOL_CHAIN_NO_DEPLOY_LIBS: Set to "1" to disable all library deployment
316
+ CLANG_TOOL_CHAIN_NO_DEPLOY_SHARED_LIB: Set to "1" to disable deployment for shared library outputs
317
+ CLANG_TOOL_CHAIN_NO_AUTO: Set to "1" to disable all automatic features
312
318
  """
313
- # Check environment variables
314
- if os.getenv("CLANG_TOOL_CHAIN_NO_DEPLOY_LIBS") == "1":
315
- logger.debug("Linux .so deployment disabled by CLANG_TOOL_CHAIN_NO_DEPLOY_LIBS")
319
+ # Check environment variables (NO_DEPLOY_LIBS or NO_AUTO)
320
+ if is_feature_disabled("DEPLOY_LIBS"):
316
321
  return 0
317
322
 
318
- if os.getenv("CLANG_TOOL_CHAIN_NO_DEPLOY_SO") == "1":
319
- logger.debug("Linux .so deployment disabled by CLANG_TOOL_CHAIN_NO_DEPLOY_SO")
323
+ # Check if output is a shared library (.so) - if so, check NO_DEPLOY_SHARED_LIB
324
+ is_shared_lib = output_path.suffix == ".so" or ".so." in output_path.name
325
+ if is_shared_lib and is_feature_disabled("DEPLOY_SHARED_LIB"):
320
326
  return 0
321
327
 
322
328
  # Check if output is a deployable binary
@@ -0,0 +1,136 @@
1
+ """
2
+ Environment variable utilities for clang-tool-chain.
3
+
4
+ This module provides centralized handling of environment variable checks,
5
+ including support for the aggregate CLANG_TOOL_CHAIN_NO_AUTO variable
6
+ that disables all automatic features.
7
+
8
+ Example:
9
+ >>> from clang_tool_chain.env_utils import is_feature_disabled
10
+ >>> if is_feature_disabled("DIRECTIVES"):
11
+ ... # Skip directive parsing
12
+ ... pass
13
+ """
14
+
15
+ import logging
16
+ import os
17
+
18
+ logger = logging.getLogger(__name__)
19
+
20
+ # Truthy values for boolean environment variables
21
+ _TRUTHY_VALUES = ("1", "true", "yes")
22
+
23
+ # All features that can be disabled via NO_AUTO
24
+ # Maps feature name to the specific environment variable suffix
25
+ CONTROLLABLE_FEATURES = {
26
+ "DIRECTIVES": "Inlined build directives (@link, @std, @cflags)",
27
+ "SHARED_ASAN": "Automatic -shared-libasan injection (Linux)",
28
+ "SANITIZER_ENV": "Automatic ASAN_OPTIONS/LSAN_OPTIONS injection",
29
+ "RPATH": "Automatic rpath injection for library loading",
30
+ "SYSROOT": "Automatic macOS SDK detection (-isysroot)",
31
+ "DEPLOY_LIBS": "Cross-platform library deployment (all outputs)",
32
+ "DEPLOY_SHARED_LIB": "Library deployment for shared library outputs only (.dll, .so, .dylib)",
33
+ }
34
+
35
+
36
+ def _is_truthy(value: str | None) -> bool:
37
+ """Check if an environment variable value is truthy."""
38
+ if value is None:
39
+ return False
40
+ return value.lower() in _TRUTHY_VALUES
41
+
42
+
43
+ def is_auto_disabled() -> bool:
44
+ """
45
+ Check if all automatic features are disabled via CLANG_TOOL_CHAIN_NO_AUTO.
46
+
47
+ Returns:
48
+ True if CLANG_TOOL_CHAIN_NO_AUTO is set to a truthy value.
49
+
50
+ Example:
51
+ >>> os.environ["CLANG_TOOL_CHAIN_NO_AUTO"] = "1"
52
+ >>> is_auto_disabled()
53
+ True
54
+ """
55
+ return _is_truthy(os.environ.get("CLANG_TOOL_CHAIN_NO_AUTO"))
56
+
57
+
58
+ def is_feature_disabled(feature: str) -> bool:
59
+ """
60
+ Check if a specific feature is disabled.
61
+
62
+ A feature is disabled if either:
63
+ 1. The aggregate CLANG_TOOL_CHAIN_NO_AUTO=1 is set, OR
64
+ 2. The specific CLANG_TOOL_CHAIN_NO_{feature}=1 is set
65
+
66
+ Args:
67
+ feature: The feature name (e.g., "DIRECTIVES", "SHARED_ASAN", "DEPLOY_LIBS").
68
+ Should match one of the keys in CONTROLLABLE_FEATURES.
69
+
70
+ Returns:
71
+ True if the feature is disabled, False otherwise.
72
+
73
+ Example:
74
+ >>> os.environ["CLANG_TOOL_CHAIN_NO_DIRECTIVES"] = "1"
75
+ >>> is_feature_disabled("DIRECTIVES")
76
+ True
77
+
78
+ >>> os.environ["CLANG_TOOL_CHAIN_NO_AUTO"] = "1"
79
+ >>> is_feature_disabled("SHARED_ASAN") # Disabled by NO_AUTO
80
+ True
81
+ """
82
+ # Check the aggregate NO_AUTO variable first
83
+ if is_auto_disabled():
84
+ logger.debug(f"Feature {feature} disabled via CLANG_TOOL_CHAIN_NO_AUTO=1")
85
+ return True
86
+
87
+ # Check the specific feature variable
88
+ var_name = f"CLANG_TOOL_CHAIN_NO_{feature}"
89
+ if _is_truthy(os.environ.get(var_name)):
90
+ logger.debug(f"Feature {feature} disabled via {var_name}=1")
91
+ return True
92
+
93
+ return False
94
+
95
+
96
+ def get_disabled_features() -> list[str]:
97
+ """
98
+ Get a list of all currently disabled features.
99
+
100
+ Returns:
101
+ List of feature names that are disabled.
102
+
103
+ Example:
104
+ >>> os.environ["CLANG_TOOL_CHAIN_NO_AUTO"] = "1"
105
+ >>> get_disabled_features()
106
+ ['DIRECTIVES', 'SHARED_ASAN', 'SANITIZER_ENV', ...]
107
+ """
108
+ disabled = []
109
+
110
+ # If NO_AUTO is set, all features are disabled
111
+ if is_auto_disabled():
112
+ return list(CONTROLLABLE_FEATURES.keys())
113
+
114
+ # Check each feature individually
115
+ for feature in CONTROLLABLE_FEATURES:
116
+ var_name = f"CLANG_TOOL_CHAIN_NO_{feature}"
117
+ if _is_truthy(os.environ.get(var_name)):
118
+ disabled.append(feature)
119
+
120
+ return disabled
121
+
122
+
123
+ def log_disabled_features_summary() -> None:
124
+ """
125
+ Log a summary of disabled features (useful for debugging).
126
+
127
+ Only logs if at least one feature is disabled.
128
+ """
129
+ disabled = get_disabled_features()
130
+ if not disabled:
131
+ return
132
+
133
+ if is_auto_disabled():
134
+ logger.info("All automatic features disabled via CLANG_TOOL_CHAIN_NO_AUTO=1")
135
+ else:
136
+ logger.info(f"Disabled features: {', '.join(disabled)}")
@@ -10,7 +10,11 @@ This package provides:
10
10
 
11
11
  from clang_tool_chain.execution.build import build_main, build_run_main
12
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
13
+ from clang_tool_chain.execution.sanitizer_env import (
14
+ detect_sanitizers_from_flags,
15
+ get_symbolizer_path,
16
+ prepare_sanitizer_environment,
17
+ )
14
18
 
15
19
  __all__ = [
16
20
  # Core execution
@@ -25,4 +29,5 @@ __all__ = [
25
29
  # Sanitizer utilities
26
30
  "prepare_sanitizer_environment",
27
31
  "detect_sanitizers_from_flags",
32
+ "get_symbolizer_path",
28
33
  ]
@@ -35,6 +35,8 @@ from dataclasses import dataclass
35
35
  from pathlib import Path
36
36
  from typing import TYPE_CHECKING
37
37
 
38
+ from clang_tool_chain.env_utils import is_feature_disabled
39
+
38
40
  if TYPE_CHECKING:
39
41
  from clang_tool_chain.directives.parser import ParsedDirectives
40
42
 
@@ -111,6 +113,7 @@ class DirectivesTransformer(ArgumentTransformer):
111
113
 
112
114
  Environment Variables:
113
115
  CLANG_TOOL_CHAIN_NO_DIRECTIVES: Set to '1' to disable directive parsing
116
+ CLANG_TOOL_CHAIN_NO_AUTO: Set to '1' to disable all automatic features
114
117
  CLANG_TOOL_CHAIN_DIRECTIVE_VERBOSE: Set to '1' to enable debug logging
115
118
  """
116
119
 
@@ -119,9 +122,8 @@ class DirectivesTransformer(ArgumentTransformer):
119
122
 
120
123
  def transform(self, args: list[str], context: ToolContext) -> list[str]:
121
124
  """Add arguments from inlined build directives in source files."""
122
- # Check if directives are disabled
123
- if os.environ.get("CLANG_TOOL_CHAIN_NO_DIRECTIVES") == "1":
124
- logger.debug("Directives disabled via CLANG_TOOL_CHAIN_NO_DIRECTIVES=1")
125
+ # Check if directives are disabled (via NO_DIRECTIVES or NO_AUTO)
126
+ if is_feature_disabled("DIRECTIVES"):
125
127
  return args
126
128
 
127
129
  # Only apply to clang/clang++ compilation commands
@@ -306,6 +308,7 @@ class ASANRuntimeTransformer(ArgumentTransformer):
306
308
 
307
309
  Environment Variables:
308
310
  CLANG_TOOL_CHAIN_NO_SHARED_ASAN: Set to '1' to disable shared ASAN
311
+ CLANG_TOOL_CHAIN_NO_AUTO: Set to '1' to disable all automatic features
309
312
  """
310
313
 
311
314
  def priority(self) -> int:
@@ -327,17 +330,14 @@ class ASANRuntimeTransformer(ArgumentTransformer):
327
330
  result = list(args)
328
331
  injected_flags = []
329
332
 
330
- # Check if user disabled 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:
340
- logger.debug("Shared ASAN disabled via CLANG_TOOL_CHAIN_NO_SHARED_ASAN=1")
333
+ # Check if user disabled shared ASAN (via NO_SHARED_ASAN or NO_AUTO)
334
+ # Also check if -shared-libasan already present
335
+ if not is_feature_disabled("SHARED_ASAN") and "-shared-libasan" not in args:
336
+ # Add -shared-libasan to use shared runtime library
337
+ # This prevents undefined symbol errors during linking
338
+ logger.info("Adding -shared-libasan for ASAN runtime linking on Linux")
339
+ result = ["-shared-libasan"] + result
340
+ injected_flags.append("-shared-libasan")
341
341
 
342
342
  # Check if building a shared library with ASAN
343
343
  # Shared libraries need to allow undefined symbols that will be provided
@@ -378,6 +378,7 @@ class RPathTransformer(ArgumentTransformer):
378
378
 
379
379
  Environment Variables:
380
380
  CLANG_TOOL_CHAIN_NO_RPATH: Set to '1' to disable automatic rpath injection
381
+ CLANG_TOOL_CHAIN_NO_AUTO: Set to '1' to disable all automatic features
381
382
  """
382
383
 
383
384
  def priority(self) -> int:
@@ -401,9 +402,8 @@ class RPathTransformer(ArgumentTransformer):
401
402
  if not has_deploy_flag and not deploy_from_env:
402
403
  return args
403
404
 
404
- # Check if user disabled rpath
405
- if os.environ.get("CLANG_TOOL_CHAIN_NO_RPATH") == "1":
406
- logger.debug("Rpath injection disabled via CLANG_TOOL_CHAIN_NO_RPATH=1")
405
+ # Check if user disabled rpath (via NO_RPATH or NO_AUTO)
406
+ if is_feature_disabled("RPATH"):
407
407
  return args
408
408
 
409
409
  # Check if rpath already present
@@ -26,6 +26,7 @@ from typing import NoReturn
26
26
 
27
27
  from clang_tool_chain.cli_parsers import parse_build_args, parse_build_run_args
28
28
  from clang_tool_chain.directives import DirectiveParser
29
+ from clang_tool_chain.env_utils import is_feature_disabled
29
30
  from clang_tool_chain.execution.core import execute_tool
30
31
  from clang_tool_chain.interrupt_utils import handle_keyboard_interrupt_properly
31
32
  from clang_tool_chain.platform import get_platform_info
@@ -47,9 +48,13 @@ def _get_directive_args(source_path: Path) -> list[str]:
47
48
 
48
49
  Returns:
49
50
  List of compiler/linker arguments derived from directives
51
+
52
+ Environment Variables:
53
+ CLANG_TOOL_CHAIN_NO_DIRECTIVES: Set to '1' to disable directive parsing
54
+ CLANG_TOOL_CHAIN_NO_AUTO: Set to '1' to disable all automatic features
50
55
  """
51
- # Check if directives parsing is disabled via environment variable
52
- if os.environ.get("CLANG_TOOL_CHAIN_NO_DIRECTIVES", "").lower() in ("1", "true", "yes"):
56
+ # Check if directives parsing is disabled (via NO_DIRECTIVES or NO_AUTO)
57
+ if is_feature_disabled("DIRECTIVES"):
53
58
  return []
54
59
 
55
60
  try:
@@ -106,10 +111,11 @@ def get_directive_args_from_compiler_args(args: list[str]) -> list[str]:
106
111
 
107
112
  Environment Variables:
108
113
  CLANG_TOOL_CHAIN_NO_DIRECTIVES: Set to '1' to disable directive parsing
114
+ CLANG_TOOL_CHAIN_NO_AUTO: Set to '1' to disable all automatic features
109
115
  CLANG_TOOL_CHAIN_DIRECTIVE_VERBOSE: Set to '1' to show parsed directives
110
116
  """
111
- # Check if directives parsing is disabled via environment variable
112
- if os.environ.get("CLANG_TOOL_CHAIN_NO_DIRECTIVES", "").lower() in ("1", "true", "yes"):
117
+ # Check if directives parsing is disabled (via NO_DIRECTIVES or NO_AUTO)
118
+ if is_feature_disabled("DIRECTIVES"):
113
119
  return []
114
120
 
115
121
  directive_args: list[str] = []
@@ -24,6 +24,7 @@ from pathlib import Path
24
24
  from typing import NoReturn
25
25
 
26
26
  from clang_tool_chain.directives import DirectiveParser
27
+ from clang_tool_chain.env_utils import is_feature_disabled
27
28
  from clang_tool_chain.execution.core import run_tool
28
29
  from clang_tool_chain.interrupt_utils import handle_keyboard_interrupt_properly
29
30
 
@@ -109,9 +110,13 @@ def _get_directive_args(source_path: Path) -> list[str]:
109
110
 
110
111
  Returns:
111
112
  List of compiler/linker arguments derived from directives
113
+
114
+ Environment Variables:
115
+ CLANG_TOOL_CHAIN_NO_DIRECTIVES: Set to '1' to disable directive parsing
116
+ CLANG_TOOL_CHAIN_NO_AUTO: Set to '1' to disable all automatic features
112
117
  """
113
- # Check if directives parsing is disabled via environment variable
114
- if os.environ.get("CLANG_TOOL_CHAIN_NO_DIRECTIVES", "").lower() in ("1", "true", "yes"):
118
+ # Check if directives parsing is disabled (via NO_DIRECTIVES or NO_AUTO)
119
+ if is_feature_disabled("DIRECTIVES"):
115
120
  return []
116
121
 
117
122
  try:
@@ -1,16 +1,23 @@
1
1
  """
2
2
  Sanitizer runtime environment configuration.
3
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.
4
+ This module provides automatic injection of ASAN_OPTIONS, LSAN_OPTIONS, and
5
+ ASAN_SYMBOLIZER_PATH environment variables to improve stack trace quality
6
+ when running executables compiled with Address Sanitizer or Leak Sanitizer.
7
7
 
8
8
  The default options fix <unknown module> entries in stack traces from
9
9
  dlopen()'d shared libraries by enabling slow unwinding and symbolization.
10
+
11
+ The symbolizer path is automatically detected from the clang-tool-chain
12
+ installation, enabling proper address-to-symbol resolution without manual
13
+ configuration.
10
14
  """
11
15
 
12
16
  import logging
13
17
  import os
18
+ import shutil
19
+
20
+ from clang_tool_chain.env_utils import is_feature_disabled
14
21
 
15
22
  logger = logging.getLogger(__name__)
16
23
 
@@ -22,6 +29,46 @@ DEFAULT_ASAN_OPTIONS = "fast_unwind_on_malloc=0:symbolize=1:detect_leaks=1"
22
29
  DEFAULT_LSAN_OPTIONS = "fast_unwind_on_malloc=0:symbolize=1"
23
30
 
24
31
 
32
+ def get_symbolizer_path() -> str | None:
33
+ """
34
+ Get the path to llvm-symbolizer from the clang-tool-chain installation.
35
+
36
+ This function finds the llvm-symbolizer binary bundled with clang-tool-chain,
37
+ which is required by ASAN/LSAN to convert memory addresses into function names
38
+ and source locations in stack traces.
39
+
40
+ Returns:
41
+ Absolute path to llvm-symbolizer, or None if not found.
42
+
43
+ Example:
44
+ >>> path = get_symbolizer_path()
45
+ >>> if path:
46
+ ... os.environ["ASAN_SYMBOLIZER_PATH"] = path
47
+
48
+ Note:
49
+ Falls back to system PATH if the clang-tool-chain binary is not available.
50
+ This allows the function to work even when clang-tool-chain is not fully
51
+ installed (e.g., during development or in CI environments).
52
+ """
53
+ # Try to find llvm-symbolizer from clang-tool-chain installation
54
+ try:
55
+ from clang_tool_chain.platform.paths import find_tool_binary
56
+
57
+ symbolizer = find_tool_binary("llvm-symbolizer")
58
+ return str(symbolizer)
59
+ except (ImportError, RuntimeError) as e:
60
+ logger.debug(f"Could not find llvm-symbolizer in clang-tool-chain: {e}")
61
+
62
+ # Fall back to system PATH
63
+ system_symbolizer = shutil.which("llvm-symbolizer")
64
+ if system_symbolizer:
65
+ logger.debug(f"Using system llvm-symbolizer: {system_symbolizer}")
66
+ return system_symbolizer
67
+
68
+ logger.debug("llvm-symbolizer not found in clang-tool-chain or system PATH")
69
+ return None
70
+
71
+
25
72
  def detect_sanitizers_from_flags(compiler_flags: list[str]) -> tuple[bool, bool]:
26
73
  """
27
74
  Detect which sanitizers are enabled from compiler flags.
@@ -64,12 +111,16 @@ def prepare_sanitizer_environment(
64
111
  compiler_flags: list[str] | None = None,
65
112
  ) -> dict[str, str]:
66
113
  """
67
- Prepare environment with optimal sanitizer options.
114
+ Prepare environment with optimal sanitizer options and symbolizer path.
68
115
 
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.
116
+ This function injects ASAN_OPTIONS, LSAN_OPTIONS, and ASAN_SYMBOLIZER_PATH
117
+ environment variables if they are not already set by the user AND the
118
+ corresponding sanitizer was enabled during compilation. The injected options
119
+ improve stack trace quality for executables using dlopen()'d shared libraries.
120
+
121
+ The ASAN_SYMBOLIZER_PATH is automatically detected from the clang-tool-chain
122
+ installation, enabling proper address-to-symbol resolution (function names,
123
+ file paths, line numbers) without manual configuration.
73
124
 
74
125
  Args:
75
126
  base_env: Base environment dictionary to modify. If None, uses os.environ.
@@ -83,20 +134,21 @@ def prepare_sanitizer_environment(
83
134
  Environment Variables:
84
135
  CLANG_TOOL_CHAIN_NO_SANITIZER_ENV: Set to "1", "true", or "yes" to
85
136
  disable automatic injection of sanitizer options.
137
+ CLANG_TOOL_CHAIN_NO_AUTO: Set to "1" to disable all automatic features.
86
138
  ASAN_OPTIONS: If already set, preserved as-is (user config takes priority).
87
139
  LSAN_OPTIONS: If already set, preserved as-is (user config takes priority).
140
+ ASAN_SYMBOLIZER_PATH: If already set, preserved as-is (user config takes priority).
88
141
 
89
142
  Example:
90
143
  >>> env = prepare_sanitizer_environment(compiler_flags=["-fsanitize=address"])
91
- >>> # env now contains ASAN_OPTIONS and LSAN_OPTIONS
144
+ >>> # env now contains ASAN_OPTIONS, LSAN_OPTIONS, and ASAN_SYMBOLIZER_PATH
92
145
  >>> env = prepare_sanitizer_environment(compiler_flags=["-O2"])
93
146
  >>> # env unchanged - no sanitizers enabled
94
147
  """
95
148
  env = base_env.copy() if base_env is not None else os.environ.copy()
96
149
 
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")
150
+ # Check if disabled via environment variable (NO_SANITIZER_ENV or NO_AUTO)
151
+ if is_feature_disabled("SANITIZER_ENV"):
100
152
  return env
101
153
 
102
154
  # If no compiler flags provided, don't inject anything (safe default)
@@ -117,4 +169,17 @@ def prepare_sanitizer_environment(
117
169
  env["LSAN_OPTIONS"] = DEFAULT_LSAN_OPTIONS
118
170
  logger.info(f"Injecting LSAN_OPTIONS={DEFAULT_LSAN_OPTIONS}")
119
171
 
172
+ # Inject ASAN_SYMBOLIZER_PATH if any sanitizer is enabled and not already set
173
+ if (asan_enabled or lsan_enabled) and "ASAN_SYMBOLIZER_PATH" not in env:
174
+ symbolizer_path = get_symbolizer_path()
175
+ if symbolizer_path:
176
+ env["ASAN_SYMBOLIZER_PATH"] = symbolizer_path
177
+ logger.info(f"Injecting ASAN_SYMBOLIZER_PATH={symbolizer_path}")
178
+ else:
179
+ logger.warning(
180
+ "llvm-symbolizer not found - ASAN/LSAN stack traces may show "
181
+ "raw addresses instead of function names. Install llvm-symbolizer "
182
+ "or ensure clang-tool-chain is properly installed."
183
+ )
184
+
120
185
  return env
@@ -151,6 +151,15 @@ from clang_tool_chain.execution.lldb import (
151
151
  get_lldb_binary_dir,
152
152
  )
153
153
 
154
+ # ============================================================================
155
+ # Sanitizer Environment
156
+ # ============================================================================
157
+ from clang_tool_chain.execution.sanitizer_env import (
158
+ detect_sanitizers_from_flags,
159
+ get_symbolizer_path,
160
+ prepare_sanitizer_environment,
161
+ )
162
+
154
163
  # ============================================================================
155
164
  # Linker Configuration
156
165
  # ============================================================================
@@ -218,6 +227,10 @@ __all__ = [
218
227
  "run_tool",
219
228
  "sccache_clang_main",
220
229
  "sccache_clang_cpp_main",
230
+ # Sanitizer Environment
231
+ "prepare_sanitizer_environment",
232
+ "detect_sanitizers_from_flags",
233
+ "get_symbolizer_path",
221
234
  # Emscripten
222
235
  "ensure_nodejs_available",
223
236
  "execute_emscripten_tool",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: clang-tool-chain
3
- Version: 1.0.44
3
+ Version: 1.0.45
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
@@ -717,11 +717,8 @@ clang-tool-chain-cpp main.cpp -o program --deploy-dependencies -lunwind
717
717
 
718
718
  **Disable deployment:**
719
719
  ```bash
720
- # Cross-platform (modern)
720
+ # Cross-platform
721
721
  export CLANG_TOOL_CHAIN_NO_DEPLOY_LIBS=1
722
-
723
- # Windows-specific (legacy)
724
- export CLANG_TOOL_CHAIN_NO_DEPLOY_DLLS=1
725
722
  ```
726
723
 
727
724
  **Enable verbose logging:**
@@ -791,7 +788,7 @@ jobs:
791
788
  **Key Environment Variables:**
792
789
  - `CLANG_TOOL_CHAIN_DOWNLOAD_PATH` - Override installation location
793
790
  - `CLANG_TOOL_CHAIN_NO_DEPLOY_LIBS` - Disable automatic library deployment (all platforms)
794
- - `CLANG_TOOL_CHAIN_NO_DEPLOY_DLLS` - Disable Windows DLL deployment (legacy, Windows only)
791
+ - `CLANG_TOOL_CHAIN_NO_DEPLOY_SHARED_LIB` - Disable library deployment for shared library outputs only
795
792
  - `CLANG_TOOL_CHAIN_LIB_DEPLOY_VERBOSE` - Enable verbose library deployment logging
796
793
  - `CLANG_TOOL_CHAIN_USE_SYSTEM_LD` - Use system linker instead of LLD
797
794
  - `CLANG_TOOL_CHAIN_NO_DIRECTIVES` - Disable inlined build directives
@@ -863,16 +860,42 @@ When running executables via `clang-tool-chain-build-run`, optimal sanitizer opt
863
860
 
864
861
  - `ASAN_OPTIONS=fast_unwind_on_malloc=0:symbolize=1:detect_leaks=1` (when `-fsanitize=address` is used)
865
862
  - `LSAN_OPTIONS=fast_unwind_on_malloc=0:symbolize=1` (when `-fsanitize=address` or `-fsanitize=leak` is used)
863
+ - `ASAN_SYMBOLIZER_PATH=/path/to/llvm-symbolizer` (automatically detected from clang-tool-chain)
866
864
 
867
865
  **What these options fix:**
868
866
  - `<unknown module>` entries in stack traces from `dlopen()`'d shared libraries
869
- - Missing function names in crash reports
867
+ - Missing function names in crash reports (raw addresses like `0x7f5a4f15ac1d` instead of `my_function`)
870
868
  - Incomplete leak detection
871
869
 
872
- **Your options are always preserved** - if you set `ASAN_OPTIONS` or `LSAN_OPTIONS` yourself, clang-tool-chain won't override them.
870
+ **Your options are always preserved** - if you set `ASAN_OPTIONS`, `LSAN_OPTIONS`, or `ASAN_SYMBOLIZER_PATH` yourself, clang-tool-chain won't override them.
873
871
 
874
872
  **Regular builds are unaffected** - sanitizer options are only injected when the compiler flags indicate sanitizers are being used.
875
873
 
874
+ ### Programmatic API (For Build Systems)
875
+
876
+ External build systems can use the sanitizer environment API to get properly configured environments:
877
+
878
+ ```python
879
+ from clang_tool_chain import prepare_sanitizer_environment, get_symbolizer_path
880
+
881
+ # Option A: Complete environment setup (recommended)
882
+ env = prepare_sanitizer_environment(
883
+ base_env=os.environ.copy(),
884
+ compiler_flags=["-fsanitize=address", "-O2"]
885
+ )
886
+ # env now contains ASAN_OPTIONS, LSAN_OPTIONS, and ASAN_SYMBOLIZER_PATH
887
+
888
+ # Option B: Just get the symbolizer path
889
+ symbolizer = get_symbolizer_path()
890
+ if symbolizer:
891
+ os.environ["ASAN_SYMBOLIZER_PATH"] = symbolizer
892
+ ```
893
+
894
+ **Available functions:**
895
+ - `prepare_sanitizer_environment(base_env, compiler_flags)` - Returns environment dict with all sanitizer variables
896
+ - `get_symbolizer_path()` - Returns path to `llvm-symbolizer` or `None`
897
+ - `detect_sanitizers_from_flags(flags)` - Returns `(asan_enabled, lsan_enabled)` tuple
898
+
876
899
  ### Configuration
877
900
 
878
901
  ```bash
@@ -888,6 +911,31 @@ export CLANG_TOOL_CHAIN_NO_SHARED_ASAN=1
888
911
  - **Windows**: Works with both GNU and MSVC ABIs
889
912
  - **macOS**: Uses bundled LLVM ASAN runtime
890
913
 
914
+ ### Dynamically Loaded Libraries
915
+
916
+ If you see `<unknown module>` in ASAN/LSAN stack traces for code in dynamically loaded libraries, apply these fixes:
917
+
918
+ **1. Use `RTLD_NOW | RTLD_GLOBAL` (not `RTLD_LAZY`)**
919
+
920
+ ```cpp
921
+ void* handle = dlopen(path, RTLD_NOW | RTLD_GLOBAL); // Good
922
+ void* handle = dlopen(path, RTLD_LAZY); // Bad - causes <unknown module>
923
+ ```
924
+
925
+ **2. Skip `dlclose()` when ASAN is active**
926
+
927
+ ASAN symbolizes at exit; if the library is unloaded, addresses become `<unknown module>`.
928
+
929
+ ```cpp
930
+ #if !defined(__SANITIZE_ADDRESS__)
931
+ dlclose(handle); // Only close when not running under ASAN
932
+ #endif
933
+ ```
934
+
935
+ On Windows, use the same pattern with `FreeLibrary()`.
936
+
937
+ See: https://github.com/google/sanitizers/issues/899
938
+
891
939
  ---
892
940
 
893
941
  ## 🔧 How It Works
@@ -1,5 +1,5 @@
1
- clang_tool_chain/__init__.py,sha256=w3f1hdA72SH-WsfwesNTQbTeiXIlhV8ignySXrV3SfU,23
2
- clang_tool_chain/__version__.py,sha256=VyBCcvXR6mMibUFhauoR0iyFq2jth9ReImF-qE_frUY,72
1
+ clang_tool_chain/__init__.py,sha256=u-qgOuQxh5W2g7n8BgUtBnUWsK66rM4N6LJXY9PiEx0,880
2
+ clang_tool_chain/__version__.py,sha256=QaMskYdjKBucedCuNyKFMIEERieKWeom7OJJ_fjGce4,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
@@ -9,6 +9,7 @@ clang_tool_chain/cli_parsers.py,sha256=cHVDyW75N_Kao1VYeAgw_L-1K65DjyvWUigQScTFi
9
9
  clang_tool_chain/component_db.py,sha256=ohtlycsrEokui83iZyPsTyxmvXgkD7_OpVwAn1Cq8gI,9096
10
10
  clang_tool_chain/downloader.py,sha256=fqErxTaI3oEYbloLZnrWXJ26j2iGOngPnl4i8kqOWNs,6041
11
11
  clang_tool_chain/env_breadcrumbs.py,sha256=bvPTz8xABILhzrXTEBzdGrSbpEXLf2YVgcYEe-IdhNY,2335
12
+ clang_tool_chain/env_utils.py,sha256=cNlsZ-BchlKh5BDe6kmGYKU3A8jxFFSn4atv2_pPc1Y,4169
12
13
  clang_tool_chain/fetch.py,sha256=DwsNl5DZkNqEYXL-FbCTnp6IA2iCAa9pMl5oPjyuOS4,4696
13
14
  clang_tool_chain/installer.py,sha256=GuGeUvVcAw4HMj9jrub-I11ixmksw-vgtSOFrlupmPA,3323
14
15
  clang_tool_chain/interrupt_utils.py,sha256=7YvazvGzyItRVDZ_pzUSK6at8PCw-Dgih69HLSz0tT4,1153
@@ -21,7 +22,7 @@ clang_tool_chain/paths.py,sha256=DwgWAAiLmPInpLDFMqyNFUyNYmkowWN626SwrMMx200,280
21
22
  clang_tool_chain/permissions.py,sha256=Okt91_fk4I0UmEiUAktqxm3OZfZQ3rUW-0r2X_seuxY,8517
22
23
  clang_tool_chain/sccache_runner.py,sha256=xkepFC4Ti8s6wv7GXA24REFj8jli86nSUqcY7TCOQzk,12810
23
24
  clang_tool_chain/settings_warnings.py,sha256=mspKHUT0Bod_SnSLyEo6Tix0ANTMn0erVLsn82jWr4I,3523
24
- clang_tool_chain/wrapper.py,sha256=v_8oLesqYAD3cW5iJLT0z0WOzfP2bwrHJwr0jpXx9dk,8031
25
+ clang_tool_chain/wrapper.py,sha256=mMLydq43AZjUc24QU6TtiMCH8jyVh1BBHY5XMWLSeX0,8493
25
26
  clang_tool_chain/abi/__init__.py,sha256=GBiAN5W2TovaZ2MzVFFV5J3udiOn4ME0CN6oGS2FMDM,922
26
27
  clang_tool_chain/abi/windows_gnu.py,sha256=ZN7xVWwoBEILi7A_FG8NBBiN5gtrXYscgmixFMEm9zg,10517
27
28
  clang_tool_chain/abi/windows_msvc.py,sha256=Z-f6HGjkBcrguDfo62qOP5cI_2EYwjQ9k3Cgnpf42Fo,3617
@@ -29,17 +30,17 @@ clang_tool_chain/commands/__init__.py,sha256=KpJD6wLVa5t3JVSjS5BQ8EUaALc5pc7SqyW
29
30
  clang_tool_chain/commands/entry_points.py,sha256=mJ3ZZkYJqoT2JqMi6m8us0w8tf5_b7QnmDR30_yij00,13824
30
31
  clang_tool_chain/deployment/__init__.py,sha256=1Bv8kpwyTd3LN9HNHVWFwkznXLbTdbOC5PLvrnDhtR0,356
31
32
  clang_tool_chain/deployment/base_deployer.py,sha256=-02O-EJllRTAYnPcBWAilfuvGWTGvpK1EG6TRnBC8_k,11565
32
- clang_tool_chain/deployment/dll_deployer.py,sha256=YRxO0o_6b7UhqfuT3NQk3pFIkn8tteJpXZJalnzhkuA,25392
33
+ clang_tool_chain/deployment/dll_deployer.py,sha256=x3_hXsPgyQMkp1orzZV4lAZa4NMP27t0B1ajYBBbzmA,24840
33
34
  clang_tool_chain/deployment/dll_detector.py,sha256=Zf2NAjAg6bEg6uvb7dFkj0qvk8Mvzj4sjyPIoxNVvJE,8629
34
- clang_tool_chain/deployment/dylib_deployer.py,sha256=daTPpT9VByHMfIUAE3oHq9pCeinuDDNeq-U2iTvMTz4,19265
35
+ clang_tool_chain/deployment/dylib_deployer.py,sha256=6GLn_CMLYUAdQZgwcTMx0XXo_AxGvUKUFYt04v2Kip0,19315
35
36
  clang_tool_chain/deployment/factory.py,sha256=Mq6cMMUctoYBZ81I16_hXUmDLQGSAngCmBzPlu_0iaU,6205
36
- clang_tool_chain/deployment/so_deployer.py,sha256=9mRKcJUXKV-8vXWJGdsUkB5cTPWjmToFUcHTVTCHdVk,11527
37
+ clang_tool_chain/deployment/so_deployer.py,sha256=i3ezy1gOOHlzH5lHNytPl2FBXu7AX-F3r1uXHFEKfmg,11892
37
38
  clang_tool_chain/directives/__init__.py,sha256=MJDNYL_MD2MF0HFsrTsSTX645bYo6vtjq2pOTtfykaU,198
38
39
  clang_tool_chain/directives/parser.py,sha256=6J7mO1JtvuHkkKS0Xges5b_jT9b3uTF6ULI0ZiwGAdw,11179
39
- clang_tool_chain/execution/__init__.py,sha256=wSYnlGmfTlaUPEKwW6PgwlxKTti6Wa5yyVjXVipdpcY,875
40
- clang_tool_chain/execution/arg_transformers.py,sha256=vN-1T1mfD61Mg-P2B6hOQeLdD1RZA3l1pmNBbJSzo-g,19750
41
- clang_tool_chain/execution/build.py,sha256=PCtHw31WXbjCp2K_qaf1liaCiIjD49036cknqdQyhJM,13040
42
- clang_tool_chain/execution/build_pipeline.py,sha256=piqh7P2-GR0mVOik3OUGRFqWFIRr8LQM3PU7TcBsujk,17622
40
+ clang_tool_chain/execution/__init__.py,sha256=fFQEW9VejCdbBvt4quNJ2X8udh_PKgewTfzUXHmXzyc,940
41
+ clang_tool_chain/execution/arg_transformers.py,sha256=8RDaUF2r3dgSqQ_2XkGiXnmoLGD3ltaf4YbqkyjG2CI,19772
42
+ clang_tool_chain/execution/build.py,sha256=YHS1BJTZg5pBS9czVko41mBdfswSPad5hxfitMoLvsI,13275
43
+ clang_tool_chain/execution/build_pipeline.py,sha256=ORJEJ8WYp8c7bhWAa-e3w_ySXwenpUczlmXgoGByToY,17823
43
44
  clang_tool_chain/execution/core.py,sha256=7CJ0azznC5lq5bw8amk2kwCIN2I_OnDiKytpapkvrdY,25273
44
45
  clang_tool_chain/execution/cosmocc.py,sha256=oGlaPK6Jpz3FaohEkWpRz8sRNu2sT-HYCoIf9xBxJHk,13319
45
46
  clang_tool_chain/execution/emscripten.py,sha256=lgxPQpeB1_wWxNILgeyyrW5lEn117dHS9dQ3ikHRn1w,44235
@@ -47,7 +48,7 @@ clang_tool_chain/execution/iwyu.py,sha256=bmP0d_PZObA1JfmFYp3qIOKCb7y32AWPm2_ReF
47
48
  clang_tool_chain/execution/lldb.py,sha256=VpxkWTPS6PsyskaKTALeziR5Z5NLwarW174Fm1SMX9k,20718
48
49
  clang_tool_chain/execution/nodejs_resolver.py,sha256=8QsJWvIfmt5mBDV7n0ypSjsPyXS-eZTizhBli937I-g,11172
49
50
  clang_tool_chain/execution/platform_executor.py,sha256=sF4GyW0ujy2EewG8y2Eo1gUWGzss5G5iIkv02w7-2_o,14362
50
- clang_tool_chain/execution/sanitizer_env.py,sha256=lrGX17BriqYPsHCCrQnwjw0ttnp9mezsq0eYAOLfBag,4853
51
+ clang_tool_chain/execution/sanitizer_env.py,sha256=g07hDdicGI2QqHzahLm8CKm6c-SthLAkR8kANbPxBIU,7583
51
52
  clang_tool_chain/installers/__init__.py,sha256=NAV5woPCEDKSbFr1UmfQsrg4Ua5UdghN4q7H3ymvRsg,279
52
53
  clang_tool_chain/installers/base.py,sha256=OS78bau9zoYPitmhla7pKsfCPEj-zLY0DkvVzjE31Tw,15437
53
54
  clang_tool_chain/installers/clang.py,sha256=rUtheVRF7mq_1YdmQ3XzIybrJqsHbm2Xf0cbhRbH7RQ,16994
@@ -67,8 +68,8 @@ clang_tool_chain/sdk/windows.py,sha256=8zMLAoFz2OKMz-w6Kqxr3A-6Cofto2VWZvCvRi7kn
67
68
  clang_tool_chain/testing/__init__.py,sha256=-sYqOOCuTV_u-MkmExrD4uKdTHG4RmMwR3D1kIG281Q,208
68
69
  clang_tool_chain/testing/diagnostic_runner.py,sha256=mnmFUEOQulY3-Ggu6hKVGZwjrKQNmV6kY80PRTUu2qU,5293
69
70
  clang_tool_chain/testing/diagnostic_tests.py,sha256=GmtKWrDcddZTpx9_yIKfhRAy6YOde8dj7SksCWVEME4,6019
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,,
71
+ clang_tool_chain-1.0.45.dist-info/METADATA,sha256=ZZZzJS3byKeOW3nToE5HXQjpIiKFNNkY2KI-dvNc2E0,52205
72
+ clang_tool_chain-1.0.45.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
73
+ clang_tool_chain-1.0.45.dist-info/entry_points.txt,sha256=DBfnqZJzHFoO6rldGY3ESaX-z2ydAvIueUPM9ss9M-w,2728
74
+ clang_tool_chain-1.0.45.dist-info/licenses/LICENSE,sha256=51FO1oc2pZbQNI0v0_THnznnZIF4iFgawG1xnQ58kKo,10997
75
+ clang_tool_chain-1.0.45.dist-info/RECORD,,