Skip to content

Commit

Permalink
Library SCons boilerplate to build projects.
Browse files Browse the repository at this point in the history
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
```
  • Loading branch information
Faless committed Oct 1, 2021
1 parent 71ed758 commit 0a2d5fe
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 126 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ jobs:
run: |
scons platform=${{ matrix.platform }} target=release generate_bindings=yes ${{ matrix.flags }} -j2
- 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:
Expand Down
54 changes: 39 additions & 15 deletions SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -144,16 +144,12 @@ 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))

# Require C++17
if host_platform == "windows" and env["platform"] == "windows" and not env["use_mingw"]:
# MSVC
env.Append(CCFLAGS=["/std:c++17"])
else:
env.Append(CCFLAGS=["-std=c++17"])

# 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
Expand All @@ -165,6 +161,13 @@ if host_platform == "windows" and env["platform"] != "android":

opts.Update(env)

# Require C++17
if host_platform == "windows" and env["platform"] == "windows" and not env["use_mingw"]:
# MSVC
env.Append(CCFLAGS=["/std:c++17"])
else:
env.Append(CCFLAGS=["-std=c++17"])

if env["target"] == "debug":
env.Append(CPPDEFINES=["DEBUG_ENABLED", "DEBUG_METHODS_ENABLED"])

Expand Down Expand Up @@ -243,14 +246,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,
Expand Down Expand Up @@ -293,8 +295,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"]:
Expand All @@ -314,9 +321,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:
Expand Down Expand Up @@ -382,11 +390,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"])
Expand Down Expand Up @@ -473,8 +483,22 @@ 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=os.path.join("bin", library_name), source=sources)
Default(library)

if env["build_projects"]:
base_env = env.Clone()
for v in env["build_projects"].split(","):
env = base_env.Clone()
env["SHLIBSUFFIX"] = "{}.{}.{}{}".format(env["platform"], env["target"], arch_suffix, env["SHLIBSUFFIX"])
Export("env")
env.Append(CPPPATH=["#gen/include", "#include", "#godot-headers"])
env.Append(LIBPATH=["#bin"])
env.Append(LIBS=library_name)

SConscript(os.path.join(v, "SConstruct"))
115 changes: 4 additions & 111 deletions test/SConstruct
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env python
import os
import sys

Import("env")

# default values, adapt them to your setup
default_library_name = "libgdexample"
Expand All @@ -10,71 +10,20 @@ default_target_path = "demo/bin/"
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=<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"),
ignorecase=2,
)
PathVariable("target_path", "The path where the lib is installed.", default_target_path, PathVariable.PathAccept)
)
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.", 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()

# For the reference:
# - CCFLAGS are compilation flags shared between C and C++
# - CFLAGS are for C-specific compilation flags
Expand All @@ -83,67 +32,11 @@ 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"] += "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"] == "debug":
env.Append(CCFLAGS=["-g", "-O2"])
else:
env.Append(CCFLAGS=["-g", "-O3"])

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"])

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"])

# determine our architecture suffix
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")

target_name = "{}.{}.{}.{}".format(env["target_name"], env["platform"], env["target"], arch_suffix)
print(target_name)
target_name = "{}{}".format(env["target_name"], env["SHLIBSUFFIX"])
library = env.SharedLibrary(target=env["target_path"] + target_name, source=sources)

Default(library)

0 comments on commit 0a2d5fe

Please sign in to comment.