import os import re import shutil from datetime import datetime from SCons.Platform.virtualenv import ImportVirtualenv from SCons.Errors import UserError EnsurePythonVersion(3, 7) EnsureSConsVersion(3, 0) def extract_version(): # Hold my beer... gl = {} exec(open("pythonscript/pandemonium/_version.py").read(), gl) return gl["__version__"] def pandemonium_binary_converter(val, env): file = File(val) if file.exists(): # Note here `env["pandemonium_binary_download_version"]` is not defined, this is ok given # this variable shouldn't be needed if Pandemonium doesn't have to be downloaded return file # Provided value is version information with format ..[-] match = re.match(r"^([0-9]+)\.([0-9]+)\.([0-9]+)(?:-(\w+))?$", val) if match: major, minor, patch, extra = match.groups() else: raise UserError( f"`{val}` is neither an existing file nor a valid ..[-] Pandemonium version format" ) env["pandemonium_binary_download_version"] = (major, minor, patch, extra or "stable") # `pandemonium_binary` is set to None to indicate it should be downloaded return None vars = Variables("custom.py") vars.Add( EnumVariable( "platform", "Target platform", "", allowed_values=("x11-64", "x11-32", "windows-64", "windows-32", "osx-64"), ) ) vars.Add("pytest_args", "Pytest arguments passed to tests functions", "") vars.Add( "pandemonium_args", "Additional arguments passed to pandemonium binary when running tests&examples", "" ) vars.Add("release_suffix", "Suffix to add to the release archive", extract_version()) vars.Add( "pandemonium_binary", "Path to Pandemonium binary or version of Pandemonium to use", default="3.2.2", converter=pandemonium_binary_converter, ) vars.Add("pandemonium_headers", "Path to Pandemonium GDnative headers", "") vars.Add("debugger", "Run test with a debugger", "") vars.Add(BoolVariable("debug", "Compile with debug symbols", False)) vars.Add(BoolVariable("headless", "Run tests in headless mode", False)) vars.Add(BoolVariable("compressed_stdlib", "Compress Python std lib as a zip to save space", True)) vars.Add( BoolVariable( "bindings_generate_sample", "Generate only a subset of the bindings (faster build time)", False, ) ) vars.Add("CC", "C compiler") vars.Add("CFLAGS", "Custom flags for the C compiler") vars.Add("LINK", "linker") vars.Add("LINKFLAGS", "Custom flags for the linker") vars.Add("CPYTHON_CFLAGS", "Custom flags for the C compiler used to compile CPython") vars.Add("CPYTHON_LINKFLAGS", "Custom flags for the linker used to compile CPython") vars.Add("OPENSSL_PATH", "Path to the root of openssl installation to link CPython against") vars.Add( "MSVC_VERSION", "MSVC version to use (Windows only) -- version num X.Y. Default: highest installed.", ) vars.Add( BoolVariable( "MSVC_USE_SCRIPT", ( "Set to True to let SCons find compiler (with MSVC_VERSION and TARGET_ARCH), " "False to use cmd.exe env (MSVC_VERSION and TARGET_ARCH will be ignored), " "or vcvarsXY.bat script name to use." ), True, ) ) # Set Visual Studio arch according to platform target vanilla_vars_update = vars.Update def _patched_vars_update(env, args=None): vanilla_vars_update(env, args=None) if env["platform"] == "windows-64": env["TARGET_ARCH"] = "x86_64" elif env["platform"] == "windows-32": env["TARGET_ARCH"] = "x86" vars.Update = _patched_vars_update env = Environment( variables=vars, tools=["default", "cython", "symlink", "virtual_target", "download"], ENV=os.environ, # ENV = {'PATH' : os.environ['PATH']}, ) # Detect compiler env["CC_IS_MSVC"] = env.get("CC") in ("cl", "cl.exe") env["CC_IS_GCC"] = "gcc" in env.get("CC") env["CC_IS_CLANG"] = "clang" in env.get("CC") Help(vars.GenerateHelpText(env)) # if env["HOST_OS"] == "win32": # # Fix ImportVirtualenv raising error if PATH make reference to other drives # from SCons.Platform import virtualenv # vanilla_IsInVirtualenv = virtualenv.IsInVirtualenv # def patched_IsInVirtualenv(path): # try: # return vanilla_IsInVirtualenv(path) # except ValueError: # return False # virtualenv.IsInVirtualenv = patched_IsInVirtualenv # ImportVirtualenv(env) if env["pandemonium_headers"]: env["pandemonium_headers"] = Dir(env["pandemonium_headers"]) else: env["pandemonium_headers"] = Dir("pandemonium_headers") env.AppendUnique(CPPPATH=["$pandemonium_headers"]) # TODO: not sure why, but CPPPATH scan result for cython modules change between # first and subsequent runs of scons (module is considered to no longer depend # on pandemonium_headers on subsequent run, so the build redone) SetOption("implicit_cache", 1) ### Save my eyes plz ### env["ENV"]["TERM"] = os.environ.get("TERM", "") if env["CC_IS_CLANG"]: env.Append(CCFLAGS=["-fcolor-diagnostics"]) if env["CC_IS_GCC"]: env.Append(CCFLAGS=["-fdiagnostics-color=always"]) ### Default compile flags ### if not env["CC_IS_MSVC"]: if env["debug"]: env.Append(CFLAGS=["-g", "-ggdb"]) env.Append(LINKFLAGS=["-g", "-ggdb"]) else: env.Append(CFLAGS=["-O2"]) else: if env["debug"]: env.Append(CFLAGS=["/DEBUG:FULL"]) env.Append(LINKFLAGS=["/DEBUG:FULL"]) else: env.Append(CFLAGS=["/WX", "/W2"]) env["DIST_ROOT"] = Dir(f"build/dist") env["DIST_PLATFORM"] = Dir(f"{env['DIST_ROOT']}/addons/pythonscript/{env['platform']}") VariantDir(f"build/{env['platform']}/platforms", f"platforms") VariantDir(f"build/{env['platform']}/pythonscript", "pythonscript") ### Load sub scons scripts ### Export(env=env) SConscript( [ f"build/{env['platform']}/platforms/SConscript", # Must be kept first f"build/{env['platform']}/pythonscript/SConscript", "tests/SConscript", "examples/SConscript", ] ) ### Define default target ### env.Default(env["DIST_ROOT"]) env.Alias("build", env["DIST_ROOT"]) ### Static files added to dist ### env.VanillaInstallAs( target="$DIST_ROOT/pythonscript.gdnlib", source="#/misc/release_pythonscript.gdnlib" ) env.VanillaInstallAs( target="$DIST_ROOT/addons/pythonscript/LICENSE.txt", source="#/misc/release_LICENSE.txt" ) env.Command(target="$DIST_ROOT/addons/pythonscript/.gdignore", source=None, action=Touch("$TARGET")) # SCons install on directory doesn't check for file changes for item in env.Glob("addons/pythonscript_repl/*"): env.VanillaInstall(target="$DIST_ROOT/addons/pythonscript_repl", source=item) ### Release archive ### def generate_release(target, source, env): for suffix, format in [(".zip", "zip"), (".tar.bz2", "bztar")]: if target[0].name.endswith(suffix): base_name = target[0].abspath[: -len(suffix)] break shutil.make_archive(base_name, format, root_dir=source[0].abspath) # Zip format doesn't support symlinks that are needed for Linux&macOS if env["platform"].startswith("windows"): release_target = "build/pandemonium-python-${release_suffix}-${platform}.zip" else: release_target = "build/pandemonium-python-${release_suffix}-${platform}.tar.bz2" release = env.Command(release_target, env["DIST_ROOT"], generate_release) env.Alias("release", release) env.AlwaysBuild("release")