diff --git a/.github/workflows/sdk.yml b/.github/workflows/sdk.yml index d96c7eb66..35c963615 100644 --- a/.github/workflows/sdk.yml +++ b/.github/workflows/sdk.yml @@ -26,7 +26,8 @@ jobs: shell: bash run: | if [[ "${TARGET}" == "Android" ]]; then - submodules="modules/sentry-java" + # Android needs sentry-native too — BuildAndroidSDK builds the NDK from source. + submodules="modules/sentry-java modules/sentry-native" elif [[ "${TARGET}" == "Cocoa" ]]; then submodules="modules/sentry-cocoa" else @@ -62,7 +63,7 @@ jobs: # hash of package/package.json for cache busting on release builds (version bump) path: | package-dev/Plugins - key: sdk=${{ env.TARGET }}-${{ hashFiles('submodules-status', 'package/package.json', 'Directory.Build.targets', 'sdk-static/**', 'scripts/build-cocoa-sdk.ps1') }} + key: sdk=${{ env.TARGET }}-${{ hashFiles('submodules-status', 'package/package.json', 'Directory.Build.targets', 'build/native-sdks.targets', 'sdk-static/**', 'scripts/build-cocoa-sdk.ps1', 'scripts/build-native-ndk-local.ps1') }} - name: Installing Linux Dependencies if: ${{ env.TARGET == 'Linux' && steps.cache.outputs.cache-hit != 'true' }} diff --git a/CLAUDE.md b/CLAUDE.md index 61fb9406d..d01a059f6 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -148,17 +148,19 @@ Builds run in Docker containers using `ghcr.io/unityci/editor` images: ### MSBuild Targets -Key targets defined in `Directory.Build.targets`: - -| Target | Purpose | -| -------------------- | --------------------------------------- | -| `DownloadNativeSDKs` | Downloads prebuilt native SDKs from CI | -| `BuildAndroidSDK` | Builds Android SDK via Gradle | -| `BuildLinuxSDK` | Builds Linux SDK via CMake | -| `BuildWindowsSDK` | Builds Windows SDK via CMake (Crashpad) | -| `BuildCocoaSDK` | Downloads iOS/macOS SDKs from releases | -| `UnityEditModeTest` | Runs edit-mode unit tests | -| `UnityPlayModeTest` | Runs play-mode tests | +Key targets defined across `build/` target files: + +| Target | Purpose | +| ----------------------- | ----------------------------------------------------------------------- | +| `BuildCocoaSDK` | Builds iOS + macOS SDKs via Xcode (`build/native-sdks.targets`) | +| `BuildAndroidSDK` | Builds Android SDK via Gradle (`build/native-sdks.targets`) | +| `BuildLinuxSDK` | Builds Linux SDK via CMake (`build/native-sdks.targets`) | +| `BuildWindowsSDK` | Builds Windows SDK via CMake + Crashpad (`build/native-sdks.targets`) | +| `EnsureSDK` | Auto-bootstrap wrapper; fires from `dotnet build` when artifacts missing | +| `PublishNativeNdkLocal` | Builds and publishes `sentry-native-ndk` to `~/.m2` | +| `DownloadNativeSDKs` | Downloads prebuilt native SDKs from CI (`build/local-dev.targets`) | +| `UnityEditModeTest` | Runs edit-mode unit tests | +| `UnityPlayModeTest` | Runs play-mode tests | ### Artifact Caching @@ -190,7 +192,7 @@ Key targets defined in `Directory.Build.targets`: ### Build System -Central configuration in `Directory.Build.targets` (900+ lines) and `Directory.Build.props`: +Core build configuration in `Directory.Build.props`. Build targets are split across `Directory.Build.targets` (CI-shared: `FindUnity`, Unity test/configure targets), `build/native-sdks.targets` (native SDK builders), and `build/local-dev.targets` (developer convenience targets): ```xml @@ -320,6 +322,41 @@ modules/ └── sentry-cocoa/ # iOS/macOS (prebuilt XCFramework) ``` +### Local Android NDK Development + +`BuildAndroidSDK` builds the NDK from source on every run (via `PublishNativeNdkLocal`) +and ships the resulting AAR alongside the sentry-java artifacts. Both +`modules/sentry-java` AND `modules/sentry-native` must be checked out — the target +aborts otherwise and prints the `git submodule update --init` command. + +sentry-java's `dependencyResolutionManagement` block already lists `mavenLocal()`, +so Gradle resolves whatever version is declared in +`modules/sentry-java/gradle/libs.versions.toml` — falling through to Maven Central +when the version isn't found locally. + +**The local build must publish a version that is NOT available on Maven Central.** +Otherwise Gradle uses the released artifact on Central (listed before `mavenLocal()` +in the repositories block) and your local changes are silently ignored. + +To iterate on NDK code: + +1. Bump the version in the sentry-native NDK source to something unique — e.g. + add a `-dev`, `-SNAPSHOT`, or hash suffix that doesn't exist on Maven Central. +2. Bump the matching `sentry-native-ndk` version in + `modules/sentry-java/gradle/libs.versions.toml` to the same value. +3. Run `dotnet msbuild /t:BuildAndroidSDK src/Sentry.Unity`. The target rebuilds + the NDK, publishes it to `~/.m2`, then builds sentry-java against the local + artifact. + +To refresh only `~/.m2` without rebuilding the Android SDK: + +```bash +dotnet msbuild /t:PublishNativeNdkLocal src/Sentry.Unity +# Purge cached Gradle artifacts (use when iterating on NDK source without +# bumping the version, so Gradle re-resolves rather than reusing its cache): +dotnet msbuild /t:PublishNativeNdkLocal src/Sentry.Unity -p:PurgeNdkCache=true +``` + ### Key Source Files **Android (`src/Sentry.Unity.Android/`):** diff --git a/Directory.Build.targets b/Directory.Build.targets index 8f6613858..ba2b8f88d 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -10,21 +10,11 @@ ../../artifacts/test/playmode/results.xml ../../artifacts/test/editmode/results.xml - $(RepoRoot)package-dev/Plugins/ - - $(RepoRoot)modules/sentry-cocoa/ - $(SentryArtifactsDestination)iOS/Sentry.xcframework~/ - $(SentryArtifactsDestination)macOS/Sentry/ - - $(RepoRoot)modules/sentry-native-ndk/ - $(RepoRoot)modules/sentry-java/ - $(SentryArtifactsDestination)Android/Sentry~/ - - $(RepoRoot)modules/sentry-native/ - $(SentryArtifactsDestination)Linux/Sentry/ - $(SentryArtifactsDestination)Windows/Sentry/ + + + @@ -87,160 +77,10 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - $([System.IO.File]::ReadAllText("$(RepoRoot)modules/sentry-java/gradle/libs.versions.toml")) - $([System.Text.RegularExpressions.Regex]::Match($(PropertiesContent), 'sentry-native-ndk\s*=\s*\{[^}]*version\s*=\s*"([^"]+)"').Groups[1].Value) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -363,54 +157,5 @@ Log.LogError("Failed to resolve 'com.unity.template.3d-*' for TestRunner at: " + - - - - - - - - - - - !l.Contains($"\"{PackageToRemove}\"")).ToArray(); -File.WriteAllLines(PackageManifestFile, lines); -]]> - - - - - - - - - - - - - - - - - - - - diff --git a/build/local-dev.targets b/build/local-dev.targets new file mode 100644 index 000000000..0e1e59340 --- /dev/null +++ b/build/local-dev.targets @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/build/native-sdks.targets b/build/native-sdks.targets new file mode 100644 index 000000000..63be39e0e --- /dev/null +++ b/build/native-sdks.targets @@ -0,0 +1,226 @@ + + + $(RepoRoot)package-dev/Plugins/ + + + $(RepoRoot)modules/sentry-cocoa/ + $(SentryArtifactsDestination)iOS/Sentry.xcframework~/ + $(SentryArtifactsDestination)macOS/Sentry/ + + + $(RepoRoot)modules/sentry-java/ + $(SentryArtifactsDestination)Android/Sentry~/ + + + $(RepoRoot)modules/sentry-native/ + $(SentryArtifactsDestination)Linux/Sentry/ + $(SentryArtifactsDestination)Windows/Sentry/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -PurgeCache + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $(SentryNativeRoot)ndk/lib/build/outputs/aar/sentry-native-ndk-release.aar + + + + + + + + + + + + diff --git a/scripts/build-cocoa-sdk.ps1 b/scripts/build-cocoa-sdk.ps1 index deb8444b7..ef745627f 100644 --- a/scripts/build-cocoa-sdk.ps1 +++ b/scripts/build-cocoa-sdk.ps1 @@ -8,7 +8,9 @@ param( [string]$iOSDestination, [Parameter(Mandatory = $true)] - [string]$macOSDestination + [string]$macOSDestination, + + [switch]$Clean ) Set-StrictMode -Version latest @@ -25,6 +27,11 @@ $buildPath = Join-Path $CocoaRoot "XCFrameworkBuildPath" $iOSXcframeworkPath = Join-Path $buildPath "Sentry-Dynamic-iOS.xcframework" $macOSXcframeworkPath = Join-Path $buildPath "Sentry-Dynamic-macOS.xcframework" +if ($Clean -and (Test-Path $buildPath)) { + Write-Host "Clean build requested — removing $buildPath" -ForegroundColor Yellow + Remove-Item -Path $buildPath -Recurse -Force +} + Write-Host "Building Cocoa SDK from source..." -ForegroundColor Yellow Push-Location $CocoaRoot diff --git a/scripts/build-native-ndk-local.ps1 b/scripts/build-native-ndk-local.ps1 new file mode 100644 index 000000000..a7b6bef7f --- /dev/null +++ b/scripts/build-native-ndk-local.ps1 @@ -0,0 +1,100 @@ +<# +.SYNOPSIS + Builds modules/sentry-native (NDK) and publishes the artifact to the local + Maven repo so sentry-java can resolve it via mavenLocal(). + +.DESCRIPTION + Runs :sentry-native-ndk:publishToMavenLocal in modules/sentry-native/ndk, + producing io.sentry:sentry-native-ndk: at ~/.m2. + + sentry-java's settings.gradle.kts already lists mavenLocal() in + dependencyResolutionManagement. For Gradle to pick the locally-published + artifact over mavenCentral, the local build's version must be unique + (i.e., not on Maven Central) — bump the version in both the NDK source + and modules/sentry-java/gradle/libs.versions.toml before iterating. + +.PARAMETER PurgeCache + Delete sentry-native-ndk from the Gradle module cache and the related + transform directories, then stop the Gradle daemon. Use when Gradle is + holding a stale cached copy (e.g., when iterating on NDK source without + bumping the version). + +.PARAMETER BuildJava + After publishing, run :sentry-android-ndk:assembleRelease in + modules/sentry-java to consume the freshly published artifact. + +.EXAMPLE + pwsh scripts/build-native-ndk-local.ps1 + # Publish ndk to ~/.m2. + +.EXAMPLE + pwsh scripts/build-native-ndk-local.ps1 -PurgeCache -BuildJava + # Wipe stale caches, publish, then rebuild sentry-android-ndk against + # the local artifact. +#> + +param( + [switch] $PurgeCache, + [switch] $BuildJava +) + +$ErrorActionPreference = 'Stop' +Set-StrictMode -Version Latest + +$repoRoot = Resolve-Path (Join-Path $PSScriptRoot '..') +$ndkDir = Join-Path $repoRoot 'modules/sentry-native/ndk' +$javaDir = Join-Path $repoRoot 'modules/sentry-java' + +if (-not (Test-Path $ndkDir)) { + throw "sentry-native NDK module not found at $ndkDir. Did you check out the submodule?" +} + +if ($PurgeCache) { + Write-Host '==> Purging Gradle caches for sentry-native-ndk' + $gradleCaches = Join-Path $HOME '.gradle/caches' + $moduleCache = Join-Path $gradleCaches 'modules-2/files-2.1/io.sentry/sentry-native-ndk' + if (Test-Path $moduleCache) { + Remove-Item -Recurse -Force $moduleCache + Write-Host " removed $moduleCache" + } + + if (Test-Path $gradleCaches) { + $transformRoots = Get-ChildItem -Path $gradleCaches -Recurse -Force -ErrorAction SilentlyContinue ` + | Where-Object { $_.FullName -like '*sentry-native-ndk*' } ` + | ForEach-Object { + $idx = $_.FullName.IndexOf('/transformed/') + if ($idx -lt 0) { $idx = $_.FullName.IndexOf([IO.Path]::DirectorySeparatorChar + 'transformed' + [IO.Path]::DirectorySeparatorChar) } + if ($idx -ge 0) { $_.FullName.Substring(0, $idx) } else { $null } + } ` + | Where-Object { $_ } ` + | Sort-Object -Unique + foreach ($dir in $transformRoots) { + if (Test-Path $dir) { + Remove-Item -Recurse -Force $dir + Write-Host " removed $dir" + } + } + } + + Write-Host '==> Stopping Gradle daemon to clear in-memory transform registry' + Push-Location $ndkDir + try { & ./gradlew --stop | Out-Null } finally { Pop-Location } +} + +Write-Host '==> Publishing sentry-native-ndk to mavenLocal' +Push-Location $ndkDir +try { + & ./gradlew :sentry-native-ndk:publishToMavenLocal + if ($LASTEXITCODE -ne 0) { throw "publishToMavenLocal failed (exit $LASTEXITCODE)" } +} finally { Pop-Location } + +if ($BuildJava) { + Write-Host '==> Building :sentry-android-ndk:assembleRelease against mavenLocal' + Push-Location $javaDir + try { + & ./gradlew :sentry-android-ndk:assembleRelease + if ($LASTEXITCODE -ne 0) { throw "sentry-android-ndk assembleRelease failed (exit $LASTEXITCODE)" } + } finally { Pop-Location } +} + +Write-Host '==> Done.'