fbuild 1.2.8__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.
Files changed (121) hide show
  1. fbuild/__init__.py +390 -0
  2. fbuild/assets/example.txt +1 -0
  3. fbuild/build/__init__.py +117 -0
  4. fbuild/build/archive_creator.py +186 -0
  5. fbuild/build/binary_generator.py +444 -0
  6. fbuild/build/build_component_factory.py +131 -0
  7. fbuild/build/build_info_generator.py +624 -0
  8. fbuild/build/build_state.py +325 -0
  9. fbuild/build/build_utils.py +93 -0
  10. fbuild/build/compilation_executor.py +422 -0
  11. fbuild/build/compiler.py +165 -0
  12. fbuild/build/compiler_avr.py +574 -0
  13. fbuild/build/configurable_compiler.py +664 -0
  14. fbuild/build/configurable_linker.py +637 -0
  15. fbuild/build/flag_builder.py +214 -0
  16. fbuild/build/library_dependency_processor.py +185 -0
  17. fbuild/build/linker.py +708 -0
  18. fbuild/build/orchestrator.py +67 -0
  19. fbuild/build/orchestrator_avr.py +651 -0
  20. fbuild/build/orchestrator_esp32.py +878 -0
  21. fbuild/build/orchestrator_rp2040.py +719 -0
  22. fbuild/build/orchestrator_stm32.py +696 -0
  23. fbuild/build/orchestrator_teensy.py +580 -0
  24. fbuild/build/source_compilation_orchestrator.py +218 -0
  25. fbuild/build/source_scanner.py +516 -0
  26. fbuild/cli.py +717 -0
  27. fbuild/cli_utils.py +314 -0
  28. fbuild/config/__init__.py +16 -0
  29. fbuild/config/board_config.py +542 -0
  30. fbuild/config/board_loader.py +92 -0
  31. fbuild/config/ini_parser.py +369 -0
  32. fbuild/config/mcu_specs.py +88 -0
  33. fbuild/daemon/__init__.py +42 -0
  34. fbuild/daemon/async_client.py +531 -0
  35. fbuild/daemon/client.py +1505 -0
  36. fbuild/daemon/compilation_queue.py +293 -0
  37. fbuild/daemon/configuration_lock.py +865 -0
  38. fbuild/daemon/daemon.py +585 -0
  39. fbuild/daemon/daemon_context.py +293 -0
  40. fbuild/daemon/error_collector.py +263 -0
  41. fbuild/daemon/file_cache.py +332 -0
  42. fbuild/daemon/firmware_ledger.py +546 -0
  43. fbuild/daemon/lock_manager.py +508 -0
  44. fbuild/daemon/logging_utils.py +149 -0
  45. fbuild/daemon/messages.py +957 -0
  46. fbuild/daemon/operation_registry.py +288 -0
  47. fbuild/daemon/port_state_manager.py +249 -0
  48. fbuild/daemon/process_tracker.py +366 -0
  49. fbuild/daemon/processors/__init__.py +18 -0
  50. fbuild/daemon/processors/build_processor.py +248 -0
  51. fbuild/daemon/processors/deploy_processor.py +664 -0
  52. fbuild/daemon/processors/install_deps_processor.py +431 -0
  53. fbuild/daemon/processors/locking_processor.py +777 -0
  54. fbuild/daemon/processors/monitor_processor.py +285 -0
  55. fbuild/daemon/request_processor.py +457 -0
  56. fbuild/daemon/shared_serial.py +819 -0
  57. fbuild/daemon/status_manager.py +238 -0
  58. fbuild/daemon/subprocess_manager.py +316 -0
  59. fbuild/deploy/__init__.py +21 -0
  60. fbuild/deploy/deployer.py +67 -0
  61. fbuild/deploy/deployer_esp32.py +310 -0
  62. fbuild/deploy/docker_utils.py +315 -0
  63. fbuild/deploy/monitor.py +519 -0
  64. fbuild/deploy/qemu_runner.py +603 -0
  65. fbuild/interrupt_utils.py +34 -0
  66. fbuild/ledger/__init__.py +52 -0
  67. fbuild/ledger/board_ledger.py +560 -0
  68. fbuild/output.py +352 -0
  69. fbuild/packages/__init__.py +66 -0
  70. fbuild/packages/archive_utils.py +1098 -0
  71. fbuild/packages/arduino_core.py +412 -0
  72. fbuild/packages/cache.py +256 -0
  73. fbuild/packages/concurrent_manager.py +510 -0
  74. fbuild/packages/downloader.py +518 -0
  75. fbuild/packages/fingerprint.py +423 -0
  76. fbuild/packages/framework_esp32.py +538 -0
  77. fbuild/packages/framework_rp2040.py +349 -0
  78. fbuild/packages/framework_stm32.py +459 -0
  79. fbuild/packages/framework_teensy.py +346 -0
  80. fbuild/packages/github_utils.py +96 -0
  81. fbuild/packages/header_trampoline_cache.py +394 -0
  82. fbuild/packages/library_compiler.py +203 -0
  83. fbuild/packages/library_manager.py +549 -0
  84. fbuild/packages/library_manager_esp32.py +725 -0
  85. fbuild/packages/package.py +163 -0
  86. fbuild/packages/platform_esp32.py +383 -0
  87. fbuild/packages/platform_rp2040.py +400 -0
  88. fbuild/packages/platform_stm32.py +581 -0
  89. fbuild/packages/platform_teensy.py +312 -0
  90. fbuild/packages/platform_utils.py +131 -0
  91. fbuild/packages/platformio_registry.py +369 -0
  92. fbuild/packages/sdk_utils.py +231 -0
  93. fbuild/packages/toolchain.py +436 -0
  94. fbuild/packages/toolchain_binaries.py +196 -0
  95. fbuild/packages/toolchain_esp32.py +489 -0
  96. fbuild/packages/toolchain_metadata.py +185 -0
  97. fbuild/packages/toolchain_rp2040.py +436 -0
  98. fbuild/packages/toolchain_stm32.py +417 -0
  99. fbuild/packages/toolchain_teensy.py +404 -0
  100. fbuild/platform_configs/esp32.json +150 -0
  101. fbuild/platform_configs/esp32c2.json +144 -0
  102. fbuild/platform_configs/esp32c3.json +143 -0
  103. fbuild/platform_configs/esp32c5.json +151 -0
  104. fbuild/platform_configs/esp32c6.json +151 -0
  105. fbuild/platform_configs/esp32p4.json +149 -0
  106. fbuild/platform_configs/esp32s3.json +151 -0
  107. fbuild/platform_configs/imxrt1062.json +56 -0
  108. fbuild/platform_configs/rp2040.json +70 -0
  109. fbuild/platform_configs/rp2350.json +76 -0
  110. fbuild/platform_configs/stm32f1.json +59 -0
  111. fbuild/platform_configs/stm32f4.json +63 -0
  112. fbuild/py.typed +0 -0
  113. fbuild-1.2.8.dist-info/METADATA +468 -0
  114. fbuild-1.2.8.dist-info/RECORD +121 -0
  115. fbuild-1.2.8.dist-info/WHEEL +5 -0
  116. fbuild-1.2.8.dist-info/entry_points.txt +5 -0
  117. fbuild-1.2.8.dist-info/licenses/LICENSE +21 -0
  118. fbuild-1.2.8.dist-info/top_level.txt +2 -0
  119. fbuild_lint/__init__.py +0 -0
  120. fbuild_lint/ruff_plugins/__init__.py +0 -0
  121. fbuild_lint/ruff_plugins/keyboard_interrupt_checker.py +158 -0
@@ -0,0 +1,312 @@
1
+ """Teensy Platform Package Management.
2
+
3
+ This module coordinates Teensy platform components including toolchain and framework.
4
+ It provides a unified interface for managing Teensy 4.x platform builds.
5
+
6
+ Platform Components:
7
+ - ARM GCC Toolchain (arm-none-eabi-gcc)
8
+ - Teensy Cores Framework (Arduino core for Teensy 4.x)
9
+
10
+ Supported Boards:
11
+ - Teensy 4.1 (NXP i.MX RT1062, ARM Cortex-M7 @ 600MHz)
12
+ - Teensy 4.0 (NXP i.MX RT1062, ARM Cortex-M7 @ 600MHz)
13
+ """
14
+
15
+ from pathlib import Path
16
+ from typing import Any, Dict, List
17
+
18
+ from .cache import Cache
19
+ from .framework_teensy import FrameworkErrorTeensy, FrameworkTeensy
20
+ from .package import IPackage, PackageError
21
+ from .toolchain_teensy import ToolchainErrorTeensy, ToolchainTeensy
22
+
23
+
24
+ class PlatformErrorTeensy(PackageError):
25
+ """Raised when Teensy platform operations fail."""
26
+
27
+ pass
28
+
29
+
30
+ class PlatformTeensy(IPackage):
31
+ """Manages Teensy platform components and configuration.
32
+
33
+ This class coordinates the Teensy toolchain and framework to provide
34
+ a complete build environment for Teensy 4.x boards.
35
+ """
36
+
37
+ def __init__(self, cache: Cache, board_mcu: str, show_progress: bool = True):
38
+ """Initialize Teensy platform manager.
39
+
40
+ Args:
41
+ cache: Cache manager instance
42
+ board_mcu: MCU type (e.g., "imxrt1062")
43
+ show_progress: Whether to show download/extraction progress
44
+ """
45
+ self.cache = cache
46
+ self.board_mcu = board_mcu
47
+ self.show_progress = show_progress
48
+
49
+ # Initialize toolchain and framework
50
+ self.toolchain = ToolchainTeensy(cache, show_progress=show_progress)
51
+ self.framework = FrameworkTeensy(cache, show_progress=show_progress)
52
+
53
+ def ensure_package(self) -> Path:
54
+ """Ensure platform components are downloaded and extracted.
55
+
56
+ Returns:
57
+ Path to the framework directory (main platform directory)
58
+
59
+ Raises:
60
+ PlatformErrorTeensy: If download or extraction fails
61
+ """
62
+ try:
63
+ # Ensure toolchain is installed
64
+ self.toolchain.ensure_toolchain()
65
+
66
+ # Ensure framework is installed
67
+ framework_path = self.framework.ensure_framework()
68
+
69
+ return framework_path
70
+
71
+ except (ToolchainErrorTeensy, FrameworkErrorTeensy) as e:
72
+ raise PlatformErrorTeensy(f"Failed to install Teensy platform: {e}")
73
+ except KeyboardInterrupt as ke:
74
+ from fbuild.interrupt_utils import handle_keyboard_interrupt_properly
75
+
76
+ handle_keyboard_interrupt_properly(ke)
77
+ raise # Never reached, but satisfies type checker
78
+ except Exception as e:
79
+ raise PlatformErrorTeensy(f"Unexpected error installing platform: {e}")
80
+
81
+ def is_installed(self) -> bool:
82
+ """Check if platform is already installed.
83
+
84
+ Returns:
85
+ True if both toolchain and framework are installed
86
+ """
87
+ return self.toolchain.is_installed() and self.framework.is_installed()
88
+
89
+ def get_compiler_flags(self, board_config: Any) -> List[str]:
90
+ """Get compiler flags for Teensy builds.
91
+
92
+ Args:
93
+ board_config: Board configuration object
94
+
95
+ Returns:
96
+ List of compiler flags
97
+ """
98
+ flags = [
99
+ # CPU and architecture
100
+ "-mcpu=cortex-m7",
101
+ "-mthumb",
102
+ "-mfloat-abi=hard",
103
+ "-mfpu=fpv5-d16",
104
+ # Optimization
105
+ "-O2",
106
+ "-g",
107
+ # Warnings
108
+ "-Wall",
109
+ "-Wextra",
110
+ "-Wno-unused-parameter",
111
+ # Standards
112
+ "-std=gnu11", # For C files
113
+ # Board-specific defines
114
+ f"-DF_CPU={board_config.f_cpu}",
115
+ "-DARDUINO_TEENSY41",
116
+ "-D__IMXRT1062__",
117
+ "-DARDUINO=10819",
118
+ "-DTEENSYDUINO=159",
119
+ "-DUSB_SERIAL",
120
+ # Memory layout
121
+ "-DARDUINO_ARCH_TEENSY",
122
+ ]
123
+
124
+ return flags
125
+
126
+ def get_compiler_flags_cpp(self, board_config: Any) -> List[str]:
127
+ """Get C++ compiler flags for Teensy builds.
128
+
129
+ Args:
130
+ board_config: Board configuration object
131
+
132
+ Returns:
133
+ List of C++ compiler flags
134
+ """
135
+ # Start with base C flags
136
+ flags = self.get_compiler_flags(board_config)
137
+
138
+ # Replace C standard with C++ standard
139
+ flags = [f for f in flags if not f.startswith("-std=gnu11")]
140
+ flags.extend(
141
+ [
142
+ "-std=gnu++14",
143
+ "-fno-exceptions",
144
+ "-fno-rtti",
145
+ "-felide-constructors",
146
+ "-fno-threadsafe-statics",
147
+ ]
148
+ )
149
+
150
+ return flags
151
+
152
+ def get_linker_flags(self, board_config: Any, board_id: str = "teensy41") -> List[str]:
153
+ """Get linker flags for Teensy builds.
154
+
155
+ Args:
156
+ board_config: Board configuration object
157
+ board_id: Board identifier for linker script selection
158
+
159
+ Returns:
160
+ List of linker flags
161
+ """
162
+ # Get linker script
163
+ linker_script = self.framework.get_linker_script(board_id)
164
+ if not linker_script:
165
+ raise PlatformErrorTeensy(f"Linker script not found for board: {board_id}")
166
+
167
+ flags = [
168
+ # CPU and architecture
169
+ "-mcpu=cortex-m7",
170
+ "-mthumb",
171
+ "-mfloat-abi=hard",
172
+ "-mfpu=fpv5-d16",
173
+ # Optimization
174
+ "-O2",
175
+ # Linker script
176
+ f"-T{linker_script}",
177
+ # Linker options
178
+ "-Wl,--gc-sections",
179
+ "-Wl,--print-memory-usage",
180
+ # Math library
181
+ "-lm",
182
+ "-lstdc++",
183
+ ]
184
+
185
+ return flags
186
+
187
+ def get_include_dirs(self, board_config: Any) -> List[Path]:
188
+ """Get include directories for Teensy builds.
189
+
190
+ Args:
191
+ board_config: Board configuration object
192
+
193
+ Returns:
194
+ List of include directory paths
195
+ """
196
+ includes = []
197
+
198
+ # Core includes
199
+ try:
200
+ core_includes = self.framework.get_core_includes("teensy4")
201
+ includes.extend(core_includes)
202
+ except FrameworkErrorTeensy:
203
+ pass
204
+
205
+ return includes
206
+
207
+ def get_core_sources(self) -> List[Path]:
208
+ """Get core source files for Teensy builds.
209
+
210
+ Returns:
211
+ List of core source file paths
212
+ """
213
+ try:
214
+ return self.framework.get_core_sources("teensy4")
215
+ except FrameworkErrorTeensy:
216
+ return []
217
+
218
+ def get_toolchain_binaries(self) -> Dict[str, Path]:
219
+ """Get paths to toolchain binaries.
220
+
221
+ Returns:
222
+ Dictionary mapping tool names to paths
223
+
224
+ Raises:
225
+ PlatformErrorTeensy: If toolchain binaries are not found
226
+ """
227
+ tools = self.toolchain.get_all_tool_paths()
228
+
229
+ # Verify all required tools exist
230
+ required_tools = ["gcc", "g++", "ar", "objcopy", "size"]
231
+ for tool_name in required_tools:
232
+ if tool_name not in tools or tools[tool_name] is None:
233
+ raise PlatformErrorTeensy(f"Required tool not found: {tool_name}")
234
+
235
+ # Filter out None values
236
+ return {name: path for name, path in tools.items() if path is not None}
237
+
238
+ def get_package_info(self) -> Dict[str, Any]:
239
+ """Get information about the installed platform.
240
+
241
+ Returns:
242
+ Dictionary with platform information
243
+ """
244
+ return self.get_platform_info()
245
+
246
+ def get_board_json(self, board_id: str) -> Dict[str, Any]:
247
+ """Get board configuration in JSON format.
248
+
249
+ This method returns board configuration compatible with the format
250
+ expected by ConfigurableCompiler and ConfigurableLinker.
251
+
252
+ Args:
253
+ board_id: Board identifier (e.g., "teensy41")
254
+
255
+ Returns:
256
+ Dictionary containing board configuration
257
+
258
+ Raises:
259
+ PlatformErrorTeensy: If board is not supported
260
+ """
261
+ # Map board IDs to their configurations
262
+ board_configs = {
263
+ "teensy41": {
264
+ "build": {
265
+ "mcu": "imxrt1062",
266
+ "f_cpu": "600000000L",
267
+ "core": "teensy4",
268
+ "variant": "teensy41",
269
+ "board": "TEENSY41",
270
+ },
271
+ "name": "Teensy 4.1",
272
+ "upload": {
273
+ "maximum_size": 8126464,
274
+ "maximum_ram_size": 524288,
275
+ },
276
+ },
277
+ "teensy40": {
278
+ "build": {
279
+ "mcu": "imxrt1062",
280
+ "f_cpu": "600000000L",
281
+ "core": "teensy4",
282
+ "variant": "teensy40",
283
+ "board": "TEENSY40",
284
+ },
285
+ "name": "Teensy 4.0",
286
+ "upload": {
287
+ "maximum_size": 2031616,
288
+ "maximum_ram_size": 524288,
289
+ },
290
+ },
291
+ }
292
+
293
+ if board_id not in board_configs:
294
+ raise PlatformErrorTeensy(f"Unsupported board: {board_id}. " + f"Supported boards: {', '.join(board_configs.keys())}")
295
+
296
+ return board_configs[board_id]
297
+
298
+ def get_platform_info(self) -> Dict[str, Any]:
299
+ """Get information about the installed platform.
300
+
301
+ Returns:
302
+ Dictionary with platform information
303
+ """
304
+ info = {
305
+ "platform": "teensy",
306
+ "mcu": self.board_mcu,
307
+ "installed": self.is_installed(),
308
+ "toolchain": self.toolchain.get_toolchain_info(),
309
+ "framework": self.framework.get_framework_info(),
310
+ }
311
+
312
+ return info
@@ -0,0 +1,131 @@
1
+ """Platform Detection Utilities.
2
+
3
+ This module provides utilities for detecting the current platform and architecture
4
+ for toolchain selection and package management.
5
+
6
+ Supported Platforms:
7
+ - Windows: win32, win64
8
+ - Linux: linux-amd64, linux-arm64, linux-armhf, linux-i686
9
+ - macOS: macos, macos-arm64
10
+ """
11
+
12
+ import platform
13
+ import sys
14
+ from typing import Literal, Tuple
15
+
16
+
17
+ class PlatformError(Exception):
18
+ """Raised when platform detection fails or platform is unsupported."""
19
+
20
+ pass
21
+
22
+
23
+ PlatformIdentifier = Literal[
24
+ "win32",
25
+ "win64",
26
+ "linux-amd64",
27
+ "linux-arm64",
28
+ "linux-armhf",
29
+ "linux-i686",
30
+ "macos",
31
+ "macos-arm64",
32
+ ]
33
+
34
+
35
+ class PlatformDetector:
36
+ """Detects the current platform and architecture for toolchain selection."""
37
+
38
+ @staticmethod
39
+ def detect_esp32_platform() -> str:
40
+ """Detect the current platform for ESP32 toolchain selection.
41
+
42
+ This format is used by ESP-IDF toolchain packages.
43
+
44
+ Returns:
45
+ Platform identifier (win32, win64, linux-amd64, linux-arm64, macos, macos-arm64)
46
+
47
+ Raises:
48
+ PlatformError: If platform is unsupported
49
+ """
50
+ system = platform.system().lower()
51
+ machine = platform.machine().lower()
52
+
53
+ if system == "windows":
54
+ # Check if 64-bit
55
+ return "win64" if sys.maxsize > 2**32 else "win32"
56
+ elif system == "linux":
57
+ if "aarch64" in machine or "arm64" in machine:
58
+ return "linux-arm64"
59
+ elif "arm" in machine:
60
+ # Check for hard float vs soft float
61
+ return "linux-armhf" # Default to hard float
62
+ elif "i686" in machine or "i386" in machine:
63
+ return "linux-i686"
64
+ else:
65
+ return "linux-amd64"
66
+ elif system == "darwin":
67
+ if "arm64" in machine or "aarch64" in machine:
68
+ return "macos-arm64"
69
+ else:
70
+ return "macos"
71
+ else:
72
+ raise PlatformError(f"Unsupported platform: {system} {machine}")
73
+
74
+ @staticmethod
75
+ def detect_avr_platform() -> Tuple[str, str]:
76
+ """Detect the current platform for AVR toolchain selection.
77
+
78
+ This format is used by Arduino AVR toolchain packages.
79
+
80
+ Returns:
81
+ Tuple of (platform, architecture)
82
+ Platform: 'windows', 'linux', or 'darwin'
83
+ Architecture: 'x86_64', 'i686', 'aarch64', 'armv7l'
84
+
85
+ Raises:
86
+ PlatformError: If platform is not supported
87
+ """
88
+ system = platform.system().lower()
89
+ machine = platform.machine().lower()
90
+
91
+ # Normalize platform name
92
+ if system == "windows":
93
+ plat = "windows"
94
+ elif system == "linux":
95
+ plat = "linux"
96
+ elif system == "darwin":
97
+ plat = "darwin"
98
+ else:
99
+ raise PlatformError(f"Unsupported platform: {system}")
100
+
101
+ # Normalize architecture
102
+ if machine in ("x86_64", "amd64"):
103
+ arch = "x86_64"
104
+ elif machine in ("i386", "i686"):
105
+ arch = "i686"
106
+ elif machine in ("aarch64", "arm64"):
107
+ arch = "aarch64"
108
+ elif machine.startswith("arm"):
109
+ arch = "armv7l"
110
+ else:
111
+ # Default to x86_64 if unknown
112
+ arch = "x86_64"
113
+
114
+ return plat, arch
115
+
116
+ @staticmethod
117
+ def get_platform_info() -> dict:
118
+ """Get detailed information about the current platform.
119
+
120
+ Returns:
121
+ Dictionary with platform information including system, machine, and Python info
122
+ """
123
+ return {
124
+ "system": platform.system(),
125
+ "machine": platform.machine(),
126
+ "platform": platform.platform(),
127
+ "python_version": platform.python_version(),
128
+ "is_64bit": sys.maxsize > 2**32,
129
+ "esp32_format": PlatformDetector.detect_esp32_platform(),
130
+ "avr_format": PlatformDetector.detect_avr_platform(),
131
+ }