JAL-3224 Removed JREs (these now need to be in ~/buildtools/jre/openjdk-java_vm/...
[jalview.git] / build.gradle
1 import org.apache.tools.ant.filters.ReplaceTokens
2 import org.gradle.internal.os.OperatingSystem
3
4 buildscript {
5   dependencies {
6         classpath 'org.openclover:clover:4.3.1'
7         classpath 'org.apache.commons:commons-compress:1.18'
8   }
9 }
10
11 plugins {
12   id 'java'
13   id 'application'
14   id 'com.github.johnrengelman.shadow' version '4.0.3'
15   id 'com.install4j.gradle' version '7.0.9'
16 }
17
18 repositories {
19   jcenter()
20   mavenCentral()
21   mavenLocal()
22   flatDir {
23     dirs gradlePluginsDir
24   }
25 }
26
27 mainClassName = launcherClass
28 def cloverInstrDir = file("$buildDir/$cloverSourcesInstrDir")
29 def classes = "$jalviewDir/$classesDir"
30 if (clover.equals("true")) {
31   clover = true
32   classes = "$buildDir/$cloverClassesDir"
33 } else {
34   clover = false
35   classes = "$jalviewDir/$classesDir"
36 }
37
38 def libDir
39 def libDistDir
40 def compile_source_compatibility
41 def compile_target_compatibility
42 def additional_compiler_args = []
43 def getdown_alt_java_min_version
44 if (JAVA_VERSION.equals("1.8")) {
45   libDir = j11libDir
46   libDistDir = j8libDir
47   compile_source_compatibility = 1.8
48   compile_target_compatibility = 1.8
49   getdown_alt_java_min_version = getdown_alt_java8_min_version
50 } else if (JAVA_VERSION.equals("11")) {
51   libDir = j11libDir
52   libDistDir = j11libDir
53   compile_source_compatibility = 11
54   compile_target_compatibility = 11
55   getdown_alt_java_min_version = getdown_alt_java11_min_version
56   additional_compiler_args += [
57     '--module-path', sourceSets.modules.compileClasspath.asPath,
58     '--add-modules', j11modules
59   ]
60 } else {
61   throw new GradleException("JAVA_VERSION=$JAVA_VERSION not currently supported by Jalview")
62 }
63
64 sourceSets {
65
66   main {
67     java {
68       srcDirs "$jalviewDir/$sourceDir"
69       outputDir = file("$classes")
70     }
71
72     resources {
73       srcDirs "$jalviewDir/$resourceDir"
74       srcDirs "$jalviewDir/$libDir"
75     }
76
77     jar.destinationDir = file("$jalviewDir/$packageDir")
78
79     compileClasspath = files(sourceSets.main.java.outputDir)
80     compileClasspath += fileTree(dir: "$jalviewDir/$libDir", include: ["*.jar"])
81
82     runtimeClasspath = compileClasspath
83   }
84
85   modules {
86     compileClasspath = fileTree(dir: "$jalviewDir/$j11modDir", include: ["*.jar"])
87
88     runtimeClasspath = compileClasspath
89   }
90   
91   clover {
92     java {
93         srcDirs = [ cloverInstrDir ]
94         outputDir = file("${buildDir}/${cloverClassesDir}")
95     }
96     
97     resources {
98       srcDirs = sourceSets.main.resources.srcDirs
99     }
100     compileClasspath = configurations.cloverRuntime + files( sourceSets.clover.java.outputDir )
101     compileClasspath += fileTree(dir: "$jalviewDir/$utilsDir", include: ["**/*.jar"])
102     compileClasspath += fileTree(dir: "$jalviewDir/$libDir", include: ["*.jar"])
103
104     runtimeClasspath = compileClasspath
105   }
106   
107   test {
108     java {
109       srcDirs "$jalviewDir/$testSourceDir"
110       outputDir = file("$jalviewDir/$testOutputDir")
111     }
112
113     resources {
114       srcDirs = sourceSets.main.resources.srcDirs
115     }
116
117     compileClasspath = files( sourceSets.test.java.outputDir ) 
118     if (clover) {
119       compileClasspath += sourceSets.clover.compileClasspath
120     } else {
121       compileClasspath += sourceSets.main.compileClasspath
122     }
123     compileClasspath += files( sourceSets.main.resources.srcDirs)
124     compileClasspath += fileTree(dir: "$jalviewDir/$utilsDir", include: ["**/*.jar"])
125     compileClasspath += fileTree(dir: "$jalviewDir/$libDir", include: ["*.jar"])
126
127     runtimeClasspath = compileClasspath
128   }
129 }
130
131 // clover bits
132 dependencies {
133   if (clover) {
134     cloverCompile 'org.openclover:clover:4.3.1'
135     testCompile 'org.openclover:clover:4.3.1'
136   }
137 }
138
139 configurations {
140     cloverRuntime
141     cloverRuntime.extendsFrom cloverCompile
142 }
143  
144 task cloverInstr() {
145   // only instrument source, we build test classes as normal
146     inputs.files files (sourceSets.main.allJava) // , fileTree(dir:"$jalviewDir/$testSourceDir", include: ["**/*.java"]))
147     outputs.dir cloverInstrDir
148
149     doFirst {
150         delete cloverInstrDir
151         def argsList = ["--initstring", "${buildDir}/clover/clover.db",
152                         "-d", "${buildDir}/${cloverSourcesInstrDir}"]
153         argsList.addAll(inputs.files.files.collect({ file ->
154             file.absolutePath
155         }))
156         String[] args = argsList.toArray()
157         println("About to instrument "+args.length +" files")
158         com.atlassian.clover.CloverInstr.mainImpl(args)
159     }
160 }
161
162  
163 task cloverReport {
164     inputs.dir "${buildDir}/clover"
165     outputs.dir "${reportsDir}/clover"
166     onlyIf {
167         file("${buildDir}/clover/clover.db").exists()
168     }
169     doFirst {
170         def argsList = ["--initstring", "${buildDir}/clover/clover.db",
171                         "-o", "${reportsDir}/clover"]
172         String[] args = argsList.toArray()
173         com.atlassian.clover.reporters.html.HtmlReporter.runReport(args)
174         
175         // and generate ${reportsDir}/clover/clover.xml
176         args = ["--initstring", "${buildDir}/clover/clover.db",
177                         "-o", "${reportsDir}/clover/clover.xml"].toArray()
178         com.atlassian.clover.reporters.xml.XMLReporter.runReport(args)
179     }
180 }
181
182 // end clover bits
183
184
185 compileJava {
186
187   doFirst {
188     sourceCompatibility = compile_source_compatibility
189     targetCompatibility = compile_target_compatibility
190     options.compilerArgs = additional_compiler_args
191     print ("Setting target compatibility to "+targetCompatibility+"\n")
192   }
193
194 }
195
196 compileTestJava {
197   if (clover) {
198     dependsOn compileCloverJava
199     classpath += configurations.cloverRuntime
200   }
201   doFirst {
202     sourceCompatibility = compile_source_compatibility
203     targetCompatibility = compile_target_compatibility
204     options.compilerArgs = additional_compiler_args
205     print ("Setting target compatibility to "+targetCompatibility+"\n")
206   }
207 }
208
209
210 compileCloverJava {
211
212   doFirst {
213     sourceCompatibility = compile_source_compatibility
214     targetCompatibility = compile_target_compatibility
215     options.compilerArgs += additional_compiler_args
216     print ("Setting target compatibility to "+targetCompatibility+"\n")
217   }
218   classpath += configurations.cloverRuntime
219 }
220
221 clean {
222   delete sourceSets.main.java.outputDir
223 }
224
225 cleanTest {
226   delete sourceSets.test.java.outputDir
227   delete cloverInstrDir
228 }
229
230 def getDate(format) {
231   def date = new Date()
232   //return date.format("dd MMMM yyyy")
233   return date.format(format)
234 }
235
236 def getGitHash() {
237   def stdout = new ByteArrayOutputStream()
238   exec {
239     commandLine "git", "rev-parse", "--short", "HEAD"
240     standardOutput = stdout
241     workingDir = jalviewDir
242   }
243   return stdout.toString().trim()
244 }
245
246 def getGitBranch() {
247   def stdout = new ByteArrayOutputStream()
248   exec {
249     commandLine "git", "rev-parse", "--abbrev-ref", "HEAD"
250     standardOutput = stdout
251     workingDir = jalviewDir
252   }
253   return stdout.toString().trim()
254 }
255
256 task createBuildProperties(type: WriteProperties) {
257   inputs.dir("$jalviewDir/$sourceDir")
258   inputs.dir("$jalviewDir/$resourceDir")
259   outputFile "$classes/$buildPropertiesFile"
260   /* taking time/date specific comment out to allow better incremental builds */
261   //comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd HH:mm:ss")
262   comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd")
263   property "BUILD_DATE", getDate("dd MMMM yyyy")
264   property "VERSION", JALVIEW_VERSION
265   property "INSTALLATION", INSTALLATION+" git-commit:"+getGitHash()+" ["+getGitBranch()+"]"
266   outputs.file(outputFile)
267   outputs.dir("$classes")
268 }
269
270 task syncDocs(type: Sync) {
271   def syncDir = "$classes/$docDir"
272   from fileTree("$jalviewDir/$docDir")
273   into syncDir
274
275 }
276
277 def helpFile = "$classes/$helpDir/help.jhm"
278 task syncHelp(type: Sync) {
279   inputs.files("$jalviewDir/$helpDir")
280   outputs.files(helpFile)
281
282   def syncDir = "$classes/$helpDir"
283   from fileTree("$jalviewDir/$helpDir")
284   into syncDir
285 }
286
287 task copyHelp(type: Copy) {
288   def inputDir = "$jalviewDir/$helpDir"
289   def outputDir = "$classes/$helpDir"
290   from inputDir
291   into outputDir
292   filter(ReplaceTokens, beginToken: '$$', endToken: '$$', tokens: ['Version-Rel': "USING_FILTER"])
293   inputs.dir(inputDir)
294   outputs.files(helpFile)
295   outputs.dir(outputDir)
296 }
297
298 task syncLib(type: Sync) {
299   def syncDir = "$classes/$libDir"
300   from fileTree("$jalviewDir/$libDir")
301   into syncDir
302 }
303
304 task syncResources(type: Sync) {
305   from "$jalviewDir/$resourceDir"
306   include "**/*.*"
307   exclude "install4j"
308   into "$classes"
309   preserve {
310     include "**"
311   }
312 }
313
314 task prepare {
315   dependsOn syncResources
316   dependsOn syncDocs
317   dependsOn copyHelp
318 }
319
320
321 //testReportDirName = "test-reports" // note that test workingDir will be $jalviewDir
322 test {
323   dependsOn prepare
324   if (clover) {
325     dependsOn cloverInstr
326   }
327   print("Running tests " + (clover?"WITH":"WITHOUT") + " clover [clover="+clover+"]\n") 
328   
329   useTestNG() {
330     includeGroups testngGroups
331     preserveOrder true
332     useDefaultListeners=true
333   }
334   
335   workingDir = jalviewDir
336   //systemProperties 'clover.jar' System.properties.clover.jar
337   sourceCompatibility = compile_source_compatibility
338   targetCompatibility = compile_target_compatibility
339   jvmArgs += additional_compiler_args
340   print ("Setting target compatibility to "+targetCompatibility+"\n")
341 }
342
343 task buildIndices(type: JavaExec) {
344   dependsOn copyHelp
345   classpath = sourceSets.main.compileClasspath
346   main = "com.sun.java.help.search.Indexer"
347   workingDir = "$classes/$helpDir"
348   def argDir = "html"
349   args = [ argDir ]
350   inputs.dir("$workingDir/$argDir")
351
352   outputs.dir("$classes/doc")
353   outputs.dir("$classes/help")
354   outputs.file("$workingDir/JavaHelpSearch/DOCS")
355   outputs.file("$workingDir/JavaHelpSearch/DOCS.TAB")
356   outputs.file("$workingDir/JavaHelpSearch/OFFSETS")
357   outputs.file("$workingDir/JavaHelpSearch/POSITIONS")
358   outputs.file("$workingDir/JavaHelpSearch/SCHEMA")
359   outputs.file("$workingDir/JavaHelpSearch/TMAP")
360 }
361
362 task compileLinkCheck(type: JavaCompile) {
363   options.fork = true
364   classpath = files("$jalviewDir/$utilsDir")
365   destinationDir = file("$jalviewDir/$utilsDir")
366   source = fileTree(dir: "$jalviewDir/$utilsDir", include: ["HelpLinksChecker.java", "BufferedLineReader.java"])
367
368   outputs.file("$jalviewDir/$utilsDir/HelpLinksChecker.class")
369   outputs.file("$jalviewDir/$utilsDir/BufferedLineReader.class")
370 }
371
372 task linkCheck(type: JavaExec) {
373   dependsOn prepare, compileLinkCheck
374   classpath = files("$jalviewDir/$utilsDir")
375   main = "HelpLinksChecker"
376   workingDir = jalviewDir
377   def help = "$classes/$helpDir"
378   args = [ "$classes/$helpDir", "-nointernet" ]
379   //args = [ "$classesDir/$helpDir", "-nointernet" ]
380
381   doFirst {
382     standardOutput new FileOutputStream("$jalviewDir/$utilsDir/HelpLinksChecker.out")
383   }
384
385   outputs.file("$jalviewDir/$utilsDir/HelpLinksChecker.out")
386 }
387
388 task cleanPackageDir(type: Delete) {
389   delete fileTree("$jalviewDir/$packageDir").include("*.jar")
390 }
391
392 jar {
393   dependsOn linkCheck
394   dependsOn buildIndices
395   dependsOn createBuildProperties
396
397   manifest {
398     attributes "Main-Class": mainClass,
399     "Permissions": "all-permissions",
400     "Application-Name": "Jalview Desktop",
401     "Codebase": application_codebase
402   }
403
404   destinationDir = file("$jalviewDir/$packageDir")
405   archiveName = rootProject.name+".jar"
406
407   exclude "cache*/**"
408   exclude "*.jar"
409   exclude "*.jar.*"
410   exclude "**/*.jar"
411   exclude "**/*.jar.*"
412
413   inputs.dir("$classes")
414   outputs.file("$jalviewDir/$packageDir/$archiveName")
415 }
416
417 task copyJars(type: Copy) {
418   from fileTree("$classes").include("**/*.jar").include("*.jar").files
419   into "$jalviewDir/$packageDir"
420 }
421
422 // doing a Sync instead of Copy as Copy doesn't deal with "outputs" very well
423 task syncJars(type: Sync) {
424   from fileTree("$jalviewDir/$libDir").include("**/*.jar").include("*.jar").files
425   into "$jalviewDir/$packageDir"
426   preserve {
427     include jar.archiveName
428   }
429 }
430
431 task makeDist {
432   // order of "cleanPackageDir", "copyJars", "jar" important!
433   jar.mustRunAfter cleanPackageDir
434   syncJars.mustRunAfter cleanPackageDir
435   dependsOn cleanPackageDir
436   dependsOn syncJars
437   dependsOn jar
438   outputs.dir("$jalviewDir/$packageDir")
439 }
440
441 task cleanDist {
442   dependsOn cleanPackageDir
443   dependsOn cleanTest
444   dependsOn clean
445 }
446
447 shadowJar {
448   dependsOn makeDist
449   if (JAVA_VERSION.equals("11")) {
450     from ("$jalviewDir/$j11libDir") {
451       include("*.jar")
452     }
453   }
454   mainClassName = shadowJarMainClass
455   mergeServiceFiles()
456   classifier = "all"
457   minimize()
458 }
459
460 ext {
461   getdownWebsiteDir = jalviewDir + '/' + getdown_website_dir
462   getdownAppDir = getdownWebsiteDir + '/' + getdown_app_dir
463   getdownJ11libDir = getdownWebsiteDir + '/' + getdown_j11lib_dir
464   getdownResourceDir = getdownWebsiteDir + '/' + getdown_resource_dir
465   getdownLauncher = jalviewDir + '/' + getdown_launcher
466   getdownFilesDir = jalviewDir + '/' + getdown_files_dir
467   getdownLib1 = jalviewDir + '/' + getdown_lib1
468   def getdownChannel = getdown_channel_name
469   if (getdown_channel_name.equals("COMMIT")) {
470     getdownChannel = getGitHash()
471   }
472   getdown_app_base = getdown_channel_base+"/"+JAVA_VERSION+"/"+getdownChannel+"/"
473 }
474
475 task getdownWebsite() {
476   dependsOn makeDist
477   def getdownWebsiteResourceFilenames = []
478   def getdownTextString = ""
479   def getdownResourceDir = project.ext.getdownResourceDir
480   def getdownAppDir = project.ext.getdownAppDir
481   def getdownResourceFilenames = []
482   doFirst {
483     // go through properties looking for getdown_txt_...
484     def props = project.properties.sort { it.key }
485     props.put("getdown_txt_java_min_version", getdown_alt_java_min_version)
486     props.put("getdown_txt_appbase", getdown_app_base)
487     props.each{ prop, val ->
488       if (prop.startsWith("getdown_txt_") && val != null) {
489         if (prop.startsWith("getdown_txt_multi_")) {
490           def key = prop.substring(18)
491           val.split(",").each{ v ->
492             def line = key + " = " + v + "\n"
493             getdownTextString += line
494           }
495         } else {
496           // file values rationalised
497           if (val.indexOf('/') > -1) {
498             def r = null
499             if (val.indexOf('/') == 0) {
500               // absolute path
501               r = file(val)
502             } else if (val.indexOf('/') > 0) {
503               // relative path (relative to jalviewDir)
504               r = file( jalviewDir + '/' + val )
505             }
506             if (r.exists()) {
507               val = getdown_resource_dir + '/' + r.getName()
508               getdownWebsiteResourceFilenames += val
509               getdownResourceFilenames += r.getPath()
510             }
511           }
512           def line = prop.substring(12) + " = " + val + "\n"
513           getdownTextString += line
514         }
515       }
516     }
517
518     getdownWebsiteResourceFilenames.each{ filename ->
519       getdownTextString += "resource = "+filename+"\n"
520     }
521     getdownResourceFilenames.each{ filename ->
522       copy {
523         from filename
524         into project.ext.getdownResourceDir
525       }
526     }
527
528     def codeFiles = []
529     makeDist.outputs.files.each{ f ->
530       if (f.isDirectory()) {
531         def files = fileTree(dir: f, include: ["*"]).getFiles()
532         codeFiles += files
533       } else if (f.exists()) {
534         codeFiles += f
535       }
536     }
537     codeFiles.sort().each{f ->
538       def line = "code = " + getdown_app_dir + '/' + f.getName() + "\n"
539       getdownTextString += line
540       copy {
541         from f.getPath()
542         into project.ext.getdownAppDir
543       }
544     }
545
546     if (JAVA_VERSION.equals("11")) {
547       def j11libFiles = fileTree(dir: "$jalviewDir/$j11libDir", include: ["*.jar"]).getFiles()
548       j11libFiles.sort().each{f ->
549         def line = "code = " + getdown_j11lib_dir + '/' + f.getName() + "\n"
550         getdownTextString += line
551         copy {
552           from f.getPath()
553           into project.ext.getdownJ11libDir
554         }
555       }
556     }
557
558     getdownTextString += "code = " + file(getdownLauncher).getName() + "\n"
559     getdownTextString += "class = " + mainClass + "\n"
560
561     def getdown_txt = file(project.ext.getdownWebsiteDir + "/getdown.txt")
562     getdown_txt.write(getdownTextString)
563
564     copy {
565       from getdown_txt
566       into project.ext.getdownFilesDir
567     }
568
569     copy {
570       from getdownLauncher
571       into project.ext.getdownWebsiteDir
572     }
573
574     copy {
575       from getdownLauncher
576       into project.ext.getdownFilesDir
577     }
578
579     copy {
580       from getdownLib1
581       into project.ext.getdownFilesDir
582     }
583
584     copy {
585       from getdownLib1
586       into project.ext.getdownWebsiteDir
587     }
588
589     copy {
590       from jalviewDir + '/' + project.getProperty('getdown_txt_ui.background_image')
591       from jalviewDir + '/' + project.getProperty('getdown_txt_ui.error_background')
592       from jalviewDir + '/' + project.getProperty('getdown_txt_ui.progress_image')
593       from jalviewDir + '/' + project.getProperty('getdown_txt_ui.icon')
594       from jalviewDir + '/' + project.getProperty('getdown_txt_ui.mac_dock_icon')
595       into project.ext.getdownFilesDir + '/' + getdown_resource_dir 
596     }
597   }
598
599   inputs.dir(jalviewDir + '/' + packageDir)
600   outputs.dir(project.ext.getdownWebsiteDir)
601   outputs.dir(project.ext.getdownFilesDir)
602 }
603
604 task getdownDigest(type: JavaExec) {
605   dependsOn getdownWebsite
606   classpath = files(jalviewDir + '/' + getdown_core)
607   classpath file(jalviewDir + '/' + getdown_lib1)
608   main = "com.threerings.getdown.tools.Digester"
609   args project.ext.getdownWebsiteDir
610   outputs.file(project.ext.getdownWebsiteDir + '/' + "digest2.txt")
611 }
612
613 task getdown() {
614   dependsOn getdownDigest
615 }
616
617 clean {
618   delete project.ext.getdownWebsiteDir
619   delete project.ext.getdownFilesDir
620 }
621
622 install4j {
623   def install4jHomeDir = "/opt/install4j"
624   def hostname = "hostname".execute().text.trim()
625   if (hostname.equals("jv-bamboo")) {
626     install4jHomeDir = System.getProperty("user.home")+"/buildtools/install4j"
627   } else if (OperatingSystem.current().isMacOsX()) {
628     install4jHomeDir = '/Applications/install4j.app/Contents/Resources/app'
629     if (! file(install4jHomeDir).exists()) {
630       install4jHomeDir = System.getProperty("user.home")+install4jHomeDir
631     }
632   } else if (OperatingSystem.current().isLinux()) {
633     install4jHomeDir = System.getProperty("user.home")+"/buildtools/install4j"
634   }
635   installDir = file(install4jHomeDir)
636   mediaTypes = Arrays.asList(install4jMediaTypes.split(","))
637 }
638
639 def install4jConf
640 def macosJavaVMDir
641 def windowsJavaVMDir
642 task copyInstall4jTemplate(type: Copy) {
643   def install4jDir = "$jalviewDir/$install4jResourceDir"
644   def install4jConfFile = "jalview-installers-java"+JAVA_VERSION+".install4j"
645   macosJavaVMDir = System.env.HOME+"/buildtools/jre/openjdk-java_vm/macos-jre"+JAVA_VERSION+"/java_vm"
646   windowsJavaVMDir = System.env.HOME+"/buildtools/jre/openjdk-java_vm/windows-jre"+JAVA_VERSION+"/java_vm"
647   from (install4jDir) {
648     include install4jTemplate
649     rename (install4jTemplate, install4jConfFile)
650     filter(ReplaceTokens, beginToken: '', endToken: '', tokens: ['9999999999': JAVA_VERSION])
651     filter(ReplaceTokens, beginToken: '$$', endToken: '$$', tokens: ['VERSION': JALVIEW_VERSION, 'MACOS_JAVA_VM_DIR': macosJavaVMDir, 'WINDOWS_JAVA_VM_DIR': windowsJavaVMDir])
652   }
653   into install4jDir
654   install4jConf = "$install4jDir/$install4jConfFile"
655   inputs.files("$install4jDir/$install4jTemplate")
656   outputs.files(install4jConf)
657 }
658
659 task installers(type: com.install4j.gradle.Install4jTask) {
660   dependsOn getdown
661   dependsOn copyInstall4jTemplate
662   projectFile = install4jConf
663   variables = [majorVersion: version.substring(2, 11), build: 001]
664   destination = "$jalviewDir/$install4jBuildDir"
665   buildSelected = true
666   inputs.dir(project.ext.getdownWebsiteDir)
667   inputs.file(install4jConf)
668   inputs.dir(macosJavaVMDir)
669   inputs.dir(windowsJavaVMDir)
670   outputs.dir("$jalviewDir/$install4jBuildDir")
671 }
672
673 clean {
674   delete install4jConf
675 }