core.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. # -*- coding: utf-8 -*-
  2. """
  3. Core module for RT-Thread build system.
  4. This module provides the central BuildContext class that manages the build state
  5. and coordinates between different components.
  6. """
  7. import os
  8. import logging
  9. from typing import Dict, List, Optional, Any
  10. from dataclasses import dataclass, field
  11. from .config import ConfigManager
  12. from .project import ProjectRegistry
  13. from .toolchain import ToolchainManager
  14. from .generator import GeneratorRegistry
  15. from .utils import PathService
  16. class BuildContext:
  17. """
  18. Central build context that manages all build-related state.
  19. This class replaces the global variables in building.py with a proper
  20. object-oriented design while maintaining compatibility.
  21. """
  22. # Class variable to store the current context (for backward compatibility)
  23. _current_context: Optional['BuildContext'] = None
  24. def __init__(self, root_directory: str):
  25. """
  26. Initialize build context.
  27. Args:
  28. root_directory: RT-Thread root directory path
  29. """
  30. self.root_directory = os.path.abspath(root_directory)
  31. self.bsp_directory = os.getcwd()
  32. # Initialize managers
  33. self.config_manager = ConfigManager()
  34. self.project_registry = ProjectRegistry()
  35. self.toolchain_manager = ToolchainManager()
  36. self.generator_registry = GeneratorRegistry()
  37. self.path_service = PathService(self.bsp_directory)
  38. # Build environment
  39. self.environment = None
  40. self.build_options = {}
  41. # Logging
  42. self.logger = self._setup_logger()
  43. # Set as current context
  44. BuildContext._current_context = self
  45. @classmethod
  46. def get_current(cls) -> Optional['BuildContext']:
  47. """Get the current build context."""
  48. return cls._current_context
  49. @classmethod
  50. def set_current(cls, context: Optional['BuildContext']) -> None:
  51. """Set the current build context."""
  52. cls._current_context = context
  53. def _setup_logger(self) -> logging.Logger:
  54. """Setup logger for build system."""
  55. logger = logging.getLogger('rtthread.build')
  56. if not logger.handlers:
  57. handler = logging.StreamHandler()
  58. formatter = logging.Formatter('[%(levelname)s] %(message)s')
  59. handler.setFormatter(formatter)
  60. logger.addHandler(handler)
  61. logger.setLevel(logging.INFO)
  62. return logger
  63. def prepare_environment(self, env) -> None:
  64. """
  65. Prepare the build environment.
  66. Args:
  67. env: SCons Environment object
  68. """
  69. self.environment = env
  70. # Set environment variables
  71. env['RTT_ROOT'] = self.root_directory
  72. env['BSP_ROOT'] = self.bsp_directory
  73. # Add to Python path
  74. import sys
  75. tools_path = os.path.join(self.root_directory, 'tools')
  76. if tools_path not in sys.path:
  77. sys.path.insert(0, tools_path)
  78. self.logger.debug(f"Prepared environment with RTT_ROOT={self.root_directory}")
  79. def load_configuration(self, config_file: str = 'rtconfig.h') -> None:
  80. """
  81. Load configuration from rtconfig.h.
  82. Args:
  83. config_file: Path to configuration file
  84. """
  85. config_path = os.path.join(self.bsp_directory, config_file)
  86. if os.path.exists(config_path):
  87. self.config_manager.load_from_file(config_path)
  88. self.build_options = self.config_manager.get_all_options()
  89. self.logger.info(f"Loaded configuration from {config_file}")
  90. else:
  91. self.logger.warning(f"Configuration file {config_file} not found")
  92. def get_dependency(self, depend: Any) -> bool:
  93. """
  94. Check if dependency is satisfied.
  95. Args:
  96. depend: Dependency name or list of names
  97. Returns:
  98. True if dependency is satisfied
  99. """
  100. return self.config_manager.get_dependency(depend)
  101. def register_project_group(self, group) -> None:
  102. """
  103. Register a project group.
  104. Args:
  105. group: ProjectGroup instance
  106. """
  107. self.project_registry.register_group(group)
  108. def merge_groups(self) -> List:
  109. """
  110. Merge all registered project groups.
  111. Returns:
  112. List of build objects
  113. """
  114. return self.project_registry.merge_groups(self.environment)
  115. @dataclass
  116. class BuildOptions:
  117. """Build options container."""
  118. verbose: bool = False
  119. strict: bool = False
  120. target: Optional[str] = None
  121. jobs: int = 1
  122. clean: bool = False
  123. @dataclass
  124. class ProjectInfo:
  125. """Project information for generators."""
  126. name: str = "rtthread"
  127. target_name: str = "rtthread.elf"
  128. # File collections
  129. source_files: List[str] = field(default_factory=list)
  130. include_paths: List[str] = field(default_factory=list)
  131. defines: Dict[str, str] = field(default_factory=dict)
  132. # Compiler options
  133. cflags: str = ""
  134. cxxflags: str = ""
  135. asflags: str = ""
  136. ldflags: str = ""
  137. # Libraries
  138. libs: List[str] = field(default_factory=list)
  139. lib_paths: List[str] = field(default_factory=list)