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