Skip to content

Commit

Permalink
[SCons] Build OpenSSL from source.
Browse files Browse the repository at this point in the history
Remove prebuilt static libraries for macOS.
  • Loading branch information
Faless committed Jun 7, 2023
1 parent 3fc541f commit 93b6d37
Show file tree
Hide file tree
Showing 10 changed files with 199 additions and 32 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,6 @@
[submodule "thirdparty/ssh2/libssh2"]
path = thirdparty/ssh2/libssh2
url = https://github.com/libssh2/libssh2
[submodule "thirdparty/openssl"]
path = thirdparty/openssl
url = https://github.com/openssl/openssl
22 changes: 11 additions & 11 deletions SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,6 @@ opts.Add(PathVariable("target_path",
"The path where the lib is installed.", "demo/addons/godot-git-plugin/"))
opts.Add(PathVariable("target_name", "The library name.",
"libgit_plugin", PathVariable.PathAccept))
opts.Add(PathVariable("macos_openssl", "Path to OpenSSL library root - only used in macOS builds.",
"/usr/local/opt/[email protected]/", PathVariable.PathAccept)) # TODO: Find a way to configure this to use the cloned OpenSSL source code, based on `macos_arch`.
opts.Add(PathVariable("macos_openssl_static_ssl", "Path to OpenSSL libssl.a library - only used in macOS builds.",
os.path.join(os.path.abspath(os.getcwd()), "thirdparty/openssl/libssl.a"), PathVariable.PathAccept))
opts.Add(PathVariable("macos_openssl_static_crypto", "Path to OpenSSL libcrypto.a library - only used in macOS builds.",
os.path.join(os.path.abspath(os.getcwd()), "thirdparty/openssl/libcrypto.a"), PathVariable.PathAccept))
opts.Add(PathVariable("linux_openssl_static_ssl", "Path to OpenSSL libssl.a library - only used in Linux builds.",
"/usr/lib/x86_64-linux-gnu/libssl.a", PathVariable.PathAccept))
opts.Add(PathVariable("linux_openssl_static_crypto", "Path to OpenSSL libcrypto.a library - only used in Linux builds.",
"/usr/lib/x86_64-linux-gnu/libcrypto.a", PathVariable.PathAccept))

# Updates the environment with the option variables.
opts.Update(env)
Expand All @@ -33,13 +23,23 @@ if ARGUMENTS.get("custom_api_file", "") != "":

ARGUMENTS["target"] = "editor"
env = SConscript("godot-cpp/SConstruct").Clone()

# OpenSSL Builder
env.Tool("openssl", toolpath=["tools"])

opts.Update(env)

if env["platform"] != "windows": # Windows does not need OpenSSL
ssl = env.OpenSSL()
else:
ssl = []

Export("ssl")
Export("env")

SConscript("thirdparty/SCsub")

SConscript("godot-git-plugin/SCsub")

# Generates help for the -h scons option.
Help(opts.GenerateHelpText(env))
Help(env["options"].GenerateHelpText(env))
5 changes: 1 addition & 4 deletions THIRDPARTY.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@ The Godot Git Plugin source code uses the following third-party source code:
1. godotengine/godot-cpp - MIT License - https://github.com/godotengine/godot-cpp/tree/02336831735fd6affbe0a6fa252ec98d3e78120c
2. libgit2/libgit2 - GPLv2 with a special Linking Exception - https://github.com/libgit2/libgit2/tree/b7bad55e4bb0a285b073ba5e02b01d3f522fc95d
3. libssh2/libssh2 - BSD-3-Clause License - https://github.com/libssh2/libssh2/tree/635caa90787220ac3773c1d5ba11f1236c22eae8

We also link to these third-party libraries (only in the compiled binary form):

1. OpenSSL - Only on Linux and MacOS - OpenSSL License - http://www.openssl.org/source/openssl-1.1.1s.tar.gz
4. openssl (only on Linux and MacOS) - OpenSSL License - https://github.com/openssl/openssl/tree/26baecb28ce461696966dac9ac889629db0b3b96

## License Texts

Expand Down
9 changes: 4 additions & 5 deletions godot-git-plugin/SCsub
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import os

env = {}
Import("env")
Import("ssl")

# Process some arguments
if env["use_llvm"]:
Expand All @@ -24,8 +25,6 @@ if env["platform"] == "macos":
env["target_path"] += "macos/"

# Force static linkage (https://stackoverflow.com/a/2995999/7370948)
env.Append(LIBS=[File(env["macos_openssl_static_ssl"]),
File(env["macos_openssl_static_crypto"])])

if env["macos_deployment_target"] != "default":
env.Append(CCFLAGS=["-mmacosx-version-min=" +
Expand All @@ -35,8 +34,6 @@ if env["platform"] == "macos":

elif env["platform"] == "linux":
env["target_path"] += "linux/"
env.Append(LIBS=[File(env["linux_openssl_static_ssl"]),
File(env["linux_openssl_static_crypto"])])

elif env["platform"] == "windows":
env["target_path"] += "win64/"
Expand All @@ -50,9 +47,11 @@ env.Append(CPPPATH=["../thirdparty/git2/libgit2/include/"])
env.Append(LIBPATH=["../thirdparty/bin/"])
env.Prepend(LIBS=["git2", "ssh2"])

lib_sources = Glob("src/*.cpp")
env.Depends(lib_sources, ssl)
library = env.SharedLibrary(
target=env["target_path"] +
"{}{}{}".format(env["target_name"], env["suffix"], env["SHLIBSUFFIX"]),
source=Glob("src/*.cpp")
source=lib_sources
)
Default(library)
8 changes: 2 additions & 6 deletions thirdparty/git2/SCsub
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# Adopted from https://github.com/goostengine/goost/blob/20d8ce4c7d74c26832d69283305b25a72165784a/modules/git/SCsub

Import("env")
Import("ssl")

env_git = env.Clone()

Expand Down Expand Up @@ -125,11 +126,6 @@ if env_git["platform"] in ["linux", "macos"]:
"UNICODE_BUILTIN"
]
)

if env_git["platform"] == "macos":
env_git.Prepend(CPPPATH=[env_git["macos_openssl"] + "include/"])
static_ssl = File(env_git["macos_openssl_static_ssl"])
static_crypto = File(env_git["macos_openssl_static_crypto"])
env_git.Append(LIBS=[static_ssl, static_crypto])
env_git.Depends(libgit2_sources, ssl)

env_git.StaticLibrary(target="../bin/" + "git2", source=libgit2_sources)
1 change: 1 addition & 0 deletions thirdparty/openssl
Submodule openssl added at 2cf4e9
Binary file removed thirdparty/openssl/libcrypto.a
Binary file not shown.
Binary file removed thirdparty/openssl/libssl.a
Binary file not shown.
8 changes: 2 additions & 6 deletions thirdparty/ssh2/SCsub
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# Adopted from https://github.com/nodegit/nodegit/blob/4561dcb7c120474a4553baa27e4c4c2f4be23a2b/vendor/libgit2.gyp

Import("env")
Import("ssl")

env_ssh2 = env.Clone()

Expand Down Expand Up @@ -104,11 +105,6 @@ if env_ssh2["platform"] in ["linux", "macos"]:
("STDC_HEADERS", 1)
]
)

if env_ssh2["platform"] == "macos":
env_ssh2.Append(CPPPATH=[env_ssh2["macos_openssl"] + "include/"])
static_ssl = File(env_ssh2["macos_openssl_static_ssl"])
static_crypto = File(env_ssh2["macos_openssl_static_crypto"])
env_ssh2.Append(LIBS=[static_ssl, static_crypto])
env_ssh2.Depends(libssh2_sources, ssl)

env_ssh2.StaticLibrary(target="../bin/" + "ssh2", source=libssh2_sources)
175 changes: 175 additions & 0 deletions tools/openssl.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
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"])
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 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"])

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["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={"OpenSSLBuilder": env.Builder(action=ssl_action, emitter=ssl_emitter)})
env.AddMethod(build_openssl, "OpenSSL")

0 comments on commit 93b6d37

Please sign in to comment.