diff --git a/Makefile b/Makefile index 1be6b20..8f302ed 100644 --- a/Makefile +++ b/Makefile @@ -157,19 +157,19 @@ run: install # This is useful for testing on e.g. Amazon Fire Stick devices. tailscale-fdroid.apk: $(AAR) (cd android_legacy && ./gradlew test assembleFdroidDebug) - mv android_legacy/build/outputs/apk/fdroid/debug/android_legacy-fdroid-debug.apk $@ + install -C android_legacy/build/outputs/apk/fdroid/debug/android_legacy-fdroid-debug.apk $@ tailscale-new-fdroid.apk: $(AAR) (cd android && ./gradlew test assembleFdroidDebug) - mv android/build/outputs/apk/fdroid/debug/android-fdroid-debug.apk $@ + install -C android/build/outputs/apk/fdroid/debug/android-fdroid-debug.apk $@ tailscale-new-debug.apk: - (cd android && ./gradlew test buildAllGoLibs assemblePlayDebug) - mv android/build/outputs/apk/play/debug/android-play-debug.apk $@ + (cd android && ./gradlew test assemblePlayDebug) + install -C android/build/outputs/apk/play/debug/android-play-debug.apk $@ $(RELEASE_AAB): $(AAR) (cd android_legacy && ./gradlew test bundlePlayRelease) - mv ./android_legacy/build/outputs/bundle/playRelease/android-play-release.aab $@ + install -C ./android_legacy/build/outputs/bundle/playRelease/android-play-release.aab $@ release: $(RELEASE_AAB) jarsigner -sigalg SHA256withRSA -digestalg SHA-256 -keystore $(KEYSTORE) $(RELEASE_AAB) $(KEYSTORE_ALIAS) diff --git a/android/build.gradle b/android/build.gradle index adc28f6..e1f534a 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -16,15 +16,15 @@ buildscript { repositories { google() mavenCentral() - flatDir { - dirs 'libs' - } } apply plugin: 'kotlin-android' apply plugin: 'com.android.application' apply plugin: 'org.jetbrains.kotlin.plugin.serialization' +def ndkLevel = 30 +def targets = [ "aarch64-linux-android", "armv7a-linux-androideabi", "i686-linux-android", "x86_64-linux-android" ] + android { ndkVersion "23.1.7779620" compileSdkVersion 34 @@ -55,6 +55,11 @@ android { } } namespace 'com.tailscale.ipn' + sourceSets { + main { + jniLibs.srcDirs = ['src/main/jniLibs'] + } + } } dependencies { @@ -96,7 +101,7 @@ dependencies { implementation("io.coil-kt:coil-compose:1.3.1") // Tailscale dependencies. - implementation ':ipn@aar' + //implementation ':ipn@aar' // Tests testImplementation "junit:junit:4.12" @@ -106,61 +111,47 @@ dependencies { playImplementation 'com.google.android.gms:play-services-auth:20.7.0' } -def ndkPath = project.hasProperty('ndkPath') ? project.property('ndkPath') : System.getenv('ANDROID_SDK_ROOT') - -task checkNDK { - doFirst { - if (ndkPath == null) { - throw new GradleException('NDK path not found. Please define ndkPath in local.properties or ANDROID_SDK_HOME environment variable.') - } - } -} - -task buildGoLibArm64(type: Exec) { - inputs.dir '../pkg/tailscale' - outputs.file 'src/main/jniLibs/arm64-v8a/libtailscale.so' - environment "CC", "$ndkPath/ndk-bundle/toolchains/llvm/prebuilt/darwin-x86_64/bin/aarch64-linux-android30-clang" - commandLine 'sh', '-c', "GOOS=android GOARCH=arm64 CGO_ENABLED=1 go build -buildmode=c-shared -ldflags=-w -o src/main/jniLibs/arm64-v8a/libtailscale.so ../pkg/tailscale" +import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform + +OperatingSystem os = DefaultNativePlatform.currentOperatingSystem + +def hostTag +if (os.isLinux()) { + // No aarch64 prebuilts + hostTag = "linux-x86_64" +} else if (os.isMacOsX()) { + hostTag = "darwin-x86_64" +} else if (os.isWindows()){ + // No aarch64 prebuilts. + hostTag = "windows-x86_64" +} else { + throw new GradleException("Unsupported host OS: $os") } -task buildGoLibArmeabi(type: Exec) { - inputs.dir '../pkg/tailscale' - outputs.file 'src/main/jniLibs/armeabi-v7a/libtailscale.so' - environment "CC", "$ndkPath/ndk-bundle/toolchains/llvm/prebuilt/darwin-x86_64/bin/armv7a-linux-androideabi30-clang" - commandLine 'sh', '-c', "GOOS=android GOARCH=arm CGO_ENABLED=1 go build -buildmode=c-shared -ldflags=-w -o src/main/jniLibs/armeabi-v7a/libtailscale.so ../pkg/tailscale" -} +def toolchainDir = "${android.ndkDirectory}/toolchains/llvm/prebuilt/${hostTag}" -task buildGoLibX86(type: Exec) { - inputs.dir '../pkg/tailscale' - outputs.file 'src/main/jniLibs/x86/libtailscale.so' - environment "CC", "$ndkPath/ndk-bundle/toolchains/llvm/prebuilt/darwin-x86_64/bin/i686-linux-android30-clang" - commandLine 'sh', '-c', "GOOS=android GOARCH=386 CGO_ENABLED=1 go build -buildmode=c-shared -ldflags=-w -o src/main/jniLibs/x86/libtailscale.so ../pkg/tailscale" -} +def targetToGoArch = [ + "aarch64-linux-android": "arm64", + "armv7a-linux-androideabi": "arm", + "i686-linux-android": "386", + "x86_64-linux-android": "amd64" +] -task buildGoLibX86_64(type: Exec) { - inputs.dir '../pkg/tailscale' - outputs.file 'src/main/jniLibs/x86_64/libtailscale.so' - environment "CC", "$ndkPath/ndk-bundle/toolchains/llvm/prebuilt/darwin-x86_64/bin/x86_64-linux-android30-clang" - commandLine 'sh', '-c', "GOOS=android GOARCH=amd64 CGO_ENABLED=1 go build -buildmode=c-shared -ldflags=-w -o src/main/jniLibs/x86_64/libtailscale.so ../pkg/tailscale" -} +def targetToAbi = [ + "aarch64-linux-android": "arm64-v8a", + "armv7a-linux-androideabi": "armeabi-v7a", + "i686-linux-android": "x86", + "x86_64-linux-android": "x86_64" +] -task buildAllGoLibs { - dependsOn checkNDK, buildGoLibArm64, buildGoLibArmeabi, buildGoLibX86, buildGoLibX86_64 -} - -assemble.dependsOn buildAllGoLibs - -task cleanGoLibs(type: Delete) { - delete 'src/main/jniLibs/arm64-v8a/libtailscale.so', - 'src/main/jniLibs/armeabi-v7a/libtailscale.so', - 'src/main/jniLibs/x86/libtailscale.so', - 'src/main/jniLibs/x86_64/libtailscale.so' -} +targets.each { target -> + tasks.create("jniLib-$target", Exec) { + environment "CC", "${toolchainDir}/bin/$target$ndkLevel-clang" -clean.dependsOn cleanGoLibs + // TODO: use cmd/dist or gocross to get the version tags + def jniLibsDir = "src/main/jniLibs/${targetToAbi[target]}" + commandLine 'sh', '-c', "mkdir -p $jniLibsDir && GOOS=android GOARM=7 GOARCH=${targetToGoArch[target]} CGO_ENABLED=1 go build -buildmode=c-shared -ldflags=\"-w -s\" -o $jniLibsDir/libtailscale.so ../pkg/tailscale" -tasks.whenTaskAdded { task -> - if (task.name.startsWith('merge') && task.name.endsWith('JniLibFolders')) { - task.mustRunAfter buildAllGoLibs + preBuild.dependsOn tasks["jniLib-$target"] } } \ No newline at end of file diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml index 6c00544..66ab43b 100644 --- a/android/src/main/AndroidManifest.xml +++ b/android/src/main/AndroidManifest.xml @@ -19,7 +19,6 @@ android:name=".App" android:allowBackup="false">