mirror of
				https://github.com/godotengine/godot.git
				synced 2025-10-31 13:41:03 +00:00 
			
		
		
		
	C# bindings generator cleanup
- Normal log messages are no longer warnings. - BindingsGenerator is no longer a singleton. - Added a log function.
This commit is contained in:
		
							parent
							
								
									bf1fe11143
								
							
						
					
					
						commit
						c20a3823a2
					
				
					 7 changed files with 139 additions and 108 deletions
				
			
		|  | @ -131,14 +131,6 @@ void CSharpLanguage::finish() { | ||||||
| 
 | 
 | ||||||
| 	finalizing = true; | 	finalizing = true; | ||||||
| 
 | 
 | ||||||
| #ifdef TOOLS_ENABLED |  | ||||||
| 	// Must be here, to avoid StringName leaks
 |  | ||||||
| 	if (BindingsGenerator::singleton) { |  | ||||||
| 		memdelete(BindingsGenerator::singleton); |  | ||||||
| 		BindingsGenerator::singleton = NULL; |  | ||||||
| 	} |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| 	// Make sure all script binding gchandles are released before finalizing GDMono
 | 	// Make sure all script binding gchandles are released before finalizing GDMono
 | ||||||
| 	for (Map<Object *, CSharpScriptBinding>::Element *E = script_bindings.front(); E; E = E->next()) { | 	for (Map<Object *, CSharpScriptBinding>::Element *E = script_bindings.front(); E; E = E->next()) { | ||||||
| 		CSharpScriptBinding &script_binding = E->value(); | 		CSharpScriptBinding &script_binding = E->value(); | ||||||
|  |  | ||||||
|  | @ -101,10 +101,6 @@ | ||||||
| 
 | 
 | ||||||
| const char *BindingsGenerator::TypeInterface::DEFAULT_VARARG_C_IN("\t%0 %1_in = %1;\n"); | const char *BindingsGenerator::TypeInterface::DEFAULT_VARARG_C_IN("\t%0 %1_in = %1;\n"); | ||||||
| 
 | 
 | ||||||
| bool BindingsGenerator::verbose_output = false; |  | ||||||
| 
 |  | ||||||
| BindingsGenerator *BindingsGenerator::singleton = NULL; |  | ||||||
| 
 |  | ||||||
| static String fix_doc_description(const String &p_bbcode) { | static String fix_doc_description(const String &p_bbcode) { | ||||||
| 
 | 
 | ||||||
| 	// This seems to be the correct way to do this. It's the same EditorHelp does.
 | 	// This seems to be the correct way to do this. It's the same EditorHelp does.
 | ||||||
|  | @ -816,9 +812,7 @@ void BindingsGenerator::_generate_global_constants(StringBuilder &p_output) { | ||||||
| 
 | 
 | ||||||
| 			CRASH_COND(enum_class_name != "Variant"); // Hard-coded...
 | 			CRASH_COND(enum_class_name != "Variant"); // Hard-coded...
 | ||||||
| 
 | 
 | ||||||
| 			if (verbose_output) { | 			_log("Declaring global enum `%s` inside static class `%s`\n", enum_proxy_name.utf8().get_data(), enum_class_name.utf8().get_data()); | ||||||
| 				WARN_PRINTS("Declaring global enum `" + enum_proxy_name + "` inside static class `" + enum_class_name + "`"); |  | ||||||
| 			} |  | ||||||
| 
 | 
 | ||||||
| 			p_output.append("\n" INDENT1 "public static partial class "); | 			p_output.append("\n" INDENT1 "public static partial class "); | ||||||
| 			p_output.append(enum_class_name); | 			p_output.append(enum_class_name); | ||||||
|  | @ -867,9 +861,7 @@ void BindingsGenerator::_generate_global_constants(StringBuilder &p_output) { | ||||||
| 	p_output.append("\n#pragma warning restore CS1591\n"); | 	p_output.append("\n#pragma warning restore CS1591\n"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Error BindingsGenerator::generate_cs_core_project(const String &p_solution_dir, DotNetSolution &r_solution, bool p_verbose_output) { | Error BindingsGenerator::generate_cs_core_project(const String &p_solution_dir, DotNetSolution &r_solution) { | ||||||
| 
 |  | ||||||
| 	verbose_output = p_verbose_output; |  | ||||||
| 
 | 
 | ||||||
| 	String proj_dir = p_solution_dir.plus_file(CORE_API_ASSEMBLY_NAME); | 	String proj_dir = p_solution_dir.plus_file(CORE_API_ASSEMBLY_NAME); | ||||||
| 
 | 
 | ||||||
|  | @ -1001,15 +993,12 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_solution_dir, | ||||||
| 
 | 
 | ||||||
| 	r_solution.add_new_project(CORE_API_ASSEMBLY_NAME, proj_info); | 	r_solution.add_new_project(CORE_API_ASSEMBLY_NAME, proj_info); | ||||||
| 
 | 
 | ||||||
| 	if (verbose_output) | 	_log("The solution and C# project for the Core API was generated successfully\n"); | ||||||
| 		OS::get_singleton()->print("The solution and C# project for the Core API was generated successfully\n"); |  | ||||||
| 
 | 
 | ||||||
| 	return OK; | 	return OK; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Error BindingsGenerator::generate_cs_editor_project(const String &p_solution_dir, DotNetSolution &r_solution, bool p_verbose_output) { | Error BindingsGenerator::generate_cs_editor_project(const String &p_solution_dir, DotNetSolution &r_solution) { | ||||||
| 
 |  | ||||||
| 	verbose_output = p_verbose_output; |  | ||||||
| 
 | 
 | ||||||
| 	String proj_dir = p_solution_dir.plus_file(EDITOR_API_ASSEMBLY_NAME); | 	String proj_dir = p_solution_dir.plus_file(EDITOR_API_ASSEMBLY_NAME); | ||||||
| 
 | 
 | ||||||
|  | @ -1100,13 +1089,12 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_solution_dir | ||||||
| 
 | 
 | ||||||
| 	r_solution.add_new_project(EDITOR_API_ASSEMBLY_NAME, proj_info); | 	r_solution.add_new_project(EDITOR_API_ASSEMBLY_NAME, proj_info); | ||||||
| 
 | 
 | ||||||
| 	if (verbose_output) | 	_log("The solution and C# project for the Editor API was generated successfully\n"); | ||||||
| 		OS::get_singleton()->print("The solution and C# project for the Editor API was generated successfully\n"); |  | ||||||
| 
 | 
 | ||||||
| 	return OK; | 	return OK; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Error BindingsGenerator::generate_cs_api(const String &p_output_dir, bool p_verbose_output) { | Error BindingsGenerator::generate_cs_api(const String &p_output_dir) { | ||||||
| 
 | 
 | ||||||
| 	DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); | 	DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); | ||||||
| 	ERR_FAIL_COND_V(!da, ERR_CANT_CREATE); | 	ERR_FAIL_COND_V(!da, ERR_CANT_CREATE); | ||||||
|  | @ -1123,13 +1111,13 @@ Error BindingsGenerator::generate_cs_api(const String &p_output_dir, bool p_verb | ||||||
| 
 | 
 | ||||||
| 	Error proj_err; | 	Error proj_err; | ||||||
| 
 | 
 | ||||||
| 	proj_err = generate_cs_core_project(p_output_dir, solution, p_verbose_output); | 	proj_err = generate_cs_core_project(p_output_dir, solution); | ||||||
| 	if (proj_err != OK) { | 	if (proj_err != OK) { | ||||||
| 		ERR_PRINT("Generation of the Core API C# project failed"); | 		ERR_PRINT("Generation of the Core API C# project failed"); | ||||||
| 		return proj_err; | 		return proj_err; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	proj_err = generate_cs_editor_project(p_output_dir, solution, p_verbose_output); | 	proj_err = generate_cs_editor_project(p_output_dir, solution); | ||||||
| 	if (proj_err != OK) { | 	if (proj_err != OK) { | ||||||
| 		ERR_PRINT("Generation of the Editor API C# project failed"); | 		ERR_PRINT("Generation of the Editor API C# project failed"); | ||||||
| 		return proj_err; | 		return proj_err; | ||||||
|  | @ -1168,8 +1156,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str | ||||||
| 
 | 
 | ||||||
| 	List<InternalCall> &custom_icalls = itype.api_type == ClassDB::API_EDITOR ? editor_custom_icalls : core_custom_icalls; | 	List<InternalCall> &custom_icalls = itype.api_type == ClassDB::API_EDITOR ? editor_custom_icalls : core_custom_icalls; | ||||||
| 
 | 
 | ||||||
| 	if (verbose_output) | 	_log("Generating %s.cs...\n", itype.proxy_name.utf8().get_data()); | ||||||
| 		OS::get_singleton()->print("Generating %s.cs...\n", itype.proxy_name.utf8().get_data()); |  | ||||||
| 
 | 
 | ||||||
| 	String ctor_method(ICALL_PREFIX + itype.proxy_name + "_Ctor"); // Used only for derived types
 | 	String ctor_method(ICALL_PREFIX + itype.proxy_name + "_Ctor"); // Used only for derived types
 | ||||||
| 
 | 
 | ||||||
|  | @ -1710,8 +1697,6 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf | ||||||
| 
 | 
 | ||||||
| Error BindingsGenerator::generate_glue(const String &p_output_dir) { | Error BindingsGenerator::generate_glue(const String &p_output_dir) { | ||||||
| 
 | 
 | ||||||
| 	verbose_output = true; |  | ||||||
| 
 |  | ||||||
| 	bool dir_exists = DirAccess::exists(p_output_dir); | 	bool dir_exists = DirAccess::exists(p_output_dir); | ||||||
| 	ERR_EXPLAIN("The output directory does not exist."); | 	ERR_EXPLAIN("The output directory does not exist."); | ||||||
| 	ERR_FAIL_COND_V(!dir_exists, ERR_FILE_BAD_PATH); | 	ERR_FAIL_COND_V(!dir_exists, ERR_FILE_BAD_PATH); | ||||||
|  | @ -2128,15 +2113,13 @@ void BindingsGenerator::_populate_object_type_interfaces() { | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (!ClassDB::is_class_exposed(type_cname)) { | 		if (!ClassDB::is_class_exposed(type_cname)) { | ||||||
| 			if (verbose_output) | 			_log("Ignoring type `%s` because it's not exposed\n", String(type_cname).utf8().get_data()); | ||||||
| 				WARN_PRINTS("Ignoring type " + type_cname.operator String() + " because it's not exposed"); |  | ||||||
| 			class_list.pop_front(); | 			class_list.pop_front(); | ||||||
| 			continue; | 			continue; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (!ClassDB::is_class_enabled(type_cname)) { | 		if (!ClassDB::is_class_enabled(type_cname)) { | ||||||
| 			if (verbose_output) | 			_log("Ignoring type `%s` because it's not enabled\n", String(type_cname).utf8().get_data()); | ||||||
| 				WARN_PRINTS("Ignoring type " + type_cname.operator String() + " because it's not enabled"); |  | ||||||
| 			class_list.pop_front(); | 			class_list.pop_front(); | ||||||
| 			continue; | 			continue; | ||||||
| 		} | 		} | ||||||
|  | @ -2186,12 +2169,10 @@ void BindingsGenerator::_populate_object_type_interfaces() { | ||||||
| 
 | 
 | ||||||
| 			iprop.proxy_name = escape_csharp_keyword(snake_to_pascal_case(iprop.cname)); | 			iprop.proxy_name = escape_csharp_keyword(snake_to_pascal_case(iprop.cname)); | ||||||
| 
 | 
 | ||||||
| 			// Prevent property and enclosing type from sharing the same name
 | 			// Prevent the property and its enclosing type from sharing the same name
 | ||||||
| 			if (iprop.proxy_name == itype.proxy_name) { | 			if (iprop.proxy_name == itype.proxy_name) { | ||||||
| 				if (verbose_output) { | 				_log("Name of property `%s` is ambiguous with the name of its enclosing class `%s`. Renaming property to `%s_`\n", | ||||||
| 					WARN_PRINTS("Name of property `" + iprop.proxy_name + "` is ambiguous with the name of its class `" + | 						iprop.proxy_name.utf8().get_data(), itype.proxy_name.utf8().get_data(), iprop.proxy_name.utf8().get_data()); | ||||||
| 								itype.proxy_name + "`. Renaming property to `" + iprop.proxy_name + "_`"); |  | ||||||
| 				} |  | ||||||
| 
 | 
 | ||||||
| 				iprop.proxy_name += "_"; | 				iprop.proxy_name += "_"; | ||||||
| 			} | 			} | ||||||
|  | @ -2258,14 +2239,13 @@ void BindingsGenerator::_populate_object_type_interfaces() { | ||||||
| 					// which could actually will return something different.
 | 					// which could actually will return something different.
 | ||||||
| 					// Let's put this to notify us if that ever happens.
 | 					// Let's put this to notify us if that ever happens.
 | ||||||
| 					if (itype.cname != name_cache.type_Object || imethod.name != "free") { | 					if (itype.cname != name_cache.type_Object || imethod.name != "free") { | ||||||
| 						if (verbose_output) { | 						ERR_PRINTS("Notification: New unexpected virtual non-overridable method found.\n" | ||||||
| 							WARN_PRINTS("Notification: New unexpected virtual non-overridable method found.\n" | 								   "We only expected Object.free, but found " + | ||||||
| 										"We only expected Object.free, but found " + | 								   itype.name + "." + imethod.name); | ||||||
| 										itype.name + "." + imethod.name); |  | ||||||
| 						} |  | ||||||
| 					} | 					} | ||||||
| 				} else { | 				} else { | ||||||
| 					ERR_PRINTS("Missing MethodBind for non-virtual method: " + itype.name + "." + imethod.name); | 					ERR_EXPLAIN("Missing MethodBind for non-virtual method: " + itype.name + "." + imethod.name); | ||||||
|  | 					ERR_FAIL(); | ||||||
| 				} | 				} | ||||||
| 			} else if (return_info.type == Variant::INT && return_info.usage & PROPERTY_USAGE_CLASS_IS_ENUM) { | 			} else if (return_info.type == Variant::INT && return_info.usage & PROPERTY_USAGE_CLASS_IS_ENUM) { | ||||||
| 				imethod.return_type.cname = return_info.class_name; | 				imethod.return_type.cname = return_info.class_name; | ||||||
|  | @ -2319,12 +2299,10 @@ void BindingsGenerator::_populate_object_type_interfaces() { | ||||||
| 
 | 
 | ||||||
| 			imethod.proxy_name = escape_csharp_keyword(snake_to_pascal_case(imethod.name)); | 			imethod.proxy_name = escape_csharp_keyword(snake_to_pascal_case(imethod.name)); | ||||||
| 
 | 
 | ||||||
| 			// Prevent naming the property and its enclosing type from sharing the same name
 | 			// Prevent the method and its enclosing type from sharing the same name
 | ||||||
| 			if (imethod.proxy_name == itype.proxy_name) { | 			if (imethod.proxy_name == itype.proxy_name) { | ||||||
| 				if (verbose_output) { | 				_log("Name of method `%s` is ambiguous with the name of its enclosing class `%s`. Renaming method to `%s_`\n", | ||||||
| 					WARN_PRINTS("Name of method `" + imethod.proxy_name + "` is ambiguous with the name of its class `" + | 						imethod.proxy_name.utf8().get_data(), itype.proxy_name.utf8().get_data(), imethod.proxy_name.utf8().get_data()); | ||||||
| 								itype.proxy_name + "`. Renaming method to `" + imethod.proxy_name + "_`"); |  | ||||||
| 				} |  | ||||||
| 
 | 
 | ||||||
| 				imethod.proxy_name += "_"; | 				imethod.proxy_name += "_"; | ||||||
| 			} | 			} | ||||||
|  | @ -2858,7 +2836,18 @@ void BindingsGenerator::_populate_global_constants() { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void BindingsGenerator::initialize() { | void BindingsGenerator::_log(const char *p_format, ...) { | ||||||
|  | 
 | ||||||
|  | 	if (log_print_enabled) { | ||||||
|  | 		va_list list; | ||||||
|  | 
 | ||||||
|  | 		va_start(list, p_format); | ||||||
|  | 		OS::get_singleton()->print("%s", str_format(p_format, list).utf8().get_data()); | ||||||
|  | 		va_end(list); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void BindingsGenerator::_initialize() { | ||||||
| 
 | 
 | ||||||
| 	EditorHelp::generate_doc(); | 	EditorHelp::generate_doc(); | ||||||
| 
 | 
 | ||||||
|  | @ -2881,12 +2870,13 @@ void BindingsGenerator::initialize() { | ||||||
| void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args) { | void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args) { | ||||||
| 
 | 
 | ||||||
| 	const int NUM_OPTIONS = 2; | 	const int NUM_OPTIONS = 2; | ||||||
| 	int options_left = NUM_OPTIONS; |  | ||||||
| 
 |  | ||||||
| 	String mono_glue_option = "--generate-mono-glue"; | 	String mono_glue_option = "--generate-mono-glue"; | ||||||
| 	String cs_api_option = "--generate-cs-api"; | 	String cs_api_option = "--generate-cs-api"; | ||||||
| 
 | 
 | ||||||
| 	verbose_output = true; | 	String mono_glue_path; | ||||||
|  | 	String cs_api_path; | ||||||
|  | 
 | ||||||
|  | 	int options_left = NUM_OPTIONS; | ||||||
| 
 | 
 | ||||||
| 	const List<String>::Element *elem = p_cmdline_args.front(); | 	const List<String>::Element *elem = p_cmdline_args.front(); | ||||||
| 
 | 
 | ||||||
|  | @ -2895,8 +2885,7 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args) | ||||||
| 			const List<String>::Element *path_elem = elem->next(); | 			const List<String>::Element *path_elem = elem->next(); | ||||||
| 
 | 
 | ||||||
| 			if (path_elem) { | 			if (path_elem) { | ||||||
| 				if (get_singleton()->generate_glue(path_elem->get()) != OK) | 				mono_glue_path = path_elem->get(); | ||||||
| 					ERR_PRINTS(mono_glue_option + ": Failed to generate mono glue"); |  | ||||||
| 				elem = elem->next(); | 				elem = elem->next(); | ||||||
| 			} else { | 			} else { | ||||||
| 				ERR_PRINTS(mono_glue_option + ": No output directory specified"); | 				ERR_PRINTS(mono_glue_option + ": No output directory specified"); | ||||||
|  | @ -2907,8 +2896,7 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args) | ||||||
| 			const List<String>::Element *path_elem = elem->next(); | 			const List<String>::Element *path_elem = elem->next(); | ||||||
| 
 | 
 | ||||||
| 			if (path_elem) { | 			if (path_elem) { | ||||||
| 				if (get_singleton()->generate_cs_api(path_elem->get()) != OK) | 				cs_api_path = path_elem->get(); | ||||||
| 					ERR_PRINTS(cs_api_option + ": Failed to generate the C# API"); |  | ||||||
| 				elem = elem->next(); | 				elem = elem->next(); | ||||||
| 			} else { | 			} else { | ||||||
| 				ERR_PRINTS(cs_api_option + ": No output directory specified"); | 				ERR_PRINTS(cs_api_option + ": No output directory specified"); | ||||||
|  | @ -2920,10 +2908,23 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args) | ||||||
| 		elem = elem->next(); | 		elem = elem->next(); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	verbose_output = false; | 	if (mono_glue_path.length() || cs_api_path.length()) { | ||||||
|  | 		BindingsGenerator bindings_generator; | ||||||
|  | 		bindings_generator.set_log_print_enabled(true); | ||||||
| 
 | 
 | ||||||
| 	if (options_left != NUM_OPTIONS) | 		if (mono_glue_path.length()) { | ||||||
|  | 			if (bindings_generator.generate_glue(mono_glue_path) != OK) | ||||||
|  | 				ERR_PRINTS(mono_glue_option + ": Failed to generate mono glue"); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (cs_api_path.length()) { | ||||||
|  | 			if (bindings_generator.generate_cs_api(cs_api_path) != OK) | ||||||
|  | 				ERR_PRINTS(cs_api_option + ": Failed to generate the C# API"); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// Exit once done
 | ||||||
| 		::exit(0); | 		::exit(0); | ||||||
|  | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -164,7 +164,6 @@ class BindingsGenerator { | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		MethodInterface() { | 		MethodInterface() { | ||||||
| 			return_type.cname = BindingsGenerator::get_singleton()->name_cache.type_void; |  | ||||||
| 			is_vararg = false; | 			is_vararg = false; | ||||||
| 			is_virtual = false; | 			is_virtual = false; | ||||||
| 			requires_object_call = false; | 			requires_object_call = false; | ||||||
|  | @ -469,7 +468,7 @@ class BindingsGenerator { | ||||||
| 		} | 		} | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 	static bool verbose_output; | 	bool log_print_enabled; | ||||||
| 
 | 
 | ||||||
| 	OrderedHashMap<StringName, TypeInterface> obj_types; | 	OrderedHashMap<StringName, TypeInterface> obj_types; | ||||||
| 
 | 
 | ||||||
|  | @ -515,6 +514,7 @@ class BindingsGenerator { | ||||||
| 			enum_Error = StaticCString::create("Error"); | 			enum_Error = StaticCString::create("Error"); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 	private: | ||||||
| 		NameCache(const NameCache &); | 		NameCache(const NameCache &); | ||||||
| 		NameCache &operator=(const NameCache &); | 		NameCache &operator=(const NameCache &); | ||||||
| 	}; | 	}; | ||||||
|  | @ -578,33 +578,26 @@ class BindingsGenerator { | ||||||
| 
 | 
 | ||||||
| 	Error _save_file(const String &p_path, const StringBuilder &p_content); | 	Error _save_file(const String &p_path, const StringBuilder &p_content); | ||||||
| 
 | 
 | ||||||
| 	BindingsGenerator() {} | 	void _log(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_2_3; | ||||||
| 
 | 
 | ||||||
| 	BindingsGenerator(const BindingsGenerator &); | 	void _initialize(); | ||||||
| 	BindingsGenerator &operator=(const BindingsGenerator &); |  | ||||||
| 
 |  | ||||||
| 	friend class CSharpLanguage; |  | ||||||
| 	static BindingsGenerator *singleton; |  | ||||||
| 
 | 
 | ||||||
| public: | public: | ||||||
| 	Error generate_cs_core_project(const String &p_solution_dir, DotNetSolution &r_solution, bool p_verbose_output = true); | 	Error generate_cs_core_project(const String &p_solution_dir, DotNetSolution &r_solution); | ||||||
| 	Error generate_cs_editor_project(const String &p_solution_dir, DotNetSolution &r_solution, bool p_verbose_output = true); | 	Error generate_cs_editor_project(const String &p_solution_dir, DotNetSolution &r_solution); | ||||||
| 	Error generate_cs_api(const String &p_output_dir, bool p_verbose_output = true); | 	Error generate_cs_api(const String &p_output_dir); | ||||||
| 	Error generate_glue(const String &p_output_dir); | 	Error generate_glue(const String &p_output_dir); | ||||||
| 
 | 
 | ||||||
|  | 	void set_log_print_enabled(bool p_enabled) { log_print_enabled = p_enabled; } | ||||||
|  | 
 | ||||||
| 	static uint32_t get_version(); | 	static uint32_t get_version(); | ||||||
| 
 | 
 | ||||||
| 	void initialize(); |  | ||||||
| 
 |  | ||||||
| 	_FORCE_INLINE_ static BindingsGenerator *get_singleton() { |  | ||||||
| 		if (!singleton) { |  | ||||||
| 			singleton = memnew(BindingsGenerator); |  | ||||||
| 			singleton->initialize(); |  | ||||||
| 		} |  | ||||||
| 		return singleton; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	static void handle_cmdline_args(const List<String> &p_cmdline_args); | 	static void handle_cmdline_args(const List<String> &p_cmdline_args); | ||||||
|  | 
 | ||||||
|  | 	BindingsGenerator() : | ||||||
|  | 			log_print_enabled(true) { | ||||||
|  | 		_initialize(); | ||||||
|  | 	} | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -323,10 +323,13 @@ bool GodotSharpBuilds::make_api_assembly(APIAssembly::Type p_api_type) { | ||||||
| 	String api_sln_file = api_sln_dir.plus_file(API_SOLUTION_NAME ".sln"); | 	String api_sln_file = api_sln_dir.plus_file(API_SOLUTION_NAME ".sln"); | ||||||
| 
 | 
 | ||||||
| 	if (!DirAccess::exists(api_sln_dir) || !FileAccess::exists(api_sln_file)) { | 	if (!DirAccess::exists(api_sln_dir) || !FileAccess::exists(api_sln_file)) { | ||||||
| 		BindingsGenerator *gen = BindingsGenerator::get_singleton(); | 		BindingsGenerator bindings_generator; | ||||||
| 		bool gen_verbose = OS::get_singleton()->is_stdout_verbose(); |  | ||||||
| 
 | 
 | ||||||
| 		Error err = gen->generate_cs_api(api_sln_dir, gen_verbose); | 		if (!OS::get_singleton()->is_stdout_verbose()) { | ||||||
|  | 			bindings_generator.set_log_print_enabled(false); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		Error err = bindings_generator.generate_cs_api(api_sln_dir); | ||||||
| 		if (err != OK) { | 		if (err != OK) { | ||||||
| 			show_build_error_dialog("Failed to generate " API_SOLUTION_NAME " solution. Error: " + itos(err)); | 			show_build_error_dialog("Failed to generate " API_SOLUTION_NAME " solution. Error: " + itos(err)); | ||||||
| 			return false; | 			return false; | ||||||
|  |  | ||||||
|  | @ -37,6 +37,7 @@ | ||||||
| #include "core/os/os.h" | #include "core/os/os.h" | ||||||
| 
 | 
 | ||||||
| #include "../godotsharp_dirs.h" | #include "../godotsharp_dirs.h" | ||||||
|  | #include "../utils/string_utils.h" | ||||||
| 
 | 
 | ||||||
| static int log_level_get_id(const char *p_log_level) { | static int log_level_get_id(const char *p_log_level) { | ||||||
| 
 | 
 | ||||||
|  | @ -125,27 +126,6 @@ void GDMonoLog::_delete_old_log_files(const String &p_logs_dir) { | ||||||
| 	da->list_dir_end(); | 	da->list_dir_end(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static String format(const char *p_fmt, ...) { |  | ||||||
| 	va_list args; |  | ||||||
| 
 |  | ||||||
| 	va_start(args, p_fmt); |  | ||||||
| 	int len = vsnprintf(NULL, 0, p_fmt, args); |  | ||||||
| 	va_end(args); |  | ||||||
| 
 |  | ||||||
| 	len += 1; // for the trailing '/0'
 |  | ||||||
| 
 |  | ||||||
| 	char *buffer(memnew_arr(char, len)); |  | ||||||
| 
 |  | ||||||
| 	va_start(args, p_fmt); |  | ||||||
| 	vsnprintf(buffer, len, p_fmt, args); |  | ||||||
| 	va_end(args); |  | ||||||
| 
 |  | ||||||
| 	String res(buffer); |  | ||||||
| 	memdelete_arr(buffer); |  | ||||||
| 
 |  | ||||||
| 	return res; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void GDMonoLog::initialize() { | void GDMonoLog::initialize() { | ||||||
| 
 | 
 | ||||||
| 	CharString log_level = OS::get_singleton()->get_environment("GODOT_MONO_LOG_LEVEL").utf8(); | 	CharString log_level = OS::get_singleton()->get_environment("GODOT_MONO_LOG_LEVEL").utf8(); | ||||||
|  | @ -172,7 +152,7 @@ void GDMonoLog::initialize() { | ||||||
| 		OS::Time time_now = OS::get_singleton()->get_time(); | 		OS::Time time_now = OS::get_singleton()->get_time(); | ||||||
| 		int pid = OS::get_singleton()->get_process_id(); | 		int pid = OS::get_singleton()->get_process_id(); | ||||||
| 
 | 
 | ||||||
| 		String log_file_name = format("%d_%02d_%02d %02d.%02d.%02d (%d).txt", | 		String log_file_name = str_format("%d_%02d_%02d %02d.%02d.%02d (%d).txt", | ||||||
| 				date_now.year, date_now.month, date_now.day, | 				date_now.year, date_now.month, date_now.day, | ||||||
| 				time_now.hour, time_now.min, time_now.sec, pid); | 				time_now.hour, time_now.min, time_now.sec, pid); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -32,6 +32,8 @@ | ||||||
| 
 | 
 | ||||||
| #include "core/os/file_access.h" | #include "core/os/file_access.h" | ||||||
| 
 | 
 | ||||||
|  | #include <stdio.h> | ||||||
|  | 
 | ||||||
| namespace { | namespace { | ||||||
| 
 | 
 | ||||||
| int sfind(const String &p_text, int p_from) { | int sfind(const String &p_text, int p_from) { | ||||||
|  | @ -184,3 +186,50 @@ Error read_all_file_utf8(const String &p_path, String &r_content) { | ||||||
| 	r_content = source; | 	r_content = source; | ||||||
| 	return OK; | 	return OK; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | // TODO: Move to variadic templates once we upgrade to C++11
 | ||||||
|  | 
 | ||||||
|  | String str_format(const char *p_format, ...) { | ||||||
|  | 	va_list list; | ||||||
|  | 
 | ||||||
|  | 	va_start(list, p_format); | ||||||
|  | 	String res = str_format(p_format, list); | ||||||
|  | 	va_end(list); | ||||||
|  | 
 | ||||||
|  | 	return res; | ||||||
|  | } | ||||||
|  | // va_copy was defined in the C99, but not in C++ standards before C++11.
 | ||||||
|  | // When you compile C++ without --std=c++<XX> option, compilers still define
 | ||||||
|  | // va_copy, otherwise you have to use the internal version (__va_copy).
 | ||||||
|  | #if !defined(va_copy) | ||||||
|  | #if defined(__GNUC__) | ||||||
|  | #define va_copy(d, s) __va_copy((d), (s)) | ||||||
|  | #else | ||||||
|  | #define va_copy(d, s) ((d) = (s)) | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #if defined(MINGW_ENABLED) || defined(_MSC_VER) | ||||||
|  | #define vsnprintf vsnprintf_s | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | String str_format(const char *p_format, va_list p_list) { | ||||||
|  | 	va_list list; | ||||||
|  | 
 | ||||||
|  | 	va_copy(list, p_list); | ||||||
|  | 	int len = vsnprintf(NULL, 0, p_format, list); | ||||||
|  | 	va_end(list); | ||||||
|  | 
 | ||||||
|  | 	len += 1; // for the trailing '/0'
 | ||||||
|  | 
 | ||||||
|  | 	char *buffer(memnew_arr(char, len)); | ||||||
|  | 
 | ||||||
|  | 	va_copy(list, p_list); | ||||||
|  | 	vsnprintf(buffer, len, p_format, list); | ||||||
|  | 	va_end(list); | ||||||
|  | 
 | ||||||
|  | 	String res(buffer); | ||||||
|  | 	memdelete_arr(buffer); | ||||||
|  | 
 | ||||||
|  | 	return res; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -34,6 +34,8 @@ | ||||||
| #include "core/ustring.h" | #include "core/ustring.h" | ||||||
| #include "core/variant.h" | #include "core/variant.h" | ||||||
| 
 | 
 | ||||||
|  | #include <stdarg.h> | ||||||
|  | 
 | ||||||
| String sformat(const String &p_text, const Variant &p1 = Variant(), const Variant &p2 = Variant(), const Variant &p3 = Variant(), const Variant &p4 = Variant(), const Variant &p5 = Variant()); | String sformat(const String &p_text, const Variant &p1 = Variant(), const Variant &p2 = Variant(), const Variant &p3 = Variant(), const Variant &p4 = Variant(), const Variant &p5 = Variant()); | ||||||
| 
 | 
 | ||||||
| #ifdef TOOLS_ENABLED | #ifdef TOOLS_ENABLED | ||||||
|  | @ -44,4 +46,15 @@ String escape_csharp_keyword(const String &p_name); | ||||||
| 
 | 
 | ||||||
| Error read_all_file_utf8(const String &p_path, String &r_content); | Error read_all_file_utf8(const String &p_path, String &r_content); | ||||||
| 
 | 
 | ||||||
|  | #if defined(__GNUC__) | ||||||
|  | #define _PRINTF_FORMAT_ATTRIBUTE_1_0 __attribute__((format(printf, 1, 0))) | ||||||
|  | #define _PRINTF_FORMAT_ATTRIBUTE_1_2 __attribute__((format(printf, 1, 2))) | ||||||
|  | #else | ||||||
|  | #define _PRINTF_FORMAT_ATTRIBUTE_1_0 | ||||||
|  | #define _PRINTF_FORMAT_ATTRIBUTE_1_2 | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | String str_format(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_1_2; | ||||||
|  | String str_format(const char *p_format, va_list p_list) _PRINTF_FORMAT_ATTRIBUTE_1_0; | ||||||
|  | 
 | ||||||
| #endif // STRING_FORMAT_H
 | #endif // STRING_FORMAT_H
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Ignacio Etcheverry
						Ignacio Etcheverry