diff options
author | Fabio Alessandrelli <fabio.alessandrelli@gmail.com> | 2023-06-19 04:58:03 +0200 |
---|---|---|
committer | Fabio Alessandrelli <fabio.alessandrelli@gmail.com> | 2023-06-20 13:22:07 +0200 |
commit | 86c27ec7efa5b4630ddeff50d02b0deda2ad3db3 (patch) | |
tree | 1d00228bde064a94d7cb9c33d74831ccc0383c14 | |
parent | f2ee596bd9a67512f69d170cbcd260e6422e97a9 (diff) | |
download | fork-godot-webrtc-native-86c27ec7efa5b4630ddeff50d02b0deda2ad3db3.tar.gz fork-godot-webrtc-native-86c27ec7efa5b4630ddeff50d02b0deda2ad3db3.tar.bz2 fork-godot-webrtc-native-86c27ec7efa5b4630ddeff50d02b0deda2ad3db3.zip |
[SCons] Refactor CMake and OpenSSL tools to use actions.
Improve build reliability, allow for more customization.
-rw-r--r-- | tools/cmake.py | 91 | ||||
-rw-r--r-- | tools/openssl.py | 223 | ||||
-rw-r--r-- | tools/rtc.py | 41 |
3 files changed, 186 insertions, 169 deletions
diff --git a/tools/cmake.py b/tools/cmake.py index 5b05d15..28e1269 100644 --- a/tools/cmake.py +++ b/tools/cmake.py @@ -1,47 +1,14 @@ import os, sys - -def exists(env): - return True - - -def generate(env): - env.AddMethod(cmake_configure, "CMakeConfigure") - env.AddMethod(cmake_build, "CMakeBuild") - env.AddMethod(cmake_platform_flags, "CMakePlatformFlags") - - -def cmake_configure(env, source, target, opt_args): - args = [ - "-B", - target, - ] - - if env["platform"] == "windows": - if env.get("is_msvc", False): - args.extend(["-G", "NMake Makefiles"]) - elif sys.platform in ["win32", "msys", "cygwin"]: - args.extend(["-G", "Ninja"]) - else: - args.extend(["-G", "Unix Makefiles"]) - - for arg in opt_args: - args.append(arg) - args.append(source) - return env.Execute("cmake " + " ".join(['"%s"' % a for a in args])) - - -def cmake_build(env, source, target="", opt_args=[]): - jobs = env.GetOption("num_jobs") - return env.Execute( - "cmake --build %s %s -j%s %s" - % (source, "-t %s" % target if target else "", jobs, " ".join(['"%s"' % a for a in opt_args])) - ) +import SCons.Util +import SCons.Builder +import SCons.Action -def cmake_platform_flags(env, config=None): - if config is None: - config = {} +def cmake_platform_config(env): + config = { + "CMAKE_BUILD_TYPE": env["CMAKEBUILDTYPE"], + } if "CC" in env: config["CMAKE_C_COMPILER"] = env["CC"] @@ -60,8 +27,8 @@ def cmake_platform_flags(env, config=None): config["CMAKE_SYSTEM_VERSION"] = api config["CMAKE_ANDROID_ARCH_ABI"] = abi config["ANDROID_ABI"] = abi - config["CMAKE_TOOLCHAIN_FILE"] = "%s/build/cmake/android.toolchain.cmake" % os.environ.get( - "ANDROID_NDK_ROOT", "" + config["CMAKE_TOOLCHAIN_FILE"] = "%s/build/cmake/android.toolchain.cmake" % env.get( + "ANDROID_NDK_ROOT", os.environ.get("ANDROID_NDK_ROOT", "") ) config["CMAKE_ANDROID_STL_TYPE"] = "c++_static" @@ -95,7 +62,7 @@ def cmake_platform_flags(env, config=None): raise ValueError("iOS architecture not supported: %s" % env["arch"]) config["CMAKE_SYSTEM_NAME"] = "iOS" config["CMAKE_OSX_ARCHITECTURES"] = env["arch"] - if env["ios_min_version"] != "default": + if env.get("ios_min_version", "default") != "default": config["CMAKE_OSX_DEPLOYMENT_TARGET"] = env["ios_min_version"] if env["ios_simulator"]: config["CMAKE_OSX_SYSROOT"] = "iphonesimulator" @@ -103,4 +70,40 @@ def cmake_platform_flags(env, config=None): elif env["platform"] == "windows": config["CMAKE_SYSTEM_NAME"] = "Windows" - return config + flags = ["'-D%s=%s'" % it for it in config.items()] + if env["CMAKEGENERATOR"]: + flags.extend(["-G", env["CMAKEGENERATOR"]]) + elif env["platform"] == "windows": + if env.get("is_msvc", False): + flags.extend(["-G", "NMake Makefiles"]) + elif sys.platform in ["win32", "msys", "cygwin"]: + flags.extend(["-G", "Ninja"]) + else: + flags.extend(["-G", "Unix Makefiles"]) + return flags + + +def cmake_emitter(target, source, env): + return [str(target[0]) + "/CMakeCache.txt"] + target[1:], [str(source[0]) + "/CMakeLists.txt"] + source[1:] + + +cmake_configure_action = SCons.Action.Action("$CMAKECONFCOM", "$CMAKECONFCOMSTR") +cmake_build_action = SCons.Action.Action("$CMAKEBUILDCOM", "$CMAKEBUILDCOMSTR") +cmake_builder = SCons.Builder.Builder(action=[cmake_configure_action, cmake_build_action], emitter=cmake_emitter) + + +def exists(env): + return True + + +def generate(env): + env["CMAKE"] = "cmake" + env["_cmake_platform_config"] = cmake_platform_config + env["CMAKEPLATFORMCONFIG"] = "${_cmake_platform_config(__env__)}" + env["CMAKEBUILDTYPE"] = "Release" + env["CMAKEGENERATOR"] = "" + env["CMAKECONFFLAGS"] = SCons.Util.CLVar("") + env["CMAKECONFCOM"] = "$CMAKE -B ${TARGET.dir} $CMAKEPLATFORMCONFIG $CMAKECONFFLAGS ${SOURCE.dir}" + env["CMAKEBUILDFLAGS"] = SCons.Util.CLVar("") + env["CMAKEBUILDCOM"] = "$CMAKE --build ${TARGET.dir} $CMAKEBUILDFLAGS" + env["BUILDERS"]["CMake"] = cmake_builder diff --git a/tools/openssl.py b/tools/openssl.py index ad61df9..936895d 100644 --- a/tools/openssl.py +++ b/tools/openssl.py @@ -1,117 +1,106 @@ import os, sys +import SCons.Util +import SCons.Builder +import SCons.Action from SCons.Defaults import Mkdir from SCons.Variables import PathVariable, BoolVariable -def ssl_emitter(target, source, env): - env.Depends(env["SSL_LIBS"], env.File(__file__)) - return env["SSL_LIBS"], [env.Dir(env["SSL_SOURCE"]), env.File(env["SSL_SOURCE"] + "/VERSION.dat")] +def ssl_platform_target(env): + targets = {} + platform = env["platform"] + if platform == "linux": + targets = { + "x86_32": "linux-x86", + "x86_64": "linux-x86_64", + } + elif platform == "android": + targets = { + "arm64": "android-arm64", + "arm32": "android-arm", + "x86_32": "android-x86", + "x86_64": "android-x86_64", + } + elif platform == "macos": + targets = { + "x86_64": "darwin64-x86_64", + "arm64": "darwin64-arm64", + } + elif platform == "ios": + if env["ios_simulator"]: + targets = { + "x86_64": "iossimulator-xcrun", + "arm64": "iossimulator-xcrun", + } + else: + targets = { + "arm64": "ios64-xcrun", + "arm32": "ios-xcrun", + } + elif platform == "windows": + if env.get("is_msvc", False): + targets = { + "x86_32": "VC-WIN32", + "x86_64": "VC-WIN64A", + } + else: + targets = { + "x86_32": "mingw", + "x86_64": "mingw64", + } + arch = env["arch"] + target = targets.get(arch, "") + if target == "": + raise ValueError("Architecture '%s' not supported for platform: '%s'" % (arch, platform)) + return target -def ssl_action(target, source, env): - build_dir = env["SSL_BUILD"] - source_dir = env["SSL_SOURCE"] - install_dir = env["SSL_INSTALL"] - ssl_env = env.Clone() - args = [ +def ssl_default_options(env): + ssl_config_options = [ "no-ssl2", "no-ssl3", "no-weak-ssl-ciphers", "no-legacy", "no-shared", "no-tests", - "--prefix=%s" % install_dir, - "--openssldir=%s" % install_dir, ] - if env["openssl_debug"]: - args.append("-d") + if env["platform"] == "windows": + ssl_config_options.append("enable-capieng") + return ssl_config_options - if env["platform"] == "linux": - if env["arch"] == "x86_32": - args.extend(["linux-x86"]) - else: - args.extend(["linux-x86_64"]) - - elif env["platform"] == "android": - api = env["android_api_level"] if int(env["android_api_level"]) > 28 else "28" - args.extend( - [ - { - "arm64": "android-arm64", - "arm32": "android-arm", - "x86_32": "android-x86", - "x86_64": "android-x86_64", - }[env["arch"]], - "-D__ANDROID_API__=%s" % api, - ] - ) - # Setup toolchain path. - ssl_env.PrependENVPath("PATH", os.path.dirname(env["CC"])) - ssl_env["ENV"]["ANDROID_NDK_ROOT"] = os.environ.get("ANDROID_NDK_ROOT", "") +def ssl_platform_config(env): + opts = ssl_default_options(env) + target = ssl_platform_target(env) + args = [] + if env["platform"] == "android" and env.get("android_api_level", ""): + api = int(env["android_api_level"]) + args.append("-D__ANDROID_API__=%s" % api) elif env["platform"] == "macos": - if env["arch"] == "x86_64": - args.extend(["darwin64-x86_64"]) - elif env["arch"] == "arm64": - args.extend(["darwin64-arm64"]) - else: - raise ValueError("macOS architecture not supported: %s" % env["arch"]) - + # OSXCross toolchain setup. if sys.platform != "darwin" and "OSXCROSS_ROOT" in os.environ: - args.extend( - [ - "CC=" + env["CC"], - "CXX=" + env["CXX"], - "AR=" + env["AR"], - "AS=" + env["AS"], - "RANLIB=" + env["RANLIB"], - ] - ) - - elif env["platform"] == "ios": - if env["ios_simulator"]: - args.extend(["iossimulator-xcrun"]) - elif env["arch"] == "arm32": - args.extend(["ios-xcrun"]) - elif env["arch"] == "arm64": - args.extend(["ios64-xcrun"]) - else: - raise ValueError("iOS architecture not supported: %s" % env["arch"]) - + for k in ["CC", "CXX", "AR", "AS", "RANLIB"]: + args.append("%s=%s" % (k, env[k])) elif env["platform"] == "windows": - args.extend(["enable-capieng"]) is_win_host = sys.platform in ["win32", "msys", "cygwin"] - if env.get("is_msvc", False): - args.extend(["VC-WIN32" if env["arch"] == "x86_32" else "VC-WIN64A"]) - else: - if env["arch"] == "x86_32": - args.extend(["mingw"]) - if not is_win_host: - args.extend(["--cross-compile-prefix=i686-w64-mingw32-"]) - else: - args.extend(["mingw64"]) - if not is_win_host: - args.extend(["--cross-compile-prefix=x86_64-w64-mingw32-"]) - - jobs = env.GetOption("num_jobs") - make_cmd = ["make -C %s -j%s" % (build_dir, jobs), "make -C %s install_sw install_ssldirs -j%s" % (build_dir, jobs)] - if env["platform"] == "windows" and env.get("is_msvc", False): - make_cmd = ["cd %s && nmake install_sw install_ssldirs" % build_dir] - ssl_env.Execute( - [ - Mkdir(build_dir), - Mkdir(install_dir), - "cd {} && perl -- {} {}".format( - build_dir, os.path.join(source_dir, "Configure"), " ".join(['"%s"' % a for a in args]) - ), - ] - + make_cmd - ) - return None + if not (is_win_host or env.get("is_msvc", False)): + mingw_prefixes = { + "x86_32": "--cross-compile-prefix=i686-w64-mingw32-", + "x86_64": "--cross-compile-prefix=x86_64-w64-mingw32-", + } + args.append(mingw_prefixes[env["arch"]]) + return opts + [target] + args + +def ssl_emitter(target, source, env): + return env["SSL_LIBS"], [env.File(env["SSL_SOURCE"] + "/Configure"), env.File(env["SSL_SOURCE"] + "/VERSION.dat")] + + +def build_openssl(env, jobs=None): + if jobs is None: + jobs = int(env.GetOption("num_jobs")) -def build_openssl(env): # Since the OpenSSL build system does not support macOS universal binaries, we first need to build the two libraries # separately, then we join them together using lipo. if env["platform"] == "macos" and env["arch"] == "universal": @@ -124,6 +113,7 @@ def build_openssl(env): benv = build_envs[arch] benv["arch"] = arch generate(benv) + benv["SSLBUILDJOBS"] = max([1, int(jobs / len(build_envs))]) ssl = benv.OpenSSLBuilder() arch_ssl.extend(ssl) benv.NoCache(ssl) # Needs refactoring to properly cache generated headers. @@ -132,16 +122,17 @@ def build_openssl(env): env["SSL_INCLUDE"] = build_envs["arm64"]["SSL_INCLUDE"] # Join libraries using lipo. + lipo_action = "lipo $SOURCES -create -output $TARGET" ssl_libs = list(map(lambda arch: build_envs[arch]["SSL_LIBRARY"], build_envs)) ssl_crypto_libs = list(map(lambda arch: build_envs[arch]["SSL_CRYPTO_LIBRARY"], build_envs)) - ssl = [ - env.Command([env["SSL_LIBRARY"]], ssl_libs, "lipo $SOURCES -output $TARGETS -create"), - env.Command([env["SSL_CRYPTO_LIBRARY"]], ssl_libs, "lipo $SOURCES -output $TARGETS -create"), - ] + ssl = env.Command(env["SSL_LIBRARY"], ssl_libs, lipo_action) + ssl += env.Command(env["SSL_CRYPTO_LIBRARY"], ssl_crypto_libs, lipo_action) env.Depends(ssl, arch_ssl) else: - ssl = env.OpenSSLBuilder() - env.NoCache(ssl) # Needs refactoring to properly cache generated headers. + benv = env.Clone() + benv["SSLBUILDJOBS"] = jobs + ssl = benv.OpenSSLBuilder() + benv.NoCache(ssl) # Needs refactoring to properly cache generated headers. env.Prepend(CPPPATH=[env["SSL_INCLUDE"]]) env.Prepend(LIBPATH=[env["SSL_BUILD"]]) @@ -164,6 +155,14 @@ def exists(env): def generate(env): + # Android needs the NDK in ENV, and proper PATH setup. + if env["platform"] == "android" and env["ENV"].get("ANDROID_NDK_ROOT", "") == "": + cc_path = os.path.dirname(env["CC"]) + if cc_path and cc_path not in env["ENV"]: + env.PrependENVPath("PATH", cc_path) + if "ANDROID_NDK_ROOT" not in env["ENV"]: + env["ENV"]["ANDROID_NDK_ROOT"] = env.get("ANDROID_NDK_ROOT", os.environ.get("ANDROID_NDK_ROOT", "")) + env["SSL_SOURCE"] = env.Dir(env["openssl_source"]).abspath env["SSL_BUILD"] = env.Dir( env["openssl_build"] @@ -175,5 +174,33 @@ def generate(env): env["SSL_LIBRARY"] = env.File(env["SSL_BUILD"] + "/libssl" + lib_ext) env["SSL_CRYPTO_LIBRARY"] = env.File(env["SSL_BUILD"] + "/libcrypto" + lib_ext) env["SSL_LIBS"] = [env["SSL_LIBRARY"], env["SSL_CRYPTO_LIBRARY"]] - env.Append(BUILDERS={"OpenSSLBuilder": env.Builder(action=ssl_action, emitter=ssl_emitter)}) + + # Configure action + env["PERL"] = env.get("PERL", "perl") + env["_ssl_platform_config"] = ssl_platform_config + env["SSLPLATFORMCONFIG"] = "${_ssl_platform_config(__env__)}" + env["SSLCONFFLAGS"] = SCons.Util.CLVar("") + # fmt: off + env["SSLCONFIGCOM"] = "cd ${TARGET.dir} && $PERL -- ${SOURCE.abspath} --prefix=$SSL_INSTALL --openssldir=$SSL_INSTALL $SSLPLATFORMCONFIG $SSLCONFFLAGS" + # fmt: on + + # Build action + env["SSLBUILDJOBS"] = "${__env__.GetOption('num_jobs')}" + # fmt: off + env["SSLBUILDCOM"] = "make -j$SSLBUILDJOBS -C ${TARGET.dir} && make -j$SSLBUILDJOBS -C ${TARGET.dir} install_sw install_ssldirs" + # fmt: on + + # Windows MSVC needs to build using NMake + if env["platform"] == "windows" and env.get("is_msvc", False): + env["SSLBUILDCOM"] = "cd ${TARGET.dir} && nmake install_sw install_ssldirs" + + env["BUILDERS"]["OpenSSLBuilder"] = SCons.Builder.Builder( + action=[ + Mkdir("$SSL_BUILD"), + Mkdir("$SSL_INSTALL"), + SCons.Action.Action("$SSLCONFIGCOM", "$SSLCONFIGCOMSTR"), + SCons.Action.Action("$SSLBUILDCOM", "$SSLBUILDCOMSTR"), + ], + emitter=ssl_emitter, + ) env.AddMethod(build_openssl, "OpenSSL") diff --git a/tools/rtc.py b/tools/rtc.py index 81c3edd..798dc94 100644 --- a/tools/rtc.py +++ b/tools/rtc.py @@ -12,49 +12,36 @@ def rtc_cmake_config(env): "OPENSSL_INCLUDE_DIR": env["SSL_INCLUDE"], "OPENSSL_SSL_LIBRARY": env["SSL_LIBRARY"], "OPENSSL_CRYPTO_LIBRARY": env["SSL_CRYPTO_LIBRARY"], - "OPENSSL_ROOT_DIR": env["SSL_BUILD"], - "CMAKE_BUILD_TYPE": "%s" % ("RelWithDebInfo" if env["debug_symbols"] else "Release"), + "OPENSSL_ROOT_DIR": env["SSL_INSTALL"], } - return env.CMakePlatformFlags(config) + return config -def rtc_emitter(target, source, env): +def build_library(env): if env["platform"] == "windows": env.PrependUnique(LIBS=["iphlpapi", "bcrypt"]) env.Prepend(LIBS=env["RTC_LIBS"]) - env.Depends(env["RTC_LIBS"], env["SSL_LIBS"]) - env.Depends( - env["RTC_LIBS"], - [env.File(__file__), env.Dir(env["RTC_SOURCE"]), env.File(env["RTC_SOURCE"] + "/CMakeLists.txt")], - ) - return env["RTC_LIBS"], env.Dir(env["RTC_SOURCE"]) - - -def rtc_action(target, source, env): rtc_env = env.Clone() - build_dir = env["RTC_BUILD"] - source_dir = env["RTC_SOURCE"] - opts = rtc_cmake_config(rtc_env) - rtc_env.CMakeConfigure(source_dir, build_dir, ["-D%s=%s" % it for it in opts.items()]) - opt_args = [] - if env.get("is_msvc", False): - opt_args = ["--config", opts["CMAKE_BUILD_TYPE"]] - rtc_env.CMakeBuild(build_dir, "datachannel-static", opt_args=opt_args) - return None + rtc_targets = [env.Dir(env["RTC_BUILD"])] + env["RTC_LIBS"] + rtc_sources = [env.Dir(env["RTC_SOURCE"])] + rtc_env.Append(CMAKECONFFLAGS=["'-D%s=%s'" % it for it in rtc_cmake_config(env).items()]) + rtc_env.Append(CMAKEBUILDFLAGS=["-t", "datachannel-static", "-j%s" % env.GetOption("num_jobs")]) + rtc = rtc_env.CMake(rtc_targets, rtc_sources, CMAKEBUILDTYPE=env["RTC_BUILD_TYPE"]) + rtc_env.Depends(rtc, rtc_env["SSL_LIBS"]) + return rtc def exists(env): - return "CMakeConfigure" in env and "CMakeBuild" in env + return "CMake" in env def generate(env): env["RTC_SOURCE"] = env.Dir("#thirdparty/libdatachannel").abspath + env["RTC_BUILD_TYPE"] = "RelWithDebInfo" if env["debug_symbols"] else "Release" env["RTC_BUILD"] = env.Dir( - "#bin/thirdparty/libdatachannel/{}/{}/{}".format( - env["platform"], env["arch"], "RelWithDebInfo" if env["debug_symbols"] else "Release" - ) + "#bin/thirdparty/libdatachannel/{}/{}/{}".format(env["platform"], env["arch"], env["RTC_BUILD_TYPE"]) ).abspath env["RTC_INCLUDE"] = env["RTC_SOURCE"] + "/include" lib_ext = ".a" @@ -71,6 +58,6 @@ def generate(env): "deps/usrsctp/usrsctplib/{}usrsctp{}".format(lib_prefix, lib_ext), ] ] - env.Append(BUILDERS={"BuildLibDataChannel": env.Builder(action=rtc_action, emitter=rtc_emitter)}) + env.AddMethod(build_library, "BuildLibDataChannel") env.Append(LIBPATH=[env["RTC_BUILD"]]) env.Append(CPPPATH=[env["RTC_INCLUDE"]]) |