IncludeCPP 4.6.2__tar.gz → 4.6.6__tar.gz
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-4.6.2 → includecpp-4.6.6}/IncludeCPP.egg-info/PKG-INFO +1 -1
- {includecpp-4.6.2 → includecpp-4.6.6}/PKG-INFO +1 -1
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/CHANGELOG.md +19 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/__init__.py +1 -1
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/__init__.pyi +1 -1
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/cli/commands.py +142 -34
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/core/build_manager.py +4 -2
- includecpp-4.6.6/includecpp/core/cpp_api_extensions.pyi +165 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/core/cssl/cssl_builtins.py +325 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/core/cssl/cssl_optimizer.py +12 -1
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/core/cssl/cssl_parser.py +12 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/core/cssl/cssl_runtime.py +15 -2
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/core/cssl/cssl_syntax.py +56 -2
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/core/cssl_bridge.py +370 -1
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/core/error_catalog.py +2 -5
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/generator/parser.cpp +203 -39
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/generator/parser.h +15 -1
- {includecpp-4.6.2 → includecpp-4.6.6}/pyproject.toml +1 -1
- {includecpp-4.6.2 → includecpp-4.6.6}/setup.py +1 -1
- includecpp-4.6.2/includecpp/core/cpp_api_extensions.pyi +0 -354
- {includecpp-4.6.2 → includecpp-4.6.6}/IncludeCPP.egg-info/SOURCES.txt +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/IncludeCPP.egg-info/dependency_links.txt +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/IncludeCPP.egg-info/entry_points.txt +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/IncludeCPP.egg-info/requires.txt +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/IncludeCPP.egg-info/top_level.txt +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/LICENSE +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/MANIFEST.in +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/README.md +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/DOCUMENTATION.md +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/__main__.py +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/cli/__init__.py +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/cli/config_parser.py +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/core/__init__.py +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/core/ai_integration.py +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/core/cpp_api.py +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/core/cpp_api.pyi +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/core/cppy_converter.py +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/core/cssl/CSSL_DOCUMENTATION.md +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/core/cssl/CSSL_DOCUMENTATION_NEW.md +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/core/cssl/__init__.py +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/core/cssl/cpp/build/api.pyd +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/core/cssl/cpp/build/cssl_core.pyi +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/core/cssl/cpp/build/libgcc_s_seh-1.dll +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/core/cssl/cpp/build/libstdc++-6.dll +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/core/cssl/cpp/build/libwinpthread-1.dll +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/core/cssl/cpp/cssl_core.cp +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/core/cssl/cpp/cssl_lexer.hpp +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/core/cssl/cssl_builtins.pyi +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/core/cssl/cssl_compiler.py +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/core/cssl/cssl_events.py +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/core/cssl/cssl_languages.py +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/core/cssl/cssl_modules.py +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/core/cssl/cssl_types.py +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/core/cssl_bridge.pyi +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/core/error_formatter.py +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/core/exceptions.py +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/core/path_discovery.py +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/core/project_ui.py +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/core/settings_ui.py +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/generator/__init__.py +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/generator/type_resolver.cpp +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/generator/type_resolver.h +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/py.typed +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/templates/cpp.proj.template +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/vscode/__init__.py +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/vscode/cssl/__init__.py +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/vscode/cssl/extension.js +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/vscode/cssl/images/cssl.png +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/vscode/cssl/images/cssl_pl.png +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/vscode/cssl/language-configuration.json +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/vscode/cssl/package.json +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/vscode/cssl/snippets/cssl.snippets.json +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/includecpp/vscode/cssl/syntaxes/cssl.tmLanguage.json +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/requirements.txt +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/setup.cfg +0 -0
- {includecpp-4.6.2 → includecpp-4.6.6}/tests/test_multilang.py +0 -0
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# IncludeCPP Changelog
|
|
2
2
|
|
|
3
|
+
## v4.6.6 (2026-01-14)
|
|
4
|
+
|
|
5
|
+
### New Features
|
|
6
|
+
- **ENUM support**: Expose C++ enums to Python via `ENUM(EnumName) CLASS { values... }` syntax
|
|
7
|
+
- **Multiple SOURCE support**: `SOURCE(file1) && SOURCE(file2)` in .cp files
|
|
8
|
+
- **FIELD_ARRAY support**: C-style arrays now properly bound as read-only `bytes` properties
|
|
9
|
+
- Automatic detection of array fields in plugin command
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
- Fixed signed/unsigned comparison warning from pybind11 enum bindings
|
|
13
|
+
- Removed SIGNED_UNSIGNED from error catalog (was a warning, not error)
|
|
14
|
+
- Fixed array fields causing `invalid array assignment` error
|
|
15
|
+
- Version display now shows X.X format in build output
|
|
16
|
+
|
|
17
|
+
### Breaking Changes
|
|
18
|
+
- Array fields in structs are now read-only (accessible as `bytes`)
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
3
22
|
## v4.3.2 (2026-01-08)
|
|
4
23
|
|
|
5
24
|
### New Features
|
|
@@ -147,7 +147,7 @@ __version__: str
|
|
|
147
147
|
# Dynamic module access via: from includecpp import <module_name>
|
|
148
148
|
# Auto-generated module declarations
|
|
149
149
|
# These allow: from includecpp import <module_name>
|
|
150
|
-
|
|
150
|
+
stepcompiler: StepcompilerModuleWrapper
|
|
151
151
|
|
|
152
152
|
def __dir__() -> List[str]:
|
|
153
153
|
"""List available modules including dynamically loaded C++ modules."""
|
|
@@ -868,6 +868,11 @@ def _check_for_updates_silent():
|
|
|
868
868
|
def _parse_cp_sources(cp_path):
|
|
869
869
|
"""Parse SOURCE() and HEADER() paths from an existing .cp file.
|
|
870
870
|
|
|
871
|
+
Supports multiple formats:
|
|
872
|
+
- Single SOURCE with multiple files: SOURCE(file1.cpp file2.cpp)
|
|
873
|
+
- Multiple SOURCE declarations: SOURCE(file1.cpp) && SOURCE(file2.cpp)
|
|
874
|
+
- Same for HEADER()
|
|
875
|
+
|
|
871
876
|
Returns:
|
|
872
877
|
Tuple of (source_files, header_files) as lists of Path objects
|
|
873
878
|
"""
|
|
@@ -881,11 +886,10 @@ def _parse_cp_sources(cp_path):
|
|
|
881
886
|
content = cp_path.read_text()
|
|
882
887
|
project_root = cp_path.parent.parent # plugins/ -> project root
|
|
883
888
|
|
|
884
|
-
# Find SOURCE(...) declarations
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
# Handle multiple files: SOURCE(file1.cpp file2.cpp) or SOURCE(file1.cpp, file2.cpp)
|
|
889
|
+
# Find ALL SOURCE(...) declarations (supports multiple SOURCE() && SOURCE())
|
|
890
|
+
source_matches = re.findall(r'SOURCE\s*\(\s*([^)]+)\s*\)', content)
|
|
891
|
+
for sources_str in source_matches:
|
|
892
|
+
# Handle multiple files within one SOURCE(): SOURCE(file1.cpp file2.cpp) or SOURCE(file1.cpp, file2.cpp)
|
|
889
893
|
sources = re.split(r'[,\s]+', sources_str.strip())
|
|
890
894
|
for src in sources:
|
|
891
895
|
src = src.strip()
|
|
@@ -896,10 +900,9 @@ def _parse_cp_sources(cp_path):
|
|
|
896
900
|
if p.exists():
|
|
897
901
|
source_files.append(p)
|
|
898
902
|
|
|
899
|
-
# Find HEADER(...) declarations
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
headers_str = header_match.group(1)
|
|
903
|
+
# Find ALL HEADER(...) declarations
|
|
904
|
+
header_matches = re.findall(r'HEADER\s*\(\s*([^)]+)\s*\)', content)
|
|
905
|
+
for headers_str in header_matches:
|
|
903
906
|
headers = re.split(r'[,\s]+', headers_str.strip())
|
|
904
907
|
for hdr in headers:
|
|
905
908
|
hdr = hdr.strip()
|
|
@@ -943,10 +946,16 @@ def rebuild(clean, keep, verbose, no_incremental, incremental, parallel, jobs, m
|
|
|
943
946
|
"""Rebuild C++ modules with automatic generator updates."""
|
|
944
947
|
from ..core.build_manager import BuildManager
|
|
945
948
|
from ..core.error_formatter import BuildErrorFormatter, BuildSuccessFormatter
|
|
949
|
+
from .. import __version__
|
|
946
950
|
import time
|
|
947
951
|
import json
|
|
948
952
|
from datetime import datetime
|
|
949
953
|
|
|
954
|
+
# Show version (X.X format)
|
|
955
|
+
short_version = '.'.join(__version__.split('.')[:2])
|
|
956
|
+
click.secho(f"[IncludeCPP v{short_version}] ", fg='cyan', nl=False)
|
|
957
|
+
click.echo("Build starting...")
|
|
958
|
+
|
|
950
959
|
# Combine -m modules with positional arguments
|
|
951
960
|
# Allows both: includecpp rebuild -m gamekit AND includecpp rebuild gamekit
|
|
952
961
|
all_modules = list(modules) + list(module_args)
|
|
@@ -2488,6 +2497,7 @@ def plugin(plugin_name, files, private):
|
|
|
2488
2497
|
classes = {}
|
|
2489
2498
|
functions = set()
|
|
2490
2499
|
template_functions = {} # v3.1.6: {name: set of types}
|
|
2500
|
+
enums = {} # v4.6.5: {name: {'is_class': bool, 'values': list}}
|
|
2491
2501
|
namespaces = set()
|
|
2492
2502
|
|
|
2493
2503
|
def find_matching_brace(text, start_pos):
|
|
@@ -2898,15 +2908,27 @@ def plugin(plugin_name, files, private):
|
|
|
2898
2908
|
if '&' not in actual_type:
|
|
2899
2909
|
actual_type += '&'
|
|
2900
2910
|
|
|
2901
|
-
#
|
|
2911
|
+
# v4.6.6: Detect array fields and capture size
|
|
2912
|
+
array_size = 0
|
|
2902
2913
|
if '[' in name:
|
|
2903
|
-
|
|
2914
|
+
# Extract array size: "magic[4]" -> size=4, name="magic"
|
|
2915
|
+
bracket_idx = name.find('[')
|
|
2916
|
+
end_bracket = name.find(']')
|
|
2917
|
+
if end_bracket > bracket_idx:
|
|
2918
|
+
size_str = name[bracket_idx+1:end_bracket].strip()
|
|
2919
|
+
try:
|
|
2920
|
+
array_size = int(size_str) if size_str else 0
|
|
2921
|
+
except ValueError:
|
|
2922
|
+
array_size = 0 # Unknown/variable size
|
|
2923
|
+
name = name[:bracket_idx].strip()
|
|
2904
2924
|
|
|
2905
2925
|
# Validate field name
|
|
2906
2926
|
if name and re.match(r'^[a-zA-Z_]\w*$', name):
|
|
2907
2927
|
# Skip if name is a keyword
|
|
2908
2928
|
if name.lower() not in cpp_keywords:
|
|
2909
|
-
|
|
2929
|
+
# v4.6.6: Include array info (type, name, array_size)
|
|
2930
|
+
# array_size=0 means not an array
|
|
2931
|
+
fields.append((actual_type, name, array_size))
|
|
2910
2932
|
|
|
2911
2933
|
return fields
|
|
2912
2934
|
|
|
@@ -2946,6 +2968,11 @@ def plugin(plugin_name, files, private):
|
|
|
2946
2968
|
is_struct = keyword == 'struct'
|
|
2947
2969
|
brace_start = match.end() - 1
|
|
2948
2970
|
|
|
2971
|
+
# v4.6.5: Skip "enum class" declarations - check if preceded by "enum"
|
|
2972
|
+
text_before_match = content[max(0, match.start()-10):match.start()]
|
|
2973
|
+
if re.search(r'\benum\s*$', text_before_match):
|
|
2974
|
+
continue
|
|
2975
|
+
|
|
2949
2976
|
text_before = content[:match.start()]
|
|
2950
2977
|
open_braces = text_before.count('{')
|
|
2951
2978
|
close_braces = text_before.count('}')
|
|
@@ -3071,23 +3098,67 @@ def plugin(plugin_name, files, private):
|
|
|
3071
3098
|
if func_name not in template_func_names:
|
|
3072
3099
|
functions.add(func_name)
|
|
3073
3100
|
|
|
3101
|
+
# v4.6.5: Find enum declarations
|
|
3102
|
+
enum_pattern = re.compile(
|
|
3103
|
+
r'\benum\s+(class\s+)?(\w+)\s*\{([^}]*)\}',
|
|
3104
|
+
re.MULTILINE | re.DOTALL
|
|
3105
|
+
)
|
|
3106
|
+
|
|
3107
|
+
for match in enum_pattern.finditer(content):
|
|
3108
|
+
is_class_enum = bool(match.group(1))
|
|
3109
|
+
enum_name = match.group(2)
|
|
3110
|
+
enum_body = match.group(3)
|
|
3111
|
+
|
|
3112
|
+
# Parse enum values
|
|
3113
|
+
values = []
|
|
3114
|
+
# Split by comma and extract value names (ignoring assignments)
|
|
3115
|
+
for part in enum_body.split(','):
|
|
3116
|
+
part = part.strip()
|
|
3117
|
+
if not part:
|
|
3118
|
+
continue
|
|
3119
|
+
# Get the value name (before any = assignment)
|
|
3120
|
+
value_name = part.split('=')[0].strip()
|
|
3121
|
+
if value_name and re.match(r'^[a-zA-Z_]\w*$', value_name):
|
|
3122
|
+
values.append(value_name)
|
|
3123
|
+
|
|
3124
|
+
if enum_name not in enums and values:
|
|
3125
|
+
enums[enum_name] = {
|
|
3126
|
+
'is_class': is_class_enum,
|
|
3127
|
+
'values': values
|
|
3128
|
+
}
|
|
3129
|
+
|
|
3074
3130
|
private_set = set(private) if private else set()
|
|
3075
3131
|
public_functions = functions - private_set - set(classes.keys())
|
|
3076
3132
|
|
|
3077
3133
|
cp_file = plugins_dir / f"{plugin_name}.cp"
|
|
3078
3134
|
|
|
3079
|
-
|
|
3080
|
-
|
|
3135
|
+
# Generate individual SOURCE() declarations for each file (cleaner format)
|
|
3136
|
+
cpp_paths = [str(f.relative_to(project_root) if f.is_relative_to(project_root) else f).replace('\\', '/') for f in cpp_files]
|
|
3137
|
+
h_paths = [str(f.relative_to(project_root) if f.is_relative_to(project_root) else f).replace('\\', '/') for f in h_files] if h_files else []
|
|
3081
3138
|
|
|
3082
3139
|
with open(cp_file, 'w', encoding='utf-8') as f:
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3140
|
+
# Build the declaration line: SOURCE(file1) && SOURCE(file2) && HEADER(h1) plugin_name
|
|
3141
|
+
parts = [f'SOURCE({p})' for p in cpp_paths]
|
|
3142
|
+
parts.extend([f'HEADER({p})' for p in h_paths])
|
|
3143
|
+
declaration = ' && '.join(parts) + f' {plugin_name}'
|
|
3144
|
+
f.write(declaration + '\n\n')
|
|
3087
3145
|
|
|
3088
|
-
if classes or public_functions or template_functions:
|
|
3146
|
+
if classes or public_functions or template_functions or enums:
|
|
3089
3147
|
f.write('PUBLIC(\n')
|
|
3090
3148
|
|
|
3149
|
+
# v4.6.5: Write enum bindings
|
|
3150
|
+
for enum_name in sorted(enums.keys()):
|
|
3151
|
+
enum_info = enums[enum_name]
|
|
3152
|
+
is_class = enum_info.get('is_class', False)
|
|
3153
|
+
values = enum_info.get('values', [])
|
|
3154
|
+
|
|
3155
|
+
class_kw = ' CLASS' if is_class else ''
|
|
3156
|
+
values_str = ' '.join(values)
|
|
3157
|
+
f.write(f' {plugin_name} ENUM({enum_name}){class_kw} {{ {values_str} }}\n')
|
|
3158
|
+
|
|
3159
|
+
if enums and classes:
|
|
3160
|
+
f.write('\n')
|
|
3161
|
+
|
|
3091
3162
|
for cls_name in sorted(classes.keys()):
|
|
3092
3163
|
cls_info = classes[cls_name]
|
|
3093
3164
|
f.write(f' {plugin_name} CLASS({cls_name}) {{\n')
|
|
@@ -3128,10 +3199,22 @@ def plugin(plugin_name, files, private):
|
|
|
3128
3199
|
for method in sorted(cls_info['methods']):
|
|
3129
3200
|
f.write(f' METHOD({method})\n')
|
|
3130
3201
|
|
|
3131
|
-
# v3.2.2: Write fields
|
|
3202
|
+
# v3.2.2: Write fields
|
|
3203
|
+
# v4.6.6: Support array fields with FIELD_ARRAY(name, type, size)
|
|
3132
3204
|
if cls_info.get('fields'):
|
|
3133
|
-
for
|
|
3134
|
-
|
|
3205
|
+
for field_info in cls_info['fields']:
|
|
3206
|
+
# Handle both old (type, name) and new (type, name, array_size) formats
|
|
3207
|
+
if len(field_info) >= 3:
|
|
3208
|
+
field_type, field_name, array_size = field_info
|
|
3209
|
+
else:
|
|
3210
|
+
field_type, field_name = field_info
|
|
3211
|
+
array_size = 0
|
|
3212
|
+
|
|
3213
|
+
if array_size > 0:
|
|
3214
|
+
# Array field: use FIELD_ARRAY with type info for proper binding
|
|
3215
|
+
f.write(f' FIELD_ARRAY({field_name}, {field_type}, {array_size})\n')
|
|
3216
|
+
else:
|
|
3217
|
+
f.write(f' FIELD({field_name})\n')
|
|
3135
3218
|
|
|
3136
3219
|
f.write(f' }}\n')
|
|
3137
3220
|
|
|
@@ -3155,6 +3238,7 @@ def plugin(plugin_name, files, private):
|
|
|
3155
3238
|
f.write(')\n')
|
|
3156
3239
|
|
|
3157
3240
|
click.secho(f"Generated plugin: {cp_file}", fg='green', bold=True)
|
|
3241
|
+
click.echo(f"Enums found: {len(enums)}")
|
|
3158
3242
|
click.echo(f"Classes found: {len(classes)}")
|
|
3159
3243
|
total_fields = sum(len(c.get('fields', [])) for c in classes.values())
|
|
3160
3244
|
if total_fields:
|
|
@@ -6439,21 +6523,45 @@ def cppy_convert(files, to_cpp, to_py, no_header, output, ns, verbose, use_ai, u
|
|
|
6439
6523
|
|
|
6440
6524
|
|
|
6441
6525
|
def _resolve_cp_source(cp_file: Path, project_root: Path) -> Path:
|
|
6442
|
-
"""Resolve SOURCE() directive from .cp file to actual source file.
|
|
6526
|
+
"""Resolve SOURCE() directive from .cp file to actual source file.
|
|
6527
|
+
|
|
6528
|
+
Returns the first valid source file found. Supports:
|
|
6529
|
+
- Single file: SOURCE(file.cpp)
|
|
6530
|
+
- Multiple files in one SOURCE: SOURCE(file1.cpp file2.cpp)
|
|
6531
|
+
- Multiple SOURCE declarations: SOURCE(file1.cpp) && SOURCE(file2.cpp)
|
|
6532
|
+
"""
|
|
6443
6533
|
try:
|
|
6444
6534
|
content = cp_file.read_text(encoding='utf-8', errors='replace')
|
|
6445
6535
|
import re
|
|
6446
|
-
|
|
6447
|
-
|
|
6448
|
-
|
|
6449
|
-
|
|
6450
|
-
|
|
6451
|
-
|
|
6452
|
-
|
|
6453
|
-
|
|
6454
|
-
|
|
6455
|
-
|
|
6456
|
-
|
|
6536
|
+
|
|
6537
|
+
# Find all SOURCE() declarations
|
|
6538
|
+
source_matches = re.findall(r'SOURCE\s*\(\s*([^)]+)\s*\)', content)
|
|
6539
|
+
for sources_str in source_matches:
|
|
6540
|
+
# Handle multiple files within one SOURCE()
|
|
6541
|
+
sources = re.split(r'[,\s]+', sources_str.strip())
|
|
6542
|
+
for source_name in sources:
|
|
6543
|
+
source_name = source_name.strip().strip('"\'')
|
|
6544
|
+
if not source_name:
|
|
6545
|
+
continue
|
|
6546
|
+
|
|
6547
|
+
include_dir = project_root / "include"
|
|
6548
|
+
|
|
6549
|
+
# Try direct path first (relative to project root)
|
|
6550
|
+
direct_from_root = project_root / source_name
|
|
6551
|
+
if direct_from_root.exists():
|
|
6552
|
+
return direct_from_root
|
|
6553
|
+
|
|
6554
|
+
# Try in include directory
|
|
6555
|
+
direct = include_dir / source_name
|
|
6556
|
+
if direct.exists():
|
|
6557
|
+
return direct
|
|
6558
|
+
|
|
6559
|
+
# Try with different extensions
|
|
6560
|
+
for ext in ['.cpp', '.h', '.hpp', '.cc', '.cxx']:
|
|
6561
|
+
base_name = source_name.replace('.cpp', '').replace('.h', '').replace('.hpp', '')
|
|
6562
|
+
candidate = include_dir / (base_name + ext)
|
|
6563
|
+
if candidate.exists():
|
|
6564
|
+
return candidate
|
|
6457
6565
|
except Exception:
|
|
6458
6566
|
pass
|
|
6459
6567
|
return None
|
|
@@ -387,9 +387,11 @@ target_include_directories(api PRIVATE
|
|
|
387
387
|
)
|
|
388
388
|
|
|
389
389
|
if(MSVC)
|
|
390
|
-
|
|
390
|
+
# /wd4018: disable signed/unsigned comparison warning (pybind11 enum issue)
|
|
391
|
+
target_compile_options(api PRIVATE /W3 /O2 /EHsc /MT /wd4018 /wd4267)
|
|
391
392
|
else()
|
|
392
|
-
|
|
393
|
+
# -Wno-sign-compare: disable signed/unsigned comparison warning (pybind11 enum issue)
|
|
394
|
+
target_compile_options(api PRIVATE -Wall -O3 -pthread -Wno-sign-compare)
|
|
393
395
|
# MinGW on Windows: static linking for MinGW runtime and pthread
|
|
394
396
|
if(WIN32)
|
|
395
397
|
target_link_options(api PRIVATE -static-libgcc -static-libstdc++ -Wl,-Bstatic -lpthread -Wl,-Bdynamic -lws2_32)
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"""Auto-generated type stubs for IncludeCPP module wrappers.
|
|
2
|
+
|
|
3
|
+
This file enables VSCode IntelliSense autocomplete for C++ modules.
|
|
4
|
+
DO NOT EDIT - Auto-generated by IncludeCPP build system.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Any, List, Dict, Optional, Union, Protocol, overload
|
|
8
|
+
|
|
9
|
+
class StepcompilerModuleWrapper(Protocol):
|
|
10
|
+
"""Type hints for stepcompiler module wrapper (VSCode autocomplete support)."""
|
|
11
|
+
|
|
12
|
+
def getInfo(self) -> Dict[str, Any]:
|
|
13
|
+
"""Get stepcompiler module information."""
|
|
14
|
+
...
|
|
15
|
+
|
|
16
|
+
class CryptoUtils:
|
|
17
|
+
"""C++ class: CryptoUtils"""
|
|
18
|
+
|
|
19
|
+
def __init__(self) -> None:
|
|
20
|
+
"""Initialize CryptoUtils instance"""
|
|
21
|
+
...
|
|
22
|
+
|
|
23
|
+
def binaryToByte(self, *args: Any, **kwargs: Any) -> Any:
|
|
24
|
+
"""C++ method: binaryToByte"""
|
|
25
|
+
...
|
|
26
|
+
|
|
27
|
+
def byteToBinary(self, *args: Any, **kwargs: Any) -> Any:
|
|
28
|
+
"""C++ method: byteToBinary"""
|
|
29
|
+
...
|
|
30
|
+
|
|
31
|
+
def compress(self, *args: Any, **kwargs: Any) -> Any:
|
|
32
|
+
"""C++ method: compress"""
|
|
33
|
+
...
|
|
34
|
+
|
|
35
|
+
def crc32(self, *args: Any, **kwargs: Any) -> Any:
|
|
36
|
+
"""C++ method: crc32"""
|
|
37
|
+
...
|
|
38
|
+
|
|
39
|
+
def decompress(self, *args: Any, **kwargs: Any) -> Any:
|
|
40
|
+
"""C++ method: decompress"""
|
|
41
|
+
...
|
|
42
|
+
|
|
43
|
+
def deriveKeyStream(self, *args: Any, **kwargs: Any) -> Any:
|
|
44
|
+
"""C++ method: deriveKeyStream"""
|
|
45
|
+
...
|
|
46
|
+
|
|
47
|
+
def fromHexString(self, *args: Any, **kwargs: Any) -> Any:
|
|
48
|
+
"""C++ method: fromHexString"""
|
|
49
|
+
...
|
|
50
|
+
|
|
51
|
+
def generateIV(self, *args: Any, **kwargs: Any) -> Any:
|
|
52
|
+
"""C++ method: generateIV"""
|
|
53
|
+
...
|
|
54
|
+
|
|
55
|
+
def hashKey(self, *args: Any, **kwargs: Any) -> Any:
|
|
56
|
+
"""C++ method: hashKey"""
|
|
57
|
+
...
|
|
58
|
+
|
|
59
|
+
def scramble(self, *args: Any, **kwargs: Any) -> Any:
|
|
60
|
+
"""C++ method: scramble"""
|
|
61
|
+
...
|
|
62
|
+
|
|
63
|
+
def toHexString(self, *args: Any, **kwargs: Any) -> Any:
|
|
64
|
+
"""C++ method: toHexString"""
|
|
65
|
+
...
|
|
66
|
+
|
|
67
|
+
def xorEncrypt(self, *args: Any, **kwargs: Any) -> Any:
|
|
68
|
+
"""C++ method: xorEncrypt"""
|
|
69
|
+
...
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class HDFileHeader:
|
|
73
|
+
"""C++ class: HDFileHeader"""
|
|
74
|
+
|
|
75
|
+
def __init__(self) -> None:
|
|
76
|
+
"""Initialize HDFileHeader instance"""
|
|
77
|
+
...
|
|
78
|
+
|
|
79
|
+
pass
|
|
80
|
+
|
|
81
|
+
class StepCompiler:
|
|
82
|
+
"""C++ class: StepCompiler"""
|
|
83
|
+
|
|
84
|
+
@overload
|
|
85
|
+
def __init__(self) -> None: ...
|
|
86
|
+
@overload
|
|
87
|
+
def __init__(self, arg0: str, arg1: str, arg2: str, arg3: str, arg4: bool, arg5: bool) -> None: ...
|
|
88
|
+
|
|
89
|
+
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
|
90
|
+
"""Initialize StepCompiler instance"""
|
|
91
|
+
...
|
|
92
|
+
|
|
93
|
+
def Decrypt(self, *args: Any, **kwargs: Any) -> Any:
|
|
94
|
+
"""C++ method: Decrypt"""
|
|
95
|
+
...
|
|
96
|
+
|
|
97
|
+
def Encrypt(self, *args: Any, **kwargs: Any) -> Any:
|
|
98
|
+
"""C++ method: Encrypt"""
|
|
99
|
+
...
|
|
100
|
+
|
|
101
|
+
def GetHeader(self, *args: Any, **kwargs: Any) -> Any:
|
|
102
|
+
"""C++ method: GetHeader"""
|
|
103
|
+
...
|
|
104
|
+
|
|
105
|
+
def GetOutputPath(self, *args: Any, **kwargs: Any) -> Any:
|
|
106
|
+
"""C++ method: GetOutputPath"""
|
|
107
|
+
...
|
|
108
|
+
|
|
109
|
+
def GetStatusMessage(self, *args: Any, **kwargs: Any) -> Any:
|
|
110
|
+
"""C++ method: GetStatusMessage"""
|
|
111
|
+
...
|
|
112
|
+
|
|
113
|
+
def Init(self, *args: Any, **kwargs: Any) -> Any:
|
|
114
|
+
"""C++ method: Init"""
|
|
115
|
+
...
|
|
116
|
+
|
|
117
|
+
def Process(self, *args: Any, **kwargs: Any) -> Any:
|
|
118
|
+
"""C++ method: Process"""
|
|
119
|
+
...
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
# CppApi with typed include() overloads for each module
|
|
125
|
+
class CppApi:
|
|
126
|
+
"""C++ API Manager with typed module loading.
|
|
127
|
+
|
|
128
|
+
The include() method returns a module wrapper with full type hints
|
|
129
|
+
for VSCode/PyCharm autocomplete support.
|
|
130
|
+
"""
|
|
131
|
+
|
|
132
|
+
def __init__(self, project_root: Optional[str] = None, auto_update: bool = True) -> None:
|
|
133
|
+
"""Initialize CppApi.
|
|
134
|
+
|
|
135
|
+
Args:
|
|
136
|
+
project_root: Path to project root (default: auto-detect)
|
|
137
|
+
auto_update: Whether to auto-rebuild on source changes
|
|
138
|
+
"""
|
|
139
|
+
...
|
|
140
|
+
|
|
141
|
+
@overload
|
|
142
|
+
def include(self, module_name: str = "stepcompiler", auto_update: Optional[bool] = None) -> StepcompilerModuleWrapper: ...
|
|
143
|
+
|
|
144
|
+
@overload
|
|
145
|
+
def include(self, module_name: str, auto_update: Optional[bool] = None) -> Any: ...
|
|
146
|
+
|
|
147
|
+
def include(self, module_name: str, auto_update: Optional[bool] = None) -> Any:
|
|
148
|
+
"""Load a C++ module.
|
|
149
|
+
|
|
150
|
+
Args:
|
|
151
|
+
module_name: Name of the module to load
|
|
152
|
+
auto_update: Override auto-update setting for this module
|
|
153
|
+
|
|
154
|
+
Returns:
|
|
155
|
+
ModuleWrapper with access to C++ classes, functions, and structs
|
|
156
|
+
"""
|
|
157
|
+
...
|
|
158
|
+
|
|
159
|
+
def rebuild(self, verbose: bool = False) -> bool:
|
|
160
|
+
"""Rebuild all C++ modules."""
|
|
161
|
+
...
|
|
162
|
+
|
|
163
|
+
def list_modules(self) -> List[str]:
|
|
164
|
+
"""List available modules."""
|
|
165
|
+
...
|