Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ class Main {
- aarch64-linux
- aarch64-linux-android

# Android native builds
Android native builds use the Android NDK compiler. If `ANDROID_NDK_HOME`, `ANDROID_NDK_ROOT`, `ANDROID_HOME`, or `ANDROID_SDK_ROOT` points to an installed NDK, the build uses it. Otherwise, Gradle downloads the NDK version configured by `androidNdkVersion` in `gradle.properties` into the root `build/android-ndk` directory.

# Developers: How to Add a Parser

To add a new language parser to this project, we provide a code generation task that handles most of the boilerplate. This is also how you can add an "unofficial" or community parser.
Expand Down
7 changes: 6 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,9 @@ subprojects {
tasks.register('buildNative', BuildNativeTask) {
zigExe = rootProject.downloadZig.zigExe
dependsOn downloadSource, rootProject.downloadZig
if (((String) rootProject.properties.get("treeSitterTargets")).contains("android")) {
dependsOn rootProject.downloadAndroidNdk
}
}

tasks.withType(Javadoc) {
Expand All @@ -139,6 +142,8 @@ tasks.register('downloadZig', DownloadZigTask){
dependsOn downloadMiniSign
}

tasks.register('downloadAndroidNdk', DownloadAndroidNdkTask)

tasks.register("gen", GenTask) {
group = "build setup"
description = "Generate sub project for tree sitter parser"
Expand Down Expand Up @@ -251,4 +256,4 @@ tasks.register("postPublish") {
}
println "Published to Portal with response body:\n${resp.body()}"
}
}
}
20 changes: 15 additions & 5 deletions buildSrc/src/main/groovy/BuildNativeTask.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -195,13 +195,17 @@ class BuildNativeTask extends DefaultTask{
}

def ndkDir = findAndroidNdkDir()
def hostTag = System.getProperty("os.name").toLowerCase(Locale.ROOT).contains("mac")
? "darwin-x86_64"
: "linux-x86_64"
def osName = System.getProperty("os.name").toLowerCase(Locale.ROOT)
def hostTag = osName.contains("win")
? "windows-x86_64"
: osName.contains("mac")
? "darwin-x86_64"
: "linux-x86_64"
def apiLevel = project.findProperty("androidApiLevel") ?: "21"
def compilerName = "aarch64-linux-android${apiLevel}-clang${osName.contains("win") ? ".cmd" : ""}"
def compiler = new File(
ndkDir,
"toolchains/llvm/prebuilt/${hostTag}/bin/aarch64-linux-android${apiLevel}-clang"
"toolchains/llvm/prebuilt/${hostTag}/bin/${compilerName}"
)
if (!compiler.exists()) {
throw new GradleException("Android compiler not found: ${compiler}. Set ANDROID_NDK_HOME or ANDROID_NDK_ROOT.")
Expand All @@ -224,7 +228,13 @@ class BuildNativeTask extends DefaultTask{
}
}

throw new GradleException("Android NDK not found. Set ANDROID_NDK_HOME, ANDROID_NDK_ROOT, ANDROID_HOME, or ANDROID_SDK_ROOT.")
def downloadAndroidNdkTask = project.rootProject.tasks.named("downloadAndroidNdk").get()
def downloadedNdk = downloadAndroidNdkTask.androidNdkHome.asFile
if (downloadedNdk.exists()) {
return downloadedNdk
}

throw new GradleException("Android NDK not found. Set ANDROID_NDK_HOME, ANDROID_NDK_ROOT, ANDROID_HOME, or ANDROID_SDK_ROOT, or run the downloadAndroidNdk task.")
}

private void removeWindowsDebugFiles(){
Expand Down
117 changes: 117 additions & 0 deletions buildSrc/src/main/groovy/DownloadAndroidNdkTask.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import org.gradle.api.DefaultTask
import org.gradle.api.GradleException
import org.gradle.api.file.Directory
import org.gradle.api.file.RegularFile
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.OutputDirectory
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.TaskAction
import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform
import org.gradle.nativeplatform.platform.internal.DefaultOperatingSystem
import org.treesitter.build.Utils

class DownloadAndroidNdkTask extends DefaultTask {

@Internal
DefaultOperatingSystem os

DownloadAndroidNdkTask() {
group = "download"
description = "Download Android NDK required for Android native targets"
os = DefaultNativePlatform.currentOperatingSystem
}

@Input
String getAndroidNdkVersion() {
return project.rootProject.property("androidNdkVersion")
}

@Internal
Directory getAndroidNdkDir() {
return project.rootProject.layout.buildDirectory.dir("android-ndk").get()
}

@OutputDirectory
Directory getAndroidNdkHome() {
return androidNdkDir.dir("android-ndk-${androidNdkVersion}")
}

@Internal
String getOsName() {
if (os.windows) {
return "windows"
} else if (os.macOsX) {
return "darwin"
} else if (os.linux) {
return "linux"
} else {
throw new GradleException("Unsupported OS: " + os.name)
}
}

@OutputFile
RegularFile getAndroidNdkArchive() {
return androidNdkDir.file("android-ndk-${androidNdkVersion}-${osName}.zip")
}

@Internal
String getAndroidNdkUrl() {
return "https://dl.google.com/android/repository/${androidNdkArchive.asFile.name}"
}

@TaskAction
void downloadAndroidNdk() {
def installedNdk = findInstalledAndroidNdkDir()
if (installedNdk != null) {
logger.lifecycle("Using installed Android NDK: {}", installedNdk)
return
}

if (androidNdkHome.asFile.exists()) {
logger.lifecycle("Using downloaded Android NDK: {}", androidNdkHome.asFile)
return
}

logger.lifecycle("Downloading Android NDK from {}", androidNdkUrl)
Utils.downloadFile(androidNdkUrl, androidNdkArchive.asFile)
Utils.unzipArchive(androidNdkArchive.asFile, androidNdkDir.asFile)
androidCompiler.asFile.setExecutable(true, true)
}

@Internal
RegularFile getAndroidCompiler() {
return androidNdkHome.file("toolchains/llvm/prebuilt/${hostTag}/bin/aarch64-linux-android21-clang${os.windows ? '.cmd' : ''}")
}

@Internal
String getHostTag() {
if (os.windows) {
return "windows-x86_64"
} else if (os.macOsX) {
return "darwin-x86_64"
} else if (os.linux) {
return "linux-x86_64"
} else {
throw new GradleException("Unsupported OS: " + os.name)
}
}

File findInstalledAndroidNdkDir() {
def envNdk = System.getenv("ANDROID_NDK_HOME") ?: System.getenv("ANDROID_NDK_ROOT")
if (envNdk) {
return new File(envNdk)
}

def sdkDir = System.getenv("ANDROID_HOME") ?: System.getenv("ANDROID_SDK_ROOT")
if (sdkDir) {
def ndkRoot = new File(sdkDir, "ndk")
def ndks = ndkRoot.listFiles()?.findAll { it.isDirectory() }?.sort { a, b -> b.name <=> a.name }
if (ndks) {
return ndks.first()
}
}

return null
}
}
1 change: 1 addition & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ miniSigDir=minisign
zigDir=zig
zigVersion=0.11.0
miniSignVersion=0.11
androidNdkVersion=r27c
zigPubKey=RWSGOq2NVecA2UPNdBUZykf1CCb147pkmdtYxgb3Ti+JO/wCYvhbAb/U
treeSitterTargets=x86_64-windows,x86_64-macos,x86_64-linux-gnu,aarch64-linux-gnu,aarch64-macos,aarch64-linux-android
org.gradle.parallel=true
Expand Down
Loading