@@ -17,7 +17,9 @@ def GlobRecursive(path, pattern, **kwargs):
1717KEYWORDS = ['GPROPERTY' , 'GMETHOD' , 'GGROUP' , 'GSUBGROUP' , 'GBITFIELD' , 'GSIGNAL' , 'GRPC' , 'GVARARG' , 'GIGNORE' ]
1818INIT_LEVELS = ['GINIT_LEVEL_CORE' , 'GINIT_LEVEL_SERVERS' , 'GINIT_LEVEL_SCENE' , 'GINIT_LEVEL_EDITOR' ]
1919
20- CPPSCRIPT_BODY = """#ifndef {0}
20+ DONOTEDIT_MSG = "/*-- GENERATED FILE - DO NOT EDIT --*/\n \n "
21+
22+ CPPSCRIPT_BODY = DONOTEDIT_MSG + """#ifndef {0}
2123#define {0}
2224#include <cppscript_defs.h>
2325#include "properties.gen.h"
@@ -39,7 +41,7 @@ class CppScriptException(Exception):
3941 pass
4042
4143def filename_to_gen_filename (name , env ):
42- return os .path .join (env ['gen_dir' ], os .path .relpath (name .replace ('.hpp' , '.gen.cpp' ), env ['src ' ]))
44+ return os .path .join (env ['gen_dir' ], os .path .relpath (name .replace ('.hpp' , '.gen.cpp' ), env ['header_dir ' ]))
4345
4446
4547def collapse_list (list , key , action ):
@@ -149,31 +151,58 @@ def is_virtual_method(cursor):
149151
150152# Builder
151153def generate_header_emitter (target , source , env ):
152- return [env .File (env ['gen_header' ] )] + [env .File (filename_to_gen_filename (str (i ), env )) for i in source ], source
154+ return [env .File (os . path . join ( env ['header_dir' ], 'scripts.gen.h' ) )] + [env .File (filename_to_gen_filename (str (i ), env )) for i in source ], source
153155
154156
155157def generate_header_scons (target , source , env ):
156- return generate_header (target , source , env , get_file_scons )
158+ # Convert scons variables to cppscript's env
159+ cppscript_env = {
160+ 'header_name' : env ['header_name' ],
161+ 'header_dir' : env ['header_dir' ],
162+ 'gen_dir' : env ['gen_dir' ],
163+ 'compile_defs' : [f'{ i [0 ]} ={ i [1 ]} ' if type (i ) is tuple else str (i ) for i in env ['CPPDEFINES' ]],
164+ 'include_paths' : env ['CPPPATH' ],
165+ 'auto_methods' : env ['auto_methods' ]
166+ }
167+
157168
169+ return generate_header (target , source , cppscript_env , get_file_scons )
158170
159- def generate_header_cmake (target , source , env ):
160- return generate_header (target , source , env , get_file_cmake )
171+
172+ def generate_header_cmake (source , env ):
173+ return generate_header (None , source , env , get_file_cmake )
161174
162175
163176def generate_header (target , source , env , get_file ):
164177 index = Index .create ()
165- prop_file_name = os .path .join (env ['src' ], 'properties.gen.h' )
178+ prop_file_name = os .path .join (env ['header_dir' ], 'properties.gen.h' )
179+
180+ # Move properties file if exists to avoid infinite cycle for auto-genereted getter/setters:
181+ # no method definition -> generate one -> parse |
182+ # ^ V
183+ # | do NOT generate one <- method exists
166184 try :
167185 shutil .move (prop_file_name , prop_file_name + '.tmp' )
168186 except :
169187 pass
170188
189+ # Create include header if not exists
190+ path = os .path .join (env ['header_dir' ], env ['header_name' ])
191+ if not os .path .exists (path ):
192+ with open (path , 'w' ) as file :
193+ file .write (CPPSCRIPT_BODY .format (env ['header_name' ].replace (' ' , '_' ).replace ('.' , '_' ).upper ()))
194+
171195 try :
172196 defs_file_path = os .path .join (env ['gen_dir' ], 'defs.json' )
173197 cached_defs_all = load_defs_json (defs_file_path )
174198 cached_defs = cached_defs_all .get ('files' , {})
175199 need_regen = False
176200
201+ # Prepare parser args
202+ env ['parser_args' ] = [f'-I{ i } ' for i in env ['include_paths' ]] + \
203+ [f'-D{ i } ' for i in env ['compile_defs' ]] + \
204+ [f'-DGDCLASS' ]
205+
177206 new_defs_files = {}
178207 for s in source :
179208 filename , file_content = get_file (s )
@@ -186,12 +215,6 @@ def generate_header(target, source, env, get_file):
186215
187216 new_defs_all = {'hash' : cached_defs_all .get ('hash' , None ), 'files' : new_defs_files }
188217
189- # Create include header if not exists
190- path = os .path .join (env ['src' ], env ['header_name' ])
191- if not os .path .exists (path ):
192- with open (path , 'w' ) as file :
193- file .write (CPPSCRIPT_BODY .format (env ['header_name' ].replace (' ' , '_' ).replace ('.' , '_' ).upper ()))
194-
195218 if write_register_header (new_defs_all , env ) or need_regen :
196219 write_property_header (new_defs_all , env )
197220 try :
@@ -213,8 +236,8 @@ def generate_header(target, source, env, get_file):
213236
214237 return 0
215238
216- def parse_header (index , filename , filecontent , src , auto_methods ):
217- translation_unit = index .parse (filename , args = [ f'-I { src } ' , '-Isrc' , '-DGDCLASS ' ], unsaved_files = [(filename , filecontent )], options = TranslationUnit .PARSE_DETAILED_PROCESSING_RECORD )
239+ def parse_header (index , filename , filecontent , env ):
240+ translation_unit = index .parse (filename , args = env [ 'parser_args ' ], unsaved_files = [(filename , filecontent )], options = TranslationUnit .PARSE_DETAILED_PROCESSING_RECORD )
218241
219242 if not translation_unit :
220243 raise CppScriptException ("{filename}: failed to create translation unit" )
@@ -433,7 +456,7 @@ def apply_macros(item, macros):
433456 case CursorKind .CXX_METHOD :
434457 is_virtual = is_virtual_method (item )
435458 properties = {}
436- if process_macros (item , macros , properties , (is_virtual and item .spelling .startswith ('_' )) or not auto_methods ):
459+ if process_macros (item , macros , properties , (is_virtual and item .spelling .startswith ('_' )) or not env [ ' auto_methods' ] ):
437460 properties |= { 'name' : item .spelling ,
438461 'bind_name' : item .spelling ,
439462 'return' : item .result_type .spelling ,
@@ -481,14 +504,13 @@ def apply_macros(item, macros):
481504
482505
483506def parse_and_write_header (index , filename , filecontent , env ):
484- defs = parse_header (index , filename , filecontent , env [ 'src' ], env [ 'auto_methods' ] )
507+ defs = parse_header (index , filename , filecontent , env )
485508 write_header (filename , defs , env )
486509
487510 return defs
488511
489512
490513def write_header (file , defs , env ):
491- src = env ['src' ]
492514 header_defs = []
493515 for class_name_full , content in defs .items ():
494516 class_name = content ['class_name' ]
@@ -584,29 +606,28 @@ def write_header(file, defs, env):
584606 ([property_set_get_defs ] if property_set_get_defs != '' else []) + \
585607 ([outside_bind ] if outside_bind != '' else [])
586608
587- file_name = filename_to_gen_filename (file , env )
609+ gen_filename = filename_to_gen_filename (file , env )
588610 content = ''
589611 if len (defs ) != 0 :
590- header_include = '#include <cppscript_bindings.h>\n \n #include <{}> \n \n using namespace godot;\n \n ' .format (os .path .relpath (file , src ).replace ('\\ ' , '/' ))
591- content = header_include + '\n ' .join (header_defs )
612+ header_include = '#include <cppscript_bindings.h>\n \n #include "{}" \n \n using namespace godot;\n \n ' .format (os .path .relpath (file , os . path . dirname ( gen_filename ) ).replace ('\\ ' , '/' ))
613+ content = DONOTEDIT_MSG + header_include + '\n ' .join (header_defs )
592614
593- os .makedirs (os .path .dirname (file_name ), exist_ok = True )
594- with open (file_name , 'w' ) as fileopen :
615+ os .makedirs (os .path .dirname (gen_filename ), exist_ok = True )
616+ with open (gen_filename , 'w' ) as fileopen :
595617 fileopen .write (content )
596618
597619
598620def write_register_header (defs_all , env ):
599- src = env ['src' ]
600- target = env ['gen_header' ]
601- scripts_header = ''
621+ target = os .path .join (env ['header_dir' ], 'scripts.gen.h' )
622+ scripts_header = DONOTEDIT_MSG
602623 classes_register_levels = {name [12 :] : [] for name in INIT_LEVELS }
603624
604625 for file , filecontent in defs_all ['files' ].items ():
605626 classes = filecontent ['content' ]
606627 if len (classes ) == 0 :
607628 continue
608629
609- scripts_header += '#include <{}> \n ' .format (os .path .relpath (file , src ).replace ('\\ ' , '/' ))
630+ scripts_header += '#include "{}" \n ' .format (os .path .relpath (file , os . path . dirname ( target ) ).replace ('\\ ' , '/' ))
610631 for class_name_full , content in classes .items ():
611632 # Ensure parent classes are registered before children
612633 # by iterating throught pairs of (base_name, register_str)
@@ -644,8 +665,8 @@ def write_register_header(defs_all, env):
644665
645666
646667def write_property_header (new_defs , env ):
647- filepath = os .path .join (env ['src ' ], 'properties.gen.h' )
648- body = ''
668+ filepath = os .path .join (env ['header_dir ' ], 'properties.gen.h' )
669+ body = DONOTEDIT_MSG
649670 for filename , filecontent in new_defs ['files' ].items ():
650671 classcontent = filecontent ['content' ]
651672 for class_name_full , content in classcontent .items ():
0 commit comments