Selaa lähdekoodia

Merge pull request #80188 from vnen/gdextension-copy-dll

GDExtension: Copy DLL to a temp file before opening
Rémi Verschelde 2 vuotta sitten
vanhempi
commit
1e3b1a7137
3 muutettua tiedostoa jossa 54 lisäystä ja 1 poistoa
  1. 41 0
      core/extension/gdextension.cpp
  2. 7 0
      core/extension/gdextension.h
  3. 6 1
      main/main.cpp

+ 41 - 0
core/extension/gdextension.cpp

@@ -485,6 +485,13 @@ void GDExtension::close_library() {
 	ERR_FAIL_COND(library == nullptr);
 	OS::get_singleton()->close_dynamic_library(library);
 
+#if defined(TOOLS_ENABLED) && defined(WINDOWS_ENABLED)
+	// Delete temporary copy of library if it exists.
+	if (!temp_lib_path.is_empty() && Engine::get_singleton()->is_editor_hint()) {
+		DirAccess::remove_absolute(temp_lib_path);
+	}
+#endif
+
 	library = nullptr;
 }
 
@@ -641,6 +648,40 @@ Ref<Resource> GDExtensionResourceLoader::load(const String &p_path, const String
 	Ref<GDExtension> lib;
 	lib.instantiate();
 	String abs_path = ProjectSettings::get_singleton()->globalize_path(library_path);
+
+#if defined(WINDOWS_ENABLED) && defined(TOOLS_ENABLED)
+	// If running on the editor on Windows, we copy the library and open the copy.
+	// This is so the original file isn't locked and can be updated by a compiler.
+	if (Engine::get_singleton()->is_editor_hint()) {
+		if (!FileAccess::exists(abs_path)) {
+			if (r_error) {
+				*r_error = ERR_FILE_NOT_FOUND;
+			}
+			ERR_PRINT("GDExtension library not found: " + library_path);
+			return Ref<Resource>();
+		}
+
+		// Copy the file to the same directory as the original with a prefix in the name.
+		// This is so relative path to dependencies are satisfied.
+		String copy_path = abs_path.get_base_dir().path_join("~" + abs_path.get_file());
+
+		Error copy_err = DirAccess::copy_absolute(abs_path, copy_path);
+		if (copy_err) {
+			if (r_error) {
+				*r_error = ERR_CANT_CREATE;
+			}
+			ERR_PRINT("Error copying GDExtension library: " + library_path);
+			return Ref<Resource>();
+		}
+		FileAccess::set_hidden_attribute(copy_path, true);
+
+		// Save the copied path so it can be deleted later.
+		lib->set_temp_library_path(copy_path);
+
+		// Use the copy to open the library.
+		abs_path = copy_path;
+	}
+#endif
 	err = lib->open_library(abs_path, entry_symbol);
 
 	if (r_error) {

+ 7 - 0
core/extension/gdextension.h

@@ -43,6 +43,9 @@ class GDExtension : public Resource {
 
 	void *library = nullptr; // pointer if valid,
 	String library_path;
+#if defined(WINDOWS_ENABLED) && defined(TOOLS_ENABLED)
+	String temp_lib_path;
+#endif
 
 	struct Extension {
 		ObjectGDExtension gdextension;
@@ -76,6 +79,10 @@ public:
 	Error open_library(const String &p_path, const String &p_entry_symbol);
 	void close_library();
 
+#if defined(WINDOWS_ENABLED) && defined(TOOLS_ENABLED)
+	void set_temp_library_path(const String &p_path) { temp_lib_path = p_path; }
+#endif
+
 	enum InitializationLevel {
 		INITIALIZATION_LEVEL_CORE = GDEXTENSION_INITIALIZATION_CORE,
 		INITIALIZATION_LEVEL_SERVERS = GDEXTENSION_INITIALIZATION_SERVERS,

+ 6 - 1
main/main.cpp

@@ -1543,6 +1543,12 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
 		}
 	}
 
+#ifdef TOOLS_ENABLED
+	if (editor) {
+		Engine::get_singleton()->set_editor_hint(true);
+	}
+#endif
+
 	// Initialize user data dir.
 	OS::get_singleton()->ensure_user_data_dir();
 
@@ -1570,7 +1576,6 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
 #ifdef TOOLS_ENABLED
 	if (editor) {
 		packed_data->set_disabled(true);
-		Engine::get_singleton()->set_editor_hint(true);
 		main_args.push_back("--editor");
 		if (!init_windowed) {
 			init_maximized = true;