Start adding third party dependencies to new gradle setup
Bug: b/270105162
Change-Id: I5b1ed67cdab4905f462d76c37fa88bab61b28f8c
diff --git a/d8_r8/commonBuildSrc/src/main/kotlin/DependenciesPlugin.kt b/d8_r8/commonBuildSrc/src/main/kotlin/DependenciesPlugin.kt
index a1796c3..4574e59 100644
--- a/d8_r8/commonBuildSrc/src/main/kotlin/DependenciesPlugin.kt
+++ b/d8_r8/commonBuildSrc/src/main/kotlin/DependenciesPlugin.kt
@@ -2,33 +2,65 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+import java.io.File
+import java.net.URI
+import java.nio.file.Paths
+import org.gradle.api.JavaVersion
import org.gradle.api.Plugin
import org.gradle.api.Project
-import org.gradle.api.JavaVersion
import org.gradle.api.Task
-import org.gradle.api.tasks.Exec
-import java.io.File
-import java.nio.file.Path
-import java.nio.file.Paths
-import java.net.URI
+import org.gradle.api.file.ConfigurableFileCollection
+import org.gradle.kotlin.dsl.register
+import org.gradle.nativeplatform.platform.OperatingSystem
+import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform
class DependenciesPlugin: Plugin<Project> {
override fun apply(target: Project) {
val dependenciesPath = "file:" +
- "${target.getRoot().resolve("third_party").resolve("dependencies").getAbsolutePath()}"
+ target.getRoot().resolve("third_party").resolve("dependencies").getAbsolutePath()
val dependenciesNewPath = "file:" +
- "${target.getRoot().resolve("third_party").resolve("dependencies_new").getAbsolutePath()}"
+ target.getRoot().resolve("third_party").resolve("dependencies_new").getAbsolutePath()
val repositories = target.getRepositories()
repositories.maven { name = "LOCAL_MAVEN_REPO"; url = URI(dependenciesPath) }
repositories.maven { name = "LOCAL_MAVEN_REPO_NEW"; url = URI(dependenciesNewPath) }
}
}
-enum class Jdk(val folder : String) {
- JDK_11("jdk-11"),
- JDK_17("jdk-17"),
- JDK_20("jdk-20");
+enum class Jdk(val name : String, val folder : String) {
+ JDK_8("jdk8", "jdk8"),
+ JDK_9("jdk9", "openjdk-9.0.4"),
+ JDK_11("jdk11", "jdk-11"),
+ JDK_17("jdk17", "jdk-17"),
+ JDK_20("jdk20", "jdk-20");
+
+ fun isJdk8() : Boolean {
+ return this == JDK_8
+ }
+
+ fun getThirdPartyDependency() : ThirdPartyDependency {
+ val os: OperatingSystem = DefaultNativePlatform.getCurrentOperatingSystem()
+ val subFolder : String
+ val fileName : String
+ if (os.isLinux) {
+ subFolder = if(isJdk8()) "linux-x86" else "linux"
+ fileName = "java"
+ } else if (os.isMacOsX) {
+ subFolder = if(isJdk8()) "darwin-x86" else "osx"
+ fileName = "java"
+ } else {
+ assert(os.isWindows())
+ if (isJdk8()) {
+ throw RuntimeException("No Jdk8 on Windows")
+ }
+ subFolder = "windows"
+ fileName = "java.bat"
+ }
+ return ThirdPartyDependency(
+ name,
+ Paths.get("third_party", "openjdk", folder, subFolder, "bin", fileName).toFile(),
+ Paths.get("third_party", "openjdk", folder, "$subFolder.tar.gz.sha1").toFile())
+ }
}
fun Project.getRoot() : File {
@@ -43,6 +75,27 @@
return "****** ${title} ******"
}
+fun Project.ensureThirdPartyDependencies(name : String, deps : List<ThirdPartyDependency>) : Task {
+ val outputFiles : MutableList<File> = mutableListOf()
+ val depsTasks = deps.map({
+ tasks.register<DownloadDependencyTask>("download-third-party-${it.packageName}") {
+ setDependency(
+ it.packageName,
+ getRoot().resolve(it.sha1File),
+ getRoot().resolve(it.path).parentFile,
+ it.type)
+ outputFiles.add(it.path)
+ }})
+ return tasks.register("ensure-third-party-$name") {
+ dependsOn(depsTasks)
+ outputs.files(outputFiles)
+ }.get()
+}
+
+fun Project.resolve(thirdPartyDependency: ThirdPartyDependency) : ConfigurableFileCollection {
+ return files(project.getRoot().resolve(thirdPartyDependency.path))
+}
+
/**
* When using composite builds, referecing tasks in other projects do not give a Task but a
* TaskReference. To get outputs from other tasks we need to have a proper task and gradle do not
@@ -83,11 +136,12 @@
}
fun Project.baseCompilerCommandLine(
- jar : File, deps : File, compiler : String, args : List<String> = listOf()) : List<String> {
+ jar: File, deps: File, compiler: String, args: List<String> = listOf(),
+) : List<String> {
// Execute r8 commands against a stable r8 with dependencies.
// TODO(b/139725780): See if we can remove or lower the heap size (-Xmx8g).
return listOf(
- "${getJavaPath(Jdk.JDK_17)}",
+ getJavaPath(Jdk.JDK_17),
"-Xmx8g",
"-ea",
"-cp",
@@ -97,11 +151,12 @@
}
fun Project.baseCompilerCommandLine(
- jar : File, compiler : String, args : List<String> = listOf()) : List<String> {
+ jar: File, compiler: String, args: List<String> = listOf(),
+) : List<String> {
// Execute r8 commands against a stable r8 with dependencies.
// TODO(b/139725780): See if we can remove or lower the heap size (-Xmx8g).
return listOf(
- "${getJavaPath(Jdk.JDK_17)}",
+ getJavaPath(Jdk.JDK_17),
"-Xmx8g",
"-ea",
"-cp",
@@ -111,14 +166,14 @@
}
fun Project.createR8LibCommandLine(
- r8Compiler : File,
- input : File,
+ r8Compiler: File,
+ input: File,
output: File,
- pgConf : List<File>,
- excludingDepsVariant : Boolean,
- lib : List<File> = listOf(),
- classpath : List<File> = listOf(),
- args : List<String> = listOf()) : List<String> {
+ pgConf: List<File>,
+ excludingDepsVariant: Boolean,
+ lib: List<File> = listOf(),
+ classpath: List<File> = listOf()
+) : List<String> {
val pgList = pgConf.flatMap({ listOf("--pg-conf", "$it") })
val libList = lib.flatMap({ listOf("--lib", "$it") })
val cpList = classpath.flatMap({ listOf("--classpath", "$it") })
@@ -142,15 +197,15 @@
object Versions {
const val asmVersion = "9.5"
+ const val errorproneVersion = "2.18.0"
const val fastUtilVersion = "7.2.1"
const val gsonVersion = "2.7"
const val guavaVersion = "31.1-jre"
+ const val javassist = "3.29.2-GA"
const val junitVersion = "4.13-beta-2"
const val kotlinVersion = "1.8.10"
const val kotlinMetadataVersion = "0.6.2"
const val smaliVersion = "3.0.3"
- const val errorproneVersion = "2.18.0"
- const val javassist = "3.29.2-GA"
}
object Deps {
@@ -169,3 +224,104 @@
val smali by lazy { "com.android.tools.smali:smali:${Versions.smaliVersion}" }
val errorprone by lazy { "com.google.errorprone:error_prone_core:${Versions.errorproneVersion}" }
}
+
+object ThirdPartyDeps {
+ val apiDatabase = ThirdPartyDependency(
+ "apiDatabase",
+ Paths.get(
+ "third_party",
+ "api_database",
+ "api_database",
+ "resources",
+ "new_api_database.ser").toFile(),
+ Paths.get("third_party", "api_database", "api_database.tar.gz.sha1").toFile())
+ val ddmLib = ThirdPartyDependency(
+ "ddmlib",
+ Paths.get("third_party", "ddmlib", "ddmlib.jar").toFile(),
+ Paths.get("third_party", "ddmlib.tar.gz.sha1").toFile())
+ val jasmin = ThirdPartyDependency(
+ "jasmin",
+ Paths.get("third_party", "jasmin", "jasmin-2.4.jar").toFile(),
+ Paths.get("third_party", "jasmin.tar.gz.sha1").toFile())
+ val jdwpTests = ThirdPartyDependency(
+ "jdwp-tests",
+ Paths.get("third_party", "jdwp-tests", "apache-harmony-jdwp-tests-host.jar").toFile(),
+ Paths.get("third_party", "jdwp-tests.tar.gz.sha1").toFile())
+ val androidJars : List<ThirdPartyDependency> = getThirdPartyAndroidJars()
+ val java8Runtime = ThirdPartyDependency(
+ "openjdk-rt-1.8",
+ Paths.get("third_party", "openjdk", "openjdk-rt-1.8", "rt.jar").toFile(),
+ Paths.get("third_party", "openjdk", "openjdk-rt-1.8.tar.gz.sha1").toFile()
+ )
+ val androidVMs : List<ThirdPartyDependency> = getThirdPartyAndroidVms()
+ val jdks : List<ThirdPartyDependency> = getJdks()
+}
+
+fun getThirdPartyAndroidJars() : List<ThirdPartyDependency> {
+ return listOf(
+ "libcore_latest",
+ "lib-master",
+ "lib-v14",
+ "lib-v15",
+ "lib-v19",
+ "lib-v21",
+ "lib-v22",
+ "lib-v23",
+ "lib-v24",
+ "lib-v25",
+ "lib-v26",
+ "lib-v27",
+ "lib-v28",
+ "lib-v29",
+ "lib-v30",
+ "lib-v31",
+ "lib-v32",
+ "lib-v33",
+ "lib-v34"
+ ).map(::getThirdPartyAndroidJar)
+}
+
+fun getThirdPartyAndroidJar(version : String) : ThirdPartyDependency {
+ return ThirdPartyDependency(
+ version,
+ Paths.get("third_party", "android_jar", version, "android.jar").toFile(),
+ Paths.get("third_party", "android_jar", "$version.tar.gz.sha1").toFile())
+}
+
+fun getThirdPartyAndroidVms() : List<ThirdPartyDependency> {
+ return listOf(
+ listOf("host", "art-master"),
+ listOf("host", "art-14.0.0-dp1"),
+ listOf("host", "art-13.0.0"),
+ listOf("host", "art-12.0.0-beta4"),
+ listOf("art-10.0.0"),
+ listOf("art-5.1.1"),
+ listOf("art-6.0.1"),
+ listOf("art-7.0.0"),
+ listOf("art-8.1.0"),
+ listOf("art-9.0.0"),
+ listOf("art"),
+ listOf("dalvik-4.0.4"),
+ listOf("dalvik")).map(::getThirdPartyAndroidVm)
+}
+
+fun getThirdPartyAndroidVm(version : List<String>) : ThirdPartyDependency {
+ val output = Paths.get("tools", "linux", *version.toTypedArray(), "bin", "art").toFile()
+ return ThirdPartyDependency(
+ version.last(),
+ output,
+ Paths.get(
+ "tools",
+ "linux",
+ *version.slice(0..version.size - 2).toTypedArray(),
+ "${version.last()}.tar.gz.sha1").toFile())
+}
+
+fun getJdks() : List<ThirdPartyDependency> {
+ val os: OperatingSystem = DefaultNativePlatform.getCurrentOperatingSystem()
+ if (os.isLinux || os.isMacOsX) {
+ return Jdk.values().map{ it.getThirdPartyDependency()}
+ } else {
+ return Jdk.values().filter{ !it.isJdk8() }.map{ it.getThirdPartyDependency()}
+ }
+}
\ No newline at end of file
diff --git a/d8_r8/commonBuildSrc/src/main/kotlin/DownloadDependencyTask.kt b/d8_r8/commonBuildSrc/src/main/kotlin/DownloadDependencyTask.kt
new file mode 100644
index 0000000..24185c6
--- /dev/null
+++ b/d8_r8/commonBuildSrc/src/main/kotlin/DownloadDependencyTask.kt
@@ -0,0 +1,143 @@
+// Copyright (c) 2023, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import java.io.BufferedReader
+import java.io.File
+import java.io.IOException
+import java.io.InputStreamReader
+import java.nio.charset.StandardCharsets
+import java.util.Arrays
+import java.util.stream.Collectors
+import javax.inject.Inject
+import org.gradle.api.DefaultTask
+import org.gradle.api.file.RegularFileProperty
+import org.gradle.api.provider.Property
+import org.gradle.api.tasks.OutputDirectory
+import org.gradle.api.tasks.TaskAction
+import org.gradle.api.tasks.options.Option
+import org.gradle.internal.os.OperatingSystem
+import org.gradle.workers.WorkAction
+import org.gradle.workers.WorkParameters
+import org.gradle.workers.WorkerExecutor
+
+abstract class DownloadDependencyTask : DefaultTask() {
+
+ private var dependencyType: DependencyType = DependencyType.GOOGLE_STORAGE
+ private var _outputDir: File? = null
+ private var _tarGzFile: File? = null
+ private var _sha1File: File? = null
+
+ @OutputDirectory
+ fun getOutputDir(): File? {
+ return _outputDir
+ }
+
+ @Inject
+ protected abstract fun getWorkerExecutor(): WorkerExecutor?
+
+ @Option(
+ option = "dependency",
+ description = "Sets the dependency information for a cloud stored file")
+ fun setDependency(
+ dependencyName : String, sha1File: File, outputDir : File, dependencyType: DependencyType) {
+ _outputDir = outputDir
+ _sha1File = sha1File
+ _tarGzFile = sha1File.resolveSibling(sha1File.name.replace(".sha1", ""))
+ this.dependencyType = dependencyType
+ }
+
+ @TaskAction
+ fun execute() {
+ val sha1File = _sha1File!!
+ val outputDir = _outputDir!!
+ val tarGzFile = _tarGzFile!!
+ if (!sha1File.exists()) {
+ throw RuntimeException("Missing sha1 file: $sha1File")
+ }
+ // First run will write the tar.gz file, causing the second run to still be out-of-date.
+ // Check if the modification time of the tar is newer than the sha in which case we are done.
+ // Also, check the contents of the out directory because gradle appears to create it for us...
+ if (outputDir.exists()
+ && outputDir.isDirectory
+ && outputDir.list().isNotEmpty() && tarGzFile.exists()
+ && sha1File.lastModified() <= tarGzFile.lastModified()) {
+ return
+ }
+ if (outputDir.exists() && outputDir.isDirectory) {
+ outputDir.delete()
+ }
+ getWorkerExecutor()!!
+ .noIsolation()
+ .submit(RunDownload::class.java) {
+ this.type.set(dependencyType)
+ this.sha1File.set(sha1File)
+ }
+ }
+
+
+ interface RunDownloadParameters : WorkParameters {
+ val type : Property<DependencyType>
+ val sha1File : RegularFileProperty
+ }
+
+ abstract class RunDownload : WorkAction<RunDownloadParameters> {
+ override fun execute() {
+ try {
+ val parameters: RunDownloadParameters = parameters
+ val type: DependencyType = parameters.type.get()
+ val sha1File: File = parameters.sha1File.asFile.get()
+ if (type == DependencyType.GOOGLE_STORAGE) {
+ downloadFromGoogleStorage(sha1File)
+ } else if (type == DependencyType.X20) {
+ downloadFromX20(sha1File)
+ } else {
+ throw RuntimeException("Unexpected or missing dependency type: $type")
+ }
+ } catch (e: Exception) {
+ throw RuntimeException(e)
+ }
+ }
+
+ @Throws(IOException::class, InterruptedException::class)
+ private fun downloadFromGoogleStorage(sha1File: File) {
+ val args = Arrays.asList("-n", "-b", "r8-deps", "-s", "-u", sha1File.toString())
+ if (OperatingSystem.current().isWindows) {
+ val command: MutableList<String> = ArrayList()
+ command.add("download_from_google_storage.bat")
+ command.addAll(args)
+ runProcess(ProcessBuilder().command(command))
+ } else {
+ runProcess(
+ ProcessBuilder()
+ .command("bash",
+ "-c",
+ "download_from_google_storage " + java.lang.String.join(" ", args)))
+ }
+ }
+
+ @Throws(IOException::class, InterruptedException::class)
+ private fun downloadFromX20(sha1File: File) {
+ if (OperatingSystem.current().isWindows) {
+ throw RuntimeException("Downloading from x20 unsupported on windows")
+ }
+ runProcess(
+ ProcessBuilder()
+ .command("bash", "-c", "tools/download_from_x20.py $sha1File"))
+ }
+
+ @Throws(IOException::class, InterruptedException::class)
+ private fun runProcess(builder: ProcessBuilder) {
+ val command = java.lang.String.join(" ", builder.command())
+ val p = builder.start()
+ val exit = p.waitFor()
+ if (exit != 0) {
+ throw IOException("Process failed for $command\n"
+ + BufferedReader(
+ InputStreamReader(p.errorStream, StandardCharsets.UTF_8))
+ .lines()
+ .collect(Collectors.joining("\n")))
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/d8_r8/commonBuildSrc/src/main/kotlin/ThirdPartyDependency.kt b/d8_r8/commonBuildSrc/src/main/kotlin/ThirdPartyDependency.kt
new file mode 100644
index 0000000..510892d
--- /dev/null
+++ b/d8_r8/commonBuildSrc/src/main/kotlin/ThirdPartyDependency.kt
@@ -0,0 +1,16 @@
+// Copyright (c) 2023, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import java.io.File
+
+enum class DependencyType {
+ GOOGLE_STORAGE,
+ X20
+}
+
+data class ThirdPartyDependency(
+ val packageName : String,
+ val path : File,
+ val sha1File : File,
+ val type: DependencyType = DependencyType.GOOGLE_STORAGE)
diff --git a/d8_r8/main/build.gradle.kts b/d8_r8/main/build.gradle.kts
index 34a1c14..681c7c3 100644
--- a/d8_r8/main/build.gradle.kts
+++ b/d8_r8/main/build.gradle.kts
@@ -23,8 +23,8 @@
dependencies {
implementation(":keepanno")
compileOnly(Deps.asm)
- compileOnly(Deps.asmUtil)
compileOnly(Deps.asmCommons)
+ compileOnly(Deps.asmUtil)
compileOnly(Deps.fastUtil)
compileOnly(Deps.gson)
compileOnly(Deps.guava)
@@ -32,6 +32,10 @@
errorprone(Deps.errorprone)
}
+val thirdPartyResourceDependenciesTask = ensureThirdPartyDependencies(
+ "resourceDeps",
+ listOf(ThirdPartyDeps.apiDatabase))
+
val keepAnnoJarTask = projectTask("keepanno", "jar")
fun mainJarDependencies() : FileCollection {
@@ -52,6 +56,10 @@
}
}
+ withType<ProcessResources> {
+ dependsOn(thirdPartyResourceDependenciesTask)
+ }
+
val swissArmyKnife by registering(Jar::class) {
from(sourceSets.main.get().output)
manifest {
diff --git a/d8_r8/settings.gradle.kts b/d8_r8/settings.gradle.kts
index 70bb38b..402137e 100644
--- a/d8_r8/settings.gradle.kts
+++ b/d8_r8/settings.gradle.kts
@@ -29,7 +29,7 @@
)
println("Executing command: ${cmd.joinToString(" ")}")
var process = ProcessBuilder().command(cmd).start()
- process.waitFor(5, java.util.concurrent.TimeUnit.SECONDS)
+ process.waitFor()
if (process.exitValue() != 0) {
throw GradleException(
"Bootstrapping dependencies_new download failed:\n"
diff --git a/d8_r8/test_modules/tests_java_8/build.gradle.kts b/d8_r8/test_modules/tests_java_8/build.gradle.kts
index 55ee7a8..28f5076 100644
--- a/d8_r8/test_modules/tests_java_8/build.gradle.kts
+++ b/d8_r8/test_modules/tests_java_8/build.gradle.kts
@@ -29,6 +29,8 @@
implementation(projectTask("keepanno", "jar").outputs.files)
implementation(projectTask("main", "jar").outputs.files)
implementation(Deps.asm)
+ implementation(Deps.asmCommons)
+ implementation(Deps.asmUtil)
implementation(Deps.gson)
implementation(Deps.guava)
implementation(Deps.javassist)
@@ -36,16 +38,28 @@
implementation(Deps.kotlinStdLib)
implementation(Deps.kotlinReflect)
implementation(Deps.kotlinMetadata)
- implementation(files(root.resolveAll("third_party", "ddmlib", "ddmlib.jar")))
- implementation(
- files(
- root.resolveAll("third_party", "jdwp-tests", "apache-harmony-jdwp-tests-host.jar")))
- implementation(files(root.resolveAll("third_party", "jasmin", "jasmin-2.4.jar")))
+ implementation(resolve(ThirdPartyDeps.ddmLib))
+ implementation(resolve(ThirdPartyDeps.jasmin))
+ implementation(resolve(ThirdPartyDeps.jdwpTests))
implementation(Deps.fastUtil)
implementation(Deps.smali)
- implementation(Deps.asmUtil)
}
+val thirdPartyCompileDependenciesTask = ensureThirdPartyDependencies(
+ "compileDeps",
+ listOf(
+ ThirdPartyDeps.apiDatabase,
+ ThirdPartyDeps.ddmLib,
+ ThirdPartyDeps.jasmin,
+ ThirdPartyDeps.jdwpTests))
+
+val thirdPartyRuntimeDependenciesTask = ensureThirdPartyDependencies(
+ "runtimeDeps",
+ listOf(ThirdPartyDeps.java8Runtime)
+ + ThirdPartyDeps.androidJars
+ + ThirdPartyDeps.androidVMs
+ + ThirdPartyDeps.jdks)
+
fun testDependencies() : FileCollection {
return sourceSets
.test
@@ -62,6 +76,7 @@
withType<JavaCompile> {
dependsOn(gradle.includedBuild("keepanno").task(":jar"))
dependsOn(gradle.includedBuild("main").task(":jar"))
+ dependsOn(thirdPartyCompileDependenciesTask)
options.setFork(true)
options.forkOptions.memoryMaximumSize = "3g"
options.forkOptions.jvmArgs = listOf(
@@ -73,6 +88,7 @@
withType<KotlinCompile> {
dependsOn(gradle.includedBuild("keepanno").task(":jar"))
dependsOn(gradle.includedBuild("main").task(":jar"))
+ dependsOn(thirdPartyCompileDependenciesTask)
kotlinOptions {
// We cannot use languageVersion.set(JavaLanguageVersion.of(8)) because gradle cannot figure
// out that the jdk is 1_8 and will try to download it.
@@ -80,12 +96,32 @@
}
}
+ withType<Test> {
+ dependsOn(thirdPartyRuntimeDependenciesTask)
+ println("NOTE: Number of processors " + Runtime.getRuntime().availableProcessors())
+ val userDefinedCoresPerFork = System.getenv("R8_GRADLE_CORES_PER_FORK")
+ val processors = Runtime.getRuntime().availableProcessors()
+ // See https://docs.gradle.org/current/dsl/org.gradle.api.tasks.testing.Test.html.
+ if (!userDefinedCoresPerFork.isNullOrEmpty()) {
+ maxParallelForks = userDefinedCoresPerFork.toInt()
+ } else {
+ // On normal work machines this seems to give the best test execution time (without freezing)
+ maxParallelForks = processors / 3
+ // On low cpu count machines (bots) we under subscribe, so increase the count.
+ if (processors == 8) {
+ maxParallelForks = 3
+ }
+ }
+ println("NOTE: Max parallel forks " + maxParallelForks)
+ }
+
val testJar by registering(Jar::class) {
from(sourceSets.test.get().output)
}
val depsJar by registering(Jar::class) {
dependsOn(gradle.includedBuild("keepanno").task(":jar"))
+ dependsOn(thirdPartyCompileDependenciesTask)
println(header("Test Java 8 dependencies"))
testDependencies().forEach({ println(it) })
from(testDependencies().map(::zipTree))
diff --git a/src/test/java/com/android/tools/r8/ToolHelper.java b/src/test/java/com/android/tools/r8/ToolHelper.java
index 069acbf..30ea8e0 100644
--- a/src/test/java/com/android/tools/r8/ToolHelper.java
+++ b/src/test/java/com/android/tools/r8/ToolHelper.java
@@ -101,11 +101,14 @@
}
public static String getProjectRoot() {
- String userDirProperty = System.getProperty("user.dir");
- if (userDirProperty.endsWith("d8_r8/test")) {
- return Paths.get(userDirProperty).getParent().getParent().toString() + "/";
+ String current = System.getProperty("user.dir");
+ if (!current.contains("test_modules")) {
+ return "";
}
- return "";
+ while (current.contains("test_modules")) {
+ current = Paths.get(current).getParent().toString();
+ }
+ return Paths.get(current).getParent().toString() + "/";
}
public static final String SOURCE_DIR = "src/main/java/";
@@ -972,7 +975,7 @@
}
if (isLinux() || isMac()) {
// The Linux version is used on Mac, where it is run in a Docker container.
- return TOOLS_DIR + "/linux/" + dir;
+ return TOOLS_DIR + "linux/" + dir;
}
fail("Unsupported platform, we currently only support mac and linux: " + getPlatform());
return ""; //never here