Beispiel #1
0
MonoAssembly *gdmono_MonoAssemblyPreLoad(MonoAssemblyName *aname, char **assemblies_path, void *user_data) {

	(void)user_data; // UNUSED

	MonoAssembly *assembly_loaded = mono_assembly_loaded(aname);
	if (assembly_loaded) // Already loaded
		return assembly_loaded;

	static Vector<String> search_dirs;

	if (search_dirs.empty()) {
		search_dirs.push_back(GodotSharpDirs::get_res_temp_assemblies_dir());
		search_dirs.push_back(GodotSharpDirs::get_res_assemblies_dir());
		search_dirs.push_back(OS::get_singleton()->get_resource_dir());
		search_dirs.push_back(OS::get_singleton()->get_executable_path().get_base_dir());

		const char *rootdir = mono_assembly_getrootdir();
		if (rootdir) {
			search_dirs.push_back(String(rootdir).plus_file("mono").plus_file("4.5"));
		}

		while (assemblies_path) {
			if (*assemblies_path)
				search_dirs.push_back(*assemblies_path);
			++assemblies_path;
		}
	}

	String name = mono_assembly_name_get_name(aname);
	bool has_extension = name.ends_with(".dll") || name.ends_with(".exe");

	String path;

	for (int i = 0; i < search_dirs.size(); i++) {
		const String &search_dir = search_dirs[i];

		if (has_extension) {
			path = search_dir.plus_file(name);
			if (FileAccess::exists(path))
				return gdmono_load_assembly_from(name.get_basename(), path);
		} else {
			path = search_dir.plus_file(name + ".dll");
			if (FileAccess::exists(path))
				return gdmono_load_assembly_from(name, path);

			path = search_dir.plus_file(name + ".exe");
			if (FileAccess::exists(path))
				return gdmono_load_assembly_from(name, path);
		}
	}

	return NULL;
}
Beispiel #2
0
MonoAssembly *GDMonoAssembly::_preload_hook(MonoAssemblyName *aname, char **assemblies_path, void *user_data) {

	(void)user_data; // UNUSED

	if (search_dirs.empty()) {
		search_dirs.push_back(GodotSharpDirs::get_res_temp_assemblies_dir());
		search_dirs.push_back(GodotSharpDirs::get_res_assemblies_dir());
		search_dirs.push_back(OS::get_singleton()->get_resource_dir());
		search_dirs.push_back(OS::get_singleton()->get_executable_path().get_base_dir());

		const char *rootdir = mono_assembly_getrootdir();
		if (rootdir) {
			search_dirs.push_back(String(rootdir).plus_file("mono").plus_file("4.5"));
		}

		while (assemblies_path) {
			if (*assemblies_path)
				search_dirs.push_back(*assemblies_path);
			++assemblies_path;
		}
	}

	return NULL;
}
Beispiel #3
0
/**
 * mono_profiler_load:
 * @desc: arguments to configure the profiler
 *
 * Invoke this method to initialize the profiler.   This will drive the
 * loading of the internal ("default") or any external profilers.
 *
 * This routine is invoked by Mono's driver, but must be called manually
 * if you embed Mono into your application.
 */
void 
mono_profiler_load (const char *desc)
{
	char *cdesc = NULL;
	mono_gc_base_init ();

	if (!desc || (strcmp ("default", desc) == 0)) {
		desc = "log:report";
	}
	/* we keep command-line compat with the old version here */
	if (strncmp (desc, "default:", 8) == 0) {
		gchar **args, **ptr;
		GString *str = g_string_new ("log:report");
		args = g_strsplit (desc + 8, ",", -1);
		for (ptr = args; ptr && *ptr; ptr++) {
			const char *arg = *ptr;

			if (!strcmp (arg, "time"))
				g_string_append (str, ",calls");
			else if (!strcmp (arg, "alloc"))
				g_string_append (str, ",alloc");
			else if (!strcmp (arg, "stat"))
				g_string_append (str, ",sample");
			else if (!strcmp (arg, "jit"))
				continue; /* accept and do nothing */
			else if (strncmp (arg, "file=", 5) == 0) {
				g_string_append_printf (str, ",output=%s", arg + 5);
			} else {
				fprintf (stderr, "profiler : Unknown argument '%s'.\n", arg);
				return;
			}
		}
		desc = cdesc = g_string_free (str, FALSE);
	}
	{
		const char* col = strchr (desc, ':');
		char* libname;
		char *mname;
		gboolean res = FALSE;

		if (col != NULL) {
			mname = g_memdup (desc, col - desc + 1);
			mname [col - desc] = 0;
		} else {
			mname = g_strdup (desc);
		}
		if (!load_embedded_profiler (desc, mname)) {
			libname = g_strdup_printf ("mono-profiler-%s", mname);
			if (mono_config_get_assemblies_dir ())
				res = load_profiler_from_directory (mono_assembly_getrootdir (), libname, desc);
			if (!res)
				res = load_profiler_from_directory (NULL, libname, desc);
			if (!res)
				res = load_profiler_from_mono_instalation (libname, desc);
			if (!res)
				g_warning ("The '%s' profiler wasn't found in the main executable nor could it be loaded from '%s'.", mname, libname);
			g_free (libname);
		}
		g_free (mname);
	}
	g_free (cdesc);
}
Beispiel #4
0
void GDMono::initialize() {

	ERR_FAIL_NULL(Engine::get_singleton());

	print_verbose("Mono: Initializing module...");

#ifdef DEBUG_METHODS_ENABLED
	_initialize_and_check_api_hashes();
#endif

	GDMonoLog::get_singleton()->initialize();

#ifdef MONO_PRINT_HANDLER_ENABLED
	mono_trace_set_print_handler(gdmono_MonoPrintCallback);
	mono_trace_set_printerr_handler(gdmono_MonoPrintCallback);
#endif

#ifdef WINDOWS_ENABLED
	mono_reg_info = MonoRegUtils::find_mono();

	CharString assembly_dir;
	CharString config_dir;

	if (mono_reg_info.assembly_dir.length() && DirAccess::exists(mono_reg_info.assembly_dir)) {
		assembly_dir = mono_reg_info.assembly_dir.utf8();
	}

	if (mono_reg_info.config_dir.length() && DirAccess::exists(mono_reg_info.config_dir)) {
		config_dir = mono_reg_info.config_dir.utf8();
	}

	mono_set_dirs(assembly_dir.length() ? assembly_dir.get_data() : NULL,
			config_dir.length() ? config_dir.get_data() : NULL);
#elif OSX_ENABLED
	mono_set_dirs(NULL, NULL);

	{
		const char *assembly_rootdir = mono_assembly_getrootdir();
		const char *config_dir = mono_get_config_dir();

		if (!assembly_rootdir || !config_dir || !DirAccess::exists(assembly_rootdir) || !DirAccess::exists(config_dir)) {
			Vector<const char *> locations;
			locations.push_back("/Library/Frameworks/Mono.framework/Versions/Current/");
			locations.push_back("/usr/local/var/homebrew/linked/mono/");

			for (int i = 0; i < locations.size(); i++) {
				String hint_assembly_rootdir = path_join(locations[i], "lib");
				String hint_mscorlib_path = path_join(hint_assembly_rootdir, "mono", "4.5", "mscorlib.dll");
				String hint_config_dir = path_join(locations[i], "etc");

				if (FileAccess::exists(hint_mscorlib_path) && DirAccess::exists(hint_config_dir)) {
					mono_set_dirs(hint_assembly_rootdir.utf8().get_data(), hint_config_dir.utf8().get_data());
					break;
				}
			}
		}
	}
#else
	mono_set_dirs(NULL, NULL);
#endif

	GDMonoAssembly::initialize();

#ifdef DEBUG_ENABLED
	gdmono_debug_init();
#endif

	mono_config_parse(NULL);

	mono_install_unhandled_exception_hook(&unhandled_exception_hook, NULL);

	root_domain = mono_jit_init_version("GodotEngine.RootDomain", "v4.0.30319");

	ERR_EXPLAIN("Mono: Failed to initialize runtime");
	ERR_FAIL_NULL(root_domain);

	GDMonoUtils::set_main_thread(GDMonoUtils::get_current_thread());

	setup_runtime_main_args(); // Required for System.Environment.GetCommandLineArgs

	runtime_initialized = true;

	print_verbose("Mono: Runtime initialized");

	// mscorlib assembly MUST be present at initialization
	ERR_EXPLAIN("Mono: Failed to load mscorlib assembly");
	ERR_FAIL_COND(!_load_corlib_assembly());

#ifdef TOOLS_ENABLED
	// The tools domain must be loaded here, before the scripts domain.
	// Otherwise domain unload on the scripts domain will hang indefinitely.

	ERR_EXPLAIN("Mono: Failed to load tools domain");
	ERR_FAIL_COND(_load_tools_domain() != OK);

	// TODO move to editor init callback, and do it lazily when required before editor init (e.g.: bindings generation)
	ERR_EXPLAIN("Mono: Failed to load Editor Tools assembly");
	ERR_FAIL_COND(!_load_editor_tools_assembly());
#endif

	ERR_EXPLAIN("Mono: Failed to load scripts domain");
	ERR_FAIL_COND(_load_scripts_domain() != OK);

#ifdef DEBUG_ENABLED
	bool debugger_attached = _wait_for_debugger_msecs(500);
	if (!debugger_attached && OS::get_singleton()->is_stdout_verbose())
		print_error("Mono: Debugger wait timeout");
#endif

	_register_internal_calls();

	// The following assemblies are not required at initialization
#ifdef MONO_GLUE_ENABLED
	if (_load_api_assemblies()) {
		if (!core_api_assembly_out_of_sync && !editor_api_assembly_out_of_sync && GDMonoUtils::mono_cache.godot_api_cache_updated) {
			// Everything is fine with the api assemblies, load the project assembly
			_load_project_assembly();
		} else {
#ifdef TOOLS_ENABLED
			// The assembly was successfully loaded, but the full api could not be cached.
			// This is most likely an outdated assembly loaded because of an invalid version in the metadata,
			// so we invalidate the version in the metadata and unload the script domain.

			if (core_api_assembly_out_of_sync) {
				ERR_PRINT("The loaded Core API assembly is out of sync");
				metadata_set_api_assembly_invalidated(APIAssembly::API_CORE, true);
			} else if (!GDMonoUtils::mono_cache.godot_api_cache_updated) {
				ERR_PRINT("The loaded Core API assembly is in sync, but the cache update failed");
				metadata_set_api_assembly_invalidated(APIAssembly::API_CORE, true);
			}

			if (editor_api_assembly_out_of_sync) {
				ERR_PRINT("The loaded Editor API assembly is out of sync");
				metadata_set_api_assembly_invalidated(APIAssembly::API_EDITOR, true);
			}

			print_line("Mono: Proceeding to unload scripts domain because of invalid API assemblies.");

			Error err = _unload_scripts_domain();
			if (err != OK) {
				WARN_PRINT("Mono: Failed to unload scripts domain");
			}
#else
			ERR_PRINT("The loaded API assembly is invalid");
			CRASH_NOW();
#endif
		}
	}
#else
	print_verbose("Mono: Glue disabled, ignoring script assemblies.");
#endif

	print_verbose("Mono: INITIALIZED");
}
Beispiel #5
0
static void
dllmap_start (gpointer user_data, 
              const gchar         *element_name,
              const gchar        **attribute_names,
              const gchar        **attribute_values)
{
	int i;
	DllInfo *info = (DllInfo *)user_data;
	
	if (strcmp (element_name, "dllmap") == 0) {
		g_free (info->dll);
		g_free (info->target);
		info->dll = info->target = NULL;
		info->ignore = FALSE;
		for (i = 0; attribute_names [i]; ++i) {
			if (strcmp (attribute_names [i], "dll") == 0)
				info->dll = g_strdup (attribute_values [i]);
			else if (strcmp (attribute_names [i], "target") == 0){
				char *p = strstr (attribute_values [i], "$mono_libdir");
				if (p != NULL){
					const char *libdir = mono_assembly_getrootdir ();
					size_t libdir_len = strlen (libdir);
					char *result;
					
					result = (char *)g_malloc (libdir_len-strlen("$mono_libdir")+strlen(attribute_values[i])+1);
					strncpy (result, attribute_values[i], p-attribute_values[i]);
					strcpy (result+(p-attribute_values[i]), libdir);
					strcat (result, p+strlen("$mono_libdir"));
					info->target = result;
				} else 
					info->target = g_strdup (attribute_values [i]);
			} else if (strcmp (attribute_names [i], "os") == 0 && !arch_matches (CONFIG_OS, attribute_values [i]))
				info->ignore = TRUE;
			else if (strcmp (attribute_names [i], "cpu") == 0 && !arch_matches (CONFIG_CPU, attribute_values [i]))
				info->ignore = TRUE;
			else if (strcmp (attribute_names [i], "wordsize") == 0 && !arch_matches (CONFIG_WORDSIZE, attribute_values [i]))
				info->ignore = TRUE;
		}
		if (!info->ignore)
			mono_dllmap_insert (info->assembly, info->dll, NULL, info->target, NULL);
	} else if (strcmp (element_name, "dllentry") == 0) {
		const char *name = NULL, *target = NULL, *dll = NULL;
		int ignore = FALSE;
		for (i = 0; attribute_names [i]; ++i) {
			if (strcmp (attribute_names [i], "dll") == 0)
				dll = attribute_values [i];
			else if (strcmp (attribute_names [i], "target") == 0)
				target = attribute_values [i];
			else if (strcmp (attribute_names [i], "name") == 0)
				name = attribute_values [i];
			else if (strcmp (attribute_names [i], "os") == 0 && !arch_matches (CONFIG_OS, attribute_values [i]))
				ignore = TRUE;
			else if (strcmp (attribute_names [i], "cpu") == 0 && !arch_matches (CONFIG_CPU, attribute_values [i]))
				ignore = TRUE;
			else if (strcmp (attribute_names [i], "wordsize") == 0 && !arch_matches (CONFIG_WORDSIZE, attribute_values [i]))
				ignore = TRUE;
		}
		if (!dll)
			dll = info->dll;
		if (!info->ignore && !ignore)
			mono_dllmap_insert (info->assembly, info->dll, name, dll, target);
	}
}