From 9b8d3be7df307cc921d82b0f66f55787a0125559 Mon Sep 17 00:00:00 2001 From: ytnuf <161308826+ytnuf@users.noreply.github.com> Date: Wed, 13 Nov 2024 22:02:15 +0000 Subject: [PATCH] Make godot-cpp installable via ScCons This aims to have feature parity with the installation via cmake --- SConstruct | 2 ++ tools/godotcpp.py | 88 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) diff --git a/SConstruct b/SConstruct index 8acea26245..f4caa47659 100644 --- a/SConstruct +++ b/SConstruct @@ -48,4 +48,6 @@ if scons_cache_path is not None: cpp_tool.generate(env) library = env.GodotCPP() +env.InstallableGodotCPP(library) + Return("env") diff --git a/tools/godotcpp.py b/tools/godotcpp.py index 77a0740fcd..ca56787ad3 100644 --- a/tools/godotcpp.py +++ b/tools/godotcpp.py @@ -338,6 +338,42 @@ def options(opts, env): opts.Add(BoolVariable("dev_build", "Developer build with dev-only debugging code (DEV_ENABLED)", False)) opts.Add(BoolVariable("verbose", "Enable verbose output for the compilation", False)) + + # Scons lack a default install prefix, so use CMake's as a default for feature parity + # https://cmake.org/cmake/help/latest/variable/CMAKE_INSTALL_PREFIX.html + opts.Add( + PathVariable( + "install_prefix_dir", + "The directory to install to", + "C:/Program Files/godot-cpp" if default_platform == "windows" else "/usr/local", + PathVariable.PathAccept + ) + ) + opts.Add( + PathVariable( + "install_lib_dir", + "The directory to install the library (relative from the prefix)", + "lib", + PathVariable.PathAccept + ) + ) + opts.Add( + PathVariable( + "install_include_dir", + "The directory to install the headers (relative from the prefix)", + "include", + PathVariable.PathAccept + ) + ) + opts.Add( + PathVariable( + "install_data_dir", + "The directory to install misc files (relative from the prefix)", + "share/godot-cpp", + PathVariable.PathAccept + ) + ) + # Add platform options (custom tools can override platforms) for pl in sorted(set(platforms + custom_platforms)): tool = Tool(pl, toolpath=get_platform_tools_paths(env)) @@ -526,6 +562,7 @@ def generate(env): } ) env.AddMethod(_godot_cpp, "GodotCPP") + env.AddMethod(_installable, "InstallableGodotCPP") def _godot_cpp(env): @@ -571,3 +608,54 @@ def _godot_cpp(env): env.AppendUnique(LIBS=[env.File("bin/%s" % library_name)]) return library + + +def _installable(env, library): + import itertools + import json + + install_lib_dir = os.path.join(env["install_prefix_dir"], env["install_lib_dir"]) + install_pkgconfig_dir = os.path.join(install_lib_dir, "pkgconfig") + install_include_dir = os.path.join(env["install_prefix_dir"], env["install_include_dir"]) + install_data_dir = os.path.join(env["install_prefix_dir"], env["install_data_dir"]) + + # Obtain the gdextension version + extension_dir = normalize_path(env.get("gdextension_dir", env.Dir("gdextension").abspath), env) + api_filename = normalize_path(env.get("custom_api_file", env.File(extension_dir + "/extension_api.json").abspath), env) + with open(api_filename, "r") as api_json_file: + api_data = json.load(api_json_file) + version_major = api_data["header"]["version_major"] + version_minor = api_data["header"]["version_minor"] + version_patch = api_data["header"]["version_patch"] + gd_version = f"{version_major}.{version_minor}.{version_patch}" + api_data = None + + #Configure and install the pkgconfig file + libname = str(library[0]) + pkgconfig = env.Substfile(target="gen/godot-cpp.pc", source="cmake/godot-cpp.pc.in", SUBST_DICT={ + "@PROJECT_NAME@": "godot-cpp", + "@CMAKE_INSTALL_LIBDIR@": install_lib_dir, + "@CMAKE_INSTALL_INCLUDEDIR@" : install_include_dir, + "@GODOT_API_VERSION@": gd_version, + "@GODOTCPP_OUTPUT_NAME@": libname + }) + env.Install(install_pkgconfig_dir, pkgconfig) + + # Install the headers + headers_from = [] + headers_to = [] + for dir_from, _, file_lst in itertools.chain(os.walk("include/godot_cpp"), os.walk("gen/include/godot_cpp") ): + headers_from += [os.path.join(dir_from,filename) for filename in file_lst] + dir_to = os.path.join(install_include_dir, dir_from[dir_from.find("/godot_cpp")+1:]) + headers_to += [os.path.join(dir_to,filename) for filename in file_lst] + env.InstallAs(headers_to, headers_from) + + # Install the gdextension files + interface_header = os.path.join(extension_dir, "gdextension_interface.h") + env.Install(install_include_dir, interface_header) + env.Install(install_data_dir, api_filename) + + # Install the static library + env.Install(install_lib_dir, library) + + env.Alias("install", env["install_prefix_dir"])