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(); +}