Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

build: Improve sentry-native build process #71

Merged
merged 13 commits into from
Jan 30, 2025
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
- Click to copy UUIDs in the demo project ([#78](https://github.com/getsentry/sentry-godot/pull/78))
- Customize `SentryEvent` tags ([#72](https://github.com/getsentry/sentry-godot/pull/72))

### Improvements

- Refine sentry-native build step and improve tracking of build artifacts ([#71](https://github.com/getsentry/sentry-godot/pull/71))

### Dependencies

- Bump Native SDK from v0.7.17 to v0.7.19 ([#61](https://github.com/getsentry/sentry-godot/pull/61), [#63](https://github.com/getsentry/sentry-godot/pull/63))
Expand Down
155 changes: 113 additions & 42 deletions SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import os
import sys
import subprocess
from functools import partial

# *** Setting.

Expand All @@ -11,8 +12,18 @@ EXTENSION_NAME = "sentrysdk"
COMPATIBILITY_MINIMUM = "4.3"

BIN_DIR = "{project_dir}/addons/{extension_name}/bin".format(
project_dir=PROJECT_DIR,
extension_name=EXTENSION_NAME)
project_dir=PROJECT_DIR, extension_name=EXTENSION_NAME
)


def run_cmd(**kwargs):
"""Run command in a subprocess and return its exit code."""
result = subprocess.run(
kwargs["args"],
check=True,
)
return result.returncode


# *** Generate version header.

Expand All @@ -38,11 +49,13 @@ version_header_content = """/* DO NOT EDIT - generated by SConstruct */
with open("src/sdk_version.gen.h", "w") as f:
f.write(version_header_content)


# *** Build godot-cpp.

print("Reading godot-cpp build configuration...")
env = SConscript("modules/godot-cpp/SConstruct")


# *** Build sentry-native.

# TODO: macOS needs to use a different SDK.
Expand Down Expand Up @@ -107,45 +120,100 @@ if env["platform"] in ["linux", "macos", "windows"]:
env.Append(CPPDEFINES=["SENTRY_BUILD_STATIC", "NATIVE_SDK"])
env.Append(CPPPATH=["modules/sentry-native/include"])
env.Append(LIBPATH=["modules/sentry-native/install/lib/"])
env.Append(
LIBS=[
"sentry",
"crashpad_client",
"crashpad_handler_lib",
"crashpad_minidump",
"crashpad_snapshot",
"crashpad_tools",
"crashpad_util",
"mini_chromium",
]
)
# Include additional platform-specific libs.
if env["platform"] == "windows":
env.Append(
LIBS=[
"crashpad_compat",
"winhttp",
"advapi32",
"DbgHelp",
"Version",
]
)
elif env["platform"] == "linux":
env.Append(
LIBS=[
"crashpad_compat",
"curl",
]
)
elif env["platform"] == "macos":
env.Append(
LIBS=[
"curl",
]
)

sn_targets = []
sn_sources = ["modules/sentry-native/src/"]

def add_target(lib_name):
env.Append(LIBS=[lib_name])
if env["platform"] == "windows":
sn_targets.append("modules/sentry-native/install/lib/" + lib_name + ".lib")
sn_targets.append("modules/sentry-native/install/lib/" + lib_name + ".pdb")
else:
sn_targets.append("modules/sentry-native/install/lib/lib" + lib_name + ".a")

add_target("sentry")
add_target("crashpad_client")
add_target("crashpad_handler_lib")
add_target("crashpad_minidump")
add_target("crashpad_snapshot")
add_target("crashpad_tools")
add_target("crashpad_util")
add_target("mini_chromium")

# Include additional platform-specific libs.
if env["platform"] == "windows":
add_target("crashpad_compat")
env.Append(
LIBS=[
"winhttp",
"advapi32",
"DbgHelp",
"Version",
]
)
elif env["platform"] == "linux":
add_target("crashpad_compat")
env.Append(
LIBS=[
"curl",
]
)
elif env["platform"] == "macos":
env.Append(
LIBS=[
"curl",
]
)

build_actions = []
dest_dir = BIN_DIR + "/" + env["platform"]

if env["platform"] == "windows":
build_actions.append(
partial(run_cmd, args=["powershell", "scripts/build-sentry-native.ps1"])
),
build_actions.append(
Copy(
dest_dir + "/crashpad_handler.exe",
"modules/sentry-native/install/bin/crashpad_handler.exe",
)
)
build_actions.append(
Copy(
dest_dir + "/crashpad_handler.pdb",
"modules/sentry-native/install/bin/crashpad_handler.pdb",
)
)
sn_targets.append(dest_dir + "/crashpad_handler.exe")
sn_targets.append(dest_dir + "/crashpad_handler.pdb")
else:
# TODO: macOS needs to use a different SDK.
build_actions.append(
partial(run_cmd, args=["sh", "scripts/build-sentry-native.sh"])
),
build_actions.append(
Copy(
dest_dir + "/crashpad_handler",
"modules/sentry-native/install/bin/crashpad_handler",
)
)
sn_targets.append(dest_dir + "/crashpad_handler")

sentry_native = env.Command(sn_targets, sn_sources, build_actions)

# Force sentry-native to be built sequential to godot-cpp (not in parallel).
Depends(sentry_native, "modules/godot-cpp")

Default(sentry_native)
Clean(sentry_native, ["modules/sentry-native/build", "modules/sentry-native/install"])


# *** Build GDExtension library.

# Include relative to project source root.
env.Append(CPPPATH=["src/"])

# Source files to compile.
sources = Glob("src/*.cpp")
sources += Glob("src/sentry/*.cpp")
Expand Down Expand Up @@ -173,13 +241,14 @@ else:
platform=env["platform"],
build_type=build_type,
arch=env["arch"],
shlib_suffix=env["SHLIBSUFFIX"]
shlib_suffix=env["SHLIBSUFFIX"],
),
source=sources,
)

Default(library)


# *** Deploy extension manifest.

manifest = env.Substfile(
Expand All @@ -196,12 +265,13 @@ manifest = env.Substfile(

Default(manifest)


# *** Create symbolic link from project addons dir to gdUnit4 testing framework submodule.

def symlink(target, source, env):
# Note: parameter `target` is a list of build targets.
assert(len(target) == 1)
assert(len(source) == 1)
assert len(target) == 1
assert len(source) == 1
dst = str(target[0])
src = str(source[0])
if env["platform"] == "windows":
Expand All @@ -212,13 +282,14 @@ def symlink(target, source, env):
_winapi.CreateJunction(src, dst)
except Exception as e:
# Don't fail the build if this step fails.
print("WARNING: Failed to create an NTFS junction for gdUnit4 testing framework: ", str(e))
print("WARNING: Failed to create NTFS junction for gdUnit4: ", str(e))
else:
# Create symlink.
src = os.path.relpath(src, os.path.dirname(dst))
os.symlink(src, dst)
return 0


gdunit_symlink = env.Command(
PROJECT_DIR + "/addons/gdUnit4",
"modules/gdUnit4/addons/gdUnit4",
Expand Down
49 changes: 45 additions & 4 deletions scripts/build-sentry-native.ps1
Original file line number Diff line number Diff line change
@@ -1,6 +1,47 @@
Push-Location modules\sentry-native
cmake -B build -DSENTRY_BUILD_SHARED_LIBS=OFF -DSENTRY_BUILD_RUNTIMESTATIC=ON -DSENTRY_BACKEND=crashpad -DSENTRY_SDK_NAME="sentry.native.godot" -DCMAKE_BUILD_TYPE=RelWithDebInfo
cmake --build build --target sentry --parallel --config RelWithDebInfo
cmake --build build --target crashpad_handler --parallel --config RelWithDebInfo
cmake --install build --prefix install --config RelWithDebInfo

$curDir = Get-Location
$buildDir = Join-Path -Path $curDir -ChildPath "build"
$installDir = Join-Path -Path $curDir -ChildPath "install"
$pdbBuildDir = Join-Path -Path $buildDir -ChildPath "pdb"
$pdbSourceDir = Join-Path -Path $pdbBuildDir -ChildPath "RelWithDebInfo"
$libInstallDir = Join-Path -Path $installDir -ChildPath "lib"

cmake -B $buildDir -DSENTRY_BUILD_SHARED_LIBS=OFF -DSENTRY_BUILD_RUNTIMESTATIC=ON -DSENTRY_BACKEND=crashpad -DSENTRY_SDK_NAME="sentry.native.godot" -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_COMPILE_PDB_OUTPUT_DIRECTORY="$pdbBuildDir"
cmake --build $buildDir --target sentry --parallel --config RelWithDebInfo
cmake --build $buildDir --target crashpad_handler --parallel --config RelWithDebInfo
cmake --install $buildDir --prefix $installDir --config RelWithDebInfo

# *** Install PDB files

Write-Host "Installing PDB files"

if (!(Test-Path -Path $libInstallDir)) {
Throw "Directory $libInstallDir does not exist."
}
if (!(Test-Path -Path $pdbSourceDir)) {
Throw "Directory $pdbSourceDir does not exist."
}

Get-ChildItem -Path $pdbSourceDir -Filter "*.pdb" -Recurse | ForEach-Object {
$pdbFile = $_.Name
$pdbSource = $_.FullName
$pdbTarget = Join-Path -Path $libInstallDir -ChildPath $pdbFile
$libBase = [System.IO.Path]::GetFileNameWithoutExtension($pdbFile)
$libPath = Join-Path -Path $libInstallDir -ChildPath "$libBase.lib"

if (Test-Path -Path $libPath) {
if (Test-Path -Path $pdbTarget) {
$sourceHash = Get-FileHash -Path $pdbSource -Algorithm SHA256
$targetHash = Get-FileHash -Path $pdbTarget -Algorithm SHA256
if ($sourceHash.Hash -eq $targetHash.Hash) {
Write-Host "-- Up-to-date: $pdbTarget."
return
}
}
Write-Host "-- Installing: $pdbFile to $libInstallDir"
Copy-Item -Path $pdbSource -Destination $pdbTarget -Force
}
}

Pop-Location