| 
									
										
										
										
											2018-02-22 13:39:41 +01:00
										 |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*  godotsharp_export.cpp                                                */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*                       This file is part of:                           */ | 
					
						
							|  |  |  | /*                           GODOT ENGINE                                */ | 
					
						
							|  |  |  | /*                      https://godotengine.org                          */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							| 
									
										
										
										
											2020-01-01 11:16:22 +01:00
										 |  |  | /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */ | 
					
						
							|  |  |  | /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */ | 
					
						
							| 
									
										
										
										
											2018-02-22 13:39:41 +01:00
										 |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* Permission is hereby granted, free of charge, to any person obtaining */ | 
					
						
							|  |  |  | /* a copy of this software and associated documentation files (the       */ | 
					
						
							|  |  |  | /* "Software"), to deal in the Software without restriction, including   */ | 
					
						
							|  |  |  | /* without limitation the rights to use, copy, modify, merge, publish,   */ | 
					
						
							|  |  |  | /* distribute, sublicense, and/or sell copies of the Software, and to    */ | 
					
						
							|  |  |  | /* permit persons to whom the Software is furnished to do so, subject to */ | 
					
						
							|  |  |  | /* the following conditions:                                             */ | 
					
						
							|  |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* The above copyright notice and this permission notice shall be        */ | 
					
						
							|  |  |  | /* included in all copies or substantial portions of the Software.       */ | 
					
						
							|  |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */ | 
					
						
							|  |  |  | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */ | 
					
						
							|  |  |  | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ | 
					
						
							|  |  |  | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */ | 
					
						
							|  |  |  | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */ | 
					
						
							|  |  |  | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */ | 
					
						
							|  |  |  | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "godotsharp_export.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-03 09:44:53 +02:00
										 |  |  | #include <mono/metadata/image.h>
 | 
					
						
							| 
									
										
										
										
											2018-10-03 19:01:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-07 19:33:38 -03:00
										 |  |  | #include "core/config/project_settings.h"
 | 
					
						
							| 
									
										
										
										
											2020-05-09 20:54:07 +02:00
										 |  |  | #include "core/io/file_access_pack.h"
 | 
					
						
							| 
									
										
										
										
											2019-10-11 01:23:35 +02:00
										 |  |  | #include "core/os/os.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-03 09:44:53 +02:00
										 |  |  | #include "../mono_gd/gd_mono.h"
 | 
					
						
							|  |  |  | #include "../mono_gd/gd_mono_assembly.h"
 | 
					
						
							| 
									
										
										
										
											2019-11-10 17:10:38 +01:00
										 |  |  | #include "../mono_gd/gd_mono_cache.h"
 | 
					
						
							| 
									
										
										
										
											2020-05-09 20:54:07 +02:00
										 |  |  | #include "../utils/macros.h"
 | 
					
						
							| 
									
										
										
										
											2018-02-22 13:39:41 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-11 01:23:35 +02:00
										 |  |  | namespace GodotSharpExport { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-30 01:48:41 +02:00
										 |  |  | MonoAssemblyName *new_mono_assembly_name() { | 
					
						
							|  |  |  | 	// Mono has no public API to create an empty MonoAssemblyName and the struct is private.
 | 
					
						
							|  |  |  | 	// As such the only way to create it is with a stub name and then clear it.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	MonoAssemblyName *aname = mono_assembly_name_new("stub"); | 
					
						
							|  |  |  | 	CRASH_COND(aname == nullptr); | 
					
						
							|  |  |  | 	mono_assembly_name_free(aname); // Frees the string fields, not the struct
 | 
					
						
							|  |  |  | 	return aname; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-09 20:54:07 +02:00
										 |  |  | struct AssemblyRefInfo { | 
					
						
							|  |  |  | 	String name; | 
					
						
							| 
									
										
										
										
											2020-11-24 10:12:55 +01:00
										 |  |  | 	uint16_t major = 0; | 
					
						
							|  |  |  | 	uint16_t minor = 0; | 
					
						
							|  |  |  | 	uint16_t build = 0; | 
					
						
							|  |  |  | 	uint16_t revision = 0; | 
					
						
							| 
									
										
										
										
											2020-05-09 20:54:07 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | AssemblyRefInfo get_assemblyref_name(MonoImage *p_image, int index) { | 
					
						
							| 
									
										
										
										
											2019-07-03 09:44:53 +02:00
										 |  |  | 	const MonoTableInfo *table_info = mono_image_get_table_info(p_image, MONO_TABLE_ASSEMBLYREF); | 
					
						
							| 
									
										
										
										
											2018-02-22 13:39:41 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-03 09:44:53 +02:00
										 |  |  | 	uint32_t cols[MONO_ASSEMBLYREF_SIZE]; | 
					
						
							| 
									
										
										
										
											2018-02-22 13:39:41 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-03 09:44:53 +02:00
										 |  |  | 	mono_metadata_decode_row(table_info, index, cols, MONO_ASSEMBLYREF_SIZE); | 
					
						
							| 
									
										
										
										
											2018-02-22 13:39:41 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-09 20:54:07 +02:00
										 |  |  | 	return { | 
					
						
							|  |  |  | 		String::utf8(mono_metadata_string_heap(p_image, cols[MONO_ASSEMBLYREF_NAME])), | 
					
						
							|  |  |  | 		(uint16_t)cols[MONO_ASSEMBLYREF_MAJOR_VERSION], | 
					
						
							|  |  |  | 		(uint16_t)cols[MONO_ASSEMBLYREF_MINOR_VERSION], | 
					
						
							|  |  |  | 		(uint16_t)cols[MONO_ASSEMBLYREF_BUILD_NUMBER], | 
					
						
							|  |  |  | 		(uint16_t)cols[MONO_ASSEMBLYREF_REV_NUMBER] | 
					
						
							|  |  |  | 	}; | 
					
						
							| 
									
										
										
										
											2018-02-22 13:39:41 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-30 01:48:41 +02:00
										 |  |  | Error get_assembly_dependencies(GDMonoAssembly *p_assembly, MonoAssemblyName *reusable_aname, const Vector<String> &p_search_dirs, Dictionary &r_assembly_dependencies) { | 
					
						
							| 
									
										
										
										
											2018-02-22 13:39:41 +01:00
										 |  |  | 	MonoImage *image = p_assembly->get_image(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (int i = 0; i < mono_image_get_table_rows(image, MONO_TABLE_ASSEMBLYREF); i++) { | 
					
						
							| 
									
										
										
										
											2020-05-09 20:54:07 +02:00
										 |  |  | 		AssemblyRefInfo ref_info = get_assemblyref_name(image, i); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		const String &ref_name = ref_info.name; | 
					
						
							| 
									
										
										
										
											2018-02-22 13:39:41 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-05 19:19:36 +02:00
										 |  |  | 		if (r_assembly_dependencies.has(ref_name)) { | 
					
						
							| 
									
										
										
										
											2018-02-22 13:39:41 +01:00
										 |  |  | 			continue; | 
					
						
							| 
									
										
										
										
											2020-07-05 19:19:36 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-02-22 13:39:41 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-30 01:48:41 +02:00
										 |  |  | 		mono_assembly_get_assemblyref(image, i, reusable_aname); | 
					
						
							| 
									
										
										
										
											2018-02-22 13:39:41 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-30 01:48:41 +02:00
										 |  |  | 		GDMonoAssembly *ref_assembly = NULL; | 
					
						
							|  |  |  | 		if (!GDMono::get_singleton()->load_assembly(ref_name, reusable_aname, &ref_assembly, /* refonly: */ true, p_search_dirs)) { | 
					
						
							|  |  |  | 			ERR_FAIL_V_MSG(ERR_CANT_RESOLVE, "Cannot load assembly (refonly): '" + ref_name + "'."); | 
					
						
							| 
									
										
										
										
											2020-05-09 20:54:07 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-02-22 13:39:41 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-30 01:48:41 +02:00
										 |  |  | 		r_assembly_dependencies[ref_name] = ref_assembly->get_path(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Error err = get_assembly_dependencies(ref_assembly, reusable_aname, p_search_dirs, r_assembly_dependencies); | 
					
						
							| 
									
										
										
										
											2019-08-09 03:39:45 +02:00
										 |  |  | 		ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot load one of the dependencies for the assembly: '" + ref_name + "'."); | 
					
						
							| 
									
										
										
										
											2018-02-22 13:39:41 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return OK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-22 16:44:03 +02:00
										 |  |  | Error get_exported_assembly_dependencies(const Dictionary &p_initial_assemblies, | 
					
						
							|  |  |  | 		const String &p_build_config, const String &p_custom_bcl_dir, Dictionary &r_assembly_dependencies) { | 
					
						
							| 
									
										
										
										
											2019-10-11 01:23:35 +02:00
										 |  |  | 	MonoDomain *export_domain = GDMonoUtils::create_domain("GodotEngine.Domain.ProjectExport"); | 
					
						
							| 
									
										
										
										
											2019-07-03 09:44:53 +02:00
										 |  |  | 	ERR_FAIL_NULL_V(export_domain, FAILED); | 
					
						
							|  |  |  | 	_GDMONO_SCOPE_EXIT_DOMAIN_UNLOAD_(export_domain); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	_GDMONO_SCOPE_DOMAIN_(export_domain); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Vector<String> search_dirs; | 
					
						
							| 
									
										
										
										
											2019-10-11 01:23:35 +02:00
										 |  |  | 	GDMonoAssembly::fill_search_dirs(search_dirs, p_build_config, p_custom_bcl_dir); | 
					
						
							| 
									
										
										
										
											2018-02-22 13:39:41 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-09 20:54:07 +02:00
										 |  |  | 	if (p_custom_bcl_dir.length()) { | 
					
						
							|  |  |  | 		// Only one mscorlib can be loaded. We need this workaround to make sure we get it from the right BCL directory.
 | 
					
						
							|  |  |  | 		r_assembly_dependencies["mscorlib"] = p_custom_bcl_dir.plus_file("mscorlib.dll").simplify_path(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-22 16:44:03 +02:00
										 |  |  | 	for (const Variant *key = p_initial_assemblies.next(); key; key = p_initial_assemblies.next(key)) { | 
					
						
							| 
									
										
										
										
											2019-12-04 15:07:00 +01:00
										 |  |  | 		String assembly_name = *key; | 
					
						
							| 
									
										
										
										
											2020-04-22 16:44:03 +02:00
										 |  |  | 		String assembly_path = p_initial_assemblies[*key]; | 
					
						
							| 
									
										
										
										
											2019-12-04 15:07:00 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 		GDMonoAssembly *assembly = nullptr; | 
					
						
							| 
									
										
										
										
											2019-12-04 15:07:00 +01:00
										 |  |  | 		bool load_success = GDMono::get_singleton()->load_assembly_from(assembly_name, assembly_path, &assembly, /* refonly: */ true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		ERR_FAIL_COND_V_MSG(!load_success, ERR_CANT_RESOLVE, "Cannot load assembly (refonly): '" + assembly_name + "'."); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-30 01:48:41 +02:00
										 |  |  | 		MonoAssemblyName *reusable_aname = new_mono_assembly_name(); | 
					
						
							|  |  |  | 		SCOPE_EXIT { mono_free(reusable_aname); }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Error err = get_assembly_dependencies(assembly, reusable_aname, search_dirs, r_assembly_dependencies); | 
					
						
							| 
									
										
										
										
											2020-07-05 19:19:36 +02:00
										 |  |  | 		if (err != OK) { | 
					
						
							| 
									
										
										
										
											2019-12-04 15:07:00 +01:00
										 |  |  | 			return err; | 
					
						
							| 
									
										
										
										
											2020-07-05 19:19:36 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-12-04 15:07:00 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return OK; | 
					
						
							| 
									
										
										
										
											2018-02-22 13:39:41 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2019-10-11 01:23:35 +02:00
										 |  |  | } // namespace GodotSharpExport
 |