From d6101538e695b0a38223fb1fa5ee32ce55e3223c Mon Sep 17 00:00:00 2001 From: O01eg Date: Sat, 28 Nov 2020 12:05:00 +0300 Subject: [PATCH 1/3] Test build GNnative library in CI --- .github/workflows/ci.yml | 16 +++++ test/SConstruct | 134 +++++++++++++++++++++++++++++++++++++++ test/demo/.gitignore | 2 + test/src/init.cpp | 70 ++++++++++++++++++++ 4 files changed, 222 insertions(+) create mode 100644 test/SConstruct create mode 100644 test/demo/.gitignore create mode 100644 test/src/init.cpp diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b6652556..8adae975 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,6 +33,10 @@ jobs: path: bin/libgodot-cpp.linux.release.64.a if-no-files-found: error + - name: Build test GDNative library + run: | + scons target=release platform=linux bits=64 -j $(nproc) -C test; + windows-msvc: name: Build (Windows, MSVC) runs-on: windows-2019 @@ -62,6 +66,10 @@ jobs: path: bin/libgodot-cpp.windows.release.64.lib if-no-files-found: error + - name: Build test GDNative library + run: | + scons target=release platform=windows bits=64 -j $env:NUMBER_OF_PROCESSORS -C test; + windows-mingw: name: Build (Windows, MinGW) runs-on: windows-2019 @@ -96,6 +104,10 @@ jobs: path: bin/libgodot-cpp.windows.release.64.a if-no-files-found: error + - name: Build test GDNative library + run: | + scons target=release platform=windows bits=64 -j $env:NUMBER_OF_PROCESSORS -C test; + macos: name: Build (macOS, Clang) runs-on: macos-10.15 @@ -125,6 +137,10 @@ jobs: path: bin/libgodot-cpp.osx.release.64.a if-no-files-found: error + - name: Build test GDNative library + run: | + scons target=release platform=osx bits=64 -j $(sysctl -n hw.logicalcpu) -C test; + static-checks: name: Static Checks (clang-format) runs-on: ubuntu-16.04 diff --git a/test/SConstruct b/test/SConstruct new file mode 100644 index 00000000..62cabd21 --- /dev/null +++ b/test/SConstruct @@ -0,0 +1,134 @@ +#!/usr/bin/env python +import os +import sys + +# Try to detect the host platform automatically. +# This is used if no `platform` argument is passed +if sys.platform.startswith('linux'): + host_platform = 'linux' +elif sys.platform == 'darwin': + host_platform = 'osx' +elif sys.platform == 'win32' or sys.platform == 'msys': + host_platform = 'windows' +else: + raise ValueError( + 'Could not detect platform automatically, please specify with ' + 'platform=' + ) + +env = Environment(ENV = os.environ) + +opts = Variables([], ARGUMENTS) + +# Define our options +opts.Add(EnumVariable('target', "Compilation target", 'debug', ['d', 'debug', 'r', 'release'])) +opts.Add(EnumVariable('platform', "Compilation platform", host_platform, ['', 'windows', 'x11', 'linux', 'osx'])) +opts.Add(EnumVariable('p', "Compilation target, alias for 'platform'", host_platform, ['', 'windows', 'x11', 'linux', 'osx'])) +opts.Add(EnumVariable('bits', 'Target platform bits', '64', ('32', '64'))) +opts.Add(BoolVariable('use_llvm', "Use the LLVM / Clang compiler", 'no')) +opts.Add(PathVariable('target_path', 'The path where the lib is installed.', 'demo/bin/', PathVariable.PathAccept)) +opts.Add(PathVariable('target_name', 'The library name.', 'libgdexample', PathVariable.PathAccept)) + +# Local dependency paths, adapt them to your setup +godot_headers_path = "../godot_headers/" +cpp_bindings_path = "../" +cpp_library = "libgodot-cpp" + +# only support 64 at this time.. +bits = 64 + +# Updates the environment with the option variables. +opts.Update(env) +# Generates help for the -h scons option. +Help(opts.GenerateHelpText(env)) + +# This makes sure to keep the session environment variables on Windows. +# This way, you can run SCons in a Visual Studio 2017 prompt and it will find +# all the required tools +if host_platform == 'windows' and env['platform'] != 'android': + if env['bits'] == '64': + env = Environment(TARGET_ARCH='amd64') + elif env['bits'] == '32': + env = Environment(TARGET_ARCH='x86') + + opts.Update(env) + +# Process some arguments +if env['use_llvm']: + env['CC'] = 'clang' + env['CXX'] = 'clang++' + +if env['p'] != '': + env['platform'] = env['p'] + +if env['platform'] == '': + print("No valid target platform selected.") + quit(); + +# For the reference: +# - CCFLAGS are compilation flags shared between C and C++ +# - CFLAGS are for C-specific compilation flags +# - CXXFLAGS are for C++-specific compilation flags +# - CPPFLAGS are for pre-processor flags +# - CPPDEFINES are for pre-processor defines +# - LINKFLAGS are for linking flags + +# Check our platform specifics +if env['platform'] == "osx": + env['target_path'] += 'osx/' + cpp_library += '.osx' + env.Append(CCFLAGS=['-arch', 'x86_64']) + env.Append(CXXFLAGS=['-std=c++17']) + env.Append(LINKFLAGS=['-arch', 'x86_64']) + if env['target'] in ('debug', 'd'): + env.Append(CCFLAGS=['-g', '-O2']) + else: + env.Append(CCFLAGS=['-g', '-O3']) + +elif env['platform'] in ('x11', 'linux'): + env['target_path'] += 'x11/' + cpp_library += '.linux' + env.Append(CCFLAGS=['-fPIC']) + env.Append(CXXFLAGS=['-std=c++17']) + if env['target'] in ('debug', 'd'): + env.Append(CCFLAGS=['-g3', '-Og']) + else: + env.Append(CCFLAGS=['-g', '-O3']) + +elif env['platform'] == "windows": + env['target_path'] += 'win64/' + cpp_library += '.windows' + # This makes sure to keep the session environment variables on windows, + # that way you can run scons in a vs 2017 prompt and it will find all the required tools + env.Append(ENV=os.environ) + + env.Append(CPPDEFINES=['WIN32', '_WIN32', '_WINDOWS', '_CRT_SECURE_NO_WARNINGS']) + env.Append(CCFLAGS=['-W3', '-GR']) + if env['target'] in ('debug', 'd'): + env.Append(CPPDEFINES=['_DEBUG']) + env.Append(CCFLAGS=['-EHsc', '-MDd', '-ZI']) + env.Append(LINKFLAGS=['-DEBUG']) + else: + env.Append(CPPDEFINES=['NDEBUG']) + env.Append(CCFLAGS=['-O2', '-EHsc', '-MD']) + +if env['target'] in ('debug', 'd'): + cpp_library += '.debug' +else: + cpp_library += '.release' + +cpp_library += '.' + str(bits) + +# make sure our binding library is properly includes +env.Append(CPPPATH=['.', godot_headers_path, cpp_bindings_path + 'include/', cpp_bindings_path + 'include/core/', cpp_bindings_path + 'include/gen/']) +env.Append(LIBPATH=[cpp_bindings_path + 'bin/']) +env.Append(LIBS=[cpp_library]) + +# tweak this if you want to use different folders, or more folders, to store your source code in. +env.Append(CPPPATH=['src/']) +sources = Glob('src/*.cpp') + +library = env.SharedLibrary(target=env['target_path'] + env['target_name'] , source=sources) + +Default(library) + diff --git a/test/demo/.gitignore b/test/demo/.gitignore new file mode 100644 index 00000000..d6b7ef32 --- /dev/null +++ b/test/demo/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/test/src/init.cpp b/test/src/init.cpp new file mode 100644 index 00000000..9164ba58 --- /dev/null +++ b/test/src/init.cpp @@ -0,0 +1,70 @@ +#include +#include + +using namespace godot; + +class SimpleClass : public Reference { + GODOT_CLASS(SimpleClass, Reference); + +public: + SimpleClass() {} + + /** `_init` must exist as it is called by Godot. */ + void _init() {} + + void test_void_method() { + Godot::print("This is test"); + } + + Variant method(Variant arg) { + Variant ret; + ret = arg; + + return ret; + } + + static void _register_methods() { + register_method("method", &SimpleClass::method); + + /** + * The line below is equivalent to the following GDScript export: + * export var _name = "SimpleClass" + **/ + register_property("base/name", &SimpleClass::_name, String("SimpleClass")); + + /** Alternatively, with getter and setter methods: */ + register_property("base/value", &SimpleClass::set_value, &SimpleClass::get_value, 0); + + /** Registering a signal: **/ + register_signal("signal_name0"); + register_signal("signal_name1", "string_argument", GODOT_VARIANT_TYPE_STRING); + } + + String _name; + int _value; + + void set_value(int p_value) { + _value = p_value; + } + + int get_value() const { + return _value; + } +}; + +/** GDNative Initialize **/ +extern "C" void GDN_EXPORT godot_gdnative_init(godot_gdnative_init_options *o) { + godot::Godot::gdnative_init(o); +} + +/** GDNative Terminate **/ +extern "C" void GDN_EXPORT godot_gdnative_terminate(godot_gdnative_terminate_options *o) { + godot::Godot::gdnative_terminate(o); +} + +/** NativeScript Initialize **/ +extern "C" void GDN_EXPORT godot_nativescript_init(void *handle) { + godot::Godot::nativescript_init(handle); + + godot::register_class(); +} From c55ef5adcfa5a608fa69e53c69ba49de495de53a Mon Sep 17 00:00:00 2001 From: O01eg Date: Sat, 6 Feb 2021 23:19:40 +0300 Subject: [PATCH 2/3] Disable Windows compilation. --- .github/workflows/ci.yml | 8 -------- test/src/init.cpp | 2 +- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8adae975..7ed4f839 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -66,10 +66,6 @@ jobs: path: bin/libgodot-cpp.windows.release.64.lib if-no-files-found: error - - name: Build test GDNative library - run: | - scons target=release platform=windows bits=64 -j $env:NUMBER_OF_PROCESSORS -C test; - windows-mingw: name: Build (Windows, MinGW) runs-on: windows-2019 @@ -104,10 +100,6 @@ jobs: path: bin/libgodot-cpp.windows.release.64.a if-no-files-found: error - - name: Build test GDNative library - run: | - scons target=release platform=windows bits=64 -j $env:NUMBER_OF_PROCESSORS -C test; - macos: name: Build (macOS, Clang) runs-on: macos-10.15 diff --git a/test/src/init.cpp b/test/src/init.cpp index 9164ba58..47d4fda3 100644 --- a/test/src/init.cpp +++ b/test/src/init.cpp @@ -36,7 +36,7 @@ public: register_property("base/value", &SimpleClass::set_value, &SimpleClass::get_value, 0); /** Registering a signal: **/ - register_signal("signal_name0"); + register_signal("signal_name0"); // windows: error C2668: 'godot::register_signal': ambiguous call to overloaded function register_signal("signal_name1", "string_argument", GODOT_VARIANT_TYPE_STRING); } From 279d63d6c53a40ab92a0357661b837e5232a5331 Mon Sep 17 00:00:00 2001 From: O01eg Date: Sat, 28 Nov 2020 13:08:17 +0300 Subject: [PATCH 3/3] Run script test --- .github/workflows/ci.yml | 16 ++++++++++++++-- test/SConstruct | 2 +- test/demo/.gitignore | 2 -- test/gdexample.gdnlib | 20 ++++++++++++++++++++ test/gdexample.gdns | 9 +++++++++ test/project.godot | 19 +++++++++++++++++++ test/script.gd | 30 ++++++++++++++++++++++++++++++ test/src/init.cpp | 9 ++++++--- 8 files changed, 99 insertions(+), 8 deletions(-) delete mode 100644 test/demo/.gitignore create mode 100644 test/gdexample.gdnlib create mode 100644 test/gdexample.gdns create mode 100644 test/project.godot create mode 100644 test/script.gd diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7ed4f839..d2005568 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,6 +21,8 @@ jobs: sudo apt-get update -qq sudo apt-get install -qqq build-essential pkg-config python -m pip install scons + curl -LO https://downloads.tuxfamily.org/godotengine/3.2.3/Godot_v3.2.3-stable_linux_server.64.zip + unzip Godot_v3.2.3-stable_linux_server.64.zip - name: Build godot-cpp run: | @@ -35,7 +37,11 @@ jobs: - name: Build test GDNative library run: | - scons target=release platform=linux bits=64 -j $(nproc) -C test; + scons target=release platform=linux bits=64 -j $(nproc) -C test + + - name: Run test GDNative library + run: | + ./Godot_v3.2.3-stable_linux_server.64 --path test -s script.gd windows-msvc: name: Build (Windows, MSVC) @@ -117,6 +123,8 @@ jobs: - name: Install dependencies run: | python -m pip install scons + curl -LO https://downloads.tuxfamily.org/godotengine/3.2.3/Godot_v3.2.3-stable_osx.64.zip + unzip Godot_v3.2.3-stable_osx.64.zip - name: Build godot-cpp run: | @@ -131,7 +139,11 @@ jobs: - name: Build test GDNative library run: | - scons target=release platform=osx bits=64 -j $(sysctl -n hw.logicalcpu) -C test; + scons target=release platform=osx bits=64 -j $(sysctl -n hw.logicalcpu) -C test + + - name: Run test GDNative library + run: | + ./Godot.app/Contents/MacOS/Godot --path test -s script.gd static-checks: name: Static Checks (clang-format) diff --git a/test/SConstruct b/test/SConstruct index 62cabd21..2dd85d5a 100644 --- a/test/SConstruct +++ b/test/SConstruct @@ -26,7 +26,7 @@ opts.Add(EnumVariable('platform', "Compilation platform", host_platform, ['', 'w opts.Add(EnumVariable('p', "Compilation target, alias for 'platform'", host_platform, ['', 'windows', 'x11', 'linux', 'osx'])) opts.Add(EnumVariable('bits', 'Target platform bits', '64', ('32', '64'))) opts.Add(BoolVariable('use_llvm', "Use the LLVM / Clang compiler", 'no')) -opts.Add(PathVariable('target_path', 'The path where the lib is installed.', 'demo/bin/', PathVariable.PathAccept)) +opts.Add(PathVariable('target_path', 'The path where the lib is installed.', 'bin/', PathVariable.PathAccept)) opts.Add(PathVariable('target_name', 'The library name.', 'libgdexample', PathVariable.PathAccept)) # Local dependency paths, adapt them to your setup diff --git a/test/demo/.gitignore b/test/demo/.gitignore deleted file mode 100644 index d6b7ef32..00000000 --- a/test/demo/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore diff --git a/test/gdexample.gdnlib b/test/gdexample.gdnlib new file mode 100644 index 00000000..260b4eab --- /dev/null +++ b/test/gdexample.gdnlib @@ -0,0 +1,20 @@ +[general] + +singleton=false +load_once=true +symbol_prefix="godot_" +reloadable=false + +[entry] + +X11.64="res://bin/x11/libgdexample.so" +Server.64="res://bin/x11/libgdexample.so" +Windows.64="res://bin/win64/libgdexample.dll" +OSX.64="res://bin/osx/libgdexample.dylib" + +[dependencies] + +X11.64=[] +Server.64=[] +Windows.64=[] +OSX.64=[] diff --git a/test/gdexample.gdns b/test/gdexample.gdns new file mode 100644 index 00000000..a9d02d35 --- /dev/null +++ b/test/gdexample.gdns @@ -0,0 +1,9 @@ +[gd_resource type="NativeScript" load_steps=2 format=2] + +[ext_resource path="res://gdexample.gdnlib" type="GDNativeLibrary" id=1] + +[resource] + +resource_name = "gdexample" +class_name = "SimpleClass" +library = ExtResource( 1 ) diff --git a/test/project.godot b/test/project.godot new file mode 100644 index 00000000..c9e426ae --- /dev/null +++ b/test/project.godot @@ -0,0 +1,19 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=4 + +_global_script_classes=[ ] +_global_script_class_icons={ + +} + +[application] + +config/name="Test CI project" + diff --git a/test/script.gd b/test/script.gd new file mode 100644 index 00000000..d9b0fe10 --- /dev/null +++ b/test/script.gd @@ -0,0 +1,30 @@ + +extends MainLoop + +func _initialize(): + OS.exit_code = 1 + var native_script = load("res://gdexample.gdns") + print("Native Script ", native_script) + if native_script == null || !is_instance_valid(native_script): + return + print("Library ", native_script.library) + if native_script.library == null || !is_instance_valid(native_script.library): + return + var ref = native_script.new() + print("Reference ", ref) + if ref == null || !is_instance_valid(ref): + return + print("Reference name ", ref.name) + if ref.name != "SimpleClass": + return + print("Reference value ", ref.value) + if ref.value != 0: + return + print("Call method ", ref.method(1)) + if ref.method(1) != 1: + return + OS.exit_code = 0 + +func _idle(_delta): + return true + diff --git a/test/src/init.cpp b/test/src/init.cpp index 47d4fda3..3eedb056 100644 --- a/test/src/init.cpp +++ b/test/src/init.cpp @@ -10,7 +10,10 @@ public: SimpleClass() {} /** `_init` must exist as it is called by Godot. */ - void _init() {} + void _init() { + _name = String("SimpleClass"); + _value = 0; + } void test_void_method() { Godot::print("This is test"); @@ -30,10 +33,10 @@ public: * The line below is equivalent to the following GDScript export: * export var _name = "SimpleClass" **/ - register_property("base/name", &SimpleClass::_name, String("SimpleClass")); + register_property("name", &SimpleClass::_name, String("SimpleClass")); /** Alternatively, with getter and setter methods: */ - register_property("base/value", &SimpleClass::set_value, &SimpleClass::get_value, 0); + register_property("value", &SimpleClass::set_value, &SimpleClass::get_value, 0); /** Registering a signal: **/ register_signal("signal_name0"); // windows: error C2668: 'godot::register_signal': ambiguous call to overloaded function