From 8916e92eecdf24efa0a9e85e878913e878208e70 Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Mon, 27 Jul 2026 21:52:23 +0200 Subject: [PATCH 1/2] Use mbedTLS instead of OpenSSL --- .gitmodules | 6 +- SConstruct | 44 ++- THIRDPARTY.md | 4 +- godot-git-plugin/SCsub | 38 --- godot-git-plugin/include/std_mbedtls_config.h | 45 +++ godot-git-plugin/include/threading_alt.h | 47 +++ godot-git-plugin/src/gdlibrary.cpp | 11 + godot-git-plugin/src/std_mbedtls_platform.cpp | 104 ++++++ thirdparty/mbedtls | 1 + thirdparty/openssl | 1 - thirdparty/ssh2/libssh2 | 2 +- tools/git2.py | 40 +-- tools/mbedtls.py | 96 ++++++ tools/openssl.py | 303 ------------------ tools/ssh2.py | 29 +- 15 files changed, 363 insertions(+), 408 deletions(-) delete mode 100644 godot-git-plugin/SCsub create mode 100644 godot-git-plugin/include/std_mbedtls_config.h create mode 100644 godot-git-plugin/include/threading_alt.h create mode 100644 godot-git-plugin/src/std_mbedtls_platform.cpp create mode 160000 thirdparty/mbedtls delete mode 160000 thirdparty/openssl create mode 100644 tools/mbedtls.py delete mode 100644 tools/openssl.py diff --git a/.gitmodules b/.gitmodules index 4d5dd20c..9471d83c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -9,6 +9,6 @@ [submodule "thirdparty/ssh2/libssh2"] path = thirdparty/ssh2/libssh2 url = https://github.com/libssh2/libssh2 -[submodule "thirdparty/openssl"] - path = thirdparty/openssl - url = https://github.com/openssl/openssl +[submodule "thirdparty/mbedtls"] + path = thirdparty/mbedtls + url = https://github.com/Mbed-TLS/mbedtls.git diff --git a/SConstruct b/SConstruct index 78454694..36a015a4 100644 --- a/SConstruct +++ b/SConstruct @@ -10,10 +10,15 @@ opts = Variables([], ARGUMENTS) env = Environment(ENV=os.environ) # Define our options -opts.Add(PathVariable("target_path", - "The path where the lib is installed.", "addons/godot-git-plugin/")) -opts.Add(PathVariable("target_name", "The library name.", - "libgit_plugin", PathVariable.PathAccept)) +opts.Add( + PathVariable( + "target_path", + "The path where the lib is installed (will be created if it does not exists).", + "addons/godot-git-plugin/", + PathVariable.PathAccept, + ) +) +opts.Add(PathVariable("target_name", "The library name.", "libgit_plugin", PathVariable.PathAccept)) # Updates the environment with the option variables. opts.Update(env) @@ -29,25 +34,32 @@ env.__class__.msvc = env.get("is_msvc", False) if env["platform"] == "windows" and env.get("is_msvc", False): env.AppendUnique(LINKFLAGS=["/LTCG"]) -# OpenSSL Builder -env.Tool("openssl", toolpath=["tools"]) - -# SSH2 Builder env.Tool("cmake", toolpath=["tools"]) +env.Tool("mbedtls", toolpath=["tools"]) env.Tool("ssh2", toolpath=["tools"]) env.Tool("git2", toolpath=["tools"]) opts.Update(env) -ssl = env.OpenSSL() +# Generates help for the -h scons option. +Help(opts.GenerateHelpText(env)) + +env["MBEDTLS_CONFIG"] = env.File("godot-git-plugin/include/std_mbedtls_config.h").abspath +env["MBEDTLS_THREADING_ALT"] = env.File("godot-git-plugin/include/threading_alt.h").abspath + +ssl = env.BuildMbedTLS() ssh2 = env.BuildSSH2(ssl) -ssl += ssh2 -git2 = env.BuildGIT2(ssl) +git2 = env.BuildGIT2(ssl, ssh2) -Export("ssl") -Export("env") +# Build our sources +env.Append(CPPPATH=["godot-git-plugin/include/", "godot-git-plugin/src/"]) -SConscript("godot-git-plugin/SCsub") +env.Append(CPPPATH=["#thirdparty/git2/libgit2/include/"]) -# Generates help for the -h scons option. -Help(opts.GenerateHelpText(env)) +lib_sources = Glob("godot-git-plugin/src/*.cpp") +env.Depends(lib_sources, ssl + ssh2) +library = env.SharedLibrary( + target=env["target_path"] + "/{}/{}{}{}".format(env["platform"], env["target_name"], env["suffix"], env["SHLIBSUFFIX"]), + source=lib_sources, +) +Default(library) diff --git a/THIRDPARTY.md b/THIRDPARTY.md index da3654f8..8e3df884 100644 --- a/THIRDPARTY.md +++ b/THIRDPARTY.md @@ -4,8 +4,8 @@ The Godot Git Plugin source code uses the following third-party source code: 1. godotengine/godot-cpp - MIT License - https://github.com/godotengine/godot-cpp/tree/58d1de720b8ffe9f8ffcdfe3a85148582cfd2e74 2. libgit2/libgit2 - GPLv2 with a special Linking Exception - https://github.com/libgit2/libgit2/tree/26055f5af74ab1cf636d272e8a34315496d3f06f -3. libssh2/libssh2 - BSD-3-Clause License - https://github.com/libssh2/libssh2/tree/635caa90787220ac3773c1d5ba11f1236c22eae8 -4. openssl - OpenSSL License - https://github.com/openssl/openssl/tree/aae016bfd52fcad2bc9657c2c782cfdf73b1ed5f +3. libssh2/libssh2 - BSD-3-Clause License - https://github.com/libssh2/libssh2/tree/a312b43325e3383c865a87bb1d26cb52e3292641 +4. mbedTLS - OpenSSL License - https://github.com/Mbed-TLS/mbedtls/tree/068ff080b369adfac81509f9b57b2afabaf82dc5 ## License Texts diff --git a/godot-git-plugin/SCsub b/godot-git-plugin/SCsub deleted file mode 100644 index 05ec9944..00000000 --- a/godot-git-plugin/SCsub +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env python - -import os - -env = {} -Import("env") -Import("ssl") - -env["target_path"] = "../" + env["target_path"] - -if not os.path.isdir(env["target_path"]): - os.mkdir(env["target_path"]) - -# Check our platform specifics -env["target_path"] += env["platform"] + "/" - -if env["platform"] == "macos": - if env["macos_deployment_target"] != "default": - env.Append(CCFLAGS=["-mmacosx-version-min=" + - env["macos_deployment_target"]]) - env.Append(LINKFLAGS=["-mmacosx-version-min=" + - env["macos_deployment_target"]]) -elif env["platform"] == "windows": - env.Append(LIBS=["advapi32", "winhttp", "rpcrt4", "crypt32", - "ole32", "user32", "wsock32", "ws2_32", "bcrypt"]) - -env.Append(CPPPATH=[".", "src/"]) - -env.Append(CPPPATH=["#thirdparty/git2/libgit2/include/"]) - -lib_sources = Glob("src/*.cpp") -env.Depends(lib_sources, ssl) -library = env.SharedLibrary( - target=env["target_path"] + - "{}{}{}".format(env["target_name"], env["suffix"], env["SHLIBSUFFIX"]), - source=lib_sources -) -Default(library) diff --git a/godot-git-plugin/include/std_mbedtls_config.h b/godot-git-plugin/include/std_mbedtls_config.h new file mode 100644 index 00000000..f658303c --- /dev/null +++ b/godot-git-plugin/include/std_mbedtls_config.h @@ -0,0 +1,45 @@ +/**************************************************************************/ +/* std_mbedtls_config.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* 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. */ +/**************************************************************************/ + +#pragma once + +// Include default mbedTLS config. +#include + +#define MBEDTLS_THREADING_C +#define MBEDTLS_THREADING_ALT +#define MBEDTLS_NO_PLATFORM_ENTROPY +#define MBEDTLS_ENTROPY_HARDWARE_ALT + +// Hack to fix libgit2 trying to load invalid certificates (hardcoded at built times). +#ifdef GIT_DEFAULT_CERT_LOCATION +#undef GIT_DEFAULT_CERT_LOCATION +#endif +#define GIT_DEFAULT_CERT_LOCATION NULL diff --git a/godot-git-plugin/include/threading_alt.h b/godot-git-plugin/include/threading_alt.h new file mode 100644 index 00000000..ae4fce59 --- /dev/null +++ b/godot-git-plugin/include/threading_alt.h @@ -0,0 +1,47 @@ +/**************************************************************************/ +/* threading_alt.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* 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. */ +/**************************************************************************/ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + void *mutex; +} mbedtls_threading_mutex_t; + +// MbedTLS 3.x compat +typedef mbedtls_threading_mutex_t mbedtls_platform_mutex_t; +#define MBEDTLS_ERR_THREADING_USAGE_ERROR MBEDTLS_ERR_THREADING_MUTEX_ERROR + +#ifdef __cplusplus +}; +#endif diff --git a/godot-git-plugin/src/gdlibrary.cpp b/godot-git-plugin/src/gdlibrary.cpp index 241245c6..6dcd5880 100644 --- a/godot-git-plugin/src/gdlibrary.cpp +++ b/godot-git-plugin/src/gdlibrary.cpp @@ -3,11 +3,21 @@ #include "godot_cpp/core/class_db.hpp" #include "godot_cpp/godot.hpp" +extern "C" { +int std_mbedtls_platform_init(); +void std_mbedtls_platform_free(); +} + void initialize_git_plugin_module(godot::ModuleInitializationLevel p_level) { if (p_level != godot::MODULE_INITIALIZATION_LEVEL_EDITOR) { return; } + int ret = std_mbedtls_platform_init(); + if (ret) { + ERR_PRINT("GitPlugin: Failed to initialize SSL library"); + return; + } godot::ClassDB::register_class(); } @@ -15,6 +25,7 @@ void uninitialize_git_plugin_module(godot::ModuleInitializationLevel p_level) { if (p_level != godot::MODULE_INITIALIZATION_LEVEL_EDITOR) { return; } + std_mbedtls_platform_free(); } extern "C" { diff --git a/godot-git-plugin/src/std_mbedtls_platform.cpp b/godot-git-plugin/src/std_mbedtls_platform.cpp new file mode 100644 index 00000000..17e49572 --- /dev/null +++ b/godot-git-plugin/src/std_mbedtls_platform.cpp @@ -0,0 +1,104 @@ +/**************************************************************************/ +/* std_mbedtls_platform.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* 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 + +#include +#include +#include + +#include + +#if !defined(MBEDTLS_THREADING_C) +#error "Godot Git Plugin require mbedTLS with threading support" +#endif + +using namespace godot; + +extern "C" { +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) +int mbedtls_hardware_poll(void *p_data, unsigned char *r_output, size_t p_output_size, size_t *r_output_len) { + *r_output_len = 0; + ERR_FAIL_NULL_V(OS::get_singleton(), -1); + PackedByteArray rnd = OS::get_singleton()->get_entropy(p_output_size); + ERR_FAIL_COND_V(rnd.size() != p_output_size, -1); + memcpy(r_output, rnd.ptr(), p_output_size); + *r_output_len = p_output_size; + return 0; +} + +#endif +#if defined(MBEDTLS_THREADING_ALT) +void std_mbedtls_mutex_init(mbedtls_platform_mutex_t *p_mutex) { + if (p_mutex == nullptr) { + return; + } + p_mutex->mutex = new std::mutex(); +} + +void std_mbedtls_mutex_free(mbedtls_platform_mutex_t *p_mutex) { + if (p_mutex == nullptr || p_mutex->mutex == nullptr) { + return; + } + delete ((std::mutex *)p_mutex->mutex); +} + +int std_mbedtls_mutex_lock(mbedtls_platform_mutex_t *p_mutex) { + if (p_mutex == nullptr || p_mutex->mutex == nullptr) { + return MBEDTLS_ERR_THREADING_USAGE_ERROR; + } + ((std::mutex *)p_mutex->mutex)->lock(); + return 0; +} + +int std_mbedtls_mutex_unlock(mbedtls_platform_mutex_t *p_mutex) { + if (p_mutex == nullptr || p_mutex->mutex == nullptr) { + return MBEDTLS_ERR_THREADING_USAGE_ERROR; + } + ((std::mutex *)p_mutex->mutex)->unlock(); + return 0; +} +#endif +int std_mbedtls_platform_init() { +#if defined(MBEDTLS_THREADING_ALT) + mbedtls_threading_set_alt( + std_mbedtls_mutex_init, + std_mbedtls_mutex_free, + std_mbedtls_mutex_lock, + std_mbedtls_mutex_unlock); +#endif + return psa_crypto_init(); +} +void std_mbedtls_platform_free() { +#if defined(MBEDTLS_THREADING_ALT) + mbedtls_threading_free_alt(); +#endif +} +}; diff --git a/thirdparty/mbedtls b/thirdparty/mbedtls new file mode 160000 index 00000000..068ff080 --- /dev/null +++ b/thirdparty/mbedtls @@ -0,0 +1 @@ +Subproject commit 068ff080b369adfac81509f9b57b2afabaf82dc5 diff --git a/thirdparty/openssl b/thirdparty/openssl deleted file mode 160000 index aae016bf..00000000 --- a/thirdparty/openssl +++ /dev/null @@ -1 +0,0 @@ -Subproject commit aae016bfd52fcad2bc9657c2c782cfdf73b1ed5f diff --git a/thirdparty/ssh2/libssh2 b/thirdparty/ssh2/libssh2 index 1c3f1b7d..a312b433 160000 --- a/thirdparty/ssh2/libssh2 +++ b/thirdparty/ssh2/libssh2 @@ -1 +1 @@ -Subproject commit 1c3f1b7da588f2652260285529ec3c1f1125eb4e +Subproject commit a312b43325e3383c865a87bb1d26cb52e3292641 diff --git a/tools/git2.py b/tools/git2.py index 39654584..0ff1b652 100644 --- a/tools/git2.py +++ b/tools/git2.py @@ -1,20 +1,17 @@ -import os - - -def build_library(env, deps): +def build_library(env, ssl, ssh2): config = { "CMAKE_BUILD_TYPE": "RelWithDebInfo" if env["debug_symbols"] else "Release", - "OPENSSL_USE_STATIC_LIBS": 1, - "OPENSSL_INCLUDE_DIR": env["SSL_INCLUDE"], - "OPENSSL_SSL_LIBRARY": env["SSL_LIBRARY"], - "OPENSSL_CRYPTO_LIBRARY": env["SSL_CRYPTO_LIBRARY"], - "OPENSSL_ROOT_DIR": env["SSL_INSTALL"], + "CMAKE_C_STANDARD": "99", + "MBEDTLS_LIBRARY": env["MBEDTLS_LIBRARY"], + "MBEDCRYPTO_LIBRARY": env["MBEDTLS_CRYPTO_LIBRARY"], + "MBEDX509_LIBRARY": env["MBEDTLS_X509_LIBRARY"], + "MBEDTLS_INCLUDE_DIR": env["MBEDTLS_INCLUDE"], "BUILD_TESTS": "OFF", "BUILD_CLI": "OFF", "BUILD_EXAMPLES": "OFF", "BUILD_FUZZERS": "OFF", - "USE_SSH": "ON", - "USE_HTTPS": "OpenSSL", + "USE_SSH": "libssh2", + "USE_HTTPS": "mbedTLS", "USE_SHA1": "CollisionDetection", "USE_BUNDLED_ZLIB": "ON", "USE_HTTP_PARSER": "builtin", @@ -22,42 +19,35 @@ def build_library(env, deps): "BUILD_SHARED_LIBS": 0, "LINK_WITH_STATIC_LIBRARIES": 1, "LIBSSH2_INCLUDE_DIRS": env.Dir("#thirdparty/ssh2/libssh2/include").abspath, - "LIBSSH2_RESOLVED": deps[-1].abspath, + "LIBSSH2_RESOLVED": ssh2[-1].abspath, "LIBSSH2_LIBRARIES": "LIBSSH2", "LIBSSH2_FOUND": 1, - "USE_WINHTTP": 0, + "CMAKE_POSITION_INDEPENDENT_CODE": "ON", "STATIC_CRT": env.get("use_static_cpp", True), - "CMAKE_DISABLE_FIND_PACKAGE_ZLIB": 1, + "CMAKE_C_FLAGS": env.MbedTLSFlags(), } - if env["platform"] != "windows": - config["CMAKE_C_FLAGS"] = "-fPIC" - else: - config["OPENSSL_ROOT_DIR"] = env["SSL_BUILD"] - is_msvc = env.get("is_msvc", False) lib_ext = ".lib" if is_msvc else ".a" lib_prefix = "" if is_msvc else "lib" libs = ["{}git2{}".format(lib_prefix, lib_ext)] - source = env.Dir("#thirdparty/git2/libgit2").abspath - target = env.Dir("#bin/thirdparty/libgit2").abspath - git2 = env.CMakeBuild( "#bin/thirdparty/git2/", "#thirdparty/git2/libgit2", cmake_options=config, cmake_outputs=libs, cmake_targets=[], - dependencies=deps, + dependencies=ssl + ssh2, ) env.Append(CPPPATH=["#thirdparty/git2/libgit2/include"]) env.Prepend(LIBS=git2[1:]) + if env["platform"] == "windows": - env.PrependUnique(LIBS=["secur32"]) + env.AppendUnique(LIBS=["secur32"]) elif env["platform"] == "macos": - env.Append(LIBS=["iconv"]) + env.AppendUnique(LIBS=["iconv"]) return git2 diff --git a/tools/mbedtls.py b/tools/mbedtls.py new file mode 100644 index 00000000..62a7567e --- /dev/null +++ b/tools/mbedtls.py @@ -0,0 +1,96 @@ +def get_build_flags(env): + flags = "" + if env["MBEDTLS_CONFIG"]: + if env.msvc: + flags += ' \\"\\"-DMBEDTLS_CONFIG_FILE=<{}>\\"\\"'.format(env["MBEDTLS_CONFIG"]) + else: + flags += " '-DMBEDTLS_CONFIG_FILE=\\\"{}\\\"'".format(env["MBEDTLS_CONFIG"]) + if env["MBEDTLS_THREADING_ALT"]: + if env.msvc: + flags += ' /I\\"\\"{}\\"\\"'.format(env.File(env["MBEDTLS_THREADING_ALT"]).dir.abspath) + else: + flags += " '-I{}'".format(env.File(env["MBEDTLS_THREADING_ALT"]).dir.abspath) + return flags + + +def build_library(env): + deps = [] + mbedtls_bin = env.Dir("bin/thirdparty/mbedtls/{}/{}/install".format(env["platform"], env["arch"])) + c_flags = env.MbedTLSFlags() + if env["MBEDTLS_CONFIG"]: + if env.msvc: + env.Append(CPPDEFINES=[("MBEDTLS_CONFIG_FILE", '"<{}>"'.format(env["MBEDTLS_CONFIG"]))]) + else: + env.Append(CPPDEFINES=[("MBEDTLS_CONFIG_FILE", '\\"{}\\"'.format(env["MBEDTLS_CONFIG"]))]) + deps.append(env["MBEDTLS_CONFIG"]) + if env["MBEDTLS_THREADING_ALT"]: + deps += [env.File(env["MBEDTLS_THREADING_ALT"])] + + if env["platform"] == "windows" and not env.msvc: + c_flags += " -D__USE_MINGW_ANSI_STDIO=0" # See https://github.com/Mbed-TLS/mbedtls/issues/10161 + + mbedtls_config = { + "CMAKE_BUILD_TYPE": "RelWithDebInfo" if env["debug_symbols"] else "Release", + "ENABLE_TESTING": 0, + "ENABLE_PROGRAMS": 0, + "CMAKE_INSTALL_PREFIX": env.Dir(mbedtls_bin).abspath, + "CMAKE_C_FLAGS": c_flags, + "MBEDTLS_FATAL_WARNINGS": 0, + "CMAKE_INSTALL_LIBDIR": "lib", + "CMAKE_POSITION_INDEPENDENT_CODE": "ON", + } + + lib_ext = ".lib" if env.msvc else ".a" + lib_prefix = "" if env.msvc else "lib" + mbedtls_libs = [ + "/install/lib/{}mbedtls{}".format(lib_prefix, lib_ext), + "/install/lib/{}mbedx509{}".format(lib_prefix, lib_ext), + "/install/lib/{}mbedcrypto{}".format(lib_prefix, lib_ext), + ] + + mbedtls_cmake_config = [ + "/install/lib/cmake/MbedTLS/MbedTLSConfig.cmake", + "/install/lib/cmake/MbedTLS/MbedTLSConfigVersion.cmake", + "/install/lib/cmake/MbedTLS/MbedTLSTargets.cmake", + ] + + # Build libdatachannel + mbedtls = env.CMakeBuild( + env.Dir("bin/thirdparty/mbedtls/"), + env.Dir("thirdparty/mbedtls"), + cmake_options=mbedtls_config, + cmake_outputs=mbedtls_libs + mbedtls_cmake_config, + dependencies=deps, + install=True, + ) + + # Configure env. + if env["platform"] == "windows": + env.PrependUnique(LIBS=["bcrypt", "ws2_32", "iphlpapi"]) + if env["platform"] == "linux": + env.PrependUnique(LIBS=["pthread"]) + env.Prepend(LIBS=list(filter(lambda f: str(f).endswith(lib_ext), mbedtls))) + env.Append(CPPPATH=[env.Dir("thirdparty/mbedtls/include")]) + + return mbedtls + + +def exists(env): + return "CMake" in env + + +def generate(env): + mbedtls_install_dir = "bin/thirdparty/mbedtls/{}/{}/install".format(env["platform"], env["arch"]) + lib_ext = ".lib" if env.msvc else ".a" + mbedtls = env.File(mbedtls_install_dir + "/lib/libmbedtls" + lib_ext) + crypto = env.File(mbedtls_install_dir + "/lib/libmbedcrypto" + lib_ext) + x509 = env.File(mbedtls_install_dir + "/lib/libmbedx509" + lib_ext) + includes = env.Dir("thirdparty/mbedtls/include") + env["MBEDTLS_LIBRARY"] = mbedtls.abspath + env["MBEDTLS_CRYPTO_LIBRARY"] = crypto.abspath + env["MBEDTLS_X509_LIBRARY"] = x509.abspath + env["MBEDTLS_INCLUDE"] = includes.abspath + env["MBEDTLS_CONFIG"] = "" + env["MBEDTLS_THREADING_ALT"] = "" + env.AddMethod(build_library, "BuildMbedTLS") + env.AddMethod(get_build_flags, "MbedTLSFlags") diff --git a/tools/openssl.py b/tools/openssl.py deleted file mode 100644 index 900f5e04..00000000 --- a/tools/openssl.py +++ /dev/null @@ -1,303 +0,0 @@ -import os -import sys - -import SCons.Action -import SCons.Builder -import SCons.Util -from SCons.Defaults import Mkdir -from SCons.Variables import PathVariable - - -def ssl_platform_target(env): - targets = {} - platform = env["platform"] - if platform == "linux": - targets = { - "x86_32": "linux-x86", - "x86_64": "linux-x86_64", - "arm64": "linux-aarch64", - "arm32": "linux-armv4", - "rv64": "linux64-riscv64", - } - elif platform == "android": - targets = { - "arm64": "android-arm64", - "arm32": "android-arm", - "x86_32": "android-x86", - "x86_64": "android-x86_64", - } - elif platform == "macos": - targets = { - "x86_64": "darwin64-x86_64", - "arm64": "darwin64-arm64", - } - elif platform == "ios": - if env["ios_simulator"]: - targets = { - "x86_64": "iossimulator-xcrun", - "arm64": "iossimulator-xcrun", - } - else: - targets = { - "arm64": "ios64-xcrun", - "arm32": "ios-xcrun", - } - elif platform == "windows": - if env.get("is_msvc", False): - targets = { - "x86_32": "VC-WIN32", - "x86_64": "VC-WIN64A", - } - else: - targets = { - "x86_32": "mingw", - "x86_64": "mingw64", - } - - arch = env["arch"] - target = targets.get(arch, "") - if target == "": - raise ValueError("Architecture '%s' not supported for platform: '%s'" % (arch, platform)) - return target - - -def ssl_platform_options(env): - ssl_config_options = [ - "no-ssl2", - "no-ssl3", - "no-weak-ssl-ciphers", - "no-legacy", - "no-shared", - "no-tests", - ] - if env["platform"] == "windows": - ssl_config_options.append("enable-capieng") - return ssl_config_options - - -def ssl_platform_flags(env): - args = [] - if env["platform"] == "android": - if env.get("android_api_level", ""): - api = int(env["android_api_level"]) - args.append("-D__ANDROID_API__=%s" % api) - elif env["platform"] == "ios": - if env.get("ios_min_version", "default") != "default": - if env.get("ios_simulator", False): - args.append("-mios-simulator-version-min=%s" % env["ios_min_version"]) - else: - args.append("-miphoneos-version-min=%s" % env["ios_min_version"]) - elif env["platform"] == "macos": - if env.get("macos_deployment_target", "default") != "default": - args.append("-mmacosx-version-min=%s" % env["macos_deployment_target"]) - # OSXCross toolchain setup. - if sys.platform != "darwin" and "OSXCROSS_ROOT" in os.environ: - for k in ["CC", "CXX", "AR", "AS", "RANLIB"]: - args.append("%s=%s" % (k, env[k])) - elif env["platform"] == "windows": - is_win_host = sys.platform in ["win32", "msys", "cygwin"] - if not (is_win_host or env.get("is_msvc", False)): - mingw_prefixes = { - "x86_32": "--cross-compile-prefix=i686-w64-mingw32-", - "x86_64": "--cross-compile-prefix=x86_64-w64-mingw32-", - } - args.append(mingw_prefixes[env["arch"]]) - return args - - -def ssl_configure_args(env): - if env.get("openssl_configure_options", ""): - opts = SCons.Util.CLVar(env["openssl_configure_options"]) - else: - opts = ssl_platform_options(env) - - if env.get("openssl_configure_target", ""): - target = [env["openssl_configure_target"]] - else: - target = [ssl_platform_target(env)] - - if env.get("openssl_configure_flags", ""): - flags = SCons.Util.CLVar(env["openssl_configure_flags"]) - else: - flags = ssl_platform_flags(env) - - return opts + target + flags - - -def ssl_emitter(target, source, env): - return env["SSL_LIBS"], [env.File(env["SSL_SOURCE"] + "/Configure"), env.File(env["SSL_SOURCE"] + "/VERSION.dat")] - - -def build_openssl(env, jobs=None): - if env["SSL_EXTERNAL"]: - # Setup the env to use the provided libraries, and return them without building. - env.Prepend(CPPPATH=[env["SSL_INCLUDE"]]) - env.Prepend(LIBPATH=[env["SSL_BUILD"]]) - if env["platform"] == "windows": - env.PrependUnique(LIBS=["crypt32", "ws2_32", "advapi32", "user32"]) - if env["platform"] == "linux": - env.PrependUnique(LIBS=["pthread", "dl"]) - env.Prepend(LIBS=env["SSL_LIBS"]) - return [env["SSL_CRYPTO_LIBRARY"], env["SSL_LIBRARY"]] - - if jobs is None: - jobs = int(env.GetOption("num_jobs")) - - # Since the OpenSSL build system does not support macOS universal binaries, we first need to build the two libraries - # separately, then we join them together using lipo. - if env["platform"] == "macos" and env["arch"] == "universal": - build_envs = { - "x86_64": env.Clone(), - "arm64": env.Clone(), - } - arch_ssl = [] - for arch in build_envs: - benv = build_envs[arch] - benv["arch"] = arch - generate(benv) - benv["SSLBUILDJOBS"] = max([1, int(jobs / len(build_envs))]) - ssl = benv.OpenSSLBuilder() - arch_ssl.extend(ssl) - benv.NoCache(ssl) # Needs refactoring to properly cache generated headers. - - # x86_64 and arm64 includes are equivalent. - env["SSL_INCLUDE"] = build_envs["arm64"]["SSL_INCLUDE"] - - # Join libraries using lipo. - lipo_action = "lipo $SOURCES -create -output $TARGET" - ssl_libs = list(map(lambda arch: build_envs[arch]["SSL_LIBRARY"], build_envs)) - ssl_crypto_libs = list(map(lambda arch: build_envs[arch]["SSL_CRYPTO_LIBRARY"], build_envs)) - ssl = env.Command(env["SSL_LIBRARY"], ssl_libs, lipo_action) - ssl += env.Command(env["SSL_CRYPTO_LIBRARY"], ssl_crypto_libs, lipo_action) - env.Depends(ssl, arch_ssl) - else: - benv = env.Clone() - benv["SSLBUILDJOBS"] = jobs - ssl = benv.OpenSSLBuilder() - benv.NoCache(ssl) # Needs refactoring to properly cache generated headers. - - # Setup the environment to use the freshly built openssl. - env.Prepend(CPPPATH=[env["SSL_INCLUDE"]]) - env.Prepend(LIBPATH=[env["SSL_BUILD"]]) - if env["platform"] == "windows": - env.PrependUnique(LIBS=["crypt32", "ws2_32", "advapi32", "user32"]) - if env["platform"] == "linux": - env.PrependUnique(LIBS=["pthread", "dl"]) - env.Prepend(LIBS=env["SSL_LIBS"]) - - return ssl - - -def ssl_generator(target, source, env, for_signature): - # Strip the -j option for signature to avoid rebuilding when num_jobs changes. - build = env["SSLBUILDCOM"].replace("-j$SSLBUILDJOBS", "") if for_signature else env["SSLBUILDCOM"] - return [ - Mkdir("$SSL_BUILD"), - Mkdir("$SSL_INSTALL"), - SCons.Action.Action("$SSLCONFIGCOM", "$SSLCONFIGCOMSTR"), - SCons.Action.Action(build, "$SSLBUILDCOMSTR"), - ] - - -def options(opts): - opts.Add(PathVariable("openssl_source", "Path to the openssl sources.", "thirdparty/openssl")) - opts.Add("openssl_build", "Destination path of the openssl build.", "bin/thirdparty/openssl") - opts.Add( - "openssl_configure_options", - "OpenSSL configure options override. Will use a reasonable default if not specified.", - "", - ) - opts.Add( - "openssl_configure_target", "OpenSSL configure target override, will be autodetected if not specified.", "" - ) - opts.Add( - "openssl_configure_flags", - "OpenSSL configure compiler flags override. Will be autodetected if not specified.", - "", - ) - opts.Add( - "openssl_external_crypto", - 'An external libcrypto static library (e.g. "/usr/lib/x86_64-linux-gnu/libcrypto.a"). If not provided, OpenSSL will be built from source.', - "", - ) - opts.Add( - "openssl_external_ssl", - 'An external libssl static library (e.g. "/usr/lib/x86_64-linux-gnu/libssl.a"). If not provided, OpenSSL will be built from source.', - "", - ) - opts.Add( - "openssl_external_include", - 'An external OpenSSL "include" folder (e.g. "/usr/include/openssl").', - "", - ) - - -def exists(env): - return True - - -def generate(env): - env.AddMethod(build_openssl, "OpenSSL") - - # Check if the user specified infos about external OpenSSL files. - external_opts = ["openssl_external_crypto", "openssl_external_ssl", "openssl_external_include"] - - def is_set(k): - return env.get(k, "") != "" - - if any(map(is_set, external_opts)): - # Need provide the whole (crypto, ssl, include) triple to proceed. - if not all(map(is_set, external_opts)): - print('Error: The options "%s" must all be set to use a external library.' % '", "'.join(external_opts)) - sys.exit(255) - - env["SSL_CRYPTO_LIBRARY"] = env.File("${openssl_external_crypto}") - env["SSL_LIBRARY"] = env.File("${openssl_external_ssl}") - env["SSL_BUILD"] = env.Dir("${SSL_LIBRARY.dir}").abspath - env["SSL_INSTALL"] = env.Dir("${SSL_LIBRARY.dir}").abspath - env["SSL_INCLUDE"] = env.Dir("${openssl_external_include}").abspath - env["SSL_LIBS"] = [env["SSL_LIBRARY"], env["SSL_CRYPTO_LIBRARY"]] - env["SSL_EXTERNAL"] = True - return - - # We will need to build our own OpenSSL library. - env["SSL_EXTERNAL"] = False - - # Android needs the NDK in ENV, and proper PATH setup. - if env["platform"] == "android" and env["ENV"].get("ANDROID_NDK_ROOT", "") == "": - cc_path = os.path.dirname(env["CC"]) - if cc_path and cc_path not in env["ENV"]: - env.PrependENVPath("PATH", cc_path) - if "ANDROID_NDK_ROOT" not in env["ENV"]: - env["ENV"]["ANDROID_NDK_ROOT"] = env.get("ANDROID_NDK_ROOT", os.environ.get("ANDROID_NDK_ROOT", "")) - - env["SSL_SOURCE"] = env.Dir(env["openssl_source"]).abspath - env["SSL_BUILD"] = env.Dir(env["openssl_build"] + "/{}/{}".format(env["platform"], env["arch"])).abspath - env["SSL_INSTALL"] = env.Dir(env["SSL_BUILD"] + "/dest").abspath - env["SSL_INCLUDE"] = env.Dir(env["SSL_INSTALL"] + "/include").abspath - lib_ext = ".lib" if env.get("is_msvc", False) else ".a" - env["SSL_LIBRARY"] = env.File(env["SSL_BUILD"] + "/libssl" + lib_ext) - env["SSL_CRYPTO_LIBRARY"] = env.File(env["SSL_BUILD"] + "/libcrypto" + lib_ext) - env["SSL_LIBS"] = [env["SSL_LIBRARY"], env["SSL_CRYPTO_LIBRARY"]] - - # Configure action - env["PERL"] = env.get("PERL", "perl") - env["_ssl_configure_args"] = ssl_configure_args - env["SSLPLATFORMCONFIG"] = "${_ssl_configure_args(__env__)}" - env["SSLCONFFLAGS"] = SCons.Util.CLVar("") - # fmt: off - env["SSLCONFIGCOM"] = 'cd ${TARGET.dir} && $PERL -- ${SOURCE.abspath} --prefix="${SSL_INSTALL}" --openssldir="${SSL_INSTALL}" $SSLPLATFORMCONFIG $SSLCONFFLAGS' - # fmt: on - - # Build action - env["SSLBUILDJOBS"] = "${__env__.GetOption('num_jobs')}" - # fmt: off - env["SSLBUILDCOM"] = "make -j$SSLBUILDJOBS -C ${TARGET.dir} && make -j$SSLBUILDJOBS -C ${TARGET.dir} install_sw install_ssldirs" - # fmt: on - - # Windows MSVC needs to build using NMake - if env["platform"] == "windows" and env.get("is_msvc", False): - env["SSLBUILDCOM"] = "cd ${TARGET.dir} && nmake install_sw install_ssldirs" - - env["BUILDERS"]["OpenSSLBuilder"] = SCons.Builder.Builder(generator=ssl_generator, emitter=ssl_emitter) - env.AddMethod(build_openssl, "OpenSSL") diff --git a/tools/ssh2.py b/tools/ssh2.py index 6bffaad3..594248fd 100644 --- a/tools/ssh2.py +++ b/tools/ssh2.py @@ -1,34 +1,22 @@ -import os - - def build_library(env, deps): config = { "CMAKE_BUILD_TYPE": "RelWithDebInfo" if env["debug_symbols"] else "Release", - "OPENSSL_USE_STATIC_LIBS": 1, - "OPENSSL_INCLUDE_DIR": env["SSL_INCLUDE"], - "OPENSSL_SSL_LIBRARY": env["SSL_LIBRARY"].abspath, - "OPENSSL_CRYPTO_LIBRARY": env["SSL_CRYPTO_LIBRARY"].abspath, - "OPENSSL_ROOT_DIR": env["SSL_INSTALL"], + "MBEDTLS_LIBRARY": env["MBEDTLS_LIBRARY"], + "MBEDCRYPTO_LIBRARY": env["MBEDTLS_CRYPTO_LIBRARY"], + "MBEDX509_LIBRARY": env["MBEDTLS_X509_LIBRARY"], + "MBEDTLS_INCLUDE_DIR": env["MBEDTLS_INCLUDE"], "BUILD_EXAMPLES": 0, "BUILD_TESTING": 0, "BUILD_SHARED_LIBS": 0, - "CMAKE_DISABLE_FIND_PACKAGE_ZLIB": 1, - "CRYPTO_BACKEND": "OpenSSL", - "CMAKE_POLICY_VERSION_MINIMUM": 3.5, + "CRYPTO_BACKEND": "mbedTLS", + "CMAKE_POSITION_INDEPENDENT_CODE": "ON", + "CMAKE_C_FLAGS": env.MbedTLSFlags(), } - if env["platform"] != "windows": - config["CMAKE_C_FLAGS"] = "-fPIC" - else: - config["OPENSSL_ROOT_DIR"] = env["SSL_BUILD"] - is_msvc = env.get("is_msvc", False) lib_ext = ".lib" if is_msvc else ".a" libs = ["src/libssh2{}".format(lib_ext)] - source = env.Dir("#thirdparty/ssh2/libssh2").abspath - target = env.Dir("#bin/thirdparty/libssh2").abspath - ssh2 = env.CMakeBuild( "#bin/thirdparty/ssh2/", "#thirdparty/ssh2/libssh2", @@ -41,6 +29,9 @@ def build_library(env, deps): env.Append(CPPPATH=["#thirdparty/ssh2/libssh2/include"]) env.Prepend(LIBS=ssh2[1:]) + if env["platform"] == "windows": + env.AppendUnique(LIBS=["advapi32", "user32"]) + return ssh2 From b28d0073426c0318745ef345986d53efb6fe7b12 Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Tue, 28 Jul 2026 15:58:51 +0200 Subject: [PATCH 2/2] Add arm builds, x86_32, android, package script --- .github/workflows/build.yml | 91 +------ .github/workflows/build_release.yml | 231 ++++++++++++++++++ .gitignore | 5 - SConstruct | 3 +- addons/.gitignore | 2 + .../godot-git-plugin/git_plugin.gdextension | 10 - misc/git_plugin.gdextension | 18 ++ misc/scripts/package_release.sh | 27 ++ 8 files changed, 282 insertions(+), 105 deletions(-) create mode 100644 .github/workflows/build_release.yml create mode 100644 addons/.gitignore delete mode 100644 addons/godot-git-plugin/git_plugin.gdextension create mode 100644 misc/git_plugin.gdextension create mode 100755 misc/scripts/package_release.sh diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3e50ecfa..1ffbdd86 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,4 +1,4 @@ -name: C/C++ CI +name: C/C++ CI Tests on: [push, pull_request] @@ -9,59 +9,6 @@ env: SCONS_CACHE: ${{ github.workspace }}/.scons-cache/ jobs: - linux-x64: - runs-on: ubuntu-24.04 - env: - BUILDROOT: x86_64-godot-linux-gnu_sdk-buildroot - steps: - - uses: actions/checkout@v6 - with: - submodules: recursive - - name: Restore Godot build cache - uses: ./godot-cpp/.github/actions/godot-cache-restore - with: - cache-name: linux-x86_64 - scons-cache: ${{ env.SCONS_CACHE }} - continue-on-error: true - - name: Setup Linux buildroot toolchain cache - uses: actions/cache@v5 - with: - path: | - ${{ env.BUILDROOT }}.tar.bz2 - key: linux-${{ env.BUILDROOT }}-buildroot - continue-on-error: true - - name: Setup Linux toolchains - run: | - if [ ! -f ${{ env.BUILDROOT }}.tar.bz2 ]; then - wget https://github.com/godotengine/buildroot/releases/download/godot-2026.05.x-1/${{ env.BUILDROOT }}.tar.bz2 - fi - tar -xjf ${{ env.BUILDROOT }}.tar.bz2 - ${{ env.BUILDROOT }}/relocate-sdk.sh - rm ${{ env.BUILDROOT }}/bin/cmake - echo "$GITHUB_WORKSPACE/${{ env.BUILDROOT }}/bin" >> $GITHUB_PATH - echo "PKG_CONFIG=$GITHUB_WORKSPACE/${{ env.BUILDROOT }}/share/pkgconfig/" >> $GITHUB_ENV - - name: Build for Linux editor x86_64 - run: | - pip3 install scons - scons platform=linux arch=x86_64 - ldd addons/godot-git-plugin/linux/*.so - - name: Save Godot build cache - uses: ./godot-cpp/.github/actions/godot-cache-save - with: - cache-name: linux-x86_64 - scons-cache: ${{ env.SCONS_CACHE }} - continue-on-error: true - - name: Prepare artifact - run: | - mkdir out - mv addons out/ - - uses: actions/upload-artifact@v7 - with: - name: libgit_plugin.linux.x86_64.editor.so-${{ github.sha }} - if-no-files-found: error - path: | - out/ - windows-x64: runs-on: windows-2022 steps: @@ -92,7 +39,7 @@ jobs: shell: bash run: | # Not needed to use the plugin. - rm -f addons/godot-git-plugin/windows/*.{exp,lib} + rm -f addons/godot-git-plugin/lib/*.{exp,lib} mkdir out mv addons out/ - uses: actions/upload-artifact@v7 @@ -101,37 +48,3 @@ jobs: if-no-files-found: error path: | out/ - - macos-universal: - runs-on: macos-latest - steps: - - uses: actions/checkout@v6 - with: - submodules: recursive - - name: Restore Godot build cache - uses: ./godot-cpp/.github/actions/godot-cache-restore - with: - cache-name: macos-universal - scons-cache: ${{ env.SCONS_CACHE }} - continue-on-error: true - - name: Build for macOS editor universal - run: | - pip install scons - scons platform=macos arch=universal macos_deployment_target=10.13 - otool -L addons/godot-git-plugin/macos/*.dylib - - name: Save Godot build cache - uses: ./godot-cpp/.github/actions/godot-cache-save - with: - cache-name: macos-universal - scons-cache: ${{ env.SCONS_CACHE }} - continue-on-error: true - - name: Prepare artifact - run: | - mkdir out - mv addons out/ - - uses: actions/upload-artifact@v7 - with: - name: libgit_plugin.macos.universal.editor.dylib-${{ github.sha }} - if-no-files-found: error - path: | - out/ diff --git a/.github/workflows/build_release.yml b/.github/workflows/build_release.yml new file mode 100644 index 00000000..4c54d072 --- /dev/null +++ b/.github/workflows/build_release.yml @@ -0,0 +1,231 @@ +name: 🔧 Build -> Package 📦 +on: [push, pull_request] + +env: + # Only used for the cache key. Increment version to force clean build. + GODOT_BASE_BRANCH: master + # LLVM version + MINGW_LLVM_VERSION: "20260616" + # Hardcoding this seem to be the only way + ANDROID_NDK_ROOT: /usr/local/lib/android/sdk/ndk/28.1.13356709/ + +jobs: + build: + runs-on: ${{ matrix.os }} + name: 🔧 Build + strategy: + fail-fast: false + matrix: + include: + # Android + - platform: android + arch: 'x86_64' + sconsflags: '' + os: 'ubuntu-24.04' + cache-name: android-x86_64 + - platform: android + arch: 'arm64' + sconsflags: '' + os: 'ubuntu-24.04' + cache-name: android-arm64 + + # Linux + - platform: linux + arch: 'x86_32' + buildroot: 'i686-godot-linux-gnu_sdk-buildroot' + sconsflags: '' + os: 'ubuntu-24.04' + cache-name: linux-x86_32 + - platform: linux + arch: 'x86_64' + buildroot: 'x86_64-godot-linux-gnu_sdk-buildroot' + sconsflags: '' + os: 'ubuntu-24.04' + cache-name: linux-x86_64 + - platform: linux + arch: 'arm32' + buildroot: 'arm-godot-linux-gnueabihf_sdk-buildroot' + sconsflags: '' + os: 'ubuntu-24.04' + cache-name: linux-arm32 + - platform: linux + arch: 'arm64' + buildroot: 'aarch64-godot-linux-gnu_sdk-buildroot' + sconsflags: '' + os: 'ubuntu-24.04' + cache-name: linux-arm64 + + # macOS + - platform: macos + arch: 'universal' + sconsflags: '' + os: 'macos-latest' + cache-name: macos-universal + + # Windows + - platform: windows + arch: 'x86_32' + sconsflags: 'use_mingw=yes' + os: 'ubuntu-24.04' + cache-name: win-x86_32 + - platform: windows + arch: 'x86_64' + sconsflags: 'use_mingw=yes' + os: 'ubuntu-24.04' + cache-name: win-x86_64 + - platform: windows + arch: 'arm64' + sconsflags: 'use_mingw=yes use_llvm=yes' + os: 'ubuntu-24.04' + cache-name: win-arm64 + + env: + SCONS_CACHE: ${{ github.workspace }}/.scons-cache/ + SCONSFLAGS: ${{ matrix.sconsflags }} platform=${{ matrix.platform }} arch=${{ matrix.arch }} build_profile=build_profile.json target=editor api_version=4.3 target_path=out/addons/godot-git-plugin/ --jobs=2 + + defaults: + run: + shell: bash + + steps: + - uses: actions/checkout@v6 + with: + submodules: recursive + + - name: Restore Godot build cache + uses: ./godot-cpp/.github/actions/godot-cache-restore + with: + cache-name: ${{ matrix.cache-name }} + scons-cache: ${{ env.SCONS_CACHE }} + continue-on-error: true + + - name: Setup Windows MinGW toolchain cache + if: ${{ matrix.platform == 'windows' && matrix.arch == 'arm64' }} + uses: actions/cache@v5 + with: + path: | + llvm-mingw-$MINGW_LLVM_VERSION-ucrt-ubuntu-22.04-x86_64.tar.bz2 + key: llvm-mingw-$MINGW_LLVM_VERSION-ucrt-ubuntu-22.04-x86_64 + + - name: Install mingw-LLVM + if: ${{ matrix.platform == 'windows' && matrix.arch == 'arm64' }} + run: | + NAME=llvm-mingw-$MINGW_LLVM_VERSION-ucrt-ubuntu-22.04-x86_64 + URL="https://github.com/mstorsjo/llvm-mingw/releases/download/$MINGW_LLVM_VERSION/$NAME.tar.xz" + if [ ! -f $NAME.bz2 ]; then + wget $URL + fi + tar -xJf $NAME.tar.xz + echo "$GITHUB_WORKSPACE/$NAME/bin" >> $GITHUB_PATH + + - name: Install mingw-GCC + if: ${{ matrix.platform == 'windows' && matrix.arch != 'arm64' }} + run: | + sudo apt-get update + sudo apt-get install build-essential mingw-w64 + sudo update-alternatives --set i686-w64-mingw32-gcc /usr/bin/i686-w64-mingw32-gcc-posix + sudo update-alternatives --set i686-w64-mingw32-g++ /usr/bin/i686-w64-mingw32-g++-posix + sudo update-alternatives --set x86_64-w64-mingw32-gcc /usr/bin/x86_64-w64-mingw32-gcc-posix + sudo update-alternatives --set x86_64-w64-mingw32-g++ /usr/bin/x86_64-w64-mingw32-g++-posix + dpkg -l | grep ii | grep mingw + update-alternatives --get-selections | grep mingw + + - name: Install Linux build dependencies + if: ${{ matrix.platform == 'linux' }} + run: | + sudo apt-get update + sudo apt-get install build-essential gcc-multilib g++-multilib wget + + - name: Setup Linux buildroot toolchain cache + if: ${{ matrix.platform == 'linux' }} + uses: actions/cache@v5 + with: + path: | + ${{ matrix.buildroot }}.tar.bz2 + key: linux-${{ matrix.buildroot }}-buildroot + + - name: Set up Python 3.x + uses: actions/setup-python@v6 + with: + python-version: '3.x' + architecture: 'x64' + + - name: Configuring Python packages + run: | + python -c "import sys; print(sys.version)" + python -m pip install scons + + - name: Setup Linux toolchains + if: ${{ matrix.platform == 'linux' }} + run: | + if [ ! -f ${{ matrix.buildroot }}.tar.bz2 ]; then + wget https://github.com/godotengine/buildroot/releases/download/godot-2026.05.x-1/${{ matrix.buildroot }}.tar.bz2 + fi + tar -xjf ${{ matrix.buildroot }}.tar.bz2 + ${{ matrix.buildroot }}/relocate-sdk.sh + rm ${{ matrix.buildroot }}/bin/cmake + echo "$GITHUB_WORKSPACE/${{ matrix.buildroot }}/bin" >> $GITHUB_PATH + echo "PKG_CONFIG=$GITHUB_WORKSPACE/${{ matrix.buildroot }}/share/pkgconfig/" >> $GITHUB_ENV + + - name: Setup Android dependencies + if: ${{ matrix.platform == 'android' }} + uses: nttld/setup-ndk@v1 + with: + ndk-version: r28b + link-to-sdk: true + + - name: Print tools versions + run: | + python --version + scons --version + cmake --version + + - name: Compile Extension (4.3+) - ${{ matrix.platform }} - ${{ matrix.arch }} + run: | + scons + + - name: Save Godot build cache + uses: ./godot-cpp/.github/actions/godot-cache-save + with: + cache-name: ${{ matrix.cache-name }} + scons-cache: ${{ env.SCONS_CACHE }} + continue-on-error: true + + - uses: actions/upload-artifact@v7 + with: + name: ${{ github.job }}-${{ matrix.platform }}-${{ matrix.arch }} + path: | + out/ + + package: + name: 📦 Package + needs: build + runs-on: "ubuntu-latest" + steps: + - uses: actions/checkout@v6 + with: + submodules: recursive + + - uses: actions/download-artifact@v8 + with: + path: artifacts + + - name: Bundle licenses. + run: | + cp LICENSE artifacts/LICENSE.godot-git-plugin + cp thirdparty/mbedtls/LICENSE artifacts/LICENSE.mbedtls + cp thirdparty/ssh2/libssh2/COPYING artifacts/LICENSE.libssh2 + cp thirdparty/git2/libgit2/COPYING artifacts/LICENSE.libgit2 + + - name: Package artifacts for release + env: + DESTINATION: "release" + run: | + mkdir release + ./misc/scripts/package_release.sh + ls -R release + + - uses: actions/upload-artifact@v7 + with: + name: godot-git-plugin + path: release/godot-git-plugin.zip diff --git a/.gitignore b/.gitignore index 7debfddd..3681f993 100644 --- a/.gitignore +++ b/.gitignore @@ -19,11 +19,6 @@ extension_api.json # Binaries __pycache__/ -build/ -bin/ -macos/ -linux/ -windows/ *.lib *.a *.obj diff --git a/SConstruct b/SConstruct index 36a015a4..8de87573 100644 --- a/SConstruct +++ b/SConstruct @@ -59,7 +59,8 @@ env.Append(CPPPATH=["#thirdparty/git2/libgit2/include/"]) lib_sources = Glob("godot-git-plugin/src/*.cpp") env.Depends(lib_sources, ssl + ssh2) library = env.SharedLibrary( - target=env["target_path"] + "/{}/{}{}{}".format(env["platform"], env["target_name"], env["suffix"], env["SHLIBSUFFIX"]), + target=env["target_path"] + "/lib/{}{}{}".format(env["target_name"], env["suffix"], env["SHLIBSUFFIX"]), source=lib_sources, ) +library += env.InstallAs(env["target_path"] + "/git_plugin.gdextension", env.File("#misc/git_plugin.gdextension")) Default(library) diff --git a/addons/.gitignore b/addons/.gitignore new file mode 100644 index 00000000..d6b7ef32 --- /dev/null +++ b/addons/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/addons/godot-git-plugin/git_plugin.gdextension b/addons/godot-git-plugin/git_plugin.gdextension deleted file mode 100644 index c936df92..00000000 --- a/addons/godot-git-plugin/git_plugin.gdextension +++ /dev/null @@ -1,10 +0,0 @@ -[configuration] - -entry_symbol = "git_plugin_init" -compatibility_minimum = "4.3" - -[libraries] - -linux.editor.x86_64 = "linux/libgit_plugin.linux.editor.x86_64.so" -macos.editor = "macos/libgit_plugin.macos.editor.universal.dylib" -windows.editor.x86_64 = "windows/libgit_plugin.windows.editor.x86_64.dll" diff --git a/misc/git_plugin.gdextension b/misc/git_plugin.gdextension new file mode 100644 index 00000000..c4c59f20 --- /dev/null +++ b/misc/git_plugin.gdextension @@ -0,0 +1,18 @@ +[configuration] + +entry_symbol = "git_plugin_init" +compatibility_minimum = "4.3" + +[libraries] + +android.editor.arm64 = "lib/libgit_plugin.android.editor.arm64.so" +android.editor.x86_64 = "lib/libgit_plugin.android.editor.x86_64.so" +linux.editor.arm64 = "lib/libgit_plugin.linux.editor.arm64.so" +linux.editor.arm32 = "lib/libgit_plugin.linux.editor.arm32.so" +linux.editor.x86_64 = "lib/libgit_plugin.linux.editor.x86_64.so" +linux.editor.x86_32 = "lib/libgit_plugin.linux.editor.x86_32.so" +macos.editor = "lib/libgit_plugin.macos.editor.universal.dylib" +windows.editor.arm64 = "lib/libgit_plugin.windows.editor.arm64.dll" +windows.editor.arm32 = "lib/libgit_plugin.windows.editor.arm32.dll" +windows.editor.x86_64 = "lib/libgit_plugin.windows.editor.x86_64.dll" +windows.editor.x86_32 = "lib/libgit_plugin.windows.editor.x86_32.dll" diff --git a/misc/scripts/package_release.sh b/misc/scripts/package_release.sh new file mode 100755 index 00000000..7364f27f --- /dev/null +++ b/misc/scripts/package_release.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +set -e +set -x + +ARTIFACTS=${ARTIFACTS:-"artifacts"} +DESTINATION=${DESTINATION:-"release"} +NAME=${NAME:-"godot-git-plugin"} + +mkdir -p ${DESTINATION} +ls -R ${DESTINATION} +ls -R ${ARTIFACTS} + +DESTDIR="${DESTINATION}/addons/${NAME}" + +mkdir -p ${DESTDIR}/lib + +find "${ARTIFACTS}" -maxdepth 5 -wholename "*/addons/${NAME}/lib/*" | xargs cp -r -t "${DESTDIR}/lib/" +find "${ARTIFACTS}" -wholename "*/LICENSE*" | xargs cp -t "${DESTDIR}/" +find "${ARTIFACTS}" -wholename "*/addons/${NAME}/*.gdextension" | head -n 1 | xargs cp -t "${DESTDIR}/" + +CURDIR=$(pwd) +cd "${DESTINATION}/" +zip -r ${NAME}.zip addons +cd "$CURDIR" + +ls -R ${DESTINATION}