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,400 @@
1
+ """RP2040/RP2350 Platform Package Management.
2
+
3
+ This module coordinates RP2040/RP2350 platform components including toolchain and framework.
4
+ It provides a unified interface for managing Raspberry Pi Pico builds.
5
+
6
+ Platform Components:
7
+ - ARM GCC Toolchain (arm-none-eabi-gcc)
8
+ - arduino-pico Framework (Arduino core for RP2040/RP2350)
9
+
10
+ Supported Boards:
11
+ - Raspberry Pi Pico (RP2040, ARM Cortex-M0+ @ 133MHz)
12
+ - Raspberry Pi Pico W (RP2040 with WiFi, ARM Cortex-M0+ @ 133MHz)
13
+ - Raspberry Pi Pico 2 (RP2350, ARM Cortex-M33 @ 150MHz)
14
+ - Raspberry Pi Pico 2 W (RP2350 with WiFi, ARM Cortex-M33 @ 150MHz)
15
+ """
16
+
17
+ from pathlib import Path
18
+ from typing import Any, Dict, List
19
+
20
+ from .cache import Cache
21
+ from .framework_rp2040 import FrameworkErrorRP2040, FrameworkRP2040
22
+ from .package import IPackage, PackageError
23
+ from .toolchain_rp2040 import ToolchainErrorRP2040, ToolchainRP2040
24
+
25
+
26
+ class PlatformErrorRP2040(PackageError):
27
+ """Raised when RP2040/RP2350 platform operations fail."""
28
+
29
+ pass
30
+
31
+
32
+ class PlatformRP2040(IPackage):
33
+ """Manages RP2040/RP2350 platform components and configuration.
34
+
35
+ This class coordinates the ARM GCC toolchain and arduino-pico framework to provide
36
+ a complete build environment for Raspberry Pi Pico boards.
37
+ """
38
+
39
+ def __init__(self, cache: Cache, board_mcu: str, show_progress: bool = True):
40
+ """Initialize RP2040/RP2350 platform manager.
41
+
42
+ Args:
43
+ cache: Cache manager instance
44
+ board_mcu: MCU type (e.g., "rp2040", "rp2350")
45
+ show_progress: Whether to show download/extraction progress
46
+ """
47
+ self.cache = cache
48
+ self.board_mcu = board_mcu
49
+ self.show_progress = show_progress
50
+
51
+ # Initialize toolchain and framework
52
+ self.toolchain = ToolchainRP2040(cache, show_progress=show_progress)
53
+ self.framework = FrameworkRP2040(cache, show_progress=show_progress)
54
+
55
+ def ensure_package(self) -> Path:
56
+ """Ensure platform components are downloaded and extracted.
57
+
58
+ Returns:
59
+ Path to the framework directory (main platform directory)
60
+
61
+ Raises:
62
+ PlatformErrorRP2040: If download or extraction fails
63
+ """
64
+ try:
65
+ # Ensure toolchain is installed
66
+ self.toolchain.ensure_toolchain()
67
+
68
+ # Ensure framework is installed
69
+ framework_path = self.framework.ensure_framework()
70
+
71
+ return framework_path
72
+
73
+ except (ToolchainErrorRP2040, FrameworkErrorRP2040) as e:
74
+ raise PlatformErrorRP2040(f"Failed to install RP2040/RP2350 platform: {e}")
75
+ except KeyboardInterrupt as ke:
76
+ from fbuild.interrupt_utils import handle_keyboard_interrupt_properly
77
+
78
+ handle_keyboard_interrupt_properly(ke)
79
+ raise # Never reached, but satisfies type checker
80
+ except Exception as e:
81
+ raise PlatformErrorRP2040(f"Unexpected error installing platform: {e}")
82
+
83
+ def is_installed(self) -> bool:
84
+ """Check if platform is already installed.
85
+
86
+ Returns:
87
+ True if both toolchain and framework are installed
88
+ """
89
+ return self.toolchain.is_installed() and self.framework.is_installed()
90
+
91
+ def get_compiler_flags(self, board_config: Any, mcu: str = "rp2040") -> List[str]:
92
+ """Get compiler flags for RP2040/RP2350 builds.
93
+
94
+ Args:
95
+ board_config: Board configuration object
96
+ mcu: MCU type ("rp2040" or "rp2350")
97
+
98
+ Returns:
99
+ List of compiler flags
100
+ """
101
+ # Base flags common to both RP2040 and RP2350
102
+ flags = [
103
+ # Optimization and debug
104
+ "-Os",
105
+ "-g",
106
+ "-ffunction-sections",
107
+ "-fdata-sections",
108
+ "-fno-exceptions",
109
+ # Warnings
110
+ "-Wall",
111
+ "-Wno-unused-parameter",
112
+ "-Wno-sign-compare",
113
+ "-Wno-error=unused-function",
114
+ "-Wno-error=unused-variable",
115
+ "-Wno-error=deprecated-declarations",
116
+ # Standards
117
+ "-std=gnu17", # For C files
118
+ # Arduino defines
119
+ "-DARDUINO_ARCH_RP2040",
120
+ "-DPICO_BOARD",
121
+ "-DPICO_BUILD",
122
+ "-DPICO_NO_HARDWARE",
123
+ "-DPICO_ON_DEVICE",
124
+ "-DCFG_TUSB_MCU=OPT_MCU_RP2040",
125
+ "-DLWIP_IPV4=1",
126
+ "-DLWIP_IPV6=0",
127
+ ]
128
+
129
+ # MCU-specific flags
130
+ if mcu.lower() == "rp2350":
131
+ # RP2350: Cortex-M33 with FPU and DSP
132
+ flags.extend(
133
+ [
134
+ "-march=armv8-m.main+fp+dsp",
135
+ "-mcpu=cortex-m33",
136
+ "-mthumb",
137
+ "-mfloat-abi=hard",
138
+ "-mfpu=fpv5-sp-d16",
139
+ f"-DF_CPU={getattr(board_config, 'f_cpu', '150000000L')}",
140
+ "-DTARGET_RP2350=1",
141
+ "-DPICO_RP2350=1",
142
+ "-DPICO_RP2350A",
143
+ "-D__ARM_FEATURE_DSP=1",
144
+ ]
145
+ )
146
+ else:
147
+ # RP2040: Cortex-M0+
148
+ flags.extend(
149
+ [
150
+ "-march=armv6-m",
151
+ "-mcpu=cortex-m0plus",
152
+ "-mthumb",
153
+ f"-DF_CPU={getattr(board_config, 'f_cpu', '133000000L')}",
154
+ "-DTARGET_RP2040=1",
155
+ "-DPICO_RP2040=1",
156
+ ]
157
+ )
158
+
159
+ return flags
160
+
161
+ def get_compiler_flags_cpp(self, board_config: Any, mcu: str = "rp2040") -> List[str]:
162
+ """Get C++ compiler flags for RP2040/RP2350 builds.
163
+
164
+ Args:
165
+ board_config: Board configuration object
166
+ mcu: MCU type ("rp2040" or "rp2350")
167
+
168
+ Returns:
169
+ List of C++ compiler flags
170
+ """
171
+ # Start with base C flags
172
+ flags = self.get_compiler_flags(board_config, mcu)
173
+
174
+ # Replace C standard with C++ standard
175
+ flags = [f for f in flags if not f.startswith("-std=gnu17")]
176
+ flags.extend(
177
+ [
178
+ "-std=gnu++17",
179
+ "-fno-exceptions",
180
+ "-fno-rtti",
181
+ "-fno-threadsafe-statics",
182
+ ]
183
+ )
184
+
185
+ return flags
186
+
187
+ def get_linker_flags(self, board_config: Any, mcu: str = "rp2040") -> List[str]:
188
+ """Get linker flags for RP2040/RP2350 builds.
189
+
190
+ Args:
191
+ board_config: Board configuration object
192
+ mcu: MCU type ("rp2040" or "rp2350")
193
+
194
+ Returns:
195
+ List of linker flags
196
+ """
197
+ flags = [
198
+ # Optimization
199
+ "-Os",
200
+ # Linker options
201
+ "-Wl,--cref",
202
+ "-Wl,--check-sections",
203
+ "-Wl,--gc-sections",
204
+ "-Wl,--unresolved-symbols=report-all",
205
+ "-Wl,--warn-common",
206
+ "-Wl,--warn-section-align",
207
+ # Memory wrappers
208
+ "-Wl,--wrap=malloc",
209
+ "-Wl,--wrap=calloc",
210
+ "-Wl,--wrap=realloc",
211
+ "-Wl,--wrap=free",
212
+ # Printf/scanf float support
213
+ "-u",
214
+ "_printf_float",
215
+ "-u",
216
+ "_scanf_float",
217
+ ]
218
+
219
+ # MCU-specific flags
220
+ if mcu.lower() == "rp2350":
221
+ flags.extend(
222
+ [
223
+ "-march=armv8-m.main+fp+dsp",
224
+ "-mcpu=cortex-m33",
225
+ "-mthumb",
226
+ "-mfloat-abi=hard",
227
+ "-mfpu=fpv5-sp-d16",
228
+ ]
229
+ )
230
+ else:
231
+ flags.extend(
232
+ [
233
+ "-march=armv6-m",
234
+ "-mcpu=cortex-m0plus",
235
+ "-mthumb",
236
+ ]
237
+ )
238
+
239
+ return flags
240
+
241
+ def get_include_dirs(self, board_config: Any) -> List[Path]:
242
+ """Get include directories for RP2040/RP2350 builds.
243
+
244
+ Args:
245
+ board_config: Board configuration object
246
+
247
+ Returns:
248
+ List of include directory paths
249
+ """
250
+ includes = []
251
+
252
+ # Core includes
253
+ try:
254
+ core_includes = self.framework.get_core_includes("rp2040")
255
+ includes.extend(core_includes)
256
+ except FrameworkErrorRP2040:
257
+ pass
258
+
259
+ # Variant includes (if board_config has variant info)
260
+ if hasattr(board_config, "variant"):
261
+ variant_dir = self.framework.get_variant_dir(board_config.variant)
262
+ if variant_dir:
263
+ includes.append(variant_dir)
264
+
265
+ return includes
266
+
267
+ def get_core_sources(self) -> List[Path]:
268
+ """Get core source files for RP2040/RP2350 builds.
269
+
270
+ Returns:
271
+ List of core source file paths
272
+ """
273
+ try:
274
+ return self.framework.get_core_sources("rp2040")
275
+ except FrameworkErrorRP2040:
276
+ return []
277
+
278
+ def get_toolchain_binaries(self) -> Dict[str, Path]:
279
+ """Get paths to toolchain binaries.
280
+
281
+ Returns:
282
+ Dictionary mapping tool names to paths
283
+
284
+ Raises:
285
+ PlatformErrorRP2040: If toolchain binaries are not found
286
+ """
287
+ tools = self.toolchain.get_all_tool_paths()
288
+
289
+ # Verify all required tools exist
290
+ required_tools = ["gcc", "g++", "ar", "objcopy", "size"]
291
+ for tool_name in required_tools:
292
+ if tool_name not in tools or tools[tool_name] is None:
293
+ raise PlatformErrorRP2040(f"Required tool not found: {tool_name}")
294
+
295
+ # Filter out None values
296
+ return {name: path for name, path in tools.items() if path is not None}
297
+
298
+ def get_package_info(self) -> Dict[str, Any]:
299
+ """Get information about the installed platform.
300
+
301
+ Returns:
302
+ Dictionary with platform information
303
+ """
304
+ return self.get_platform_info()
305
+
306
+ def get_board_json(self, board_id: str) -> Dict[str, Any]:
307
+ """Get board configuration in JSON format.
308
+
309
+ This method returns board configuration compatible with the format
310
+ expected by ConfigurableCompiler and ConfigurableLinker.
311
+
312
+ Args:
313
+ board_id: Board identifier (e.g., "rpipico", "rpipico2")
314
+
315
+ Returns:
316
+ Dictionary containing board configuration
317
+
318
+ Raises:
319
+ PlatformErrorRP2040: If board is not supported
320
+ """
321
+ # Map board IDs to their configurations
322
+ board_configs = {
323
+ "rpipico": {
324
+ "build": {
325
+ "mcu": "rp2040",
326
+ "f_cpu": "133000000L",
327
+ "core": "rp2040",
328
+ "variant": "rpipico",
329
+ "board": "RASPBERRY_PI_PICO",
330
+ },
331
+ "name": "Raspberry Pi Pico",
332
+ "upload": {
333
+ "maximum_size": 2097152, # 2MB flash
334
+ "maximum_ram_size": 270336, # 264KB RAM
335
+ },
336
+ },
337
+ "rpipicow": {
338
+ "build": {
339
+ "mcu": "rp2040",
340
+ "f_cpu": "133000000L",
341
+ "core": "rp2040",
342
+ "variant": "rpipicow",
343
+ "board": "RASPBERRY_PI_PICO_W",
344
+ },
345
+ "name": "Raspberry Pi Pico W",
346
+ "upload": {
347
+ "maximum_size": 2097152, # 2MB flash
348
+ "maximum_ram_size": 270336, # 264KB RAM
349
+ },
350
+ },
351
+ "rpipico2": {
352
+ "build": {
353
+ "mcu": "rp2350",
354
+ "f_cpu": "150000000L",
355
+ "core": "rp2040",
356
+ "variant": "rpipico2",
357
+ "board": "RASPBERRY_PI_PICO_2",
358
+ },
359
+ "name": "Raspberry Pi Pico 2",
360
+ "upload": {
361
+ "maximum_size": 4194304, # 4MB flash
362
+ "maximum_ram_size": 532480, # 520KB RAM
363
+ },
364
+ },
365
+ "rpipico2w": {
366
+ "build": {
367
+ "mcu": "rp2350",
368
+ "f_cpu": "150000000L",
369
+ "core": "rp2040",
370
+ "variant": "rpipico2w",
371
+ "board": "RASPBERRY_PI_PICO_2_W",
372
+ },
373
+ "name": "Raspberry Pi Pico 2 W",
374
+ "upload": {
375
+ "maximum_size": 4194304, # 4MB flash
376
+ "maximum_ram_size": 532480, # 520KB RAM
377
+ },
378
+ },
379
+ }
380
+
381
+ if board_id not in board_configs:
382
+ raise PlatformErrorRP2040(f"Unsupported board: {board_id}. " + f"Supported boards: {', '.join(board_configs.keys())}")
383
+
384
+ return board_configs[board_id]
385
+
386
+ def get_platform_info(self) -> Dict[str, Any]:
387
+ """Get information about the installed platform.
388
+
389
+ Returns:
390
+ Dictionary with platform information
391
+ """
392
+ info = {
393
+ "platform": "raspberrypi",
394
+ "mcu": self.board_mcu,
395
+ "installed": self.is_installed(),
396
+ "toolchain": self.toolchain.get_toolchain_info(),
397
+ "framework": self.framework.get_framework_info(),
398
+ }
399
+
400
+ return info