Skip to content

Commit 9600a52

Browse files
committed
Wire native dependency build into Gradle
1 parent dd25110 commit 9600a52

4 files changed

Lines changed: 124 additions & 19 deletions

File tree

.github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ jobs:
7878
uses: actions/cache@v5.0.5
7979
with:
8080
path: app/src/main/go/third_party/output
81-
key: third-party-${{ matrix.os }}-${{ hashFiles('app/src/main/go/third_party/CMakeLists.txt', 'app/src/main/go/build.sh', 'app/src/main/go/build.ps1') }}
81+
key: third-party-${{ matrix.os }}-ndk-r27c-${{ hashFiles('app/build.gradle.kts', 'app/src/main/go/third_party/CMakeLists.txt', 'app/src/main/go/build.sh', 'app/src/main/go/build.ps1') }}
8282

8383
- name: Build with Gradle
8484
shell: bash

app/build.gradle.kts

Lines changed: 80 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,43 @@ plugins {
77
id("kotlin-parcelize")
88
}
99

10-
// Task to build the Go library with native JNI
11-
tasks.register<Exec>("buildGoLibrary") {
12-
group = "build"
13-
description = "Build the Go kinetic library with native JNI"
14-
workingDir = file("src/main/go")
10+
val nativeAbis = listOf("arm64-v8a", "armeabi-v7a", "x86", "x86_64")
11+
val goSourceDir = layout.projectDirectory.dir("src/main/go")
12+
val thirdPartyOutputDir = goSourceDir.dir("third_party/output")
13+
val jniLibsDir = layout.projectDirectory.dir("src/main/jniLibs")
14+
val sharedThirdPartyLibs = listOf("libusb-1.0.so", "libsrt.so", "librist.so")
15+
val isWindowsHost = System.getProperty("os.name").lowercase().contains("windows")
16+
17+
fun thirdPartyLibraries() = nativeAbis.flatMap { abi ->
18+
val libDir = thirdPartyOutputDir.dir("$abi/lib")
19+
val opensslLibExtension = if (isWindowsHost) "a" else "so"
20+
sharedThirdPartyLibs.map { libDir.file(it) } + listOf(
21+
libDir.file("libssl.$opensslLibExtension"),
22+
libDir.file("libcrypto.$opensslLibExtension"),
23+
)
24+
}
1525

16-
// Detect OS and use appropriate command
17-
val isWindows = System.getProperty("os.name").lowercase().contains("windows")
26+
fun jniLibraries() = nativeAbis.flatMap { abi ->
27+
val libDir = jniLibsDir.dir(abi)
28+
val requiredLibs = listOf(
29+
libDir.file("libkinetic.so"),
30+
libDir.file("libusb-1.0.so"),
31+
libDir.file("libsrt.so"),
32+
libDir.file("librist.so"),
33+
)
34+
if (isWindowsHost) requiredLibs else requiredLibs + listOf(
35+
libDir.file("libssl.so"),
36+
libDir.file("libcrypto.so"),
37+
)
38+
}
1839

19-
if (isWindows) {
20-
commandLine("powershell", "-ExecutionPolicy", "Bypass", "-File", "./build.ps1")
21-
} else {
22-
commandLine("bash", "./build.sh")
23-
}
40+
fun Exec.configureNativeBuildEnvironment() {
41+
workingDir = goSourceDir.asFile
2442

2543
// Set environment variables if needed
2644
// Look for NDK in the Android SDK location, falling back to local.properties / OS defaults
2745
val osName = System.getProperty("os.name").lowercase()
46+
val isWindows = osName.contains("windows")
2847
val isMac = osName.contains("mac") || osName.contains("darwin")
2948
val sdkDirFromProps = rootProject.file("local.properties").takeIf { it.exists() }
3049
?.readLines()
@@ -52,6 +71,55 @@ tasks.register<Exec>("buildGoLibrary") {
5271
environment("ANDROID_HOME", androidHome)
5372
}
5473

74+
val buildThirdPartyDeps = tasks.register<Exec>("buildThirdPartyDeps") {
75+
group = "build"
76+
description = "Build third-party native dependencies used by the Go JNI library"
77+
78+
configureNativeBuildEnvironment()
79+
80+
if (isWindowsHost) {
81+
commandLine("powershell", "-ExecutionPolicy", "Bypass", "-File", "./build.ps1", "-DepsOnly")
82+
} else {
83+
commandLine("bash", "./build.sh", "--deps-only")
84+
}
85+
86+
inputs.file(goSourceDir.file("build.sh"))
87+
inputs.file(goSourceDir.file("build.ps1"))
88+
inputs.file(goSourceDir.file("third_party/CMakeLists.txt"))
89+
outputs.files(thirdPartyLibraries())
90+
outputs.dirs(nativeAbis.map { abi -> thirdPartyOutputDir.dir("$abi/include") })
91+
}
92+
93+
// Task to build the Go library with native JNI
94+
tasks.register<Exec>("buildGoLibrary") {
95+
group = "build"
96+
description = "Build the Go kinetic library with native JNI"
97+
dependsOn(buildThirdPartyDeps)
98+
99+
configureNativeBuildEnvironment()
100+
101+
// Detect OS and use appropriate command
102+
if (isWindowsHost) {
103+
commandLine("powershell", "-ExecutionPolicy", "Bypass", "-File", "./build.ps1", "-SkipDeps")
104+
} else {
105+
commandLine("bash", "./build.sh", "--skip-deps")
106+
}
107+
108+
inputs.files(fileTree(goSourceDir) {
109+
include("**/*.go")
110+
include("**/*.c")
111+
include("**/*.h")
112+
include("go.mod")
113+
include("go.sum")
114+
exclude("include/**")
115+
exclude("third_party/**")
116+
})
117+
inputs.files(thirdPartyLibraries())
118+
inputs.file(goSourceDir.file("build.sh"))
119+
inputs.file(goSourceDir.file("build.ps1"))
120+
outputs.files(jniLibraries())
121+
}
122+
55123
// Make preBuild depend on buildGoLibrary
56124
tasks.named("preBuild") {
57125
dependsOn("buildGoLibrary")

app/src/main/go/build.ps1

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,18 @@
88
# Outputs to ../jniLibs/<abi>/libkinetic.so plus the third-party .so's alongside.
99

1010
param(
11-
[switch]$RebuildDeps
11+
[switch]$RebuildDeps,
12+
[switch]$DepsOnly,
13+
[switch]$SkipDeps
1214
)
1315

1416
$ErrorActionPreference = "Stop"
1517

18+
if ($DepsOnly -and $SkipDeps) {
19+
Write-Error "-DepsOnly and -SkipDeps cannot be used together"
20+
exit 1
21+
}
22+
1623
# ---- shared environment ----------------------------------------------------
1724
$SCRIPT_DIR = $PSScriptRoot
1825
$THIRD_PARTY_DIR = Join-Path $SCRIPT_DIR "third_party\output"
@@ -79,7 +86,12 @@ function Test-DepsBuilt {
7986
return $true
8087
}
8188

82-
if ($RebuildDeps -or -not (Test-DepsBuilt)) {
89+
if ($SkipDeps -and -not (Test-DepsBuilt)) {
90+
Write-Error "Third-party dependencies are missing. Run without -SkipDeps or build them first."
91+
exit 1
92+
}
93+
94+
if (-not $SkipDeps -and ($RebuildDeps -or -not (Test-DepsBuilt))) {
8395
$bashCmd = Get-Command bash -ErrorAction SilentlyContinue
8496
$bash = if ($bashCmd) { $bashCmd.Source } else { $null }
8597
if (-not $bash) {
@@ -95,14 +107,21 @@ Options:
95107
exit 1
96108
}
97109
Write-Host "Building third-party C dependencies via bash..."
98-
$rebuildArg = if ($RebuildDeps) { "--rebuild-deps" } else { "" }
99-
& $bash (Join-Path $SCRIPT_DIR "build.sh") $rebuildArg
110+
$bashArgs = @()
111+
if ($RebuildDeps) { $bashArgs += "--rebuild-deps" }
112+
if ($DepsOnly) { $bashArgs += "--deps-only" }
113+
& $bash (Join-Path $SCRIPT_DIR "build.sh") @bashArgs
100114
if ($LASTEXITCODE -ne 0) {
101115
Write-Error "Third-party build failed"
102116
exit 1
103117
}
104118
}
105119

120+
if ($DepsOnly) {
121+
Write-Host "Third-party dependencies built to: $THIRD_PARTY_DIR"
122+
exit 0
123+
}
124+
106125
# ---- stage 2: Go shared library --------------------------------------------
107126
if (-not (Test-Path $INCLUDE_DIR)) { New-Item -ItemType Directory -Path $INCLUDE_DIR | Out-Null }
108127
foreach ($hdr in @("libusb-1.0","srt","openssl")) {

app/src/main/go/build.sh

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,27 @@ set -eo pipefail
1313

1414
# ---- arg parsing -----------------------------------------------------------
1515
REBUILD_DEPS=0
16+
DEPS_ONLY=0
17+
SKIP_DEPS=0
1618
for arg in "$@"; do
1719
case "$arg" in
1820
--rebuild-deps) REBUILD_DEPS=1 ;;
21+
--deps-only) DEPS_ONLY=1 ;;
22+
--skip-deps) SKIP_DEPS=1 ;;
1923
-h|--help)
2024
sed -n '2,9p' "$0" | sed 's/^# \?//'
2125
echo
22-
echo "Usage: $0 [--rebuild-deps]"
26+
echo "Usage: $0 [--rebuild-deps] [--deps-only|--skip-deps]"
2327
exit 0
2428
;;
2529
*) echo "Unknown arg: $arg"; exit 1 ;;
2630
esac
2731
done
2832

33+
if [ "$DEPS_ONLY" -eq 1 ] && [ "$SKIP_DEPS" -eq 1 ]; then
34+
echo "--deps-only and --skip-deps cannot be used together"
35+
exit 1
36+
fi
2937

3038
# ---- shared environment ----------------------------------------------------
3139
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
@@ -116,7 +124,12 @@ deps_built() {
116124
return 0
117125
}
118126

119-
if [ "$REBUILD_DEPS" -eq 1 ] || ! deps_built; then
127+
if [ "$SKIP_DEPS" -eq 1 ] && ! deps_built; then
128+
echo "Third-party dependencies are missing. Run without --skip-deps or build them first."
129+
exit 1
130+
fi
131+
132+
if [ "$SKIP_DEPS" -eq 0 ] && { [ "$REBUILD_DEPS" -eq 1 ] || ! deps_built; }; then
120133
cd "$SCRIPT_DIR"
121134
# Build sequentially. Parallel builds combined with OpenSSL's 'make -j'
122135
# (no job limit) fork-bomb the host.
@@ -128,6 +141,11 @@ if [ "$REBUILD_DEPS" -eq 1 ] || ! deps_built; then
128141
echo
129142
fi
130143

144+
if [ "$DEPS_ONLY" -eq 1 ]; then
145+
echo "Third-party dependencies built to: $THIRD_PARTY_DIR"
146+
exit 0
147+
fi
148+
131149
# ---- stage 2: Go shared library --------------------------------------------
132150
mkdir -p "$INCLUDE_DIR"
133151
for hdr in libusb-1.0 srt openssl; do

0 commit comments

Comments
 (0)