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