jeudi 5 novembre 2020

How can I run Gradle tests on a different machine without recompiling?

I am trying to set up a Windows test server to run the unit tests of a Java library project via SSH. The actual building happens on a Linux server.

As a consequence, I would like to be able to copy the pre-built project to the Windows machine and run .\gradlew.bat test on it without recompiling it. Since I’m copying the entire src and build folder, I was expecting Gradle to realise that the build artefacts are more recent than the sources, and thus to avoid recompilation.

However, Gradle does attempt to recompile the sources, and fails (there’s intentionally no JDK installed on the Windows machine, since I don’t want to build on the Windows machine):

> Task :compileJava FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':compileJava'.
> Could not find tools.jar. Please check that C:\Program Files\Java\jre1.8.0_251 contains a valid JDK installation.

(scp does not preserve timestamps when copying from Linux to Windows, but I verified that the timestamps of the files in the build directory are newer than that of the src directory.)

Next I tried removing the compileTestJava dependency from testClasses, but this is no longer supported as of Gradle 6 (and I don’t think this would have worked anyway, and it seems like hack).

So:

  • Why does Gradle think my project needs recompiling after copying it to a Windows machine, even thought the file modification timestamps seem ordered correctly (build is newer than src is newer than build.gradle)?
  • How can I ensure that Gradle does not attempt to rebuild up-to-date dependencies before running tests after copying the project to a different (Windows) machine?

Here’s my build.gradle file (it‘s really quite barebone):

version '1.0-SNAPSHOT'

apply plugin: 'java-library'

sourceCompatibility = 1.8
targetCompatibility = 1.8

compileJava.options.encoding = 'UTF-8'

repositories {
    mavenCentral()
}

sourceSets {
    main.java.srcDirs = ["src/main/java"]
    test.java.srcDirs = ["src/test/java"]
}

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.12'
}

test {
    testLogging {
        outputs.upToDateWhen {false}
        showStandardStreams = true
    }
}

Here’s how I kick off the build from the Linux server (copying the individual files/directories manually one after the other to ensure well-ordered timestamps makes no difference):

ssh test@win 'rmdir /Q /S Workspace\test' || :
ssh test@win 'mkdir Workspace\test'
scp -r build.gradle gradle gradlew.bat src build test@win:Workspace\\test
ssh test@win 'cd Workspace\test & .\gradlew.bat --no-daemon test'

Why not just install the JDK and build on the Windows server?
The Windows machine is resource-constrained (it’s also a VM). Furthermore, the build needs to happen anyway on the Linux server. I would really like to avoid a slow and redundant rebuild.
Why not test on the Linux server (using Wine)?
I tried that, but our Linux library uses some Win32 APIs (via cross-compiled JNI) which Wine doesn’t support, and which reproducibly lead to a hang.

Further notes:

Aucun commentaire:

Enregistrer un commentaire