Path: blob/master/editor/export/gdextension_export_plugin.h
9902 views
/**************************************************************************/1/* gdextension_export_plugin.h */2/**************************************************************************/3/* This file is part of: */4/* GODOT ENGINE */5/* https://godotengine.org */6/**************************************************************************/7/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */8/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */9/* */10/* Permission is hereby granted, free of charge, to any person obtaining */11/* a copy of this software and associated documentation files (the */12/* "Software"), to deal in the Software without restriction, including */13/* without limitation the rights to use, copy, modify, merge, publish, */14/* distribute, sublicense, and/or sell copies of the Software, and to */15/* permit persons to whom the Software is furnished to do so, subject to */16/* the following conditions: */17/* */18/* The above copyright notice and this permission notice shall be */19/* included in all copies or substantial portions of the Software. */20/* */21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */23/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */24/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */25/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */26/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */27/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */28/**************************************************************************/2930#pragma once3132#include "core/extension/gdextension_library_loader.h"33#include "editor/export/editor_export.h"3435class GDExtensionExportPlugin : public EditorExportPlugin {36protected:37virtual void _export_file(const String &p_path, const String &p_type, const HashSet<String> &p_features);38virtual String get_name() const { return "GDExtension"; }39};4041void GDExtensionExportPlugin::_export_file(const String &p_path, const String &p_type, const HashSet<String> &p_features) {42if (p_type != "GDExtension") {43return;44}4546Ref<ConfigFile> config;47config.instantiate();4849Error err = config->load(p_path);50ERR_FAIL_COND_MSG(err, "Failed to load GDExtension file: " + p_path);5152// Check whether this GDExtension should be exported.53bool android_aar_plugin = config->get_value("configuration", "android_aar_plugin", false);54if (android_aar_plugin && p_features.has("android")) {55// The gdextension configuration and Android .so files will be provided by the Android aar56// plugin it's part of, so we abort here.57skip();58return;59}6061ERR_FAIL_COND_MSG(!config->has_section_key("configuration", "entry_symbol"), "Failed to export GDExtension file, missing entry symbol: " + p_path);6263String entry_symbol = config->get_value("configuration", "entry_symbol");6465HashSet<String> all_archs;66all_archs.insert("x86_32");67all_archs.insert("x86_64");68all_archs.insert("arm32");69all_archs.insert("arm64");70all_archs.insert("rv64");71all_archs.insert("ppc64");72all_archs.insert("wasm32");73all_archs.insert("loongarch64");74all_archs.insert("universal");7576HashSet<String> archs;77HashSet<String> features_wo_arch;78Vector<String> features_vector;79for (const String &tag : p_features) {80if (all_archs.has(tag)) {81archs.insert(tag);82} else {83features_wo_arch.insert(tag);84}85features_vector.append(tag);86}8788if (archs.is_empty()) {89archs.insert("unknown_arch"); // Not archs specified, still try to match.90}9192HashSet<String> libs_added;93struct FoundLibInfo {94int count = 0;95Vector<String> libs;96};97HashMap<String, FoundLibInfo> libs_found;98for (const String &arch_tag : archs) {99if (arch_tag != "universal") {100libs_found[arch_tag] = FoundLibInfo();101}102}103104for (const String &arch_tag : archs) {105PackedStringArray tags;106String library_path = GDExtensionLibraryLoader::find_extension_library(107p_path, config, [features_wo_arch, arch_tag](const String &p_feature) { return features_wo_arch.has(p_feature) || (p_feature == arch_tag); }, &tags);108109if (libs_added.has(library_path)) {110continue; // Universal library, already added for another arch, do not duplicate.111}112if (!library_path.is_empty()) {113libs_added.insert(library_path);114add_shared_object(library_path, tags);115116if (p_features.has("apple_embedded") && (library_path.ends_with(".a") || library_path.ends_with(".xcframework"))) {117String additional_code = "extern void register_dynamic_symbol(char *name, void *address);\n"118"extern void add_apple_embedded_platform_init_callback(void (*cb)());\n"119"\n"120"extern \"C\" void $ENTRY();\n"121"void $ENTRY_init() {\n"122" if (&$ENTRY) register_dynamic_symbol((char *)\"$ENTRY\", (void *)$ENTRY);\n"123"}\n"124"struct $ENTRY_struct {\n"125" $ENTRY_struct() {\n"126" add_apple_embedded_platform_init_callback($ENTRY_init);\n"127" }\n"128"};\n"129"$ENTRY_struct $ENTRY_struct_instance;\n\n";130additional_code = additional_code.replace("$ENTRY", entry_symbol);131add_apple_embedded_platform_cpp_code(additional_code);132133String linker_flags = "-Wl,-U,_" + entry_symbol;134add_apple_embedded_platform_linker_flags(linker_flags);135}136137// Update found library info.138if (arch_tag == "universal") {139for (const String &sub_arch_tag : archs) {140if (sub_arch_tag != "universal") {141libs_found[sub_arch_tag].count++;142libs_found[sub_arch_tag].libs.push_back(library_path);143}144}145} else {146libs_found[arch_tag].count++;147libs_found[arch_tag].libs.push_back(library_path);148}149}150151Vector<SharedObject> dependencies_shared_objects = GDExtensionLibraryLoader::find_extension_dependencies(p_path, config, [p_features](String p_feature) { return p_features.has(p_feature); });152for (const SharedObject &shared_object : dependencies_shared_objects) {153_add_shared_object(shared_object);154}155}156157for (const KeyValue<String, FoundLibInfo> &E : libs_found) {158if (E.value.count == 0) {159if (get_export_platform().is_valid()) {160get_export_platform()->add_message(EditorExportPlatform::EXPORT_MESSAGE_WARNING, TTR("GDExtension"), vformat(TTR("No \"%s\" library found for GDExtension: \"%s\". Possible feature flags for your platform: %s"), E.key, p_path, String(", ").join(features_vector)));161}162} else if (E.value.count > 1) {163if (get_export_platform().is_valid()) {164get_export_platform()->add_message(EditorExportPlatform::EXPORT_MESSAGE_WARNING, TTR("GDExtension"), vformat(TTR("Multiple \"%s\" libraries found for GDExtension: \"%s\": \"%s\"."), E.key, p_path, String(", ").join(E.value.libs)));165}166}167}168}169170171