clang-tool-chain 1.0.3__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.
@@ -0,0 +1,158 @@
1
+ """
2
+ CLI tool for fetching clang toolchain binaries.
3
+
4
+ This module provides a command-line interface for downloading and installing
5
+ the LLVM/Clang toolchain binaries.
6
+ """
7
+
8
+ import argparse
9
+ import sys
10
+ from dataclasses import dataclass
11
+
12
+ from . import downloader, wrapper
13
+
14
+
15
+ @dataclass
16
+ class FetchConfig:
17
+ """Configuration for fetching toolchain binaries."""
18
+
19
+ platform: str | None
20
+ arch: str | None
21
+ output_dir: str | None
22
+ verbose: bool
23
+
24
+
25
+ def parse_args() -> FetchConfig:
26
+ """
27
+ Parse command-line arguments.
28
+
29
+ Returns:
30
+ FetchConfig dataclass with parsed arguments
31
+ """
32
+ parser = argparse.ArgumentParser(
33
+ description="Fetch and install clang-tool-chain binaries",
34
+ formatter_class=argparse.RawDescriptionHelpFormatter,
35
+ epilog="""
36
+ Examples:
37
+ # Download for current platform
38
+ clang-tool-chain-fetch
39
+
40
+ # Download for specific platform (verbose)
41
+ clang-tool-chain-fetch --platform win --arch x86_64 --verbose
42
+
43
+ # Download to custom directory
44
+ clang-tool-chain-fetch --output-dir /custom/path --verbose
45
+
46
+ Environment Variables:
47
+ CLANG_TOOL_CHAIN_DOWNLOAD_PATH Override default download path (~/.clang-tool-chain)
48
+ """,
49
+ )
50
+
51
+ parser.add_argument(
52
+ "--platform",
53
+ choices=["win", "linux", "darwin"],
54
+ help="Target platform (default: current platform)",
55
+ )
56
+
57
+ parser.add_argument(
58
+ "--arch",
59
+ choices=["x86_64", "arm64"],
60
+ help="Target architecture (required if --platform is specified, default: current arch)",
61
+ )
62
+
63
+ parser.add_argument(
64
+ "--output-dir",
65
+ metavar="PATH",
66
+ help="Output directory for downloads (overrides CLANG_TOOL_CHAIN_DOWNLOAD_PATH)",
67
+ )
68
+
69
+ parser.add_argument(
70
+ "--verbose",
71
+ "-v",
72
+ action="store_true",
73
+ help="Show detailed progress information",
74
+ )
75
+
76
+ args = parser.parse_args()
77
+
78
+ # Validate platform/arch combination
79
+ if args.platform and not args.arch:
80
+ parser.error("--arch is required when --platform is specified")
81
+
82
+ return FetchConfig(
83
+ platform=args.platform,
84
+ arch=args.arch,
85
+ output_dir=args.output_dir,
86
+ verbose=args.verbose,
87
+ )
88
+
89
+
90
+ def main() -> int:
91
+ """
92
+ Main entry point for clang-tool-chain-fetch.
93
+
94
+ Returns:
95
+ Exit code (0 for success, 1 for error)
96
+ """
97
+ try:
98
+ config = parse_args()
99
+
100
+ # Determine platform and arch
101
+ if config.platform and config.arch:
102
+ platform = config.platform
103
+ arch = config.arch
104
+ else:
105
+ # Auto-detect current platform
106
+ platform, arch = wrapper.get_platform_info()
107
+
108
+ if config.verbose:
109
+ print(f"Platform: {platform}")
110
+ print(f"Architecture: {arch}")
111
+
112
+ # Set output directory if specified
113
+ if config.output_dir:
114
+ import os
115
+
116
+ os.environ["CLANG_TOOL_CHAIN_DOWNLOAD_PATH"] = config.output_dir
117
+ if config.verbose:
118
+ print(f"Output directory: {config.output_dir}")
119
+
120
+ # Download and install
121
+ downloader.ensure_toolchain(platform, arch)
122
+
123
+ # Check if download happened or was already installed
124
+ if downloader.is_toolchain_installed(platform, arch):
125
+ install_dir = downloader.get_install_dir(platform, arch)
126
+ bin_dir = install_dir / "bin"
127
+
128
+ if config.verbose or not downloader.is_toolchain_installed(platform, arch):
129
+ print("\nToolchain installed successfully!")
130
+ print(f"Install directory: {install_dir}")
131
+ print(f"Binary directory: {bin_dir}")
132
+
133
+ # Count binaries
134
+ if bin_dir.exists():
135
+ bin_count = len(list(bin_dir.iterdir()))
136
+ print(f"Binaries available: {bin_count}")
137
+ else:
138
+ print(f"Toolchain already installed at: {install_dir}")
139
+
140
+ return 0
141
+ else:
142
+ print("ERROR: Toolchain installation failed", file=sys.stderr)
143
+ return 1
144
+
145
+ except KeyboardInterrupt:
146
+ print("\nInterrupted by user", file=sys.stderr)
147
+ return 130
148
+ except Exception as e:
149
+ print(f"ERROR: {e}", file=sys.stderr)
150
+ if "--verbose" in sys.argv or "-v" in sys.argv:
151
+ import traceback
152
+
153
+ traceback.print_exc()
154
+ return 1
155
+
156
+
157
+ if __name__ == "__main__":
158
+ sys.exit(main())
@@ -0,0 +1,93 @@
1
+ """
2
+ CLI tool for displaying paths to installed toolchain binaries.
3
+
4
+ This module provides a command-line interface for listing all installed
5
+ toolchain binary paths in JSON format.
6
+ """
7
+
8
+ import json
9
+ import sys
10
+
11
+ from . import downloader, wrapper
12
+
13
+
14
+ def main() -> int:
15
+ """
16
+ Main entry point for clang-tool-chain-paths.
17
+
18
+ Outputs JSON with paths to all installed tools.
19
+
20
+ Returns:
21
+ Exit code (0 for success, 1 for error)
22
+ """
23
+ try:
24
+ # Get current platform info
25
+ platform, arch = wrapper.get_platform_info()
26
+
27
+ # Check if toolchain is installed
28
+ if not downloader.is_toolchain_installed(platform, arch):
29
+ result = {
30
+ "error": "Toolchain not installed",
31
+ "platform": platform,
32
+ "arch": arch,
33
+ "installed": False,
34
+ "install_dir": None,
35
+ "bin_dir": None,
36
+ "tools": {},
37
+ }
38
+ print(json.dumps(result, indent=2))
39
+ return 1
40
+
41
+ # Get installation directories
42
+ install_dir = downloader.get_install_dir(platform, arch)
43
+ bin_dir = install_dir / "bin"
44
+
45
+ if not bin_dir.exists():
46
+ result = {
47
+ "error": "Binary directory not found",
48
+ "platform": platform,
49
+ "arch": arch,
50
+ "installed": True,
51
+ "install_dir": str(install_dir),
52
+ "bin_dir": str(bin_dir),
53
+ "tools": {},
54
+ }
55
+ print(json.dumps(result, indent=2))
56
+ return 1
57
+
58
+ # Enumerate all tools in bin directory
59
+ tools = {}
60
+ for binary_path in sorted(bin_dir.iterdir()):
61
+ if binary_path.is_file():
62
+ tool_name = binary_path.stem # Remove .exe on Windows
63
+ tools[tool_name] = str(binary_path)
64
+
65
+ # Build result
66
+ result = {
67
+ "platform": platform,
68
+ "arch": arch,
69
+ "installed": True,
70
+ "install_dir": str(install_dir),
71
+ "bin_dir": str(bin_dir),
72
+ "tool_count": len(tools),
73
+ "tools": tools,
74
+ }
75
+
76
+ # Output as JSON
77
+ print(json.dumps(result, indent=2))
78
+ return 0
79
+
80
+ except KeyboardInterrupt:
81
+ print("\nInterrupted by user", file=sys.stderr)
82
+ return 130
83
+ except Exception as e:
84
+ result = {
85
+ "error": str(e),
86
+ "installed": False,
87
+ }
88
+ print(json.dumps(result, indent=2))
89
+ return 1
90
+
91
+
92
+ if __name__ == "__main__":
93
+ sys.exit(main())
@@ -0,0 +1,160 @@
1
+ """
2
+ sccache runner using iso-env for isolated execution.
3
+
4
+ This module provides fallback functionality to run sccache via iso-env
5
+ when sccache is not found in the system PATH.
6
+ """
7
+
8
+ import os
9
+ import shutil
10
+ import subprocess
11
+ import sys
12
+ from pathlib import Path
13
+
14
+
15
+ def get_sccache_path() -> str | None:
16
+ """
17
+ Get the path to sccache executable.
18
+
19
+ Returns:
20
+ Path to sccache if found in PATH, None otherwise.
21
+ """
22
+ return shutil.which("sccache")
23
+
24
+
25
+ def get_iso_env_cache_dir() -> Path:
26
+ """
27
+ Get the cache directory for iso-env sccache installation.
28
+
29
+ Returns:
30
+ Path to the cache directory.
31
+ """
32
+ # Use the same directory as clang-tool-chain for consistency
33
+ base_dir = os.environ.get("CLANG_TOOL_CHAIN_DOWNLOAD_PATH")
34
+ cache_dir = Path(base_dir) / "sccache-env" if base_dir else Path.home() / ".clang-tool-chain" / "sccache-env"
35
+
36
+ return cache_dir
37
+
38
+
39
+ def run_sccache_via_isoenv(args: list[str]) -> int:
40
+ """
41
+ Run sccache via iso-env in an isolated environment.
42
+
43
+ Args:
44
+ args: Command-line arguments to pass to sccache
45
+
46
+ Returns:
47
+ Exit code from sccache execution
48
+ """
49
+ try:
50
+ from iso_env import IsoEnv, IsoEnvArgs, Requirements
51
+ except ImportError:
52
+ print("=" * 70, file=sys.stderr)
53
+ print("ERROR: iso-env package not found", file=sys.stderr)
54
+ print("=" * 70, file=sys.stderr)
55
+ print(file=sys.stderr)
56
+ print("iso-env is required as a fallback when sccache is not in PATH.", file=sys.stderr)
57
+ print("Please install it with:", file=sys.stderr)
58
+ print(" pip install clang-tool-chain", file=sys.stderr)
59
+ print(file=sys.stderr)
60
+ print("Or install sccache directly:", file=sys.stderr)
61
+ print(" pip install clang-tool-chain[sccache]", file=sys.stderr)
62
+ print(file=sys.stderr)
63
+ print("=" * 70, file=sys.stderr)
64
+ return 1
65
+
66
+ cache_dir = get_iso_env_cache_dir()
67
+
68
+ # Create iso-env configuration for sccache
69
+ try:
70
+ # First time setup - create the environment
71
+ print(f"Setting up isolated sccache environment at {cache_dir}...", file=sys.stderr)
72
+
73
+ # Create requirements for sccache
74
+ requirements_txt = "sccache>=0.7.0\n"
75
+ requirements = Requirements(requirements_txt)
76
+
77
+ # Create IsoEnvArgs
78
+ iso_args = IsoEnvArgs(venv_path=cache_dir, build_info=requirements)
79
+
80
+ # Create IsoEnv instance
81
+ env = IsoEnv(iso_args)
82
+
83
+ # Run sccache with the provided arguments
84
+ result = env.run(["sccache"] + args)
85
+
86
+ return result.returncode if result.returncode is not None else 0
87
+
88
+ except Exception as e:
89
+ print("=" * 70, file=sys.stderr)
90
+ print("ERROR: Failed to run sccache via iso-env", file=sys.stderr)
91
+ print("=" * 70, file=sys.stderr)
92
+ print(file=sys.stderr)
93
+ print(f"Error details: {e}", file=sys.stderr)
94
+ print(file=sys.stderr)
95
+ print("You may want to install sccache directly:", file=sys.stderr)
96
+ print(" pip install clang-tool-chain[sccache]", file=sys.stderr)
97
+ print(" cargo install sccache", file=sys.stderr)
98
+ print(" # or use your system package manager", file=sys.stderr)
99
+ print(file=sys.stderr)
100
+ print("=" * 70, file=sys.stderr)
101
+ return 1
102
+
103
+
104
+ def run_sccache(args: list[str]) -> int:
105
+ """
106
+ Run sccache, using iso-env as fallback if not found in PATH.
107
+
108
+ Args:
109
+ args: Command-line arguments to pass to sccache
110
+
111
+ Returns:
112
+ Exit code from sccache execution
113
+ """
114
+ sccache_path = get_sccache_path()
115
+
116
+ if sccache_path:
117
+ # sccache found in PATH, use it directly
118
+ cmd = [sccache_path] + args
119
+
120
+ try:
121
+ result = subprocess.run(cmd)
122
+ return result.returncode
123
+ except Exception as e:
124
+ print(f"ERROR: Failed to execute sccache: {e}", file=sys.stderr)
125
+ return 1
126
+ else:
127
+ # sccache not found in PATH, use iso-env fallback
128
+ print("sccache not found in PATH, using isolated environment...", file=sys.stderr)
129
+ print(file=sys.stderr)
130
+ return run_sccache_via_isoenv(args)
131
+
132
+
133
+ def run_sccache_with_compiler(compiler_path: str, args: list[str]) -> int:
134
+ """
135
+ Run sccache with a compiler, using iso-env as fallback if sccache not found in PATH.
136
+
137
+ Args:
138
+ compiler_path: Path to the compiler executable
139
+ args: Command-line arguments to pass to the compiler
140
+
141
+ Returns:
142
+ Exit code from sccache execution
143
+ """
144
+ sccache_path = get_sccache_path()
145
+
146
+ if sccache_path:
147
+ # sccache found in PATH, use it directly
148
+ cmd = [sccache_path, compiler_path] + args
149
+
150
+ try:
151
+ result = subprocess.run(cmd)
152
+ return result.returncode
153
+ except Exception as e:
154
+ print(f"ERROR: Failed to execute sccache: {e}", file=sys.stderr)
155
+ return 1
156
+ else:
157
+ # sccache not found in PATH, use iso-env fallback
158
+ print("sccache not found in PATH, using isolated environment...", file=sys.stderr)
159
+ print(file=sys.stderr)
160
+ return run_sccache_via_isoenv([compiler_path] + args)