IncludeCPP 3.7.3__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.
- includecpp/__init__.py +59 -0
- includecpp/__init__.pyi +255 -0
- includecpp/__main__.py +4 -0
- includecpp/cli/__init__.py +4 -0
- includecpp/cli/commands.py +8270 -0
- includecpp/cli/config_parser.py +127 -0
- includecpp/core/__init__.py +19 -0
- includecpp/core/ai_integration.py +2132 -0
- includecpp/core/build_manager.py +2416 -0
- includecpp/core/cpp_api.py +376 -0
- includecpp/core/cpp_api.pyi +95 -0
- includecpp/core/cppy_converter.py +3448 -0
- includecpp/core/cssl/CSSL_DOCUMENTATION.md +2075 -0
- includecpp/core/cssl/__init__.py +42 -0
- includecpp/core/cssl/cssl_builtins.py +2271 -0
- includecpp/core/cssl/cssl_builtins.pyi +1393 -0
- includecpp/core/cssl/cssl_events.py +621 -0
- includecpp/core/cssl/cssl_modules.py +2803 -0
- includecpp/core/cssl/cssl_parser.py +2575 -0
- includecpp/core/cssl/cssl_runtime.py +3051 -0
- includecpp/core/cssl/cssl_syntax.py +488 -0
- includecpp/core/cssl/cssl_types.py +1512 -0
- includecpp/core/cssl_bridge.py +882 -0
- includecpp/core/cssl_bridge.pyi +488 -0
- includecpp/core/error_catalog.py +802 -0
- includecpp/core/error_formatter.py +1016 -0
- includecpp/core/exceptions.py +97 -0
- includecpp/core/path_discovery.py +77 -0
- includecpp/core/project_ui.py +3370 -0
- includecpp/core/settings_ui.py +326 -0
- includecpp/generator/__init__.py +1 -0
- includecpp/generator/parser.cpp +1903 -0
- includecpp/generator/parser.h +281 -0
- includecpp/generator/type_resolver.cpp +363 -0
- includecpp/generator/type_resolver.h +68 -0
- includecpp/py.typed +0 -0
- includecpp/templates/cpp.proj.template +18 -0
- includecpp/vscode/__init__.py +1 -0
- includecpp/vscode/cssl/__init__.py +1 -0
- includecpp/vscode/cssl/language-configuration.json +38 -0
- includecpp/vscode/cssl/package.json +50 -0
- includecpp/vscode/cssl/snippets/cssl.snippets.json +1080 -0
- includecpp/vscode/cssl/syntaxes/cssl.tmLanguage.json +341 -0
- includecpp-3.7.3.dist-info/METADATA +1076 -0
- includecpp-3.7.3.dist-info/RECORD +49 -0
- includecpp-3.7.3.dist-info/WHEEL +5 -0
- includecpp-3.7.3.dist-info/entry_points.txt +2 -0
- includecpp-3.7.3.dist-info/licenses/LICENSE +21 -0
- includecpp-3.7.3.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,1016 @@
|
|
|
1
|
+
"""Enhanced error formatting for IncludeCPP build system.
|
|
2
|
+
|
|
3
|
+
Provides user-friendly error messages with context and suggestions.
|
|
4
|
+
Error messages are always printed LAST so users who only read the end still see the fix.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import List, Optional, Dict
|
|
8
|
+
import re
|
|
9
|
+
import sys
|
|
10
|
+
|
|
11
|
+
from .error_catalog import ERROR_CATALOG, get_error_message, format_error_box, format_unknown_error
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _supports_unicode():
|
|
15
|
+
"""Check if terminal supports Unicode output."""
|
|
16
|
+
if sys.platform == 'win32':
|
|
17
|
+
try:
|
|
18
|
+
'✓✗❌→←'.encode(sys.stdout.encoding or 'utf-8')
|
|
19
|
+
return True
|
|
20
|
+
except (UnicodeEncodeError, LookupError, AttributeError):
|
|
21
|
+
return False
|
|
22
|
+
return True
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
_UNICODE_OK = _supports_unicode()
|
|
26
|
+
|
|
27
|
+
# Box drawing characters with ASCII fallbacks
|
|
28
|
+
BOX_TL = '╔' if _UNICODE_OK else '+'
|
|
29
|
+
BOX_TR = '╗' if _UNICODE_OK else '+'
|
|
30
|
+
BOX_BL = '╚' if _UNICODE_OK else '+'
|
|
31
|
+
BOX_BR = '╝' if _UNICODE_OK else '+'
|
|
32
|
+
BOX_H = '═' if _UNICODE_OK else '='
|
|
33
|
+
BOX_V = '║' if _UNICODE_OK else '|'
|
|
34
|
+
BULLET = '•' if _UNICODE_OK else '*'
|
|
35
|
+
ARROW = '→' if _UNICODE_OK else '->'
|
|
36
|
+
DBLARROW = '↔' if _UNICODE_OK else '<->'
|
|
37
|
+
CHECK = '✓' if _UNICODE_OK else '[OK]'
|
|
38
|
+
CROSS = '✗' if _UNICODE_OK else '[X]'
|
|
39
|
+
ERR_CROSS = '❌' if _UNICODE_OK else '[X]'
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class BuildErrorFormatter:
|
|
43
|
+
"""Format C++ compilation errors with context and suggestions."""
|
|
44
|
+
|
|
45
|
+
@staticmethod
|
|
46
|
+
def format_type_mismatch(expected: str, got: str, location: str) -> str:
|
|
47
|
+
"""Format type mismatch error with suggestions.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
expected: Expected type string
|
|
51
|
+
got: Actual type string
|
|
52
|
+
location: Location of error (file:line)
|
|
53
|
+
|
|
54
|
+
Returns:
|
|
55
|
+
Formatted error message with suggestions
|
|
56
|
+
"""
|
|
57
|
+
h_line = BOX_H * 62
|
|
58
|
+
return f"""
|
|
59
|
+
{BOX_TL}{h_line}{BOX_TR}
|
|
60
|
+
{BOX_V} TYPE MISMATCH ERROR {BOX_V}
|
|
61
|
+
{BOX_BL}{h_line}{BOX_BR}
|
|
62
|
+
|
|
63
|
+
Location: {location}
|
|
64
|
+
|
|
65
|
+
Expected: {expected}
|
|
66
|
+
Got: {got}
|
|
67
|
+
|
|
68
|
+
Suggestions:
|
|
69
|
+
{BULLET} Check if you're passing the correct type
|
|
70
|
+
{BULLET} For struct {ARROW} dict: use struct_instance.to_dict()
|
|
71
|
+
{BULLET} For dict {ARROW} struct: use StructName.from_dict(dict_instance)
|
|
72
|
+
{BULLET} For vector conversions: Python list {DBLARROW} std::vector is automatic
|
|
73
|
+
|
|
74
|
+
Type Conversion Examples:
|
|
75
|
+
# Struct to dict
|
|
76
|
+
point_dict = point.to_dict()
|
|
77
|
+
|
|
78
|
+
# Dict to struct
|
|
79
|
+
point = Point.from_dict({{"x": 10, "y": 20}})
|
|
80
|
+
|
|
81
|
+
# Vector of structs
|
|
82
|
+
points: List[Point] = [...] # Automatically converts
|
|
83
|
+
"""
|
|
84
|
+
|
|
85
|
+
@staticmethod
|
|
86
|
+
def format_dependency_error(module: str, missing_dep: str) -> str:
|
|
87
|
+
"""Format missing dependency error.
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
module: Module name that has missing dependency
|
|
91
|
+
missing_dep: Name of missing dependency module
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
Formatted error message with fix instructions
|
|
95
|
+
"""
|
|
96
|
+
return f"""
|
|
97
|
+
╔══════════════════════════════════════════════════════════════╗
|
|
98
|
+
║ DEPENDENCY ERROR ║
|
|
99
|
+
╚══════════════════════════════════════════════════════════════╝
|
|
100
|
+
|
|
101
|
+
Module: {module}
|
|
102
|
+
Missing Dependency: {missing_dep}
|
|
103
|
+
|
|
104
|
+
To Fix:
|
|
105
|
+
1. Add dependency to {module}.cp:
|
|
106
|
+
|
|
107
|
+
SOURCE(path/to/{module}.cpp) {module}
|
|
108
|
+
DEPENDS({missing_dep})
|
|
109
|
+
PUBLIC(
|
|
110
|
+
...
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
2. Ensure {missing_dep} module exists in plugins/ directory
|
|
114
|
+
|
|
115
|
+
3. Rebuild:
|
|
116
|
+
python -m includecpp rebuild --verbose
|
|
117
|
+
|
|
118
|
+
Dependency Chain:
|
|
119
|
+
{{module}} {ARROW} {{missing_dep}}
|
|
120
|
+
"""
|
|
121
|
+
|
|
122
|
+
@staticmethod
|
|
123
|
+
def format_circular_dependency(cycle: List[str]) -> str:
|
|
124
|
+
"""Format circular dependency error.
|
|
125
|
+
|
|
126
|
+
Args:
|
|
127
|
+
cycle: List of module names forming the cycle
|
|
128
|
+
|
|
129
|
+
Returns:
|
|
130
|
+
Formatted error message with refactoring suggestions
|
|
131
|
+
"""
|
|
132
|
+
cycle_display = f" {ARROW} ".join(cycle + [cycle[0]])
|
|
133
|
+
h_line = BOX_H * 62
|
|
134
|
+
return f"""
|
|
135
|
+
{BOX_TL}{h_line}{BOX_TR}
|
|
136
|
+
{BOX_V} CIRCULAR DEPENDENCY DETECTED {BOX_V}
|
|
137
|
+
{BOX_BL}{h_line}{BOX_BR}
|
|
138
|
+
|
|
139
|
+
Dependency Cycle:
|
|
140
|
+
{cycle_display}
|
|
141
|
+
|
|
142
|
+
To Fix:
|
|
143
|
+
{BULLET} Refactor modules to remove circular dependency
|
|
144
|
+
{BULLET} Use forward declarations where possible
|
|
145
|
+
{BULLET} Consider merging modules if they're tightly coupled
|
|
146
|
+
{BULLET} Create a third module for shared types
|
|
147
|
+
|
|
148
|
+
Example Refactoring:
|
|
149
|
+
Before:
|
|
150
|
+
module_a {ARROW} module_b {ARROW} module_a {ERR_CROSS}
|
|
151
|
+
|
|
152
|
+
After:
|
|
153
|
+
module_a {ARROW} shared_types
|
|
154
|
+
module_b {ARROW} shared_types {CHECK}
|
|
155
|
+
"""
|
|
156
|
+
|
|
157
|
+
@staticmethod
|
|
158
|
+
def format_module_not_found(module: str, available: List[str]) -> str:
|
|
159
|
+
"""Format module not found error.
|
|
160
|
+
|
|
161
|
+
Args:
|
|
162
|
+
module: Requested module name
|
|
163
|
+
available: List of available module names
|
|
164
|
+
|
|
165
|
+
Returns:
|
|
166
|
+
Formatted error message
|
|
167
|
+
"""
|
|
168
|
+
return f"""
|
|
169
|
+
╔══════════════════════════════════════════════════════════════╗
|
|
170
|
+
║ MODULE NOT FOUND ║
|
|
171
|
+
╚══════════════════════════════════════════════════════════════╝
|
|
172
|
+
|
|
173
|
+
Requested: {module}
|
|
174
|
+
|
|
175
|
+
Available modules:
|
|
176
|
+
{', '.join(available) if available else '(none)'}
|
|
177
|
+
|
|
178
|
+
To Fix:
|
|
179
|
+
• Check spelling of module name
|
|
180
|
+
• Ensure {module}.cp exists in plugins/ directory
|
|
181
|
+
• Run 'python -m includecpp rebuild' to build all modules
|
|
182
|
+
• Run 'python -m includecpp list' to see available modules
|
|
183
|
+
"""
|
|
184
|
+
|
|
185
|
+
@staticmethod
|
|
186
|
+
def format_build_failed(module: str, reason: str) -> str:
|
|
187
|
+
"""Format general build failure error.
|
|
188
|
+
|
|
189
|
+
Args:
|
|
190
|
+
module: Module name that failed to build
|
|
191
|
+
reason: Reason for failure
|
|
192
|
+
|
|
193
|
+
Returns:
|
|
194
|
+
Formatted error message
|
|
195
|
+
"""
|
|
196
|
+
return f"""
|
|
197
|
+
╔══════════════════════════════════════════════════════════════╗
|
|
198
|
+
║ BUILD FAILED ║
|
|
199
|
+
╚══════════════════════════════════════════════════════════════╝
|
|
200
|
+
|
|
201
|
+
Module: {module}
|
|
202
|
+
|
|
203
|
+
Reason:
|
|
204
|
+
{reason}
|
|
205
|
+
|
|
206
|
+
To Debug:
|
|
207
|
+
• Run with --verbose flag for detailed output
|
|
208
|
+
• Check {module}.cpp for syntax errors
|
|
209
|
+
• Verify all includes are available
|
|
210
|
+
• Check build log in AppData/IncludeCPP/
|
|
211
|
+
"""
|
|
212
|
+
|
|
213
|
+
@staticmethod
|
|
214
|
+
def parse_compiler_error(stderr: str, module_name: str) -> str:
|
|
215
|
+
"""Parse C++ compiler errors and add helpful context.
|
|
216
|
+
|
|
217
|
+
Args:
|
|
218
|
+
stderr: Standard error output from compiler
|
|
219
|
+
module_name: Name of module being compiled
|
|
220
|
+
|
|
221
|
+
Returns:
|
|
222
|
+
Formatted error messages with context
|
|
223
|
+
"""
|
|
224
|
+
lines = stderr.split('\n')
|
|
225
|
+
formatted = []
|
|
226
|
+
error_count = 0
|
|
227
|
+
|
|
228
|
+
for line in lines:
|
|
229
|
+
# GCC/Clang format: file:line:col: error: message
|
|
230
|
+
if ': error:' in line:
|
|
231
|
+
error_count += 1
|
|
232
|
+
parts = line.split(':')
|
|
233
|
+
|
|
234
|
+
if len(parts) >= 4:
|
|
235
|
+
file_path = parts[0].strip()
|
|
236
|
+
line_num = parts[1].strip() if parts[1].strip().isdigit() else "?"
|
|
237
|
+
error_msg = ':'.join(parts[3:]).strip()
|
|
238
|
+
|
|
239
|
+
formatted.append("")
|
|
240
|
+
formatted.append("╔══════════════════════════════════════════╗")
|
|
241
|
+
formatted.append("║ COMPILATION ERROR ║")
|
|
242
|
+
formatted.append("╚══════════════════════════════════════════╝")
|
|
243
|
+
formatted.append("")
|
|
244
|
+
formatted.append(f"Module: {module_name}")
|
|
245
|
+
formatted.append(f"File: {file_path}")
|
|
246
|
+
formatted.append(f"Line: {line_num}")
|
|
247
|
+
formatted.append(f"Error: {error_msg}")
|
|
248
|
+
formatted.append("")
|
|
249
|
+
|
|
250
|
+
# Add context based on error type
|
|
251
|
+
if "undefined reference" in error_msg.lower() or "unresolved external" in error_msg.lower():
|
|
252
|
+
formatted.append("Suggestion:")
|
|
253
|
+
formatted.append(" • Check if function/class is declared in header")
|
|
254
|
+
formatted.append(" • Verify all source files are listed in .cp file")
|
|
255
|
+
formatted.append(" • Check for missing DEPENDS() if using types from other modules")
|
|
256
|
+
formatted.append(" • Ensure function is in 'includecpp' namespace")
|
|
257
|
+
|
|
258
|
+
elif "no matching function" in error_msg.lower() or "no member named" in error_msg.lower():
|
|
259
|
+
formatted.append("Suggestion:")
|
|
260
|
+
formatted.append(" • Check parameter types match function signature")
|
|
261
|
+
formatted.append(" • Verify template instantiations are correct")
|
|
262
|
+
formatted.append(" • Check for const/reference qualifiers")
|
|
263
|
+
formatted.append(" • Ensure all required headers are included")
|
|
264
|
+
|
|
265
|
+
elif "expected" in error_msg.lower() and "before" in error_msg.lower():
|
|
266
|
+
formatted.append("Suggestion:")
|
|
267
|
+
formatted.append(" • Check for missing semicolons")
|
|
268
|
+
formatted.append(" • Verify bracket/parenthesis matching")
|
|
269
|
+
formatted.append(" • Check for typos in type names")
|
|
270
|
+
|
|
271
|
+
elif "does not name a type" in error_msg.lower():
|
|
272
|
+
formatted.append("Suggestion:")
|
|
273
|
+
formatted.append(" • Check if type is defined before use")
|
|
274
|
+
formatted.append(" • Verify #include statements are correct")
|
|
275
|
+
formatted.append(" • Check namespace qualifications (std::, includecpp::)")
|
|
276
|
+
|
|
277
|
+
elif "incomplete type" in error_msg.lower():
|
|
278
|
+
formatted.append("Suggestion:")
|
|
279
|
+
formatted.append(" • Add forward declaration or full type definition")
|
|
280
|
+
formatted.append(" • Check if header file is included")
|
|
281
|
+
formatted.append(" • Verify struct/class definition is complete")
|
|
282
|
+
|
|
283
|
+
# MSVC format: file(line): error C####: message
|
|
284
|
+
elif re.match(r'.*\(\d+\):\s*error\s+C\d+:', line):
|
|
285
|
+
error_count += 1
|
|
286
|
+
match = re.match(r'(.*)\((\d+)\):\s*error\s+C\d+:\s*(.*)', line)
|
|
287
|
+
if match:
|
|
288
|
+
file_path = match.group(1).strip()
|
|
289
|
+
line_num = match.group(2)
|
|
290
|
+
error_msg = match.group(3).strip()
|
|
291
|
+
|
|
292
|
+
formatted.append("")
|
|
293
|
+
formatted.append("╔══════════════════════════════════════════╗")
|
|
294
|
+
formatted.append("║ COMPILATION ERROR ║")
|
|
295
|
+
formatted.append("╚══════════════════════════════════════════╝")
|
|
296
|
+
formatted.append("")
|
|
297
|
+
formatted.append(f"Module: {module_name}")
|
|
298
|
+
formatted.append(f"File: {file_path}")
|
|
299
|
+
formatted.append(f"Line: {line_num}")
|
|
300
|
+
formatted.append(f"Error: {error_msg}")
|
|
301
|
+
formatted.append("")
|
|
302
|
+
|
|
303
|
+
# Warning lines - pass through but mark them
|
|
304
|
+
elif ': warning:' in line or 'warning C' in line:
|
|
305
|
+
if not formatted or formatted[-1] != "":
|
|
306
|
+
formatted.append("")
|
|
307
|
+
formatted.append(f"⚠️ {line}")
|
|
308
|
+
|
|
309
|
+
# Note lines
|
|
310
|
+
elif ': note:' in line:
|
|
311
|
+
formatted.append(f"ℹ️ {line}")
|
|
312
|
+
|
|
313
|
+
# Empty lines
|
|
314
|
+
elif not line.strip():
|
|
315
|
+
if formatted and formatted[-1] != "":
|
|
316
|
+
formatted.append("")
|
|
317
|
+
|
|
318
|
+
if error_count > 0:
|
|
319
|
+
header = [
|
|
320
|
+
"",
|
|
321
|
+
"═" * 60,
|
|
322
|
+
f"COMPILATION FAILED: {error_count} error(s) in {module_name}",
|
|
323
|
+
"═" * 60,
|
|
324
|
+
""
|
|
325
|
+
]
|
|
326
|
+
formatted = header + formatted
|
|
327
|
+
|
|
328
|
+
return '\n'.join(formatted) if formatted else stderr
|
|
329
|
+
|
|
330
|
+
@staticmethod
|
|
331
|
+
def format_cmake_error(stderr: str, module_name: str) -> str:
|
|
332
|
+
"""Format CMake configuration errors.
|
|
333
|
+
|
|
334
|
+
Args:
|
|
335
|
+
stderr: CMake error output
|
|
336
|
+
module_name: Name of module being configured
|
|
337
|
+
|
|
338
|
+
Returns:
|
|
339
|
+
Formatted error message
|
|
340
|
+
"""
|
|
341
|
+
return f"""
|
|
342
|
+
╔══════════════════════════════════════════════════════════════╗
|
|
343
|
+
║ CMAKE CONFIGURATION ERROR ║
|
|
344
|
+
╚══════════════════════════════════════════════════════════════╝
|
|
345
|
+
|
|
346
|
+
Module: {module_name}
|
|
347
|
+
|
|
348
|
+
CMake Output:
|
|
349
|
+
{stderr}
|
|
350
|
+
|
|
351
|
+
Common Issues:
|
|
352
|
+
• CMake not installed or not in PATH
|
|
353
|
+
• C++ compiler not found (install g++, clang++, or MSVC)
|
|
354
|
+
• pybind11 not found (auto-installed, check network)
|
|
355
|
+
• Python development headers missing
|
|
356
|
+
|
|
357
|
+
To Fix:
|
|
358
|
+
• Install CMake 3.15+ from cmake.org
|
|
359
|
+
• Install C++ compiler:
|
|
360
|
+
- Windows: Visual Studio or MinGW
|
|
361
|
+
- Linux: apt-get install g++ cmake python3-dev
|
|
362
|
+
- macOS: xcode-select --install
|
|
363
|
+
• Run with --verbose for detailed CMake output
|
|
364
|
+
"""
|
|
365
|
+
|
|
366
|
+
@staticmethod
|
|
367
|
+
def format_import_error(module: str, error_msg: str, pyd_path: str) -> str:
|
|
368
|
+
"""Format Python import errors for .pyd modules.
|
|
369
|
+
|
|
370
|
+
Args:
|
|
371
|
+
module: Module name
|
|
372
|
+
error_msg: Import error message
|
|
373
|
+
pyd_path: Path to .pyd file
|
|
374
|
+
|
|
375
|
+
Returns:
|
|
376
|
+
Formatted error message
|
|
377
|
+
"""
|
|
378
|
+
return f"""
|
|
379
|
+
╔══════════════════════════════════════════════════════════════╗
|
|
380
|
+
║ MODULE IMPORT ERROR ║
|
|
381
|
+
╚══════════════════════════════════════════════════════════════╝
|
|
382
|
+
|
|
383
|
+
Module: {module}
|
|
384
|
+
Path: {pyd_path}
|
|
385
|
+
|
|
386
|
+
Error:
|
|
387
|
+
{error_msg}
|
|
388
|
+
|
|
389
|
+
Common Causes:
|
|
390
|
+
• Missing dependencies (DLLs on Windows, .so on Linux)
|
|
391
|
+
• Python version mismatch (rebuild for current Python)
|
|
392
|
+
• Corrupted .pyd file (rebuild module)
|
|
393
|
+
• Missing Visual C++ Redistributable (Windows)
|
|
394
|
+
|
|
395
|
+
To Fix:
|
|
396
|
+
1. Rebuild module:
|
|
397
|
+
python -m includecpp rebuild {module} --clean
|
|
398
|
+
|
|
399
|
+
2. Check Python version matches build:
|
|
400
|
+
python --version
|
|
401
|
+
|
|
402
|
+
3. Windows: Install Visual C++ Redistributable
|
|
403
|
+
https://aka.ms/vs/17/release/vc_redist.x64.exe
|
|
404
|
+
|
|
405
|
+
4. Run with --verbose for detailed output
|
|
406
|
+
"""
|
|
407
|
+
|
|
408
|
+
@staticmethod
|
|
409
|
+
def format_namespace_error(module: str, source_file: str) -> str:
|
|
410
|
+
"""Format namespace error when includecpp namespace is missing.
|
|
411
|
+
|
|
412
|
+
Args:
|
|
413
|
+
module: Module name
|
|
414
|
+
source_file: Path to source file
|
|
415
|
+
|
|
416
|
+
Returns:
|
|
417
|
+
Formatted error message
|
|
418
|
+
"""
|
|
419
|
+
return f"""
|
|
420
|
+
╔══════════════════════════════════════════════════════════════╗
|
|
421
|
+
║ NAMESPACE ERROR ║
|
|
422
|
+
╚══════════════════════════════════════════════════════════════╝
|
|
423
|
+
|
|
424
|
+
Module: {module}
|
|
425
|
+
Source: {source_file}
|
|
426
|
+
|
|
427
|
+
Problem:
|
|
428
|
+
Your C++ code is not wrapped in the 'includecpp' namespace.
|
|
429
|
+
IncludeCPP requires all exported code to be in this namespace.
|
|
430
|
+
|
|
431
|
+
Why this matters:
|
|
432
|
+
The generated Python bindings expect functions/classes in the
|
|
433
|
+
'includecpp' namespace. Without it, the compiler cannot find
|
|
434
|
+
your code and you'll get "undefined reference" errors.
|
|
435
|
+
|
|
436
|
+
To Fix:
|
|
437
|
+
Wrap your code in the namespace:
|
|
438
|
+
|
|
439
|
+
// {source_file}
|
|
440
|
+
#include <...>
|
|
441
|
+
|
|
442
|
+
namespace includecpp {{
|
|
443
|
+
|
|
444
|
+
// Your functions and classes here
|
|
445
|
+
int my_function(int x) {{
|
|
446
|
+
return x * 2;
|
|
447
|
+
}}
|
|
448
|
+
|
|
449
|
+
class MyClass {{
|
|
450
|
+
public:
|
|
451
|
+
void method() {{ ... }}
|
|
452
|
+
}};
|
|
453
|
+
|
|
454
|
+
}} // namespace includecpp
|
|
455
|
+
|
|
456
|
+
After fixing:
|
|
457
|
+
python -m includecpp rebuild
|
|
458
|
+
"""
|
|
459
|
+
|
|
460
|
+
@staticmethod
|
|
461
|
+
def format_syntax_error(module: str, file: str, line: int, error: str) -> str:
|
|
462
|
+
"""Format C++ syntax error.
|
|
463
|
+
|
|
464
|
+
Args:
|
|
465
|
+
module: Module name
|
|
466
|
+
file: Source file path
|
|
467
|
+
line: Line number
|
|
468
|
+
error: Error message
|
|
469
|
+
|
|
470
|
+
Returns:
|
|
471
|
+
Formatted error message
|
|
472
|
+
"""
|
|
473
|
+
return f"""
|
|
474
|
+
╔══════════════════════════════════════════════════════════════╗
|
|
475
|
+
║ C++ SYNTAX ERROR ║
|
|
476
|
+
╚══════════════════════════════════════════════════════════════╝
|
|
477
|
+
|
|
478
|
+
Module: {module}
|
|
479
|
+
File: {file}
|
|
480
|
+
Line: {line}
|
|
481
|
+
|
|
482
|
+
Error:
|
|
483
|
+
{error}
|
|
484
|
+
|
|
485
|
+
Common Causes:
|
|
486
|
+
• Missing semicolon (;) at end of statement
|
|
487
|
+
• Unbalanced braces {{ }} or parentheses ( )
|
|
488
|
+
• Missing #include directive
|
|
489
|
+
• Typo in keyword or identifier
|
|
490
|
+
• Wrong order of template/class declaration
|
|
491
|
+
|
|
492
|
+
How to Debug:
|
|
493
|
+
1. Open {file} at line {line}
|
|
494
|
+
2. Check the line and lines immediately before it
|
|
495
|
+
3. Look for missing ; or }}
|
|
496
|
+
4. Verify all includes are correct
|
|
497
|
+
|
|
498
|
+
After fixing:
|
|
499
|
+
python -m includecpp rebuild --verbose
|
|
500
|
+
"""
|
|
501
|
+
|
|
502
|
+
@staticmethod
|
|
503
|
+
def format_linker_error(module: str, undefined_symbol: str, hint: str = "") -> str:
|
|
504
|
+
"""Format linker error for undefined references.
|
|
505
|
+
|
|
506
|
+
Args:
|
|
507
|
+
module: Module name
|
|
508
|
+
undefined_symbol: The undefined symbol
|
|
509
|
+
hint: Optional hint about cause
|
|
510
|
+
|
|
511
|
+
Returns:
|
|
512
|
+
Formatted error message
|
|
513
|
+
"""
|
|
514
|
+
return f"""
|
|
515
|
+
╔══════════════════════════════════════════════════════════════╗
|
|
516
|
+
║ LINKER ERROR - UNDEFINED REFERENCE ║
|
|
517
|
+
╚══════════════════════════════════════════════════════════════╝
|
|
518
|
+
|
|
519
|
+
Module: {module}
|
|
520
|
+
Missing Symbol: {undefined_symbol}
|
|
521
|
+
{f"Hint: {hint}" if hint else ""}
|
|
522
|
+
|
|
523
|
+
What this means:
|
|
524
|
+
The linker cannot find the implementation of '{undefined_symbol}'.
|
|
525
|
+
The symbol is declared (perhaps in a header) but not defined.
|
|
526
|
+
|
|
527
|
+
Common Causes:
|
|
528
|
+
• Function declared but not implemented
|
|
529
|
+
• Typo in function/class name
|
|
530
|
+
• Missing namespace qualifier (forgot 'includecpp::')
|
|
531
|
+
• Missing source file in .cp configuration
|
|
532
|
+
• Template function defined in .cpp instead of header
|
|
533
|
+
|
|
534
|
+
To Fix:
|
|
535
|
+
1. Check if '{undefined_symbol}' is fully implemented
|
|
536
|
+
2. Verify the function is in 'namespace includecpp'
|
|
537
|
+
3. For templates: move implementation to header file
|
|
538
|
+
4. Check your .cp file includes all necessary sources:
|
|
539
|
+
|
|
540
|
+
SOURCE(path/to/all_sources.cpp) {module}
|
|
541
|
+
|
|
542
|
+
5. If using multiple files:
|
|
543
|
+
|
|
544
|
+
SOURCES(file1.cpp, file2.cpp)
|
|
545
|
+
HEADER(headers.h) {module}
|
|
546
|
+
|
|
547
|
+
After fixing:
|
|
548
|
+
python -m includecpp rebuild --clean
|
|
549
|
+
"""
|
|
550
|
+
|
|
551
|
+
@staticmethod
|
|
552
|
+
def format_missing_include_error(module: str, missing_header: str, file: str) -> str:
|
|
553
|
+
"""Format missing include error.
|
|
554
|
+
|
|
555
|
+
Args:
|
|
556
|
+
module: Module name
|
|
557
|
+
missing_header: The missing header file
|
|
558
|
+
file: Source file that needs the include
|
|
559
|
+
|
|
560
|
+
Returns:
|
|
561
|
+
Formatted error message
|
|
562
|
+
"""
|
|
563
|
+
common_headers = {
|
|
564
|
+
'string': '#include <string>',
|
|
565
|
+
'vector': '#include <vector>',
|
|
566
|
+
'map': '#include <map>',
|
|
567
|
+
'iostream': '#include <iostream>',
|
|
568
|
+
'cmath': '#include <cmath>',
|
|
569
|
+
'memory': '#include <memory>',
|
|
570
|
+
'algorithm': '#include <algorithm>',
|
|
571
|
+
'functional': '#include <functional>',
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
suggestion = common_headers.get(missing_header.lower(), f'#include <{missing_header}>')
|
|
575
|
+
|
|
576
|
+
return f"""
|
|
577
|
+
╔══════════════════════════════════════════════════════════════╗
|
|
578
|
+
║ MISSING INCLUDE ERROR ║
|
|
579
|
+
╚══════════════════════════════════════════════════════════════╝
|
|
580
|
+
|
|
581
|
+
Module: {module}
|
|
582
|
+
File: {file}
|
|
583
|
+
Missing: {missing_header}
|
|
584
|
+
|
|
585
|
+
To Fix:
|
|
586
|
+
Add at the top of {file}:
|
|
587
|
+
|
|
588
|
+
{suggestion}
|
|
589
|
+
|
|
590
|
+
Common Standard Library Headers:
|
|
591
|
+
#include <string> // std::string
|
|
592
|
+
#include <vector> // std::vector
|
|
593
|
+
#include <map> // std::map, std::unordered_map
|
|
594
|
+
#include <memory> // std::unique_ptr, std::shared_ptr
|
|
595
|
+
#include <algorithm> // std::sort, std::find, etc.
|
|
596
|
+
#include <cmath> // Mathematical functions
|
|
597
|
+
#include <iostream> // std::cout, std::cin
|
|
598
|
+
|
|
599
|
+
After fixing:
|
|
600
|
+
python -m includecpp rebuild
|
|
601
|
+
"""
|
|
602
|
+
|
|
603
|
+
@staticmethod
|
|
604
|
+
def format_generic_build_error(module: str, stage: str, error: str) -> str:
|
|
605
|
+
"""Format a generic build error with helpful context.
|
|
606
|
+
|
|
607
|
+
Args:
|
|
608
|
+
module: Module name
|
|
609
|
+
stage: Build stage (compile, link, etc.)
|
|
610
|
+
error: Error message
|
|
611
|
+
|
|
612
|
+
Returns:
|
|
613
|
+
Formatted error message
|
|
614
|
+
"""
|
|
615
|
+
return f"""
|
|
616
|
+
╔══════════════════════════════════════════════════════════════╗
|
|
617
|
+
║ BUILD ERROR ║
|
|
618
|
+
╚══════════════════════════════════════════════════════════════╝
|
|
619
|
+
|
|
620
|
+
Module: {module}
|
|
621
|
+
Stage: {stage}
|
|
622
|
+
|
|
623
|
+
Error Details:
|
|
624
|
+
{error}
|
|
625
|
+
|
|
626
|
+
Troubleshooting Steps:
|
|
627
|
+
1. Run with verbose output:
|
|
628
|
+
python -m includecpp rebuild --verbose
|
|
629
|
+
|
|
630
|
+
2. Check your C++ code for errors:
|
|
631
|
+
- Syntax errors (missing ; or }})
|
|
632
|
+
- Missing namespace includecpp {{ }}
|
|
633
|
+
- Undefined functions or classes
|
|
634
|
+
|
|
635
|
+
3. Verify your .cp configuration:
|
|
636
|
+
- All source files listed
|
|
637
|
+
- Correct module name
|
|
638
|
+
- Valid DEPENDS() if using other modules
|
|
639
|
+
|
|
640
|
+
4. Try a clean rebuild:
|
|
641
|
+
python -m includecpp rebuild --clean
|
|
642
|
+
|
|
643
|
+
5. Check compiler is installed:
|
|
644
|
+
g++ --version (Linux/macOS)
|
|
645
|
+
cl (Windows MSVC)
|
|
646
|
+
|
|
647
|
+
If the error persists:
|
|
648
|
+
- Check the full error output above
|
|
649
|
+
- Verify all #include statements are correct
|
|
650
|
+
- Ensure no circular dependencies between modules
|
|
651
|
+
"""
|
|
652
|
+
|
|
653
|
+
@staticmethod
|
|
654
|
+
def format_bindings_error(module: str, bad_method: str, bad_class: str) -> str:
|
|
655
|
+
"""Format error in auto-generated bindings.cpp file.
|
|
656
|
+
|
|
657
|
+
Args:
|
|
658
|
+
module: Module name
|
|
659
|
+
bad_method: The method/member that doesn't exist
|
|
660
|
+
bad_class: The class that should have the method
|
|
661
|
+
|
|
662
|
+
Returns:
|
|
663
|
+
Formatted error message
|
|
664
|
+
"""
|
|
665
|
+
specific_hint = ""
|
|
666
|
+
if bad_method and bad_class:
|
|
667
|
+
specific_hint = f"""
|
|
668
|
+
The generated bindings tried to bind '{bad_method}' as a method of '{bad_class}',
|
|
669
|
+
but '{bad_class}' doesn't have a member called '{bad_method}'.
|
|
670
|
+
"""
|
|
671
|
+
|
|
672
|
+
return f"""
|
|
673
|
+
+======================================================================+
|
|
674
|
+
| BUILD ERROR |
|
|
675
|
+
+======================================================================+
|
|
676
|
+
{specific_hint}
|
|
677
|
+
Try regenerating your .cp file:
|
|
678
|
+
|
|
679
|
+
includecpp plugin {module if module else '<name>'}
|
|
680
|
+
|
|
681
|
+
This re-scans your C++ source files and updates the plugin definition.
|
|
682
|
+
Then run:
|
|
683
|
+
|
|
684
|
+
includecpp rebuild
|
|
685
|
+
"""
|
|
686
|
+
|
|
687
|
+
@staticmethod
|
|
688
|
+
def format_redefinition_error(module: str, type_name: str, file1: str, file2: str) -> str:
|
|
689
|
+
"""Format redefinition/duplicate declaration error.
|
|
690
|
+
|
|
691
|
+
Args:
|
|
692
|
+
module: Module name
|
|
693
|
+
type_name: Name of redefined type (class, struct, function)
|
|
694
|
+
file1: First file where type is defined
|
|
695
|
+
file2: Second file where type is redefined
|
|
696
|
+
|
|
697
|
+
Returns:
|
|
698
|
+
Formatted error message
|
|
699
|
+
"""
|
|
700
|
+
return f"""
|
|
701
|
+
+======================================================================+
|
|
702
|
+
| REDEFINITION ERROR - YOUR CODE HAS DUPLICATE DECLARATIONS |
|
|
703
|
+
+======================================================================+
|
|
704
|
+
|
|
705
|
+
Module: {module}
|
|
706
|
+
Conflict: '{type_name}' is defined in multiple files
|
|
707
|
+
|
|
708
|
+
File 1: {file1}
|
|
709
|
+
File 2: {file2}
|
|
710
|
+
|
|
711
|
+
PROBLEM:
|
|
712
|
+
You have the same class/struct/function defined twice.
|
|
713
|
+
C++ does not allow multiple definitions of the same type.
|
|
714
|
+
|
|
715
|
+
THIS IS A USER CODE ERROR, NOT AN IncludeCPP BUG.
|
|
716
|
+
|
|
717
|
+
HOW TO FIX:
|
|
718
|
+
Option 1: Remove the duplicate
|
|
719
|
+
- Delete '{type_name}' from one of the files
|
|
720
|
+
|
|
721
|
+
Option 2: Use different names
|
|
722
|
+
- Rename one to '{type_name}2' or a more descriptive name
|
|
723
|
+
|
|
724
|
+
Option 3: Share the type
|
|
725
|
+
- Put '{type_name}' in a common header file
|
|
726
|
+
- Include that header in both modules
|
|
727
|
+
- Use DEPENDS() in .cp files to share types
|
|
728
|
+
|
|
729
|
+
Option 4: Use namespaces
|
|
730
|
+
- Put each in a different sub-namespace:
|
|
731
|
+
namespace includecpp::module1 {{ class {type_name} {{ }}; }}
|
|
732
|
+
namespace includecpp::module2 {{ class {type_name} {{ }}; }}
|
|
733
|
+
|
|
734
|
+
After fixing:
|
|
735
|
+
python -m includecpp rebuild --clean
|
|
736
|
+
"""
|
|
737
|
+
|
|
738
|
+
@staticmethod
|
|
739
|
+
def get_final_message(stderr: str, module_name: str = "") -> str:
|
|
740
|
+
"""Get the final helpful message to print LAST.
|
|
741
|
+
|
|
742
|
+
This is the short, actionable message that lazy users will see.
|
|
743
|
+
Always call this and print it as the last line of output.
|
|
744
|
+
|
|
745
|
+
Args:
|
|
746
|
+
stderr: Standard error output
|
|
747
|
+
module_name: Name of module
|
|
748
|
+
|
|
749
|
+
Returns:
|
|
750
|
+
Short, helpful message for the end of output
|
|
751
|
+
"""
|
|
752
|
+
context = {"module": module_name} if module_name else None
|
|
753
|
+
msg = get_error_message(stderr, context)
|
|
754
|
+
if msg:
|
|
755
|
+
return msg
|
|
756
|
+
return format_unknown_error(stderr)
|
|
757
|
+
|
|
758
|
+
@staticmethod
|
|
759
|
+
def analyze_error(stderr: str, module_name: str = "") -> str:
|
|
760
|
+
"""Analyze stderr and return appropriate formatted error.
|
|
761
|
+
|
|
762
|
+
Args:
|
|
763
|
+
stderr: Standard error output from build
|
|
764
|
+
module_name: Name of module being built
|
|
765
|
+
|
|
766
|
+
Returns:
|
|
767
|
+
Formatted error message with hints
|
|
768
|
+
"""
|
|
769
|
+
# First try the error catalog for quick matching
|
|
770
|
+
context = {"module": module_name} if module_name else None
|
|
771
|
+
catalog_msg = get_error_message(stderr, context)
|
|
772
|
+
if catalog_msg:
|
|
773
|
+
return format_error_box(catalog_msg, "BUILD ERROR")
|
|
774
|
+
|
|
775
|
+
stderr_lower = stderr.lower()
|
|
776
|
+
|
|
777
|
+
redef_match = re.search(r"redefinition of ['\"]?(?:class |struct |)?([^'\"]+)['\"]?", stderr)
|
|
778
|
+
if redef_match:
|
|
779
|
+
type_name = redef_match.group(1).strip()
|
|
780
|
+
# Try to find the two file locations
|
|
781
|
+
file_matches = re.findall(r"([^\s:]+\.[ch](?:pp)?):(\d+)", stderr)
|
|
782
|
+
file1 = file_matches[0][0] if len(file_matches) > 0 else "unknown"
|
|
783
|
+
file2 = file_matches[1][0] if len(file_matches) > 1 else "unknown"
|
|
784
|
+
return BuildErrorFormatter.format_redefinition_error(module_name, type_name, file1, file2)
|
|
785
|
+
|
|
786
|
+
# Check for namespace error
|
|
787
|
+
if 'namespace includecpp' in stderr or 'using namespace includecpp' in stderr:
|
|
788
|
+
if 'undefined' in stderr_lower or 'not found' in stderr_lower:
|
|
789
|
+
return BuildErrorFormatter.format_namespace_error(module_name, "your source file")
|
|
790
|
+
|
|
791
|
+
# Check for undefined reference (linker error)
|
|
792
|
+
undefined_match = re.search(r"undefined reference to ['\"]?([^'\"]+)['\"]?", stderr)
|
|
793
|
+
if undefined_match:
|
|
794
|
+
symbol = undefined_match.group(1)
|
|
795
|
+
hint = ""
|
|
796
|
+
if '::' in symbol and 'includecpp' not in symbol:
|
|
797
|
+
hint = "Symbol is not in 'includecpp' namespace"
|
|
798
|
+
return BuildErrorFormatter.format_linker_error(module_name, symbol, hint)
|
|
799
|
+
|
|
800
|
+
# Check for missing include
|
|
801
|
+
include_match = re.search(r"fatal error: ([^:]+): No such file", stderr)
|
|
802
|
+
if not include_match:
|
|
803
|
+
include_match = re.search(r"cannot open include file[:\s]+['\"]?([^'\"]+)['\"]?", stderr, re.IGNORECASE)
|
|
804
|
+
if include_match:
|
|
805
|
+
missing = include_match.group(1).strip()
|
|
806
|
+
return BuildErrorFormatter.format_missing_include_error(module_name, missing, "your source file")
|
|
807
|
+
|
|
808
|
+
if 'bindings.cpp' in stderr or 'bindings\\bindings.cpp' in stderr:
|
|
809
|
+
# Extract what's wrong (e.g., "'Vector2D' is not a member of 'Circle'")
|
|
810
|
+
member_error = re.search(r"'(\w+)' is not a member of '([^']+)'", stderr)
|
|
811
|
+
if member_error:
|
|
812
|
+
bad_method = member_error.group(1)
|
|
813
|
+
bad_class = member_error.group(2).split('::')[-1]
|
|
814
|
+
return BuildErrorFormatter.format_bindings_error(module_name, bad_method, bad_class)
|
|
815
|
+
|
|
816
|
+
# Check for syntax error with line number
|
|
817
|
+
syntax_match = re.search(r"([^:]+):(\d+):\d*:?\s*error:\s*(.+)", stderr)
|
|
818
|
+
if syntax_match:
|
|
819
|
+
file = syntax_match.group(1)
|
|
820
|
+
line = int(syntax_match.group(2))
|
|
821
|
+
error = syntax_match.group(3)
|
|
822
|
+
# Skip if it's bindings.cpp - already handled above
|
|
823
|
+
if 'bindings.cpp' in file:
|
|
824
|
+
return BuildErrorFormatter.format_bindings_error(module_name, "", "")
|
|
825
|
+
return BuildErrorFormatter.format_syntax_error(module_name, file, line, error)
|
|
826
|
+
|
|
827
|
+
# Check for circular dependency
|
|
828
|
+
if 'circular' in stderr_lower and 'dependency' in stderr_lower:
|
|
829
|
+
cycle_match = re.findall(r'\b([a-zA-Z_]\w*)\b', stderr)
|
|
830
|
+
if cycle_match:
|
|
831
|
+
return BuildErrorFormatter.format_circular_dependency(list(set(cycle_match[:5])))
|
|
832
|
+
|
|
833
|
+
# Check for missing dependency
|
|
834
|
+
dep_match = re.search(r"depends on unknown module[:\s]+['\"]?(\w+)['\"]?", stderr, re.IGNORECASE)
|
|
835
|
+
if dep_match:
|
|
836
|
+
missing_dep = dep_match.group(1)
|
|
837
|
+
return BuildErrorFormatter.format_dependency_error(module_name, missing_dep)
|
|
838
|
+
|
|
839
|
+
# Default: generic build error
|
|
840
|
+
return BuildErrorFormatter.format_generic_build_error(module_name, "build", stderr)
|
|
841
|
+
|
|
842
|
+
|
|
843
|
+
class BuildSuccessFormatter:
|
|
844
|
+
"""Format build success messages with professional styling."""
|
|
845
|
+
|
|
846
|
+
@staticmethod
|
|
847
|
+
def format_build_success(modules: List[str], build_time: float, stats: dict = None) -> str:
|
|
848
|
+
"""Format successful build completion message.
|
|
849
|
+
|
|
850
|
+
Args:
|
|
851
|
+
modules: List of successfully built modules
|
|
852
|
+
build_time: Total build time in seconds
|
|
853
|
+
stats: Optional build statistics dict
|
|
854
|
+
|
|
855
|
+
Returns:
|
|
856
|
+
Formatted success message
|
|
857
|
+
"""
|
|
858
|
+
module_count = len(modules)
|
|
859
|
+
module_list = "\n ".join(f"{m}" for m in modules) if modules else " (no modules)"
|
|
860
|
+
|
|
861
|
+
stats_section = ""
|
|
862
|
+
if stats:
|
|
863
|
+
stats_lines = []
|
|
864
|
+
if 'total_functions' in stats:
|
|
865
|
+
stats_lines.append(f" Functions exported: {stats['total_functions']}")
|
|
866
|
+
if 'total_classes' in stats:
|
|
867
|
+
stats_lines.append(f" Classes exported: {stats['total_classes']}")
|
|
868
|
+
if 'total_structs' in stats:
|
|
869
|
+
stats_lines.append(f" Structs exported: {stats['total_structs']}")
|
|
870
|
+
if stats_lines:
|
|
871
|
+
stats_section = "\n" + "\n".join(stats_lines)
|
|
872
|
+
|
|
873
|
+
return f"""
|
|
874
|
+
╔══════════════════════════════════════════════════════════════╗
|
|
875
|
+
║ BUILD SUCCESSFUL ║
|
|
876
|
+
╚══════════════════════════════════════════════════════════════╝
|
|
877
|
+
|
|
878
|
+
Modules built ({module_count}):
|
|
879
|
+
{module_list}
|
|
880
|
+
|
|
881
|
+
Build time: {build_time:.2f}s{stats_section}
|
|
882
|
+
|
|
883
|
+
Usage:
|
|
884
|
+
from includecpp import CppApi
|
|
885
|
+
api = CppApi()
|
|
886
|
+
module = api.include("<module_name>")
|
|
887
|
+
"""
|
|
888
|
+
|
|
889
|
+
@staticmethod
|
|
890
|
+
def format_module_compile_start(module: str) -> str:
|
|
891
|
+
"""Format module compilation start message.
|
|
892
|
+
|
|
893
|
+
Args:
|
|
894
|
+
module: Module name
|
|
895
|
+
|
|
896
|
+
Returns:
|
|
897
|
+
Formatted start message
|
|
898
|
+
"""
|
|
899
|
+
return f"┌─ Building: {module}"
|
|
900
|
+
|
|
901
|
+
@staticmethod
|
|
902
|
+
def format_module_compile_success(module: str, time_seconds: float) -> str:
|
|
903
|
+
"""Format module compilation success message.
|
|
904
|
+
|
|
905
|
+
Args:
|
|
906
|
+
module: Module name
|
|
907
|
+
time_seconds: Compilation time
|
|
908
|
+
|
|
909
|
+
Returns:
|
|
910
|
+
Formatted success message
|
|
911
|
+
"""
|
|
912
|
+
return f"└─ {module} ({time_seconds:.2f}s)"
|
|
913
|
+
|
|
914
|
+
@staticmethod
|
|
915
|
+
def format_module_compile_failed(module: str, error_summary: str) -> str:
|
|
916
|
+
"""Format module compilation failure message.
|
|
917
|
+
|
|
918
|
+
Args:
|
|
919
|
+
module: Module name
|
|
920
|
+
error_summary: Brief error summary
|
|
921
|
+
|
|
922
|
+
Returns:
|
|
923
|
+
Formatted failure message
|
|
924
|
+
"""
|
|
925
|
+
return f"└─ ✗ {module}: {error_summary}"
|
|
926
|
+
|
|
927
|
+
@staticmethod
|
|
928
|
+
def format_build_start(modules: List[str], incremental: bool = False) -> str:
|
|
929
|
+
"""Format build start message.
|
|
930
|
+
|
|
931
|
+
Args:
|
|
932
|
+
modules: List of modules to build
|
|
933
|
+
incremental: Whether this is an incremental build
|
|
934
|
+
|
|
935
|
+
Returns:
|
|
936
|
+
Formatted start message
|
|
937
|
+
"""
|
|
938
|
+
build_type = "Incremental" if incremental else "Full"
|
|
939
|
+
module_count = len(modules) if modules else "all"
|
|
940
|
+
|
|
941
|
+
return f"""
|
|
942
|
+
╔══════════════════════════════════════════════════════════════╗
|
|
943
|
+
║ IncludeCPP {build_type} Build
|
|
944
|
+
╚══════════════════════════════════════════════════════════════╝
|
|
945
|
+
Modules: {module_count}
|
|
946
|
+
"""
|
|
947
|
+
|
|
948
|
+
@staticmethod
|
|
949
|
+
def format_build_failed(failed_modules: List[str], succeeded_modules: List[str]) -> str:
|
|
950
|
+
"""Format build failure summary.
|
|
951
|
+
|
|
952
|
+
Args:
|
|
953
|
+
failed_modules: List of modules that failed
|
|
954
|
+
succeeded_modules: List of modules that succeeded
|
|
955
|
+
|
|
956
|
+
Returns:
|
|
957
|
+
Formatted failure message
|
|
958
|
+
"""
|
|
959
|
+
failed_list = "\n ".join(f"✗ {m}" for m in failed_modules)
|
|
960
|
+
succeeded_list = "\n ".join(f"{m}" for m in succeeded_modules) if succeeded_modules else " (none)"
|
|
961
|
+
|
|
962
|
+
return f"""
|
|
963
|
+
╔══════════════════════════════════════════════════════════════╗
|
|
964
|
+
║ ✗ BUILD FAILED ║
|
|
965
|
+
╚══════════════════════════════════════════════════════════════╝
|
|
966
|
+
|
|
967
|
+
Failed ({len(failed_modules)}):
|
|
968
|
+
{failed_list}
|
|
969
|
+
|
|
970
|
+
Succeeded ({len(succeeded_modules)}):
|
|
971
|
+
{succeeded_list}
|
|
972
|
+
|
|
973
|
+
To fix:
|
|
974
|
+
• Check the error messages above
|
|
975
|
+
• Run with --verbose for more details
|
|
976
|
+
• Fix errors and run: python -m includecpp rebuild
|
|
977
|
+
"""
|
|
978
|
+
|
|
979
|
+
@staticmethod
|
|
980
|
+
def format_up_to_date(modules: List[str]) -> str:
|
|
981
|
+
"""Format message when all modules are up to date.
|
|
982
|
+
|
|
983
|
+
Args:
|
|
984
|
+
modules: List of up-to-date modules
|
|
985
|
+
|
|
986
|
+
Returns:
|
|
987
|
+
Formatted message
|
|
988
|
+
"""
|
|
989
|
+
return f"""
|
|
990
|
+
╔══════════════════════════════════════════════════════════════╗
|
|
991
|
+
║ ALL MODULES UP TO DATE ║
|
|
992
|
+
╚══════════════════════════════════════════════════════════════╝
|
|
993
|
+
|
|
994
|
+
{len(modules)} module(s) already built and unchanged.
|
|
995
|
+
Use --clean to force a full rebuild.
|
|
996
|
+
"""
|
|
997
|
+
|
|
998
|
+
@staticmethod
|
|
999
|
+
def format_clean_success(cleaned_items: List[str]) -> str:
|
|
1000
|
+
"""Format successful clean operation message.
|
|
1001
|
+
|
|
1002
|
+
Args:
|
|
1003
|
+
cleaned_items: List of cleaned items/modules
|
|
1004
|
+
|
|
1005
|
+
Returns:
|
|
1006
|
+
Formatted message
|
|
1007
|
+
"""
|
|
1008
|
+
items = "\n ".join(f"• {item}" for item in cleaned_items) if cleaned_items else " (nothing to clean)"
|
|
1009
|
+
return f"""
|
|
1010
|
+
╔══════════════════════════════════════════════════════════════╗
|
|
1011
|
+
║ CLEAN COMPLETE ║
|
|
1012
|
+
╚══════════════════════════════════════════════════════════════╝
|
|
1013
|
+
|
|
1014
|
+
Cleaned:
|
|
1015
|
+
{items}
|
|
1016
|
+
"""
|