generate_config_from_multiple_build_logs
Generate delphi_config.toml files from multiple IDE build logs, producing separate platform-specific configs or a unified config for different configurations and platforms.
Instructions
Generate delphi_config.toml file from multiple IDE build logs for different configurations and platforms. By default, creates separate platform-specific config files (e.g., delphi_config_win32.toml, delphi_config_win64.toml). Use this when you have build logs from multiple configurations (Debug/Release) and/or platforms (Win32/Win64/Linux64/Android/Android64).
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| build_log_paths | Yes | Array of absolute paths to IDE build log files (e.g., Debug-Win32, Release-Win64, Debug-Linux64, Debug-Android64) | |
| output_config_path | No | Output path for unified config file. Only used when generate_separate_files=False. | delphi_config.toml |
| generate_separate_files | No | Generate separate platform-specific config files (default). Set to false for a single unified config. | |
| output_dir | No | Output directory for generated platform-specific files. Defaults to current directory. | . |
| use_env_vars | No | Replace user paths with ${USERNAME} environment variable |
Implementation Reference
- main.py:329-361 (handler)The async handler function that executes the generate_config_from_multiple_build_logs tool. It extracts arguments from the tool call, instantiates MultiConfigGenerator, calls generate_from_build_logs(), and returns JSON result.
async def handle_generate_multi_config(arguments: dict) -> str: """Handle generate_config_from_multiple_build_logs tool invocation. Args: arguments: Tool arguments Returns: JSON string with generation result """ import json # Extract arguments (convert WSL paths when running on Windows) build_log_paths = [convert_wsl_to_windows_path(p) for p in arguments["build_log_paths"]] output_config_path_str = arguments.get("output_config_path") output_config_path = Path(convert_wsl_to_windows_path(output_config_path_str)) if output_config_path_str else None generate_separate_files = arguments.get("generate_separate_files", True) output_dir_str = arguments.get("output_dir", ".") output_dir = Path(convert_wsl_to_windows_path(output_dir_str)) use_env_vars = arguments.get("use_env_vars", True) # Initialize generator generator = MultiConfigGenerator(use_env_vars=use_env_vars) # Generate config from multiple logs result = generator.generate_from_build_logs( build_log_paths=build_log_paths, output_path=output_config_path, generate_separate_files=generate_separate_files, output_dir=output_dir, ) # Convert to JSON return json.dumps(result.model_dump(), indent=2) - main.py:117-157 (registration)The Tool definition object registering the tool with the MCP server, including its name, description, and JSON input schema.
GENERATE_MULTI_CONFIG_TOOL = Tool( name="generate_config_from_multiple_build_logs", description=( "Generate delphi_config.toml file from multiple IDE build logs for different configurations " "and platforms. By default, creates separate platform-specific config files " "(e.g., delphi_config_win32.toml, delphi_config_win64.toml). " "Use this when you have build logs from multiple configurations (Debug/Release) and/or " "platforms (Win32/Win64/Linux64/Android/Android64)." ), inputSchema={ "type": "object", "properties": { "build_log_paths": { "type": "array", "items": {"type": "string"}, "description": "Array of absolute paths to IDE build log files (e.g., Debug-Win32, Release-Win64, Debug-Linux64, Debug-Android64)", }, "output_config_path": { "type": "string", "description": "Output path for unified config file. Only used when generate_separate_files=False.", "default": "delphi_config.toml", }, "generate_separate_files": { "type": "boolean", "description": "Generate separate platform-specific config files (default). Set to false for a single unified config.", "default": True, }, "output_dir": { "type": "string", "description": "Output directory for generated platform-specific files. Defaults to current directory.", "default": ".", }, "use_env_vars": { "type": "boolean", "description": "Replace user paths with ${USERNAME} environment variable", "default": True, }, }, "required": ["build_log_paths"], }, ) - main.py:212-214 (registration)The call_tool dispatcher that routes the tool name to the handler function.
elif name == "generate_config_from_multiple_build_logs": result = await handle_generate_multi_config(arguments) return [TextContent(type="text", text=result)] - main.py:195-197 (registration)The list_tools function that exposes the tool definition to the MCP client.
async def list_tools() -> list[Tool]: """List available tools.""" return [COMPILE_TOOL, GENERATE_CONFIG_TOOL, GENERATE_MULTI_CONFIG_TOOL, EXTEND_CONFIG_TOOL] - src/multi_config_generator.py:40-182 (helper)The core logic: MultiConfigGenerator.generate_from_build_logs() method. Parses multiple build logs, then either generates separate platform-specific configs (Windows gets minimal, cross-compile gets full) or a single unified config.
def generate_from_build_logs( self, build_log_paths: list[str], output_path: Optional[Path] = None, generate_separate_files: bool = True, output_dir: Optional[Path] = None, ) -> MultiConfigGenerationResult: """Generate configuration from multiple build log files. Args: build_log_paths: List of paths to IDE build log files output_path: Path where to save the generated config. Used when generate_separate_files=False. generate_separate_files: If True (default), generates separate platform-specific config files (e.g., delphi_config_win32.toml, delphi_config_win64.toml). Set to False to generate a single unified config. output_dir: Directory for output files when generate_separate_files=True. Defaults to current directory. Returns: MultiConfigGenerationResult with generation statistics Raises: FileNotFoundError: If any build log doesn't exist ValueError: If no build logs can be parsed """ # Parse all build logs parsed_logs: dict[tuple[str, str], BuildLogInfo] = {} log_entries: list[BuildLogEntry] = [] for log_path_str in build_log_paths: log_path = Path(log_path_str) if not log_path.exists(): raise FileNotFoundError(f"Build log not found: {log_path}") parser = BuildLogParser(log_path) # Parse the log content log_info = parser.parse() # Get config and platform from parsed log config = log_info.build_config platform = log_info.platform.value auto_detected = True # Values are detected from compiler command # Normalize config and platform names config = self._normalize_config(config) platform = self._normalize_platform(platform) # Store parsed log info keyed by (config, platform) key = (config, platform) if key in parsed_logs: # If we already have this config/platform, merge paths self._merge_log_info(parsed_logs[key], log_info) else: parsed_logs[key] = log_info log_entries.append(BuildLogEntry( path=str(log_path), config=config, platform=platform, auto_detected=auto_detected, )) if not parsed_logs: raise ValueError("No build logs could be parsed successfully") # Determine output directory if output_dir is None: output_dir = Path(".") generated_files: list[str] = [] if generate_separate_files: # Generate separate platform-specific config files. # All Windows platform logs are grouped into one minimal delphi_config.toml. # Cross-compile platforms (Linux64, Android, Android64) each get their own file. platforms = set(k[1] for k in parsed_logs.keys()) windows_platforms_found = platforms & WINDOWS_PLATFORMS crosscompile_platforms = platforms - WINDOWS_PLATFORMS if windows_platforms_found: # Collect all Windows logs; pick the first one as representative windows_logs = { k: v for k, v in parsed_logs.items() if k[1] in WINDOWS_PLATFORMS } first_windows_log = next(iter(windows_logs.values())) # Generate minimal config: only [delphi] section + MSBuild comment toml_content = self._generate_windows_minimal_toml(first_windows_log) windows_output_path = output_dir / "delphi_config.toml" with open(windows_output_path, "w", encoding="utf-8") as f: f.write(toml_content) generated_files.append(str(windows_output_path.absolute())) for platform in sorted(crosscompile_platforms): # Get logs for this platform only platform_logs = { k: v for k, v in parsed_logs.items() if k[1] == platform } # Generate TOML content for this platform toml_content = self._generate_toml(platform_logs) # Write to platform-specific file platform_filename = get_platform_config_filename(platform) platform_output_path = output_dir / platform_filename with open(platform_output_path, "w", encoding="utf-8") as f: f.write(toml_content) generated_files.append(str(platform_output_path.absolute())) # config_file_path will contain comma-separated list of files config_file_path = ", ".join(generated_files) message = f"Generated {len(generated_files)} platform-specific config file(s) from {len(build_log_paths)} build log(s)" else: # Generate single unified config if output_path is None: output_path = output_dir / "delphi_config.toml" toml_content = self._generate_toml(parsed_logs) # Write to file with open(output_path, "w", encoding="utf-8") as f: f.write(toml_content) config_file_path = str(output_path.absolute()) generated_files.append(config_file_path) message = f"Configuration file generated successfully from {len(build_log_paths)} build log(s)" # Prepare statistics statistics = { "build_logs_parsed": len(build_log_paths), "configs_found": list(set(e.config for e in log_entries)), "platforms_found": list(set(e.platform for e in log_entries)), "total_library_paths": self._count_total_paths(parsed_logs), "files_generated": generated_files, } return MultiConfigGenerationResult( success=True, config_file_path=config_file_path, build_logs_processed=log_entries, statistics=statistics, message=message, )