fbuild 1.1.0__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.

Potentially problematic release.


This version of fbuild might be problematic. Click here for more details.

Files changed (93) hide show
  1. fbuild/__init__.py +0 -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_state.py +325 -0
  8. fbuild/build/build_utils.py +98 -0
  9. fbuild/build/compilation_executor.py +422 -0
  10. fbuild/build/compiler.py +165 -0
  11. fbuild/build/compiler_avr.py +574 -0
  12. fbuild/build/configurable_compiler.py +612 -0
  13. fbuild/build/configurable_linker.py +637 -0
  14. fbuild/build/flag_builder.py +186 -0
  15. fbuild/build/library_dependency_processor.py +185 -0
  16. fbuild/build/linker.py +708 -0
  17. fbuild/build/orchestrator.py +67 -0
  18. fbuild/build/orchestrator_avr.py +656 -0
  19. fbuild/build/orchestrator_esp32.py +797 -0
  20. fbuild/build/orchestrator_teensy.py +543 -0
  21. fbuild/build/source_compilation_orchestrator.py +220 -0
  22. fbuild/build/source_scanner.py +516 -0
  23. fbuild/cli.py +566 -0
  24. fbuild/cli_utils.py +312 -0
  25. fbuild/config/__init__.py +16 -0
  26. fbuild/config/board_config.py +457 -0
  27. fbuild/config/board_loader.py +92 -0
  28. fbuild/config/ini_parser.py +209 -0
  29. fbuild/config/mcu_specs.py +88 -0
  30. fbuild/daemon/__init__.py +34 -0
  31. fbuild/daemon/client.py +929 -0
  32. fbuild/daemon/compilation_queue.py +293 -0
  33. fbuild/daemon/daemon.py +474 -0
  34. fbuild/daemon/daemon_context.py +196 -0
  35. fbuild/daemon/error_collector.py +263 -0
  36. fbuild/daemon/file_cache.py +332 -0
  37. fbuild/daemon/lock_manager.py +270 -0
  38. fbuild/daemon/logging_utils.py +149 -0
  39. fbuild/daemon/messages.py +301 -0
  40. fbuild/daemon/operation_registry.py +288 -0
  41. fbuild/daemon/process_tracker.py +366 -0
  42. fbuild/daemon/processors/__init__.py +12 -0
  43. fbuild/daemon/processors/build_processor.py +157 -0
  44. fbuild/daemon/processors/deploy_processor.py +327 -0
  45. fbuild/daemon/processors/monitor_processor.py +146 -0
  46. fbuild/daemon/request_processor.py +401 -0
  47. fbuild/daemon/status_manager.py +216 -0
  48. fbuild/daemon/subprocess_manager.py +316 -0
  49. fbuild/deploy/__init__.py +17 -0
  50. fbuild/deploy/deployer.py +67 -0
  51. fbuild/deploy/deployer_esp32.py +314 -0
  52. fbuild/deploy/monitor.py +495 -0
  53. fbuild/interrupt_utils.py +34 -0
  54. fbuild/packages/__init__.py +53 -0
  55. fbuild/packages/archive_utils.py +1098 -0
  56. fbuild/packages/arduino_core.py +412 -0
  57. fbuild/packages/cache.py +249 -0
  58. fbuild/packages/downloader.py +366 -0
  59. fbuild/packages/framework_esp32.py +538 -0
  60. fbuild/packages/framework_teensy.py +346 -0
  61. fbuild/packages/github_utils.py +96 -0
  62. fbuild/packages/header_trampoline_cache.py +394 -0
  63. fbuild/packages/library_compiler.py +203 -0
  64. fbuild/packages/library_manager.py +549 -0
  65. fbuild/packages/library_manager_esp32.py +413 -0
  66. fbuild/packages/package.py +163 -0
  67. fbuild/packages/platform_esp32.py +383 -0
  68. fbuild/packages/platform_teensy.py +312 -0
  69. fbuild/packages/platform_utils.py +131 -0
  70. fbuild/packages/platformio_registry.py +325 -0
  71. fbuild/packages/sdk_utils.py +231 -0
  72. fbuild/packages/toolchain.py +436 -0
  73. fbuild/packages/toolchain_binaries.py +196 -0
  74. fbuild/packages/toolchain_esp32.py +484 -0
  75. fbuild/packages/toolchain_metadata.py +185 -0
  76. fbuild/packages/toolchain_teensy.py +404 -0
  77. fbuild/platform_configs/esp32.json +150 -0
  78. fbuild/platform_configs/esp32c2.json +144 -0
  79. fbuild/platform_configs/esp32c3.json +143 -0
  80. fbuild/platform_configs/esp32c5.json +151 -0
  81. fbuild/platform_configs/esp32c6.json +151 -0
  82. fbuild/platform_configs/esp32p4.json +149 -0
  83. fbuild/platform_configs/esp32s3.json +151 -0
  84. fbuild/platform_configs/imxrt1062.json +56 -0
  85. fbuild-1.1.0.dist-info/METADATA +447 -0
  86. fbuild-1.1.0.dist-info/RECORD +93 -0
  87. fbuild-1.1.0.dist-info/WHEEL +5 -0
  88. fbuild-1.1.0.dist-info/entry_points.txt +5 -0
  89. fbuild-1.1.0.dist-info/licenses/LICENSE +21 -0
  90. fbuild-1.1.0.dist-info/top_level.txt +2 -0
  91. fbuild_lint/__init__.py +0 -0
  92. fbuild_lint/ruff_plugins/__init__.py +0 -0
  93. fbuild_lint/ruff_plugins/keyboard_interrupt_checker.py +158 -0
@@ -0,0 +1,574 @@
1
+ """
2
+ AVR compiler wrapper for building Arduino sketches.
3
+
4
+ This module provides a wrapper around avr-gcc and avr-g++ for compiling
5
+ C and C++ source files to object files with sccache support.
6
+ """
7
+
8
+ import subprocess
9
+ import shutil
10
+ from pathlib import Path
11
+ from typing import List, Dict, Optional, TYPE_CHECKING
12
+ from dataclasses import dataclass
13
+
14
+ from .compiler import ICompiler, CompilerError
15
+
16
+ if TYPE_CHECKING:
17
+ from ..daemon.compilation_queue import CompilationJobQueue
18
+
19
+
20
+ @dataclass
21
+ class CompileResult:
22
+ """Result of a compilation operation."""
23
+ success: bool
24
+ object_file: Optional[Path]
25
+ stdout: str
26
+ stderr: str
27
+ returncode: int
28
+
29
+
30
+ class CompilerAVR(ICompiler):
31
+ """
32
+ Wrapper for AVR-GCC compiler.
33
+
34
+ Compiles C and C++ source files to object files using avr-gcc and avr-g++
35
+ with appropriate flags for Arduino builds.
36
+ """
37
+
38
+ def __init__(
39
+ self,
40
+ avr_gcc: Path,
41
+ avr_gpp: Path,
42
+ mcu: str,
43
+ f_cpu: str,
44
+ includes: List[Path],
45
+ defines: Dict[str, str],
46
+ use_sccache: bool = True,
47
+ compilation_queue: Optional['CompilationJobQueue'] = None
48
+ ):
49
+ """
50
+ Initialize compiler.
51
+
52
+ Args:
53
+ avr_gcc: Path to avr-gcc executable
54
+ avr_gpp: Path to avr-g++ executable
55
+ mcu: MCU type (e.g., atmega328p)
56
+ f_cpu: CPU frequency (e.g., 16000000L)
57
+ includes: List of include directories
58
+ defines: Dictionary of preprocessor defines
59
+ use_sccache: Whether to use sccache for caching (default: True)
60
+ compilation_queue: Optional compilation queue for async/parallel compilation
61
+ """
62
+ self.avr_gcc = Path(avr_gcc)
63
+ self.avr_gpp = Path(avr_gpp)
64
+ self.mcu = mcu
65
+ self.f_cpu = f_cpu
66
+ self.includes = [Path(p) for p in includes]
67
+ self.defines = defines
68
+ self.use_sccache = use_sccache
69
+ self.sccache_path: Optional[Path] = None
70
+ self.compilation_queue = compilation_queue
71
+ self.pending_jobs: List[str] = [] # Track async job IDs
72
+
73
+ # Check if sccache is available
74
+ if self.use_sccache:
75
+ sccache_exe = shutil.which("sccache")
76
+ if sccache_exe:
77
+ self.sccache_path = Path(sccache_exe)
78
+ print(f"[sccache] Enabled for AVR compiler: {self.sccache_path}")
79
+ else:
80
+ print("[sccache] Warning: not found in PATH, proceeding without cache")
81
+
82
+ # Verify tools exist
83
+ if not self.avr_gcc.exists():
84
+ raise CompilerError(f"avr-gcc not found: {self.avr_gcc}")
85
+ if not self.avr_gpp.exists():
86
+ raise CompilerError(f"avr-g++ not found: {self.avr_gpp}")
87
+
88
+ def compile_c(
89
+ self,
90
+ source: Path,
91
+ output: Path,
92
+ extra_flags: Optional[List[str]] = None
93
+ ) -> CompileResult:
94
+ """
95
+ Compile C source file.
96
+
97
+ Args:
98
+ source: Path to .c source file
99
+ output: Path to output .o object file
100
+ extra_flags: Additional compiler flags
101
+
102
+ Returns:
103
+ CompileResult with compilation status
104
+ """
105
+ cmd = self._build_c_command(source, output, extra_flags or [])
106
+ return self._execute_compiler(cmd, output)
107
+
108
+ def compile_cpp(
109
+ self,
110
+ source: Path,
111
+ output: Path,
112
+ extra_flags: Optional[List[str]] = None
113
+ ) -> CompileResult:
114
+ """
115
+ Compile C++ source file.
116
+
117
+ Args:
118
+ source: Path to .cpp source file
119
+ output: Path to output .o object file
120
+ extra_flags: Additional compiler flags
121
+
122
+ Returns:
123
+ CompileResult with compilation status
124
+ """
125
+ cmd = self._build_cpp_command(source, output, extra_flags or [])
126
+ return self._execute_compiler(cmd, output)
127
+
128
+ def compile(
129
+ self,
130
+ source: Path,
131
+ output: Path,
132
+ extra_flags: Optional[List[str]] = None
133
+ ) -> CompileResult:
134
+ """
135
+ Compile source file (auto-detects C vs C++).
136
+
137
+ Supports dual-mode operation:
138
+ - If compilation_queue is set: submits job asynchronously and returns deferred result
139
+ - If compilation_queue is None: executes synchronously (legacy mode)
140
+
141
+ Args:
142
+ source: Path to source file
143
+ output: Path to output .o object file
144
+ extra_flags: Additional compiler flags
145
+
146
+ Returns:
147
+ CompileResult with compilation status
148
+ When async mode: returns success=True with deferred=True, actual result via wait_all_jobs()
149
+ When sync mode: returns actual compilation result immediately
150
+ """
151
+ source = Path(source)
152
+
153
+ # Async mode: submit to queue and defer result
154
+ if self.compilation_queue is not None:
155
+ # Build the command based on file type
156
+ if source.suffix == '.c':
157
+ cmd = self._build_c_command(source, output, extra_flags or [])
158
+ elif source.suffix in ['.cpp', '.cxx', '.cc']:
159
+ cmd = self._build_cpp_command(source, output, extra_flags or [])
160
+ else:
161
+ raise CompilerError(f"Unknown source file type: {source.suffix}")
162
+
163
+ # Submit to async compilation queue
164
+ job_id = self._submit_async_compilation(source, output, cmd)
165
+ self.pending_jobs.append(job_id)
166
+
167
+ # Return deferred result (actual result via wait_all_jobs())
168
+ return CompileResult(
169
+ success=True,
170
+ object_file=output, # Optimistic - will be validated in wait_all_jobs()
171
+ stdout="",
172
+ stderr="",
173
+ returncode=0
174
+ )
175
+
176
+ # Sync mode: execute synchronously (legacy behavior)
177
+ if source.suffix == '.c':
178
+ return self.compile_c(source, output, extra_flags)
179
+ elif source.suffix in ['.cpp', '.cxx', '.cc']:
180
+ return self.compile_cpp(source, output, extra_flags)
181
+ else:
182
+ raise CompilerError(f"Unknown source file type: {source.suffix}")
183
+
184
+ def compile_sources(
185
+ self,
186
+ sources: List[Path],
187
+ output_dir: Path,
188
+ extra_flags: Optional[List[str]] = None
189
+ ) -> List[Path]:
190
+ """
191
+ Compile multiple source files.
192
+
193
+ Args:
194
+ sources: List of source files
195
+ output_dir: Output directory for object files
196
+ extra_flags: Additional compiler flags
197
+
198
+ Returns:
199
+ List of compiled object file paths
200
+
201
+ Raises:
202
+ CompilerError: If any compilation fails
203
+ """
204
+ output_dir = Path(output_dir)
205
+ output_dir.mkdir(parents=True, exist_ok=True)
206
+
207
+ object_files = []
208
+
209
+ for source in sources:
210
+ source = Path(source)
211
+ # Generate object file name
212
+ obj_name = source.stem + '.o'
213
+ obj_path = output_dir / obj_name
214
+
215
+ # Compile
216
+ result = self.compile(source, obj_path, extra_flags)
217
+
218
+ if not result.success:
219
+ raise CompilerError(
220
+ f"Failed to compile {source}:\n{result.stderr}"
221
+ )
222
+
223
+ object_files.append(obj_path)
224
+
225
+ return object_files
226
+
227
+ def needs_rebuild(self, source: Path, object_file: Path) -> bool:
228
+ """
229
+ Check if source file needs to be recompiled.
230
+
231
+ Args:
232
+ source: Source file path
233
+ object_file: Object file path
234
+
235
+ Returns:
236
+ True if source is newer than object file
237
+ """
238
+ if not object_file.exists():
239
+ return True
240
+
241
+ source_mtime = source.stat().st_mtime
242
+ obj_mtime = object_file.stat().st_mtime
243
+
244
+ return source_mtime > obj_mtime
245
+
246
+ def _build_c_command(
247
+ self,
248
+ source: Path,
249
+ output: Path,
250
+ extra_flags: List[str]
251
+ ) -> List[str]:
252
+ """Build avr-gcc command for C compilation."""
253
+ cmd = []
254
+ # Prepend sccache if available
255
+ if self.sccache_path:
256
+ cmd.append(str(self.sccache_path))
257
+ cmd.extend([
258
+ str(self.avr_gcc),
259
+ '-c', # Compile only, don't link
260
+ '-g', # Include debug symbols
261
+ '-Os', # Optimize for size
262
+ '-w', # Suppress warnings (matches Arduino)
263
+ '-std=gnu11', # C11 with GNU extensions
264
+ '-ffunction-sections', # Function sections for linker GC
265
+ '-fdata-sections', # Data sections for linker GC
266
+ '-flto', # Link-time optimization
267
+ '-fno-fat-lto-objects', # LTO bytecode only
268
+ f'-mmcu={self.mcu}', # Target MCU
269
+ ])
270
+
271
+ # Add defines
272
+ for key, value in self.defines.items():
273
+ if value:
274
+ cmd.append(f'-D{key}={value}')
275
+ else:
276
+ cmd.append(f'-D{key}')
277
+
278
+ # Add F_CPU explicitly
279
+ if 'F_CPU' not in self.defines:
280
+ cmd.append(f'-DF_CPU={self.f_cpu}')
281
+
282
+ # Add include paths
283
+ for include in self.includes:
284
+ cmd.append(f'-I{include}')
285
+
286
+ # Add extra flags
287
+ cmd.extend(extra_flags)
288
+
289
+ # Add source and output
290
+ cmd.extend([str(source), '-o', str(output)])
291
+
292
+ return cmd
293
+
294
+ def _build_cpp_command(
295
+ self,
296
+ source: Path,
297
+ output: Path,
298
+ extra_flags: List[str]
299
+ ) -> List[str]:
300
+ """Build avr-g++ command for C++ compilation."""
301
+ cmd = []
302
+ # Prepend sccache if available
303
+ if self.sccache_path:
304
+ cmd.append(str(self.sccache_path))
305
+ cmd.extend([
306
+ str(self.avr_gpp),
307
+ '-c', # Compile only, don't link
308
+ '-g', # Include debug symbols
309
+ '-Os', # Optimize for size
310
+ '-w', # Suppress warnings (matches Arduino)
311
+ '-std=gnu++11', # C++11 with GNU extensions
312
+ '-fpermissive', # Allow some non-standard code
313
+ '-fno-exceptions', # Disable exceptions (no room on AVR)
314
+ '-ffunction-sections', # Function sections
315
+ '-fdata-sections', # Data sections
316
+ '-fno-threadsafe-statics', # No thread safety needed
317
+ '-flto', # Link-time optimization
318
+ '-fno-fat-lto-objects', # LTO bytecode only
319
+ f'-mmcu={self.mcu}', # Target MCU
320
+ ])
321
+
322
+ # Add defines
323
+ for key, value in self.defines.items():
324
+ if value:
325
+ cmd.append(f'-D{key}={value}')
326
+ else:
327
+ cmd.append(f'-D{key}')
328
+
329
+ # Add F_CPU explicitly
330
+ if 'F_CPU' not in self.defines:
331
+ cmd.append(f'-DF_CPU={self.f_cpu}')
332
+
333
+ # Add include paths
334
+ for include in self.includes:
335
+ cmd.append(f'-I{include}')
336
+
337
+ # Add extra flags
338
+ cmd.extend(extra_flags)
339
+
340
+ # Add source and output
341
+ cmd.extend([str(source), '-o', str(output)])
342
+
343
+ return cmd
344
+
345
+ def _execute_compiler(
346
+ self,
347
+ cmd: List[str],
348
+ output: Path
349
+ ) -> CompileResult:
350
+ """Execute compiler command."""
351
+ try:
352
+ result = subprocess.run(
353
+ cmd,
354
+ capture_output=True,
355
+ text=True,
356
+ check=False
357
+ )
358
+
359
+ success = result.returncode == 0
360
+ obj_file = output if success and output.exists() else None
361
+
362
+ return CompileResult(
363
+ success=success,
364
+ object_file=obj_file,
365
+ stdout=result.stdout,
366
+ stderr=result.stderr,
367
+ returncode=result.returncode
368
+ )
369
+
370
+ except KeyboardInterrupt as ke:
371
+ from fbuild.interrupt_utils import handle_keyboard_interrupt_properly
372
+ handle_keyboard_interrupt_properly(ke)
373
+ raise # Never reached, but satisfies type checker
374
+ except Exception as e:
375
+ return CompileResult(
376
+ success=False,
377
+ object_file=None,
378
+ stdout='',
379
+ stderr=str(e),
380
+ returncode=-1
381
+ )
382
+
383
+ def _submit_async_compilation(
384
+ self,
385
+ source: Path,
386
+ output: Path,
387
+ cmd: List[str]
388
+ ) -> str:
389
+ """
390
+ Submit compilation job to async queue.
391
+
392
+ Args:
393
+ source: Source file path
394
+ output: Output object file path
395
+ cmd: Full compiler command
396
+
397
+ Returns:
398
+ Job ID for tracking
399
+ """
400
+ import time
401
+ from ..daemon.compilation_queue import CompilationJob
402
+
403
+ job_id = f"compile_{source.stem}_{int(time.time() * 1000000)}"
404
+
405
+ job = CompilationJob(
406
+ job_id=job_id,
407
+ source_path=source,
408
+ output_path=output,
409
+ compiler_cmd=cmd,
410
+ response_file=None # AVR doesn't use response files for includes
411
+ )
412
+
413
+ if self.compilation_queue is None:
414
+ raise CompilerError("Compilation queue not initialized")
415
+ self.compilation_queue.submit_job(job)
416
+ return job_id
417
+
418
+ def wait_all_jobs(self) -> List[CompileResult]:
419
+ """
420
+ Wait for all pending async compilation jobs to complete.
421
+
422
+ This method must be called after using async compilation mode
423
+ to wait for all submitted jobs and collect their results.
424
+
425
+ Returns:
426
+ List of CompileResult for all pending jobs
427
+
428
+ Raises:
429
+ CompilerError: If any compilation fails
430
+ """
431
+ if not self.compilation_queue:
432
+ return []
433
+
434
+ if not self.pending_jobs:
435
+ return []
436
+
437
+ # Wait for all jobs to complete
438
+ self.compilation_queue.wait_for_completion(self.pending_jobs)
439
+
440
+ # Collect results
441
+ results = []
442
+ failed_jobs = []
443
+
444
+ for job_id in self.pending_jobs:
445
+ job = self.compilation_queue.get_job_status(job_id)
446
+
447
+ if job is None:
448
+ # This shouldn't happen
449
+ failed_jobs.append(f"Job {job_id} not found")
450
+ continue
451
+
452
+ result = CompileResult(
453
+ success=(job.state.value == "completed"),
454
+ object_file=job.output_path if job.state.value == "completed" else None,
455
+ stdout=job.stdout,
456
+ stderr=job.stderr,
457
+ returncode=job.result_code or -1
458
+ )
459
+
460
+ results.append(result)
461
+
462
+ if not result.success:
463
+ failed_jobs.append(f"{job.source_path.name}: {job.stderr[:200]}")
464
+
465
+ # Clear pending jobs
466
+ self.pending_jobs.clear()
467
+
468
+ # Raise error if any jobs failed
469
+ if failed_jobs:
470
+ error_msg = f"Compilation failed for {len(failed_jobs)} file(s):\n"
471
+ error_msg += "\n".join(f" - {err}" for err in failed_jobs[:5])
472
+ if len(failed_jobs) > 5:
473
+ error_msg += f"\n ... and {len(failed_jobs) - 5} more"
474
+ raise CompilerError(error_msg)
475
+
476
+ return results
477
+
478
+ def get_statistics(self) -> Dict[str, int]:
479
+ """
480
+ Get compilation statistics from the queue.
481
+
482
+ Returns:
483
+ Dictionary with compilation statistics
484
+ """
485
+ if not self.compilation_queue:
486
+ return {
487
+ "total_jobs": 0,
488
+ "pending": 0,
489
+ "running": 0,
490
+ "completed": 0,
491
+ "failed": 0
492
+ }
493
+
494
+ return self.compilation_queue.get_statistics()
495
+
496
+ # BaseCompiler interface implementation
497
+ def compile_source(
498
+ self,
499
+ source_path: Path,
500
+ output_path: Optional[Path] = None
501
+ ) -> Path:
502
+ """Compile a single source file to object file.
503
+
504
+ Args:
505
+ source_path: Path to .c or .cpp source file
506
+ output_path: Optional path for output .o file
507
+
508
+ Returns:
509
+ Path to generated .o file
510
+
511
+ Raises:
512
+ CompilerError: If compilation fails
513
+ """
514
+ source_path = Path(source_path)
515
+
516
+ # Generate output path if not provided
517
+ if output_path is None:
518
+ output_path = source_path.parent / f"{source_path.stem}.o"
519
+
520
+ # Compile the source
521
+ result = self.compile(source_path, output_path)
522
+
523
+ if not result.success:
524
+ raise CompilerError(
525
+ f"Failed to compile {source_path}:\n{result.stderr}"
526
+ )
527
+
528
+ return output_path
529
+
530
+ def get_include_paths(self) -> List[Path]:
531
+ """Get all include paths needed for compilation.
532
+
533
+ Returns:
534
+ List of include directory paths
535
+ """
536
+ return self.includes
537
+
538
+ def get_compile_flags(self) -> Dict[str, List[str]]:
539
+ """Get compilation flags.
540
+
541
+ Returns:
542
+ Dictionary with 'cflags', 'cxxflags', and 'common' keys
543
+ """
544
+ # Common flags for both C and C++
545
+ common = [
546
+ '-c',
547
+ '-g',
548
+ '-Os',
549
+ '-w',
550
+ '-ffunction-sections',
551
+ '-fdata-sections',
552
+ '-flto',
553
+ '-fno-fat-lto-objects',
554
+ f'-mmcu={self.mcu}',
555
+ ]
556
+
557
+ # C-specific flags
558
+ cflags = [
559
+ '-std=gnu11',
560
+ ]
561
+
562
+ # C++-specific flags
563
+ cxxflags = [
564
+ '-std=gnu++11',
565
+ '-fpermissive',
566
+ '-fno-exceptions',
567
+ '-fno-threadsafe-statics',
568
+ ]
569
+
570
+ return {
571
+ 'common': common,
572
+ 'cflags': cflags,
573
+ 'cxxflags': cxxflags,
574
+ }