From dcc52f4321ee143257858adefaf4cb55f63733a3 Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Thu, 30 Sep 2021 04:29:42 +0200 Subject: [PATCH] Library SCons boilerplate to build projects. Works by executing project `SConstruct`s file in a cloned env (a bit like Godot does for modules) so you don't have to worry about platform and toolchain setup. Convert the project test file to work as submodule, add it to CI Run with: ``` scons build_projects=test,/path/to/other/project ``` --- .github/workflows/ci.yml | 4 ++ SConstruct | 34 ++++++--- test/SConstruct | 148 +-------------------------------------- 3 files changed, 32 insertions(+), 154 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fce6c2d..af76eed 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -152,6 +152,10 @@ jobs: # cd test # scons target=release use_mingw=yes -j $env:NUMBER_OF_PROCESSORS + - name: Build test + run: | + scons platform=${{ matrix.platform }} target=release ${{ matrix.flags }} -j2 build_projects=test + - name: Upload artifact uses: actions/upload-artifact@v2 with: diff --git a/SConstruct b/SConstruct index f77f6f8..3105daf 100644 --- a/SConstruct +++ b/SConstruct @@ -144,6 +144,9 @@ opts.Add( ) opts.Add(BoolVariable("generate_template_get_node", "Generate a template version of the Node class's get_node.", True)) +opts.Add(BoolVariable("build_library", "Build the godot-cpp library.", True)) +opts.Add("build_projects", "List of projects to build (comma-separated list of paths).", "") + opts.Update(env) Help(opts.GenerateHelpText(env)) @@ -250,14 +253,13 @@ elif env["platform"] == "ios": env["CXX"] = compiler_path + "clang++" env["AR"] = compiler_path + "ar" env["RANLIB"] = compiler_path + "ranlib" + env["SHLIBSUFFIX"] = ".dylib" env.Append(CCFLAGS=["-arch", env["ios_arch"], "-isysroot", sdk_path]) env.Append( LINKFLAGS=[ "-arch", env["ios_arch"], - "-framework", - "Cocoa", "-Wl,-undefined,dynamic_lookup", "-isysroot", sdk_path, @@ -300,8 +302,13 @@ elif env["platform"] == "windows": # Still need to use C++17. env.Append(CCFLAGS=["-std=c++17"]) + # Don't want lib prefixes + env["IMPLIBPREFIX"] = "" + env["SHLIBPREFIX"] = "" + # Long line hack. Use custom spawn, quick AR append (to avoid files with the same names to override each other). env["SPAWN"] = mySpawn + env.Replace(ARFLAGS=["q"]) # Native or cross-compilation using MinGW if host_platform == "linux" or host_platform == "freebsd" or host_platform == "osx" or env["use_mingw"]: @@ -321,9 +328,10 @@ elif env["platform"] == "android": # Don't Clone the environment. Because otherwise, SCons will pick up msvc stuff. env = Environment(ENV=os.environ, tools=["mingw"]) opts.Update(env) - # env = env.Clone(tools=['mingw']) + # Long line hack. Use custom spawn, quick AR append (to avoid files with the same names to override each other). env["SPAWN"] = mySpawn + env.Replace(ARFLAGS=["q"]) # Verify NDK root if not "ANDROID_NDK_ROOT" in env: @@ -389,11 +397,13 @@ elif env["platform"] == "android": env["CC"] = toolchain + "/bin/clang" env["CXX"] = toolchain + "/bin/clang++" env["AR"] = toolchain + "/bin/" + arch_info["tool_path"] + "-ar" + env["SHLIBSUFFIX"] = ".so" env.Append( CCFLAGS=["--target=" + arch_info["target"] + env["android_api_level"], "-march=" + arch_info["march"], "-fPIC"] ) # , '-fPIE', '-fno-addrsig', '-Oz']) env.Append(CCFLAGS=arch_info["ccflags"]) + env.Append(LINKFLAGS=["--target=" + arch_info["target"] + env["android_api_level"], "-march=" + arch_info["march"]]) if env["target"] == "debug": env.Append(CCFLAGS=["-Og", "-g"]) @@ -481,8 +491,16 @@ elif env["platform"] == "javascript": elif env["platform"] == "osx": arch_suffix = env["macos_arch"] -library = env.StaticLibrary( - target="bin/" + "libgodot-cpp.{}.{}.{}{}".format(env["platform"], env["target"], arch_suffix, env["LIBSUFFIX"]), - source=sources, -) -Default(library) +library = None +env["OBJSUFFIX"] = ".{}.{}.{}{}".format(env["platform"], env["target"], arch_suffix, env["OBJSUFFIX"]) +library_name = "libgodot-cpp.{}.{}.{}{}".format(env["platform"], env["target"], arch_suffix, env["LIBSUFFIX"]) + +if env["build_library"]: + library = env.StaticLibrary(target=env.File("bin/%s" % library_name), source=sources) + Default(library) + +env["SHLIBSUFFIX"] = "{}.{}.{}{}".format(env["platform"], env["target"], arch_suffix, env["SHLIBSUFFIX"]) +env.Append(CPPPATH=[env.Dir(f) for f in ["gen/include", "include", "godot-headers"]]) +env.Append(LIBPATH=[env.Dir("bin")]) +env.Append(LIBS=library_name) +Return("env") diff --git a/test/SConstruct b/test/SConstruct index 0bd80ac..b2ddba1 100644 --- a/test/SConstruct +++ b/test/SConstruct @@ -2,79 +2,7 @@ import os import sys -# default values, adapt them to your setup -default_library_name = "libgdexample" -default_target_path = "demo/bin/" - -# Local dependency paths, adapt them to your setup -cpp_bindings_path = "../" -# cpp_bindings_path = "godot-cpp/" -godot_headers_path = cpp_bindings_path + "godot-headers/" -cpp_library = "libgodot-cpp" - -# 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.startswith("freebsd"): - host_platform = "freebsd" -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", allowed_values=("debug", "release"), ignorecase=2)) -opts.Add( - EnumVariable( - "platform", - "Compilation platform", - host_platform, - # We'll need to support these in due times - # allowed_values=("linux", "freebsd", "osx", "windows", "android", "ios", "javascript"), - allowed_values=("linux", "windows", "osx"), - ignorecase=2, - ) -) -opts.Add(EnumVariable("bits", "Target platform bits", "64", ("32", "64"))) -opts.Add(BoolVariable("use_llvm", "Use the LLVM / Clang compiler", "no")) -opts.Add(EnumVariable("macos_arch", "Target macOS architecture", "universal", ["universal", "x86_64", "arm64"])) -opts.Add(PathVariable("target_path", "The path where the lib is installed.", default_target_path, PathVariable.PathAccept)) -opts.Add(PathVariable("target_name", "The library name.", default_library_name, PathVariable.PathAccept)) - -# 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["platform"] == "": - print("No valid target platform selected.") - quit() +env = SConscript("../SConstruct") # For the reference: # - CCFLAGS are compilation flags shared between C and C++ @@ -84,82 +12,10 @@ if env["platform"] == "": # - CPPDEFINES are for pre-processor defines # - LINKFLAGS are for linking flags -if env["target"] == "debug": - env.Append(CPPDEFINES=["DEBUG_ENABLED", "DEBUG_METHODS_ENABLED"]) - -# Check our platform specifics -if env["platform"] == "osx": - env["target_path"] += "{}.{}.framework/".format(env["target_name"], env["target"]) - cpp_library += ".osx" - - if env["bits"] == "32": - raise ValueError("Only 64-bit builds are supported for the macOS target.") - - if env["macos_arch"] == "universal": - env.Append(LINKFLAGS=["-arch", "x86_64", "-arch", "arm64"]) - env.Append(CCFLAGS=["-arch", "x86_64", "-arch", "arm64"]) - else: - env.Append(LINKFLAGS=["-arch", env["macos_arch"]]) - env.Append(CCFLAGS=["-arch", env["macos_arch"]]) - - env.Append(CXXFLAGS=["-std=c++17"]) - if env["target"] == "debug": - env.Append(CCFLAGS=["-g", "-O2"]) - else: - env.Append(CCFLAGS=["-g", "-O3"]) - - arch_suffix = env["macos_arch"] - -elif env["platform"] in ("x11", "linux"): - cpp_library += ".linux" - env.Append(CCFLAGS=["-fPIC"]) - env.Append(CXXFLAGS=["-std=c++17"]) - if env["target"] == "debug": - env.Append(CCFLAGS=["-g3", "-Og"]) - else: - env.Append(CCFLAGS=["-g", "-O3"]) - - arch_suffix = str(bits) -elif env["platform"] == "windows": - 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"]) - env.Append(CXXFLAGS=["-std:c++17"]) - if env["target"] == "debug": - env.Append(CPPDEFINES=["_DEBUG"]) - env.Append(CCFLAGS=["-EHsc", "-MDd", "-ZI", "-FS"]) - env.Append(LINKFLAGS=["-DEBUG"]) - else: - env.Append(CPPDEFINES=["NDEBUG"]) - env.Append(CCFLAGS=["-O2", "-EHsc", "-MD"]) - - if not(env["use_llvm"]): - env.Append(CPPDEFINES=["TYPED_METHOD_BIND"]) - - arch_suffix = str(bits) - -# suffix our godot-cpp library -cpp_library += "." + env["target"] + "." + arch_suffix - -# make sure our binding library is properly includes -env.Append(CPPPATH=[".", godot_headers_path, cpp_bindings_path + "include/", cpp_bindings_path + "gen/include/"]) -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") -if env["platform"] == "osx": - target_name = "{}.{}".format(env["target_name"], env["target"]) -else: - target_name = "{}.{}.{}.{}".format(env["target_name"], env["platform"], env["target"], arch_suffix) - -print(target_name) -library = env.SharedLibrary(target=env["target_path"] + target_name, source=sources) +library = env.SharedLibrary("demo/bin/libgdexample" + env["SHLIBSUFFIX"], source=sources) Default(library)