diff options
-rw-r--r-- | SConstruct | 84 | ||||
-rw-r--r-- | tools/cmake.py | 37 | ||||
-rw-r--r-- | tools/common.py | 9 | ||||
-rw-r--r-- | tools/openssl.py | 179 | ||||
-rw-r--r-- | tools/rtc.py | 34 | ||||
-rw-r--r-- | tools/ssl.py | 121 |
6 files changed, 264 insertions, 200 deletions
@@ -81,13 +81,17 @@ if env["godot_version"] == "3": env["suffix"] = ".{}.{}.{}".format(env["platform"], target_compat, env["arch_suffix"]) env["debug_symbols"] = False - # Set missing CC for MinGW from upstream build module. - if env["platform"] == "windows" and sys.platform != "win32" and sys.platform != "msys": - # Cross-compilation using MinGW - if env["bits"] == "64": - env["CC"] = "x86_64-w64-mingw32-gcc" - elif env["bits"] == "32": - env["CC"] = "i686-w64-mingw32-gcc" + # Some windows specific hacks. + if env["platform"] == "windows": + if sys.platform not in ["win32", "msys"]: + # Set missing CC for MinGW from upstream build module. + if env["bits"] == "64": + env["CC"] = "x86_64-w64-mingw32-gcc" + elif env["bits"] == "32": + env["CC"] = "i686-w64-mingw32-gcc" + elif not env["use_mingw"]: + # Mark as MSVC build (would have failed to build the library otherwise). + env["is_msvc"] = True else: env = SConscript("godot-cpp/SConstruct").Clone() @@ -104,6 +108,12 @@ if "TERM" in os.environ: # Used for colored output. if env["platform"] == "windows" and env["use_mingw"]: env["SHLIBSUFFIX"] = ".dll" +# Patch OSXCross config. +if env["platform"] == "macos" and os.environ.get("OSXCROSS_ROOT", ""): + env["SHLIBSUFFIX"] = ".dylib" + if env["macos_deployment_target"] != "default": + env["ENV"]["MACOSX_DEPLOYMENT_TARGET"] = env["macos_deployment_target"] + opts.Update(env) target = env["target"] @@ -129,52 +139,20 @@ else: sources.append("src/init_gdnative.cpp") add_sources(sources, "src/net/", "cpp") -# 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. -mac_universal = env["platform"] == "macos" and env["arch"] == "universal" -build_targets = [] -build_envs = [env] - -# For macOS universal builds, setup one build environment per architecture. -if mac_universal: - build_envs = [] - for arch in ["x86_64", "arm64"]: - benv = env.Clone() - benv["arch"] = arch - benv["CCFLAGS"] = SCons.Util.CLVar(str(benv["CCFLAGS"]).replace("-arch x86_64 -arch arm64", "-arch " + arch)) - benv["LINKFLAGS"] = SCons.Util.CLVar( - str(benv["LINKFLAGS"]).replace("-arch x86_64 -arch arm64", "-arch " + arch) - ) - benv["suffix"] = benv["suffix"].replace("universal", arch) - benv["SHOBJSUFFIX"] = benv["suffix"] + benv["SHOBJSUFFIX"] - build_envs.append(benv) - -# Build our library and its dependencies. -for benv in build_envs: - # Dependencies - for tool in ["cmake", "common", "ssl", "rtc"]: - benv.Tool(tool, toolpath=["tools"]) - - ssl = benv.BuildOpenSSL() - benv.NoCache(ssl) # Needs refactoring to properly cache generated headers. - rtc = benv.BuildLibDataChannel() - - benv.Depends(sources, [ssl, rtc]) - - # Make the shared library - result_name = "webrtc_native{}{}".format(benv["suffix"], benv["SHLIBSUFFIX"]) - library = benv.SharedLibrary(target=os.path.join(result_path, "lib", result_name), source=sources) - build_targets.append(library) - -Default(build_targets) - -# For macOS universal builds, join the libraries using lipo. -if mac_universal: - result_name = "libwebrtc_native{}{}".format(env["suffix"], env["SHLIBSUFFIX"]) - universal_target = env.Command( - os.path.join(result_path, "lib", result_name), build_targets, "lipo $SOURCES -output $TARGETS -create" - ) - Default(universal_target) +# Add our build tools +for tool in ["openssl", "cmake", "rtc"]: + env.Tool(tool, toolpath=["tools"]) + +ssl = env.OpenSSL() + +rtc = env.BuildLibDataChannel() + +env.Depends(sources, [ssl, rtc]) + +# Make the shared library +result_name = "libwebrtc_native{}{}".format(env["suffix"], env["SHLIBSUFFIX"]) +library = env.SharedLibrary(target=os.path.join(result_path, "lib", result_name), source=sources) +Default(library) # GDNativeLibrary if env["godot_version"] == "3": diff --git a/tools/cmake.py b/tools/cmake.py index d552da6..5b05d15 100644 --- a/tools/cmake.py +++ b/tools/cmake.py @@ -1,4 +1,4 @@ -import os +import os, sys def exists(env): @@ -16,17 +16,27 @@ def cmake_configure(env, source, target, opt_args): "-B", target, ] - if env["platform"] == "windows" and env["use_mingw"]: - args.extend(["-G", "Unix Makefiles"]) + + 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=""): +def cmake_build(env, source, target="", opt_args=[]): jobs = env.GetOption("num_jobs") - return env.Execute("cmake --build %s %s -j%s" % (source, "-t %s" % target if target else "", 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])) + ) def cmake_platform_flags(env, config=None): @@ -62,11 +72,24 @@ def cmake_platform_flags(env, config=None): elif env["platform"] == "macos": if env["arch"] == "universal": - raise ValueError("OSX architecture not supported: %s" % env["arch"]) - config["CMAKE_OSX_ARCHITECTURES"] = env["arch"] + config["CMAKE_OSX_ARCHITECTURES"] = "x86_64;arm64" + else: + config["CMAKE_OSX_ARCHITECTURES"] = env["arch"] if env["macos_deployment_target"] != "default": config["CMAKE_OSX_DEPLOYMENT_TARGET"] = env["macos_deployment_target"] + if env["platform"] == "macos" and sys.platform != "darwin" and "OSXCROSS_ROOT" in os.environ: + config["CMAKE_AR"] = env["AR"] + config["CMAKE_RANLIB"] = env["RANLIB"] + if env["arch"] == "universal": + flags = "-arch x86_64 -arch arm64" + else: + flags = "-arch " + env["arch"] + if env["macos_deployment_target"] != "default": + flags += " -mmacosx-version-min=" + env["macos_deployment_target"] + config["CMAKE_C_FLAGS"] = flags + config["CMAKE_CXX_FLAGS"] = flags + elif env["platform"] == "ios": if env["arch"] == "universal": raise ValueError("iOS architecture not supported: %s" % env["arch"]) diff --git a/tools/common.py b/tools/common.py deleted file mode 100644 index 4bd5ada..0000000 --- a/tools/common.py +++ /dev/null @@ -1,9 +0,0 @@ -def exists(env): - return True - - -def generate(env): - env["DEPS_SOURCE"] = env.Dir("#thirdparty").abspath - env["DEPS_BUILD"] = env.Dir("#bin/thirdparty").abspath + "/{}.{}.dir".format( - env["suffix"][1:], "RelWithDebInfo" if env["debug_symbols"] else "Release" - ) diff --git a/tools/openssl.py b/tools/openssl.py new file mode 100644 index 0000000..ad61df9 --- /dev/null +++ b/tools/openssl.py @@ -0,0 +1,179 @@ +import os, sys +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_action(target, source, env): + build_dir = env["SSL_BUILD"] + source_dir = env["SSL_SOURCE"] + install_dir = env["SSL_INSTALL"] + + ssl_env = env.Clone() + args = [ + "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"] == "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", "") + + 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"]) + + 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"]) + + 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 + + +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": + build_envs = { + "x86_64": env.Clone(), + "arm64": env.Clone(), + } + arch_ssl = [] + for arch in build_envs: + benv = build_envs[arch] + benv["arch"] = arch + generate(benv) + ssl = benv.OpenSSLBuilder() + arch_ssl.extend(ssl) + benv.NoCache(ssl) # Needs refactoring to properly cache generated headers. + + # x86_64 and arm64 includes are equivalent. + env["SSL_INCLUDE"] = build_envs["arm64"]["SSL_INCLUDE"] + + # Join libraries using lipo. + 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"), + ] + env.Depends(ssl, arch_ssl) + else: + ssl = env.OpenSSLBuilder() + env.NoCache(ssl) # Needs refactoring to properly cache generated headers. + + env.Prepend(CPPPATH=[env["SSL_INCLUDE"]]) + env.Prepend(LIBPATH=[env["SSL_BUILD"]]) + if env["platform"] == "windows": + env.PrependUnique(LIBS=["crypt32", "ws2_32", "advapi32", "user32"]) + + env.Prepend(LIBS=env["SSL_LIBS"]) + + return ssl + + +def options(opts): + opts.Add(PathVariable("openssl_source", "Path to the openssl sources.", "thirdparty/openssl")) + opts.Add("openssl_build", "Destination path of the openssl build.", "bin/thirdparty/openssl") + opts.Add(BoolVariable("openssl_debug", "Make a debug build of OpenSSL.", False)) + + +def exists(env): + return True + + +def generate(env): + env["SSL_SOURCE"] = env.Dir(env["openssl_source"]).abspath + env["SSL_BUILD"] = env.Dir( + env["openssl_build"] + + "/{}/{}/{}".format(env["platform"], env["arch"], "debug" if env["openssl_debug"] else "release") + ).abspath + env["SSL_INSTALL"] = env.Dir(env["SSL_BUILD"] + "/dest").abspath + env["SSL_INCLUDE"] = env.Dir(env["SSL_INSTALL"] + "/include").abspath + lib_ext = ".lib" if env.get("is_msvc", False) else ".a" + 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)}) + env.AddMethod(build_openssl, "OpenSSL") diff --git a/tools/rtc.py b/tools/rtc.py index 680e772..81c3edd 100644 --- a/tools/rtc.py +++ b/tools/rtc.py @@ -19,6 +19,11 @@ def rtc_cmake_config(env): def rtc_emitter(target, source, 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"], @@ -33,7 +38,10 @@ def rtc_action(target, source, env): 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()]) - rtc_env.CMakeBuild(build_dir, "datachannel-static") + 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 @@ -42,21 +50,27 @@ def exists(env): def generate(env): - env["RTC_SOURCE"] = env["DEPS_SOURCE"] + "/libdatachannel" - env["RTC_BUILD"] = env["DEPS_BUILD"] + "/libdatachannel" + env["RTC_SOURCE"] = env.Dir("#thirdparty/libdatachannel").abspath + env["RTC_BUILD"] = env.Dir( + "#bin/thirdparty/libdatachannel/{}/{}/{}".format( + env["platform"], env["arch"], "RelWithDebInfo" if env["debug_symbols"] else "Release" + ) + ).abspath env["RTC_INCLUDE"] = env["RTC_SOURCE"] + "/include" + lib_ext = ".a" + lib_prefix = "lib" + if env.get("is_msvc", False): + lib_ext = ".lib" + lib_prefix = "" env["RTC_LIBS"] = [ env.File(env["RTC_BUILD"] + "/" + lib) for lib in [ - "libdatachannel-static.a", - "deps/libjuice/libjuice-static.a", - "deps/libsrtp/libsrtp2.a", - "deps/usrsctp/usrsctplib/libusrsctp.a", + "{}datachannel-static{}".format(lib_prefix, lib_ext), + "deps/libjuice/{}juice-static{}".format(lib_prefix, lib_ext), + "deps/libsrtp/{}srtp2{}".format(lib_prefix, lib_ext), + "deps/usrsctp/usrsctplib/{}usrsctp{}".format(lib_prefix, lib_ext), ] ] env.Append(BUILDERS={"BuildLibDataChannel": env.Builder(action=rtc_action, emitter=rtc_emitter)}) env.Append(LIBPATH=[env["RTC_BUILD"]]) env.Append(CPPPATH=[env["RTC_INCLUDE"]]) - env.Prepend(LIBS=env["RTC_LIBS"]) - if env["platform"] == "windows": - env.AppendUnique(LIBS=["iphlpapi", "bcrypt"]) diff --git a/tools/ssl.py b/tools/ssl.py deleted file mode 100644 index 64436ec..0000000 --- a/tools/ssl.py +++ /dev/null @@ -1,121 +0,0 @@ -import os -from SCons.Defaults import Mkdir - - -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_action(target, source, env): - build_dir = env["SSL_BUILD"] - source_dir = env["SSL_SOURCE"] - install_dir = env["SSL_INSTALL"] - - ssl_env = env.Clone() - args = [ - "no-ssl2", - "no-ssl3", - "no-weak-ssl-ciphers", - "no-legacy", - "no-shared", - "no-tests", - "--prefix=%s" % install_dir, - "--openssldir=%s" % install_dir, - ] - if env["debug_symbols"]: - args.append("-d") - - 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", "") - - 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"]) - - 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"]) - - elif env["platform"] == "windows": - if env["arch"] == "x86_32": - if env["use_mingw"]: - args.extend( - [ - "mingw", - "--cross-compile-prefix=i686-w64-mingw32-", - ] - ) - else: - args.extend(["VC-WIN32"]) - else: - if env["use_mingw"]: - args.extend( - [ - "mingw64", - "--cross-compile-prefix=x86_64-w64-mingw32-", - ] - ) - else: - args.extend(["VC-WIN64A"]) - - jobs = env.GetOption("num_jobs") - ssl_env.Execute( - [ - Mkdir(build_dir), - "cd %s && perl %s/Configure %s" % (build_dir, source_dir, " ".join(['"%s"' % a for a in args])), - "make -C %s -j%s" % (build_dir, jobs), - "make -C %s install_sw install_ssldirs -j%s" % (build_dir, jobs), - ] - ) - return None - - -def exists(env): - return True - - -def generate(env): - env["SSL_SOURCE"] = env["DEPS_SOURCE"] + "/openssl" - env["SSL_BUILD"] = env["DEPS_BUILD"] + "/openssl" - env["SSL_INSTALL"] = env["SSL_BUILD"] + "/dest" - env["SSL_INCLUDE"] = env["SSL_INSTALL"] + "/include" - env["SSL_LIBRARY"] = env.File(env["SSL_BUILD"] + "/libssl.a") - env["SSL_CRYPTO_LIBRARY"] = env.File(env["SSL_BUILD"] + "/libcrypto.a") - env["SSL_LIBS"] = [env["SSL_LIBRARY"], env["SSL_CRYPTO_LIBRARY"]] - env.Append(BUILDERS={"BuildOpenSSL": env.Builder(action=ssl_action, emitter=ssl_emitter)}) - env.Prepend(CPPPATH=[env["SSL_INCLUDE"]]) - env.Prepend(LIBPATH=[env["SSL_BUILD"]]) - env.Append(LIBS=env["SSL_LIBS"]) - if env["platform"] == "windows": - env.AppendUnique(LIBS=["ws2_32", "gdi32", "advapi32", "crypt32", "user32"]) |