1 import org.apache.tools.ant.filters.ReplaceTokens
2 import org.gradle.internal.os.OperatingSystem
3 import org.gradle.plugins.ide.internal.generator.PropertiesPersistableConfigurationObject
4 import org.gradle.api.internal.PropertiesTransformer
5 import org.gradle.util.ConfigureUtil
6 import org.gradle.plugins.ide.eclipse.model.Output
7 import org.gradle.plugins.ide.eclipse.model.Library
8 import java.security.MessageDigest
9 import groovy.transform.ExternalizeMethods
10 import groovy.util.XmlParser
11 import groovy.xml.XmlUtil
20 classpath 'org.openclover:clover:4.4.1'
29 id "com.diffplug.gradle.spotless" version "3.28.0"
30 id 'com.github.johnrengelman.shadow' version '4.0.3'
31 id 'com.install4j.gradle' version '8.0.4'
32 id 'com.dorongold.task-tree' version '1.5' // only needed to display task dependency tree with gradle task1 [task2 ...] taskTree
42 // in ext the values are cast to Object. Ensure string values are cast as String (and not GStringImpl) for later use
43 def string(Object o) {
44 return o == null ? "" : o.toString()
49 jalviewDirAbsolutePath = file(jalviewDir).getAbsolutePath()
50 jalviewDirRelativePath = jalviewDir
52 // local build environment properties
53 // can be "projectDir/local.properties"
54 def localProps = "${projectDir}/local.properties"
56 if (file(localProps).exists()) {
57 propsFile = localProps
59 // or "../projectDir_local.properties"
60 def dirLocalProps = projectDir.getParent() + "/" + projectDir.getName() + "_local.properties"
61 if (file(dirLocalProps).exists()) {
62 propsFile = dirLocalProps
64 if (propsFile != null) {
66 def p = new Properties()
67 def localPropsFIS = new FileInputStream(propsFile)
72 def oldval = findProperty(key)
75 println("Overriding property '${key}' ('${oldval}') with ${file(propsFile).getName()} value '${val}'")
77 println("Setting unknown property '${key}' with ${file(propsFile).getName()}s value '${val}'")
80 } catch (Exception e) {
81 System.out.println("Exception reading local.properties")
86 // Import releaseProps from the RELEASE file
87 // or a file specified via JALVIEW_RELEASE_FILE if defined
88 // Expect jalview.version and target release branch in jalview.release
89 def releaseProps = new Properties();
90 def releasePropFile = findProperty("JALVIEW_RELEASE_FILE");
91 def defaultReleasePropFile = "${jalviewDirAbsolutePath}/RELEASE";
93 (new File(releasePropFile!=null ? releasePropFile : defaultReleasePropFile)).withInputStream {
96 } catch (Exception fileLoadError) {
97 throw new Error("Couldn't load release properties file "+(releasePropFile==null ? defaultReleasePropFile : "from custom location: releasePropFile"),fileLoadError);
100 // Set JALVIEW_VERSION if it is not already set
101 if (findProperty(JALVIEW_VERSION)==null || "".equals(JALVIEW_VERSION)) {
102 JALVIEW_VERSION = releaseProps.get("jalview.version")
105 // this property set when running Eclipse headlessly
106 j2sHeadlessBuildProperty = string("net.sf.j2s.core.headlessbuild")
107 // this property set by Eclipse
108 eclipseApplicationProperty = string("eclipse.application")
109 // CHECK IF RUNNING FROM WITHIN ECLIPSE
110 def eclipseApplicationPropertyVal = System.properties[eclipseApplicationProperty]
111 IN_ECLIPSE = eclipseApplicationPropertyVal != null && eclipseApplicationPropertyVal.startsWith("org.eclipse.ui.")
112 // BUT WITHOUT THE HEADLESS BUILD PROPERTY SET
113 if (System.properties[j2sHeadlessBuildProperty].equals("true")) {
114 println("Setting IN_ECLIPSE to ${IN_ECLIPSE} as System.properties['${j2sHeadlessBuildProperty}'] == '${System.properties[j2sHeadlessBuildProperty]}'")
118 println("WITHIN ECLIPSE IDE")
120 println("HEADLESS BUILD")
123 J2S_ENABLED = (project.hasProperty('j2s.compiler.status') && project['j2s.compiler.status'] != null && project['j2s.compiler.status'] == "enable")
125 println("J2S ENABLED")
128 System.properties.sort { it.key }.each {
129 key, val -> println("SYSTEM PROPERTY ${key}='${val}'")
132 if (false && IN_ECLIPSE) {
133 jalviewDir = jalviewDirAbsolutePath
138 bareSourceDir = string(source_dir)
139 sourceDir = string("${jalviewDir}/${bareSourceDir}")
140 resourceDir = string("${jalviewDir}/${resource_dir}")
141 bareTestSourceDir = string(test_source_dir)
142 testSourceDir = string("${jalviewDir}/${bareTestSourceDir}")
145 cloverInstrDir = file("${buildDir}/${cloverSourcesInstrDir}")
146 cloverDb = string("${buildDir}/clover/clover.db")
147 classesDir = string("${jalviewDir}/${classes_dir}")
148 if (clover.equals("true")) {
150 classesDir = string("${buildDir}/${cloverClassesDir}")
153 classesDir = string("${jalviewDir}/${classes_dir}")
158 getdownWebsiteDir = string("${jalviewDir}/${getdown_website_dir}/${JAVA_VERSION}")
161 // the following values might be overridden by the CHANNEL switch
162 getdownChannelName = CHANNEL.toLowerCase()
163 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
164 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
165 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher}")
166 getdownAppDistDir = getdown_app_dir_alt
167 buildProperties = string("${resourceDir}/${build_properties_file}")
168 reportRsyncCommand = false
169 jvlChannelName = CHANNEL.toLowerCase()
170 install4jSuffix = CHANNEL.substring(0, 1).toUpperCase() + CHANNEL.substring(1).toLowerCase(); // BUILD -> Build
171 install4jDSStore = "DS_Store-NON-RELEASE"
172 install4jDMGBackgroundImage = "jalview_dmg_background-NON-RELEASE.png"
173 install4jInstallerName = "${jalview_name} Non-Release Installer"
174 install4jExecutableName = jalview_name.replaceAll("[^\\w]+", "_").toLowerCase()
175 install4jExtraScheme = "jalviewx"
179 // TODO: get bamboo build artifact URL for getdown artifacts
180 getdown_channel_base = bamboo_channelbase
181 getdownChannelName = string("${bamboo_planKey}/${JAVA_VERSION}")
182 getdownAppBase = string("${bamboo_channelbase}/${bamboo_planKey}${bamboo_getdown_channel_suffix}/${JAVA_VERSION}")
183 jvlChannelName += "_${getdownChannelName}"
184 // automatically add the test group Not-bamboo for exclusion
185 if ("".equals(testngExcludedGroups)) {
186 testngExcludedGroups = "Not-bamboo"
188 install4jExtraScheme = "jalviewb"
192 getdownAppDistDir = getdown_app_dir_release
193 reportRsyncCommand = true
194 // Don't ignore transpile errors for release build
195 if (jalviewjs_ignore_transpile_errors.equals("true")) {
196 jalviewjs_ignore_transpile_errors = "false"
197 println("Setting jalviewjs_ignore_transpile_errors to 'false'")
200 install4jDSStore = "DS_Store"
201 install4jDMGBackgroundImage = "jalview_dmg_background.png"
202 install4jInstallerName = "${jalview_name} Installer"
206 getdownChannelName = CHANNEL.toLowerCase()+"/${JALVIEW_VERSION}"
207 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
208 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
209 if (!file("${ARCHIVEDIR}/${packageDir}").exists()) {
210 throw new GradleException("Must provide an ARCHIVEDIR value to produce an archive distribution")
212 packageDir = string("${ARCHIVEDIR}/${packageDir}")
213 buildProperties = string("${buildDir}/archive/${build_properties_file}")
216 reportRsyncCommand = true
217 install4jExtraScheme = "jalviewa"
221 getdownChannelName = string("archive/${JALVIEW_VERSION}")
222 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
223 getdownAppBase = file(getdownWebsiteDir).toURI().toString()
224 if (!file("${ARCHIVEDIR}/${packageDir}").exists()) {
225 throw new GradleException("Must provide an ARCHIVEDIR value to produce an archive distribution")
227 packageDir = string("${ARCHIVEDIR}/${packageDir}")
228 buildProperties = string("${buildDir}/archive/${build_properties_file}")
231 reportRsyncCommand = true
232 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
233 install4jSuffix = "Archive"
234 install4jExtraScheme = "jalviewa"
238 reportRsyncCommand = true
240 // DEVELOP-RELEASE is usually associated with a Jalview release series so set the version
241 JALVIEW_VERSION=JALVIEW_VERSION+"-develop"
243 install4jSuffix = "Develop"
244 install4jDSStore = "DS_Store-DEVELOP"
245 install4jDMGBackgroundImage = "jalview_dmg_background-DEVELOP.png"
246 install4jExtraScheme = "jalviewd"
247 install4jInstallerName = "${jalview_name} Develop Installer"
251 reportRsyncCommand = true
252 // Don't ignore transpile errors for release build
253 if (jalviewjs_ignore_transpile_errors.equals("true")) {
254 jalviewjs_ignore_transpile_errors = "false"
255 println("Setting jalviewjs_ignore_transpile_errors to 'false'")
257 JALVIEW_VERSION = JALVIEW_VERSION+"-test"
258 install4jSuffix = "Test"
259 install4jDSStore = "DS_Store-TEST-RELEASE"
260 install4jDMGBackgroundImage = "jalview_dmg_background-TEST.png"
261 install4jExtraScheme = "jalviewt"
262 install4jInstallerName = "${jalview_name} Test Installer"
265 case ~/^SCRATCH(|-[-\w]*)$/:
266 getdownChannelName = CHANNEL
267 JALVIEW_VERSION = JALVIEW_VERSION+"-"+CHANNEL
269 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
270 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
271 reportRsyncCommand = true
272 install4jSuffix = "Scratch"
276 if (!file("${LOCALDIR}").exists()) {
277 throw new GradleException("Must provide a LOCALDIR value to produce a local distribution")
279 getdownAppBase = file(file("${LOCALDIR}").getAbsolutePath()).toURI().toString()
280 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
282 JALVIEW_VERSION = "TEST"
283 install4jSuffix = "Test-Local"
284 install4jDSStore = "DS_Store-TEST-RELEASE"
285 install4jDMGBackgroundImage = "jalview_dmg_background-TEST.png"
286 install4jExtraScheme = "jalviewt"
287 install4jInstallerName = "${jalview_name} Test Installer"
291 JALVIEW_VERSION = "TEST"
292 getdownAppBase = file(getdownWebsiteDir).toURI().toString()
293 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
294 install4jExtraScheme = "jalviewl"
297 default: // something wrong specified
298 throw new GradleException("CHANNEL must be one of BUILD, RELEASE, ARCHIVE, DEVELOP, TEST-RELEASE, SCRATCH-..., LOCAL [default]")
302 // override getdownAppBase if requested
303 if (findProperty("getdown_appbase_override") != null) {
304 getdownAppBase = string(getProperty("getdown_appbase_override"))
305 println("Overriding getdown appbase with '${getdownAppBase}'")
307 // sanitise file name for jalview launcher file for this channel
308 jvlChannelName = jvlChannelName.replaceAll("[^\\w\\-]+", "_")
309 // install4j application and folder names
310 if (install4jSuffix == "") {
311 install4jApplicationName = "${jalview_name}"
312 install4jBundleId = "${install4j_bundle_id}"
313 install4jWinApplicationId = install4j_release_win_application_id
315 install4jApplicationName = "${jalview_name} ${install4jSuffix}"
316 install4jBundleId = "${install4j_bundle_id}-" + install4jSuffix.toLowerCase()
317 // add int hash of install4jSuffix to the last part of the application_id
318 def id = install4j_release_win_application_id
319 def idsplitreverse = id.split("-").reverse()
320 idsplitreverse[0] = idsplitreverse[0].toInteger() + install4jSuffix.hashCode()
321 install4jWinApplicationId = idsplitreverse.reverse().join("-")
323 // sanitise folder and id names
324 // install4jApplicationFolder = e.g. "Jalview Build"
325 install4jApplicationFolder = install4jApplicationName
326 .replaceAll("[\"'~:/\\\\\\s]", "_") // replace all awkward filename chars " ' ~ : / \
327 .replaceAll("_+", "_") // collapse __
328 install4jInternalId = install4jApplicationName
330 .replaceAll("[^\\w\\-\\.]", "_") // replace other non [alphanumeric,_,-,.]
331 .replaceAll("_+", "") // collapse __
332 //.replaceAll("_*-_*", "-") // collapse _-_
333 install4jUnixApplicationFolder = install4jApplicationName
335 .replaceAll("[^\\w\\-\\.]", "_") // replace other non [alphanumeric,_,-,.]
336 .replaceAll("_+", "_") // collapse __
337 .replaceAll("_*-_*", "-") // collapse _-_
340 getdownAppDir = string("${getdownWebsiteDir}/${getdownAppDistDir}")
341 //getdownJ11libDir = "${getdownWebsiteDir}/${getdown_j11lib_dir}"
342 getdownResourceDir = string("${getdownWebsiteDir}/${getdown_resource_dir}")
343 getdownInstallDir = string("${getdownWebsiteDir}/${getdown_install_dir}")
344 getdownFilesDir = string("${jalviewDir}/${getdown_files_dir}/${JAVA_VERSION}/")
345 getdownFilesInstallDir = string("${getdownFilesDir}/${getdown_install_dir}")
346 /* compile without modules -- using classpath libraries
347 modules_compileClasspath = fileTree(dir: "${jalviewDir}/${j11modDir}", include: ["*.jar"])
348 modules_runtimeClasspath = modules_compileClasspath
351 gitBranch = string("")
353 println("Using a ${CHANNEL} profile.")
355 additional_compiler_args = []
356 // configure classpath/args for j8/j11 compilation
357 if (JAVA_VERSION.equals("1.8")) {
358 JAVA_INTEGER_VERSION = string("8")
361 libDistDir = j8libDir
362 compile_source_compatibility = 1.8
363 compile_target_compatibility = 1.8
364 // these are getdown.txt properties defined dependent on the JAVA_VERSION
365 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java8_min_version"))
366 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java8_max_version"))
367 // this property is assigned below and expanded to multiple lines in the getdown task
368 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java8_txt_multi_java_location"))
369 // this property is for the Java library used in eclipse
370 eclipseJavaRuntimeName = string("JavaSE-1.8")
371 } else if (JAVA_VERSION.equals("11")) {
372 JAVA_INTEGER_VERSION = string("11")
374 libDistDir = j11libDir
375 compile_source_compatibility = 11
376 compile_target_compatibility = 11
377 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java11_min_version"))
378 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java11_max_version"))
379 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java11_txt_multi_java_location"))
380 eclipseJavaRuntimeName = string("JavaSE-11")
381 /* compile without modules -- using classpath libraries
382 additional_compiler_args += [
383 '--module-path', modules_compileClasspath.asPath,
384 '--add-modules', j11modules
387 } else if (JAVA_VERSION.equals("12") || JAVA_VERSION.equals("13")) {
388 JAVA_INTEGER_VERSION = JAVA_VERSION
390 libDistDir = j11libDir
391 compile_source_compatibility = JAVA_VERSION
392 compile_target_compatibility = JAVA_VERSION
393 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java11_min_version"))
394 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java11_max_version"))
395 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java11_txt_multi_java_location"))
396 eclipseJavaRuntimeName = string("JavaSE-11")
397 /* compile without modules -- using classpath libraries
398 additional_compiler_args += [
399 '--module-path', modules_compileClasspath.asPath,
400 '--add-modules', j11modules
404 throw new GradleException("JAVA_VERSION=${JAVA_VERSION} not currently supported by Jalview")
409 JAVA_MIN_VERSION = JAVA_VERSION
410 JAVA_MAX_VERSION = JAVA_VERSION
411 def jreInstallsDir = string(jre_installs_dir)
412 if (jreInstallsDir.startsWith("~/")) {
413 jreInstallsDir = System.getProperty("user.home") + jreInstallsDir.substring(1)
415 macosJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-mac-x64/jre")
416 macosJavaVMTgz = string("${jreInstallsDir}/tgz/jre-${JAVA_INTEGER_VERSION}-mac-x64.tar.gz")
417 windowsJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-windows-x64/jre")
418 windowsJavaVMTgz = string("${jreInstallsDir}/tgz/jre-${JAVA_INTEGER_VERSION}-windows-x64.tar.gz")
419 linuxJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-linux-x64/jre")
420 linuxJavaVMTgz = string("${jreInstallsDir}/tgz/jre-${JAVA_INTEGER_VERSION}-linux-x64.tar.gz")
421 install4jDir = string("${jalviewDir}/${install4j_utils_dir}")
422 install4jConfFileName = string("jalview-install4j-conf.install4j")
423 install4jConfFile = file("${install4jDir}/${install4jConfFileName}")
424 install4jHomeDir = install4j_home_dir
425 if (install4jHomeDir.startsWith("~/")) {
426 install4jHomeDir = System.getProperty("user.home") + install4jHomeDir.substring(1)
431 buildingHTML = string("${jalviewDir}/${docDir}/building.html")
432 helpFile = string("${classesDir}/${help_dir}/help.jhm")
433 helpParentDir = string("${jalviewDir}/${help_parent_dir}")
434 helpSourceDir = string("${helpParentDir}/${help_dir}")
437 relativeBuildDir = file(jalviewDirAbsolutePath).toPath().relativize(buildDir.toPath())
438 jalviewjsBuildDir = string("${relativeBuildDir}/jalviewjs")
439 jalviewjsSiteDir = string("${jalviewjsBuildDir}/${jalviewjs_site_dir}")
441 jalviewjsTransferSiteJsDir = string(jalviewjsSiteDir)
443 jalviewjsTransferSiteJsDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_js")
445 jalviewjsTransferSiteLibDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_lib")
446 jalviewjsTransferSiteSwingJsDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_swingjs")
447 jalviewjsTransferSiteCoreDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_core")
448 jalviewjsJalviewCoreHtmlFile = string("")
449 jalviewjsJalviewCoreName = string(jalviewjs_core_name)
450 jalviewjsCoreClasslists = []
451 jalviewjsJalviewTemplateName = string(jalviewjs_name)
452 jalviewjsJ2sSettingsFileName = string("${jalviewDir}/${jalviewjs_j2s_settings}")
453 jalviewjsJ2sProps = null
454 jalviewjsJ2sPlugin = jalviewjs_j2s_plugin
456 eclipseWorkspace = null
457 eclipseBinary = string("")
458 eclipseVersion = string("")
468 outputDir = file(classesDir)
473 srcDirs += helpParentDir
476 jar.destinationDir = file("${jalviewDir}/${packageDir}")
478 compileClasspath = files(sourceSets.main.java.outputDir)
479 //compileClasspath += files(sourceSets.main.resources.srcDirs)
480 compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
482 runtimeClasspath = compileClasspath
487 srcDirs = [ cloverInstrDir ]
488 outputDir = file("${buildDir}/${cloverClassesDir}")
492 srcDirs = sourceSets.main.resources.srcDirs
494 compileClasspath = configurations.cloverRuntime + files( sourceSets.clover.java.outputDir )
495 compileClasspath += files(sourceSets.main.java.outputDir)
496 compileClasspath += sourceSets.main.compileClasspath
497 compileClasspath += fileTree(dir: "${jalviewDir}/${utilsDir}", include: ["**/*.jar"])
498 compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
500 runtimeClasspath = compileClasspath
505 srcDirs testSourceDir
506 outputDir = file("${jalviewDir}/${testOutputDir}")
510 srcDirs = sourceSets.main.resources.srcDirs
513 compileClasspath = files( sourceSets.test.java.outputDir )
516 compileClasspath = sourceSets.clover.compileClasspath
518 compileClasspath += files(sourceSets.main.java.outputDir)
521 compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
522 compileClasspath += fileTree(dir: "${jalviewDir}/${utilsDir}/testnglibs", include: ["**/*.jar"])
523 compileClasspath += fileTree(dir: "${jalviewDir}/${utilsDir}/testlibs", include: ["**/*.jar"])
525 runtimeClasspath = compileClasspath
533 cloverCompile 'org.openclover:clover:4.4.1'
534 testCompile 'org.openclover:clover:4.4.1'
541 cloverRuntime.extendsFrom cloverCompile
545 // eclipse project and settings files creation, also used by buildship
548 name = eclipse_project_name
550 natures 'org.eclipse.jdt.core.javanature',
551 'org.eclipse.jdt.groovy.core.groovyNature',
552 'org.eclipse.buildship.core.gradleprojectnature'
554 buildCommand 'org.eclipse.jdt.core.javabuilder'
555 buildCommand 'org.eclipse.buildship.core.gradleprojectbuilder'
559 //defaultOutputDir = sourceSets.main.java.outputDir
562 if (it.isCanBeResolved()) {
567 minusConfigurations += removeThese
568 plusConfigurations = [ ]
572 def removeTheseToo = []
573 HashMap<String, Boolean> alreadyAddedSrcPath = new HashMap<>();
574 cp.entries.each { entry ->
575 // This conditional removes all src classpathentries that a) have already been added or b) aren't "src" or "test".
576 // e.g. this removes the resources dir being copied into bin/main, bin/test AND bin/clover
577 // we add the resources and help/help dirs in as libs afterwards (see below)
578 if (entry.kind == 'src') {
579 if (alreadyAddedSrcPath.getAt(entry.path) || !(entry.path == bareSourceDir || entry.path == bareTestSourceDir)) {
580 removeTheseToo += entry
582 alreadyAddedSrcPath.putAt(entry.path, true)
587 cp.entries.removeAll(removeTheseToo)
589 //cp.entries += new Output("${eclipse_bin_dir}/main")
590 if (file(helpParentDir).isDirectory()) {
591 cp.entries += new Library(fileReference(helpParentDir))
593 if (file(resourceDir).isDirectory()) {
594 cp.entries += new Library(fileReference(resourceDir))
597 HashMap<String, Boolean> alreadyAddedLibPath = new HashMap<>();
599 sourceSets.main.compileClasspath.findAll { it.name.endsWith(".jar") }.any {
600 //don't want to add outputDir as eclipse is using its own output dir in bin/main
601 if (it.isDirectory() || ! it.exists()) {
602 // don't add dirs to classpath, especially if they don't exist
603 return false // groovy "continue" in .any closure
605 def itPath = it.toString()
606 if (itPath.startsWith("${jalviewDirAbsolutePath}/")) {
607 // make relative path
608 itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
610 if (alreadyAddedLibPath.get(itPath)) {
611 //println("Not adding duplicate entry "+itPath)
613 //println("Adding entry "+itPath)
614 cp.entries += new Library(fileReference(itPath))
615 alreadyAddedLibPath.put(itPath, true)
619 sourceSets.test.compileClasspath.findAll { it.name.endsWith(".jar") }.any {
620 //no longer want to add outputDir as eclipse is using its own output dir in bin/main
621 if (it.isDirectory() || ! it.exists()) {
622 // don't add dirs to classpath
623 return false // groovy "continue" in .any closure
626 def itPath = it.toString()
627 if (itPath.startsWith("${jalviewDirAbsolutePath}/")) {
628 itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
630 if (alreadyAddedLibPath.get(itPath)) {
633 def lib = new Library(fileReference(itPath))
634 lib.entryAttributes["test"] = "true"
636 alreadyAddedLibPath.put(itPath, true)
644 containers 'org.eclipse.buildship.core.gradleclasspathcontainer'
649 // for the IDE, use java 11 compatibility
650 sourceCompatibility = compile_source_compatibility
651 targetCompatibility = compile_target_compatibility
652 javaRuntimeName = eclipseJavaRuntimeName
654 // add in jalview project specific properties/preferences into eclipse core preferences
655 // and also the codestyle XML file
657 withProperties { props ->
658 def jalview_prefs = new Properties()
659 def ins = new FileInputStream("${jalviewDirAbsolutePath}/${eclipse_extra_jdt_prefs_file}")
660 jalview_prefs.load(ins)
662 jalview_prefs.forEach { t, v ->
663 if (props.getAt(t) == null) {
667 // codestyle file -- overrides previous formatter prefs
668 def csFile = file("${jalviewDirAbsolutePath}/${eclipse_codestyle_file}")
669 if (csFile.exists()) {
670 XmlParser parser = new XmlParser()
671 def profiles = parser.parse(csFile)
672 def profile = profiles.'profile'.find { p -> (p.'@kind' == "CodeFormatterProfile" && p.'@name' == "Jalview") }
673 if (profile != null) {
674 profile.'setting'.each { s ->
676 def value = s.'@value'
677 if (id != null && value != null) {
678 props.putAt(id, value)
689 // Don't want these to be activated if in headless build
690 synchronizationTasks "eclipseSynchronizationTask"
691 //autoBuildTasks "eclipseAutoBuildTask"
697 /* hack to change eclipse prefs in .settings files other than org.eclipse.jdt.core.prefs */
698 // Class to allow updating arbitrary properties files
699 class PropertiesFile extends PropertiesPersistableConfigurationObject {
700 public PropertiesFile(PropertiesTransformer t) { super(t); }
701 @Override protected void load(Properties properties) { }
702 @Override protected void store(Properties properties) { }
703 @Override protected String getDefaultResourceName() { return ""; }
704 // This is necessary, because PropertiesPersistableConfigurationObject fails
705 // if no default properties file exists.
706 @Override public void loadDefaults() { load(new StringBufferInputStream("")); }
709 // Task to update arbitrary properties files (set outputFile)
710 class PropertiesFileTask extends PropertiesGeneratorTask<PropertiesFile> {
711 private final PropertiesFileContentMerger file;
712 public PropertiesFileTask() { file = new PropertiesFileContentMerger(getTransformer()); }
713 protected PropertiesFile create() { return new PropertiesFile(getTransformer()); }
714 protected void configure(PropertiesFile props) {
715 file.getBeforeMerged().execute(props); file.getWhenMerged().execute(props);
717 public void file(Closure closure) { ConfigureUtil.configure(closure, file); }
720 task eclipseUIPreferences(type: PropertiesFileTask) {
721 description = "Generate Eclipse additional settings"
722 def filename = "org.eclipse.jdt.ui.prefs"
723 outputFile = "$projectDir/.settings/${filename}" as File
726 it.load new FileInputStream("$projectDir/utils/eclipse/${filename}" as String)
731 task eclipseGroovyCorePreferences(type: PropertiesFileTask) {
732 description = "Generate Eclipse additional settings"
733 def filename = "org.eclipse.jdt.groovy.core.prefs"
734 outputFile = "$projectDir/.settings/${filename}" as File
737 it.load new FileInputStream("$projectDir/utils/eclipse/${filename}" as String)
742 task eclipseAllPreferences {
744 dependsOn eclipseUIPreferences
745 dependsOn eclipseGroovyCorePreferences
748 eclipseUIPreferences.mustRunAfter eclipseJdt
749 eclipseGroovyCorePreferences.mustRunAfter eclipseJdt
751 /* end of eclipse preferences hack */
755 // only instrument source, we build test classes as normal
756 inputs.files files (sourceSets.main.allJava,sourceSets.test.allJava) // , fileTree(dir:"$jalviewDir/$testSourceDir", include: ["**/*.java"]))
757 outputs.dir cloverInstrDir
760 delete cloverInstrDir
765 cloverInstrDir.getPath(),
768 inputs.files.files.collect(
769 { file -> file.absolutePath }
772 String[] args = argsList.toArray()
773 println("About to instrument "+args.length +" files")
774 com.atlassian.clover.CloverInstr.mainImpl(args)
779 cloverClasses.dependsOn cloverInstr
783 group = "Verification"
784 description = "Creates the Clover report"
785 inputs.dir "${buildDir}/clover"
786 outputs.dir "${reportsDir}/clover"
788 file(cloverDb).exists()
795 "${reportsDir}/clover"
797 String[] args = argsList.toArray()
798 com.atlassian.clover.reporters.html.HtmlReporter.runReport(args)
800 // and generate ${reportsDir}/clover/clover.xml
805 "${reportsDir}/clover/clover.xml"
807 com.atlassian.clover.reporters.xml.XMLReporter.runReport(args)
815 sourceCompatibility = compile_source_compatibility
816 targetCompatibility = compile_target_compatibility
817 options.compilerArgs += additional_compiler_args
818 print ("Setting target compatibility to "+targetCompatibility+"\n")
820 classpath += configurations.cloverRuntime
826 delete cloverInstrDir
834 // JBP->BS should the print statement in doFirst refer to compile_target_compatibility ?
835 sourceCompatibility = compile_source_compatibility
836 targetCompatibility = compile_target_compatibility
837 options.compilerArgs = additional_compiler_args
838 options.encoding = "UTF-8"
840 print ("Setting target compatibility to "+targetCompatibility+"\n")
848 dependsOn compileCloverJava
849 classpath += configurations.cloverRuntime
851 classpath += sourceSets.main.runtimeClasspath
854 sourceCompatibility = compile_source_compatibility
855 targetCompatibility = compile_target_compatibility
856 options.compilerArgs = additional_compiler_args
857 print ("Setting target compatibility to "+targetCompatibility+"\n")
864 delete sourceSets.main.java.outputDir
870 dependsOn cleanClover
872 delete sourceSets.test.java.outputDir
877 // format is a string like date.format("dd MMMM yyyy")
878 def getDate(format) {
879 def date = new Date()
880 return date.format(format)
885 def hashStdOut = new ByteArrayOutputStream()
887 commandLine "git", "rev-parse", "--short", "HEAD"
888 standardOutput = hashStdOut
892 def branchStdOut = new ByteArrayOutputStream()
894 commandLine "git", "rev-parse", "--abbrev-ref", "HEAD"
895 standardOutput = branchStdOut
899 gitHash = hashStdOut.toString().trim()
900 gitBranch = branchStdOut.toString().trim()
902 outputs.upToDateWhen { false }
906 task createBuildProperties(type: WriteProperties) {
908 description = "Create the ${buildProperties} file"
911 inputs.dir(sourceDir)
912 inputs.dir(resourceDir)
913 file(buildProperties).getParentFile().mkdirs()
914 outputFile (buildProperties)
915 // taking time specific comment out to allow better incremental builds
916 comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd HH:mm:ss")
917 //comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd")
918 property "BUILD_DATE", getDate("HH:mm:ss dd MMMM yyyy")
919 property "VERSION", JALVIEW_VERSION
920 property "INSTALLATION", INSTALLATION+" git-commit:"+gitHash+" ["+gitBranch+"]"
921 outputs.file(outputFile)
927 delete buildProperties
932 task cleanBuildingHTML(type: Delete) {
939 task convertBuildingMD(type: Exec) {
940 dependsOn cleanBuildingHTML
941 def buildingMD = "${jalviewDir}/${docDir}/building.md"
942 def css = "${jalviewDir}/${docDir}/github.css"
945 pandoc_exec.split(",").each {
946 if (file(it.trim()).exists()) {
952 def buildtoolsPandoc = System.getProperty("user.home")+"/buildtools/pandoc/bin/pandoc"
953 if ((pandoc == null || ! file(pandoc).exists()) && file(buildtoolsPandoc).exists()) {
954 pandoc = System.getProperty("user.home")+"/buildtools/pandoc/bin/pandoc"
958 if (pandoc != null && file(pandoc).exists()) {
959 commandLine pandoc, '-s', '-o', buildingHTML, '--metadata', 'pagetitle="Building Jalview from Source"', '--toc', '-H', css, buildingMD
961 println("Cannot find pandoc. Skipping convert building.md to HTML")
962 throw new StopExecutionException("Cannot find pandoc. Skipping convert building.md to HTML")
968 inputs.file(buildingMD)
970 outputs.file(buildingHTML)
974 task syncDocs(type: Sync) {
975 dependsOn convertBuildingMD
976 def syncDir = "${classesDir}/${docDir}"
977 from fileTree("${jalviewDir}/${docDir}")
983 task copyHelp(type: Copy) {
984 def inputDir = helpSourceDir
985 def outputDir = "${classesDir}/${help_dir}"
990 filter(ReplaceTokens,
994 'Version-Rel': JALVIEW_VERSION,
995 'Year-Rel': getDate("yyyy")
1006 inputs.dir(inputDir)
1007 outputs.files(helpFile)
1008 outputs.dir(outputDir)
1012 task syncLib(type: Sync) {
1013 def syncDir = "${classesDir}/${libDistDir}"
1014 from fileTree("${jalviewDir}/${libDistDir}")
1019 task syncResources(type: Sync) {
1020 dependsOn createBuildProperties
1023 into "${classesDir}"
1031 dependsOn syncResources
1037 //testReportDirName = "test-reports" // note that test workingDir will be $jalviewDir
1040 dependsOn compileJava
1042 dependsOn cloverInstr
1046 print("Running tests " + (use_clover?"WITH":"WITHOUT") + " clover [clover="+use_clover+"]\n")
1050 includeGroups testngGroups
1051 excludeGroups testngExcludedGroups
1053 useDefaultListeners=true
1056 maxHeapSize = "1024m"
1058 workingDir = jalviewDir
1059 //systemProperties 'clover.jar' System.properties.clover.jar
1060 sourceCompatibility = compile_source_compatibility
1061 targetCompatibility = compile_target_compatibility
1062 jvmArgs += additional_compiler_args
1067 task buildIndices(type: JavaExec) {
1069 classpath = sourceSets.main.compileClasspath
1070 main = "com.sun.java.help.search.Indexer"
1071 workingDir = "${classesDir}/${help_dir}"
1074 inputs.dir("${workingDir}/${argDir}")
1076 outputs.dir("${classesDir}/doc")
1077 outputs.dir("${classesDir}/help")
1078 outputs.file("${workingDir}/JavaHelpSearch/DOCS")
1079 outputs.file("${workingDir}/JavaHelpSearch/DOCS.TAB")
1080 outputs.file("${workingDir}/JavaHelpSearch/OFFSETS")
1081 outputs.file("${workingDir}/JavaHelpSearch/POSITIONS")
1082 outputs.file("${workingDir}/JavaHelpSearch/SCHEMA")
1083 outputs.file("${workingDir}/JavaHelpSearch/TMAP")
1087 task compileLinkCheck(type: JavaCompile) {
1089 classpath = files("${jalviewDir}/${utilsDir}")
1090 destinationDir = file("${jalviewDir}/${utilsDir}")
1091 source = fileTree(dir: "${jalviewDir}/${utilsDir}", include: ["HelpLinksChecker.java", "BufferedLineReader.java"])
1093 inputs.file("${jalviewDir}/${utilsDir}/HelpLinksChecker.java")
1094 inputs.file("${jalviewDir}/${utilsDir}/HelpLinksChecker.java")
1095 outputs.file("${jalviewDir}/${utilsDir}/HelpLinksChecker.class")
1096 outputs.file("${jalviewDir}/${utilsDir}/BufferedLineReader.class")
1100 task linkCheck(type: JavaExec) {
1101 dependsOn prepare, compileLinkCheck
1103 def helpLinksCheckerOutFile = file("${jalviewDir}/${utilsDir}/HelpLinksChecker.out")
1104 classpath = files("${jalviewDir}/${utilsDir}")
1105 main = "HelpLinksChecker"
1106 workingDir = jalviewDir
1107 args = [ "${classesDir}/${help_dir}", "-nointernet" ]
1109 def outFOS = new FileOutputStream(helpLinksCheckerOutFile, false) // false == don't append
1111 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
1114 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
1118 inputs.dir("${classesDir}/${help_dir}")
1119 outputs.file(helpLinksCheckerOutFile)
1122 // import the pubhtmlhelp target
1123 ant.properties.basedir = "${jalviewDir}"
1124 ant.properties.helpBuildDir = "${jalviewDirAbsolutePath}/${classes_dir}/${help_dir}"
1125 ant.importBuild "${utilsDir}/publishHelp.xml"
1128 task cleanPackageDir(type: Delete) {
1130 delete fileTree(dir: "${jalviewDir}/${packageDir}", include: "*.jar")
1137 dependsOn buildIndices
1138 dependsOn createBuildProperties
1141 attributes "Main-Class": mainClass,
1142 "Permissions": "all-permissions",
1143 "Application-Name": "Jalview Desktop",
1144 "Codebase": application_codebase
1147 destinationDir = file("${jalviewDir}/${packageDir}")
1148 archiveName = rootProject.name+".jar"
1154 exclude "**/*.jar.*"
1156 inputs.dir(classesDir)
1157 outputs.file("${jalviewDir}/${packageDir}/${archiveName}")
1161 task copyJars(type: Copy) {
1162 from fileTree(dir: classesDir, include: "**/*.jar").files
1163 into "${jalviewDir}/${packageDir}"
1167 // doing a Sync instead of Copy as Copy doesn't deal with "outputs" very well
1168 task syncJars(type: Sync) {
1169 from fileTree(dir: "${jalviewDir}/${libDistDir}", include: "**/*.jar").files
1170 into "${jalviewDir}/${packageDir}"
1172 include jar.archiveName
1179 description = "Put all required libraries in dist"
1180 // order of "cleanPackageDir", "copyJars", "jar" important!
1181 jar.mustRunAfter cleanPackageDir
1182 syncJars.mustRunAfter cleanPackageDir
1183 dependsOn cleanPackageDir
1186 outputs.dir("${jalviewDir}/${packageDir}")
1191 dependsOn cleanPackageDir
1197 group = "distribution"
1201 from ("${jalviewDir}/${libDistDir}") {
1205 attributes 'Implementation-Version': JALVIEW_VERSION
1207 mainClassName = shadowJarMainClass
1209 classifier = "all-"+JALVIEW_VERSION+"-j"+JAVA_VERSION
1214 task getdownWebsite() {
1215 group = "distribution"
1216 description = "Create the getdown minimal app folder, and website folder for this version of jalview. Website folder also used for offline app installer"
1221 def getdownWebsiteResourceFilenames = []
1222 def getdownTextString = ""
1223 def getdownResourceDir = getdownResourceDir
1224 def getdownResourceFilenames = []
1227 // clean the getdown website and files dir before creating getdown folders
1228 delete getdownWebsiteDir
1229 delete getdownFilesDir
1232 from buildProperties
1233 rename(build_properties_file, getdown_build_properties)
1236 getdownWebsiteResourceFilenames += "${getdownAppDistDir}/${getdown_build_properties}"
1238 // set some getdown_txt_ properties then go through all properties looking for getdown_txt_...
1239 def props = project.properties.sort { it.key }
1240 if (getdownAltJavaMinVersion != null && getdownAltJavaMinVersion.length() > 0) {
1241 props.put("getdown_txt_java_min_version", getdownAltJavaMinVersion)
1243 if (getdownAltJavaMaxVersion != null && getdownAltJavaMaxVersion.length() > 0) {
1244 props.put("getdown_txt_java_max_version", getdownAltJavaMaxVersion)
1246 if (getdownAltMultiJavaLocation != null && getdownAltMultiJavaLocation.length() > 0) {
1247 props.put("getdown_txt_multi_java_location", getdownAltMultiJavaLocation)
1250 props.put("getdown_txt_title", jalview_name)
1251 props.put("getdown_txt_ui.name", install4jApplicationName)
1253 // start with appbase
1254 getdownTextString += "appbase = ${getdownAppBase}\n"
1255 props.each{ prop, val ->
1256 if (prop.startsWith("getdown_txt_") && val != null) {
1257 if (prop.startsWith("getdown_txt_multi_")) {
1258 def key = prop.substring(18)
1259 val.split(",").each{ v ->
1260 def line = "${key} = ${v}\n"
1261 getdownTextString += line
1264 // file values rationalised
1265 if (val.indexOf('/') > -1 || prop.startsWith("getdown_txt_resource")) {
1267 if (val.indexOf('/') == 0) {
1270 } else if (val.indexOf('/') > 0) {
1271 // relative path (relative to jalviewDir)
1272 r = file( "${jalviewDir}/${val}" )
1275 val = "${getdown_resource_dir}/" + r.getName()
1276 getdownWebsiteResourceFilenames += val
1277 getdownResourceFilenames += r.getPath()
1280 if (! prop.startsWith("getdown_txt_resource")) {
1281 def line = prop.substring(12) + " = ${val}\n"
1282 getdownTextString += line
1288 getdownWebsiteResourceFilenames.each{ filename ->
1289 getdownTextString += "resource = ${filename}\n"
1291 getdownResourceFilenames.each{ filename ->
1294 into getdownResourceDir
1299 fileTree(file(packageDir)).each{ f ->
1300 if (f.isDirectory()) {
1301 def files = fileTree(dir: f, include: ["*"]).getFiles()
1303 } else if (f.exists()) {
1307 codeFiles.sort().each{f ->
1308 def name = f.getName()
1309 def line = "code = ${getdownAppDistDir}/${name}\n"
1310 getdownTextString += line
1317 // NOT USING MODULES YET, EVERYTHING SHOULD BE IN dist
1319 if (JAVA_VERSION.equals("11")) {
1320 def j11libFiles = fileTree(dir: "${jalviewDir}/${j11libDir}", include: ["*.jar"]).getFiles()
1321 j11libFiles.sort().each{f ->
1322 def name = f.getName()
1323 def line = "code = ${getdown_j11lib_dir}/${name}\n"
1324 getdownTextString += line
1327 into getdownJ11libDir
1333 // getdown-launcher.jar should not be in main application class path so the main application can move it when updated. Listed as a resource so it gets updated.
1334 //getdownTextString += "class = " + file(getdownLauncher).getName() + "\n"
1335 getdownTextString += "resource = ${getdown_launcher_new}\n"
1336 getdownTextString += "class = ${mainClass}\n"
1338 def getdown_txt = file("${getdownWebsiteDir}/getdown.txt")
1339 getdown_txt.write(getdownTextString)
1341 def getdownLaunchJvl = getdown_launch_jvl_name + ( (jvlChannelName != null && jvlChannelName.length() > 0)?"-${jvlChannelName}":"" ) + ".jvl"
1342 def launchJvl = file("${getdownWebsiteDir}/${getdownLaunchJvl}")
1343 launchJvl.write("appbase=${getdownAppBase}")
1346 from getdownLauncher
1347 rename(file(getdownLauncher).getName(), getdown_launcher_new)
1348 into getdownWebsiteDir
1352 from getdownLauncher
1353 if (file(getdownLauncher).getName() != getdown_launcher) {
1354 rename(file(getdownLauncher).getName(), getdown_launcher)
1356 into getdownWebsiteDir
1359 if (! (CHANNEL.startsWith("ARCHIVE") || CHANNEL.startsWith("DEVELOP"))) {
1362 from getdownLauncher
1363 from "${getdownWebsiteDir}/${getdown_build_properties}"
1364 if (file(getdownLauncher).getName() != getdown_launcher) {
1365 rename(file(getdownLauncher).getName(), getdown_launcher)
1367 into getdownInstallDir
1371 from getdownInstallDir
1372 into getdownFilesInstallDir
1379 from getdownLauncher
1380 from "${getdownWebsiteDir}/${getdown_build_properties}"
1381 if (file(getdownLauncher).getName() != getdown_launcher) {
1382 rename(file(getdownLauncher).getName(), getdown_launcher)
1384 into getdownFilesDir
1388 from getdownResourceDir
1389 into "${getdownFilesDir}/${getdown_resource_dir}"
1394 inputs.dir("${jalviewDir}/${packageDir}")
1396 outputs.dir(getdownWebsiteDir)
1397 outputs.dir(getdownFilesDir)
1401 // a helper task to allow getdown digest of any dir: `gradle getdownDigestDir -PDIGESTDIR=/path/to/my/random/getdown/dir
1402 task getdownDigestDir(type: JavaExec) {
1403 def digestDirPropertyName = "DIGESTDIR"
1404 description = "Digest a local dir (-P${digestDirPropertyName}=...) for getdown"
1406 classpath = files(getdownLauncher)
1407 def digestDir = findProperty(digestDirPropertyName)
1408 if (digestDir == null) {
1409 throw new GradleException("Must provide a DIGESTDIR value to produce an alternative getdown digest")
1413 main = "com.threerings.getdown.tools.Digester"
1417 task getdownDigest(type: JavaExec) {
1418 group = "distribution"
1419 description = "Digest the getdown website folder"
1420 dependsOn getdownWebsite
1422 classpath = files(getdownLauncher)
1424 main = "com.threerings.getdown.tools.Digester"
1425 args getdownWebsiteDir
1426 inputs.dir(getdownWebsiteDir)
1427 outputs.file("${getdownWebsiteDir}/digest2.txt")
1432 group = "distribution"
1433 description = "Create the minimal and full getdown app folder for installers and website and create digest file"
1434 dependsOn getdownDigest
1436 if (reportRsyncCommand) {
1437 def fromDir = getdownWebsiteDir + (getdownWebsiteDir.endsWith('/')?'':'/')
1438 def toDir = "${getdown_rsync_dest}/${getdownDir}" + (getdownDir.endsWith('/')?'':'/')
1439 println "LIKELY RSYNC COMMAND:"
1440 println "mkdir -p '$toDir'\nrsync -avh --delete '$fromDir' '$toDir'"
1441 if (RUNRSYNC == "true") {
1443 commandLine "mkdir", "-p", toDir
1446 commandLine "rsync", "-avh", "--delete", fromDir, toDir
1454 tasks.withType(JavaCompile) {
1455 options.encoding = 'UTF-8'
1461 delete getdownWebsiteDir
1462 delete getdownFilesDir
1468 if (file(install4jHomeDir).exists()) {
1470 } else if (file(System.getProperty("user.home")+"/buildtools/install4j").exists()) {
1471 install4jHomeDir = System.getProperty("user.home")+"/buildtools/install4j"
1472 } else if (file("/Applications/install4j.app/Contents/Resources/app").exists()) {
1473 install4jHomeDir = "/Applications/install4j.app/Contents/Resources/app"
1475 installDir(file(install4jHomeDir))
1477 mediaTypes = Arrays.asList(install4j_media_types.split(","))
1481 task copyInstall4jTemplate {
1482 def install4jTemplateFile = file("${install4jDir}/${install4j_template}")
1483 def install4jFileAssociationsFile = file("${install4jDir}/${install4j_installer_file_associations}")
1484 inputs.file(install4jTemplateFile)
1485 inputs.file(install4jFileAssociationsFile)
1486 inputs.property("CHANNEL", { CHANNEL })
1487 outputs.file(install4jConfFile)
1490 def install4jConfigXml = new XmlParser().parse(install4jTemplateFile)
1492 // turn off code signing if no OSX_KEYPASS
1493 if (OSX_KEYPASS == "") {
1494 install4jConfigXml.'**'.codeSigning.each { codeSigning ->
1495 codeSigning.'@macEnabled' = "false"
1497 install4jConfigXml.'**'.windows.each { windows ->
1498 windows.'@runPostProcessor' = "false"
1502 // turn off checksum creation for LOCAL channel
1503 def e = install4jConfigXml.application[0]
1504 if (CHANNEL == "LOCAL") {
1505 e.'@createChecksums' = "false"
1507 e.'@createChecksums' = "true"
1510 // put file association actions where placeholder action is
1511 def install4jFileAssociationsText = install4jFileAssociationsFile.text
1512 def fileAssociationActions = new XmlParser().parseText("<actions>${install4jFileAssociationsText}</actions>")
1513 install4jConfigXml.'**'.action.any { a -> // .any{} stops after the first one that returns true
1514 if (a.'@name' == 'EXTENSIONS_REPLACED_BY_GRADLE') {
1515 def parent = a.parent()
1517 fileAssociationActions.each { faa ->
1520 // don't need to continue in .any loop once replacements have been made
1525 // use Windows Program Group with Examples folder for RELEASE, and Program Group without Examples for everything else
1526 // NB we're deleting the /other/ one!
1527 // Also remove the examples subdir from non-release versions
1528 def customizedIdToDelete = "PROGRAM_GROUP_RELEASE"
1529 // 2.11.1.0 NOT releasing with the Examples folder in the Program Group
1530 if (false && CHANNEL=="RELEASE") { // remove 'false && ' to include Examples folder in RELEASE channel
1531 customizedIdToDelete = "PROGRAM_GROUP_NON_RELEASE"
1533 // remove the examples subdir from Full File Set
1534 def files = install4jConfigXml.files[0]
1535 def fileset = files.filesets.fileset.find { fs -> fs.'@customizedId' == "FULL_FILE_SET" }
1536 def root = files.roots.root.find { r -> r.'@fileset' == fileset.'@id' }
1537 def mountPoint = files.mountPoints.mountPoint.find { mp -> mp.'@root' == root.'@id' }
1538 def dirEntry = files.entries.dirEntry.find { de -> de.'@mountPoint' == mountPoint.'@id' && de.'@subDirectory' == "examples" }
1539 dirEntry.parent().remove(dirEntry)
1541 install4jConfigXml.'**'.action.any { a ->
1542 if (a.'@customizedId' == customizedIdToDelete) {
1543 def parent = a.parent()
1549 // remove the "Uninstall Old Jalview (optional)" symlink from DMG for non-release DS_Stores
1550 if (! (CHANNEL == "RELEASE" || CHANNEL == "TEST-RELEASE" ) ) {
1551 def symlink = install4jConfigXml.'**'.topLevelFiles.symlink.find { sl -> sl.'@name' == "Uninstall Old Jalview (optional).app" }
1552 symlink.parent().remove(symlink)
1555 // write install4j file
1556 install4jConfFile.text = XmlUtil.serialize(install4jConfigXml)
1563 delete install4jConfFile
1568 task installers(type: com.install4j.gradle.Install4jTask) {
1569 group = "distribution"
1570 description = "Create the install4j installers"
1571 dependsOn setGitVals
1573 dependsOn copyInstall4jTemplate
1575 projectFile = install4jConfFile
1577 // create an md5 for the input files to use as version for install4j conf file
1578 def digest = MessageDigest.getInstance("MD5")
1580 (file("${install4jDir}/${install4j_template}").text +
1581 file("${install4jDir}/${install4j_info_plist_file_associations}").text +
1582 file("${install4jDir}/${install4j_installer_file_associations}").text).bytes)
1583 def filesMd5 = new BigInteger(1, digest.digest()).toString(16)
1584 if (filesMd5.length() >= 8) {
1585 filesMd5 = filesMd5.substring(0,8)
1587 def install4jTemplateVersion = "${JALVIEW_VERSION}_F${filesMd5}_C${gitHash}"
1588 // make install4jBuildDir relative to jalviewDir
1589 def install4jBuildDir = "${install4j_build_dir}/${JAVA_VERSION}"
1592 'JALVIEW_NAME': jalview_name,
1593 'JALVIEW_APPLICATION_NAME': install4jApplicationName,
1594 'JALVIEW_DIR': "../..",
1595 'OSX_KEYSTORE': OSX_KEYSTORE,
1596 'JSIGN_SH': JSIGN_SH,
1597 'JRE_DIR': getdown_app_dir_java,
1598 'INSTALLER_TEMPLATE_VERSION': install4jTemplateVersion,
1599 'JALVIEW_VERSION': JALVIEW_VERSION,
1600 'JAVA_MIN_VERSION': JAVA_MIN_VERSION,
1601 'JAVA_MAX_VERSION': JAVA_MAX_VERSION,
1602 'JAVA_VERSION': JAVA_VERSION,
1603 'JAVA_INTEGER_VERSION': JAVA_INTEGER_VERSION,
1604 'VERSION': JALVIEW_VERSION,
1605 'MACOS_JAVA_VM_DIR': macosJavaVMDir,
1606 'WINDOWS_JAVA_VM_DIR': windowsJavaVMDir,
1607 'LINUX_JAVA_VM_DIR': linuxJavaVMDir,
1608 'MACOS_JAVA_VM_TGZ': macosJavaVMTgz,
1609 'WINDOWS_JAVA_VM_TGZ': windowsJavaVMTgz,
1610 'LINUX_JAVA_VM_TGZ': linuxJavaVMTgz,
1611 'COPYRIGHT_MESSAGE': install4j_copyright_message,
1612 'BUNDLE_ID': install4jBundleId,
1613 'INTERNAL_ID': install4jInternalId,
1614 'WINDOWS_APPLICATION_ID': install4jWinApplicationId,
1615 'MACOS_DS_STORE': install4jDSStore,
1616 'MACOS_DMG_BG_IMAGE': install4jDMGBackgroundImage,
1617 'INSTALLER_NAME': install4jInstallerName,
1618 'INSTALL4J_UTILS_DIR': install4j_utils_dir,
1619 'GETDOWN_WEBSITE_DIR': getdown_website_dir,
1620 'GETDOWN_FILES_DIR': getdown_files_dir,
1621 'GETDOWN_RESOURCE_DIR': getdown_resource_dir,
1622 'GETDOWN_DIST_DIR': getdownAppDistDir,
1623 'GETDOWN_ALT_DIR': getdown_app_dir_alt,
1624 'GETDOWN_INSTALL_DIR': getdown_install_dir,
1625 'INFO_PLIST_FILE_ASSOCIATIONS_FILE': install4j_info_plist_file_associations,
1626 'BUILD_DIR': install4jBuildDir,
1627 'APPLICATION_CATEGORIES': install4j_application_categories,
1628 'APPLICATION_FOLDER': install4jApplicationFolder,
1629 'UNIX_APPLICATION_FOLDER': install4jUnixApplicationFolder,
1630 'EXECUTABLE_NAME': install4jExecutableName,
1631 'EXTRA_SCHEME': install4jExtraScheme,
1634 //println("INSTALL4J VARIABLES:")
1635 //variables.each{k,v->println("${k}=${v}")}
1637 destination = "${jalviewDir}/${install4jBuildDir}"
1638 buildSelected = true
1640 if (install4j_faster.equals("true") || CHANNEL.startsWith("LOCAL")) {
1642 disableSigning = true
1646 macKeystorePassword = OSX_KEYPASS
1650 println("Using projectFile "+projectFile)
1653 inputs.dir(getdownWebsiteDir)
1654 inputs.file(install4jConfFile)
1655 inputs.file("${install4jDir}/${install4j_info_plist_file_associations}")
1656 inputs.dir(macosJavaVMDir)
1657 inputs.dir(windowsJavaVMDir)
1658 outputs.dir("${jalviewDir}/${install4j_build_dir}/${JAVA_VERSION}")
1664 eclipse().configFile(eclipse_codestyle_file)
1669 task sourceDist(type: Tar) {
1671 def VERSION_UNDERSCORES = JALVIEW_VERSION.replaceAll("\\.", "_")
1672 def outputFileName = "${project.name}_${VERSION_UNDERSCORES}.tar.gz"
1673 // cater for buildship < 3.1 [3.0.1 is max version in eclipse 2018-09]
1675 archiveFileName = outputFileName
1676 } catch (Exception e) {
1677 archiveName = outputFileName
1680 compression Compression.GZIP
1695 "**/*.class","$j11modDir/**/*.jar","appletlib","**/*locales",
1697 "utils/InstallAnywhere",
1712 "gradle.properties",
1723 ".settings/org.eclipse.jdt.core.jalview.prefs",
1727 exclude (EXCLUDE_FILES)
1728 include (PROCESS_FILES)
1729 filter(ReplaceTokens,
1733 'Version-Rel': JALVIEW_VERSION,
1734 'Year-Rel': getDate("yyyy")
1739 exclude (EXCLUDE_FILES)
1740 exclude (PROCESS_FILES)
1741 exclude ("appletlib")
1742 exclude ("**/*locales")
1743 exclude ("*locales/**")
1744 exclude ("utils/InstallAnywhere")
1746 exclude (getdown_files_dir)
1747 exclude (getdown_website_dir)
1749 // exluding these as not using jars as modules yet
1750 exclude ("${j11modDir}/**/*.jar")
1753 include(INCLUDE_FILES)
1755 // from (jalviewDir) {
1756 // // explicit includes for stuff that seemed to not get included
1757 // include(fileTree("test/**/*."))
1758 // exclude(EXCLUDE_FILES)
1759 // exclude(PROCESS_FILES)
1766 dependsOn pubhtmlhelp
1768 inputs.dir("${classesDir}/${help_dir}")
1769 outputs.dir("${buildDir}/distributions/${help_dir}")
1773 task j2sSetHeadlessBuild {
1780 task jalviewjsSetEclipseWorkspace {
1781 def propKey = "jalviewjs_eclipse_workspace"
1783 if (project.hasProperty(propKey)) {
1784 propVal = project.getProperty(propKey)
1785 if (propVal.startsWith("~/")) {
1786 propVal = System.getProperty("user.home") + propVal.substring(1)
1789 def propsFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_workspace_location_file}"
1790 def propsFile = file(propsFileName)
1791 def eclipseWsDir = propVal
1792 def props = new Properties()
1794 def writeProps = true
1795 if (( eclipseWsDir == null || !file(eclipseWsDir).exists() ) && propsFile.exists()) {
1796 def ins = new FileInputStream(propsFileName)
1799 if (props.getProperty(propKey, null) != null) {
1800 eclipseWsDir = props.getProperty(propKey)
1805 if (eclipseWsDir == null || !file(eclipseWsDir).exists()) {
1806 def tempDir = File.createTempDir()
1807 eclipseWsDir = tempDir.getAbsolutePath()
1810 eclipseWorkspace = file(eclipseWsDir)
1813 // do not run a headless transpile when we claim to be in Eclipse
1815 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
1816 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
1818 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
1822 props.setProperty(propKey, eclipseWsDir)
1823 propsFile.parentFile.mkdirs()
1824 def bytes = new ByteArrayOutputStream()
1825 props.store(bytes, null)
1826 def propertiesString = bytes.toString()
1827 propsFile.text = propertiesString
1833 println("ECLIPSE WORKSPACE: "+eclipseWorkspace.getPath())
1836 //inputs.property(propKey, eclipseWsDir) // eclipseWsDir only gets set once this task runs, so will be out-of-date
1837 outputs.file(propsFileName)
1838 outputs.upToDateWhen { eclipseWorkspace.exists() && propsFile.exists() }
1842 task jalviewjsEclipsePaths {
1845 def eclipseRoot = jalviewjs_eclipse_root
1846 if (eclipseRoot.startsWith("~/")) {
1847 eclipseRoot = System.getProperty("user.home") + eclipseRoot.substring(1)
1849 if (OperatingSystem.current().isMacOsX()) {
1850 eclipseRoot += "/Eclipse.app"
1851 eclipseBinary = "${eclipseRoot}/Contents/MacOS/eclipse"
1852 eclipseProduct = "${eclipseRoot}/Contents/Eclipse/.eclipseproduct"
1853 } else if (OperatingSystem.current().isWindows()) { // check these paths!!
1854 if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
1855 eclipseRoot += "/eclipse"
1857 eclipseBinary = "${eclipseRoot}/eclipse.exe"
1858 eclipseProduct = "${eclipseRoot}/.eclipseproduct"
1859 } else { // linux or unix
1860 if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
1861 eclipseRoot += "/eclipse"
1862 println("eclipseDir exists")
1864 eclipseBinary = "${eclipseRoot}/eclipse"
1865 eclipseProduct = "${eclipseRoot}/.eclipseproduct"
1868 eclipseVersion = "4.13" // default
1869 def assumedVersion = true
1870 if (file(eclipseProduct).exists()) {
1871 def fis = new FileInputStream(eclipseProduct)
1872 def props = new Properties()
1874 eclipseVersion = props.getProperty("version")
1876 assumedVersion = false
1879 def propKey = "eclipse_debug"
1880 eclipseDebug = (project.hasProperty(propKey) && project.getProperty(propKey).equals("true"))
1883 // do not run a headless transpile when we claim to be in Eclipse
1885 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
1886 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
1888 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
1891 if (!assumedVersion) {
1892 println("ECLIPSE VERSION=${eclipseVersion}")
1898 task printProperties {
1900 description "Output to console all System.properties"
1902 System.properties.each { key, val -> System.out.println("Property: ${key}=${val}") }
1908 dependsOn eclipseProject
1909 dependsOn eclipseClasspath
1910 dependsOn eclipseJdt
1914 // this version (type: Copy) will delete anything in the eclipse dropins folder that isn't in fromDropinsDir
1915 task jalviewjsEclipseCopyDropins(type: Copy) {
1916 dependsOn jalviewjsEclipsePaths
1918 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_eclipse_dropins_dir}", include: "*.jar")
1919 inputFiles += file("${jalviewDir}/${jalviewjsJ2sPlugin}")
1920 def outputDir = "${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}"
1927 // this eclipse -clean doesn't actually work
1928 task jalviewjsCleanEclipse(type: Exec) {
1929 dependsOn eclipseSetup
1930 dependsOn jalviewjsEclipsePaths
1931 dependsOn jalviewjsEclipseCopyDropins
1933 executable(eclipseBinary)
1934 args(["-nosplash", "--launcher.suppressErrors", "-data", eclipseWorkspace.getPath(), "-clean", "-console", "-consoleLog"])
1940 def inputString = """exit
1943 def inputByteStream = new ByteArrayInputStream(inputString.getBytes())
1944 standardInput = inputByteStream
1947 /* not really working yet
1948 jalviewjsEclipseCopyDropins.finalizedBy jalviewjsCleanEclipse
1952 task jalviewjsTransferUnzipSwingJs {
1953 def file_zip = "${jalviewDir}/${jalviewjs_swingjs_zip}"
1957 from zipTree(file_zip)
1958 into "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
1962 inputs.file file_zip
1963 outputs.dir "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
1967 task jalviewjsTransferUnzipLib {
1968 def zipFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_libjs_dir}", include: "*.zip")
1971 zipFiles.each { file_zip ->
1973 from zipTree(file_zip)
1974 into "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
1979 inputs.files zipFiles
1980 outputs.dir "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
1984 task jalviewjsTransferUnzipAllLibs {
1985 dependsOn jalviewjsTransferUnzipSwingJs
1986 dependsOn jalviewjsTransferUnzipLib
1990 task jalviewjsCreateJ2sSettings(type: WriteProperties) {
1992 description "Create the .j2s file from the j2s.* properties"
1994 jalviewjsJ2sProps = project.properties.findAll { it.key.startsWith("j2s.") }.sort { it.key }
1995 def siteDirProperty = "j2s.site.directory"
1996 def setSiteDir = false
1997 jalviewjsJ2sProps.each { prop, val ->
1999 if (prop == siteDirProperty) {
2000 if (!(val.startsWith('/') || val.startsWith("file://") )) {
2001 val = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${val}"
2007 if (!setSiteDir) { // default site location, don't override specifically set property
2008 property(siteDirProperty,"${jalviewDirRelativePath}/${jalviewjsTransferSiteJsDir}")
2011 outputFile = jalviewjsJ2sSettingsFileName
2014 inputs.properties(jalviewjsJ2sProps)
2015 outputs.file(jalviewjsJ2sSettingsFileName)
2020 task jalviewjsEclipseSetup {
2021 dependsOn jalviewjsEclipseCopyDropins
2022 dependsOn jalviewjsSetEclipseWorkspace
2023 dependsOn jalviewjsCreateJ2sSettings
2027 task jalviewjsSyncAllLibs (type: Sync) {
2028 dependsOn jalviewjsTransferUnzipAllLibs
2029 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteLibDir}")
2030 inputFiles += fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}")
2031 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
2035 def outputFiles = []
2036 rename { filename ->
2037 outputFiles += "${outputDir}/${filename}"
2043 outputs.files outputFiles
2044 inputs.files inputFiles
2048 task jalviewjsSyncResources (type: Sync) {
2049 def inputFiles = fileTree(dir: resourceDir)
2050 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
2054 def outputFiles = []
2055 rename { filename ->
2056 outputFiles += "${outputDir}/${filename}"
2062 outputs.files outputFiles
2063 inputs.files inputFiles
2067 task jalviewjsSyncSiteResources (type: Sync) {
2068 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_site_resource_dir}")
2069 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
2073 def outputFiles = []
2074 rename { filename ->
2075 outputFiles += "${outputDir}/${filename}"
2081 outputs.files outputFiles
2082 inputs.files inputFiles
2086 task jalviewjsSyncBuildProperties (type: Sync) {
2087 dependsOn createBuildProperties
2088 def inputFiles = [file(buildProperties)]
2089 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
2093 def outputFiles = []
2094 rename { filename ->
2095 outputFiles += "${outputDir}/${filename}"
2101 outputs.files outputFiles
2102 inputs.files inputFiles
2106 task jalviewjsProjectImport(type: Exec) {
2107 dependsOn eclipseSetup
2108 dependsOn jalviewjsEclipsePaths
2109 dependsOn jalviewjsEclipseSetup
2112 // do not run a headless import when we claim to be in Eclipse
2114 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2115 throw new StopExecutionException("Not running headless import whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2117 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2121 //def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview/org.eclipse.jdt.core"
2122 def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview"
2123 executable(eclipseBinary)
2124 args(["-nosplash", "--launcher.suppressErrors", "-application", "com.seeq.eclipse.importprojects.headlessimport", "-data", eclipseWorkspace.getPath(), "-import", jalviewDirAbsolutePath])
2128 args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
2130 args += [ "-D${j2sHeadlessBuildProperty}=true" ]
2133 inputs.file("${jalviewDir}/.project")
2134 outputs.upToDateWhen {
2135 file(projdir).exists()
2140 task jalviewjsTranspile(type: Exec) {
2141 dependsOn jalviewjsEclipseSetup
2142 dependsOn jalviewjsProjectImport
2143 dependsOn jalviewjsEclipsePaths
2146 // do not run a headless transpile when we claim to be in Eclipse
2148 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2149 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2151 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2155 executable(eclipseBinary)
2156 args(["-nosplash", "--launcher.suppressErrors", "-application", "org.eclipse.jdt.apt.core.aptBuild", "-data", eclipseWorkspace, "-${jalviewjs_eclipse_build_arg}", eclipse_project_name ])
2160 args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
2162 args += [ "-D${j2sHeadlessBuildProperty}=true" ]
2168 stdout = new ByteArrayOutputStream()
2169 stderr = new ByteArrayOutputStream()
2171 def logOutFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}"
2172 def logOutFile = file(logOutFileName)
2173 logOutFile.createNewFile()
2174 logOutFile.text = """ROOT: ${jalviewjs_eclipse_root}
2175 BINARY: ${eclipseBinary}
2176 VERSION: ${eclipseVersion}
2177 WORKSPACE: ${eclipseWorkspace}
2178 DEBUG: ${eclipseDebug}
2181 def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
2182 // combine stdout and stderr
2183 def logErrFOS = logOutFOS
2185 if (jalviewjs_j2s_to_console.equals("true")) {
2186 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
2187 new org.apache.tools.ant.util.TeeOutputStream(
2191 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
2192 new org.apache.tools.ant.util.TeeOutputStream(
2197 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
2200 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
2207 if (stdout.toString().contains("Error processing ")) {
2208 // j2s did not complete transpile
2209 //throw new TaskExecutionException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
2210 if (jalviewjs_ignore_transpile_errors.equals("true")) {
2211 println("IGNORING TRANSPILE ERRORS")
2212 println("See eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
2214 throw new GradleException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
2219 inputs.dir("${jalviewDir}/${sourceDir}")
2220 outputs.dir("${jalviewDir}/${jalviewjsTransferSiteJsDir}")
2221 outputs.upToDateWhen( { file("${jalviewDir}/${jalviewjsTransferSiteJsDir}${jalviewjs_server_resource}").exists() } )
2225 def jalviewjsCallCore(String name, FileCollection list, String prefixFile, String suffixFile, String jsfile, String zjsfile, File logOutFile, Boolean logOutConsole) {
2227 def stdout = new ByteArrayOutputStream()
2228 def stderr = new ByteArrayOutputStream()
2230 def coreFile = file(jsfile)
2232 msg = "Creating core for ${name}...\nGenerating ${jsfile}"
2234 logOutFile.createNewFile()
2235 logOutFile.append(msg+"\n")
2237 def coreTop = file(prefixFile)
2238 def coreBottom = file(suffixFile)
2239 coreFile.getParentFile().mkdirs()
2240 coreFile.createNewFile()
2241 coreFile.write( coreTop.getText("UTF-8") )
2245 def t = f.getText("UTF-8")
2246 t.replaceAll("Clazz\\.([^_])","Clazz_${1}")
2247 coreFile.append( t )
2249 msg = "...file '"+f.getPath()+"' does not exist, skipping"
2251 logOutFile.append(msg+"\n")
2254 coreFile.append( coreBottom.getText("UTF-8") )
2256 msg = "Generating ${zjsfile}"
2258 logOutFile.append(msg+"\n")
2259 def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
2260 def logErrFOS = logOutFOS
2263 classpath = files(["${jalviewDir}/${jalviewjs_closure_compiler}"])
2264 main = "com.google.javascript.jscomp.CommandLineRunner"
2265 jvmArgs = [ "-Dfile.encoding=UTF-8" ]
2266 args = [ "--compilation_level", "SIMPLE_OPTIMIZATIONS", "--warning_level", "QUIET", "--charset", "UTF-8", "--js", jsfile, "--js_output_file", zjsfile ]
2269 msg = "\nRunning '"+commandLine.join(' ')+"'\n"
2271 logOutFile.append(msg+"\n")
2273 if (logOutConsole) {
2274 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
2275 new org.apache.tools.ant.util.TeeOutputStream(
2279 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
2280 new org.apache.tools.ant.util.TeeOutputStream(
2285 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
2288 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
2295 logOutFile.append(msg+"\n")
2299 task jalviewjsBuildAllCores {
2301 description "Build the core js lib closures listed in the classlists dir"
2302 dependsOn jalviewjsTranspile
2303 dependsOn jalviewjsTransferUnzipSwingJs
2305 def j2sDir = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${jalviewjs_j2s_subdir}"
2306 def swingJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_j2s_subdir}"
2307 def libJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteLibDir}/${jalviewjs_j2s_subdir}"
2308 def jsDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_js_subdir}"
2309 def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}/${jalviewjs_j2s_subdir}/core"
2310 def prefixFile = "${jsDir}/core/coretop2.js"
2311 def suffixFile = "${jsDir}/core/corebottom2.js"
2313 inputs.file prefixFile
2314 inputs.file suffixFile
2316 def classlistFiles = []
2317 // add the classlists found int the jalviewjs_classlists_dir
2318 fileTree(dir: "${jalviewDir}/${jalviewjs_classlists_dir}", include: "*.txt").each {
2320 def name = file.getName() - ".txt"
2327 // _jmol and _jalview cores. Add any other peculiar classlist.txt files here
2328 //classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jmol}"), 'name': "_jvjmol" ]
2329 classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jalview}"), 'name': jalviewjsJalviewCoreName ]
2331 jalviewjsCoreClasslists = []
2333 classlistFiles.each {
2336 def file = hash['file']
2337 if (! file.exists()) {
2338 //println("...classlist file '"+file.getPath()+"' does not exist, skipping")
2339 return false // this is a "continue" in groovy .each closure
2341 def name = hash['name']
2343 name = file.getName() - ".txt"
2351 def list = fileTree(dir: j2sDir, includes: filelist)
2353 def jsfile = "${outputDir}/core${name}.js"
2354 def zjsfile = "${outputDir}/core${name}.z.js"
2356 jalviewjsCoreClasslists += [
2365 outputs.file(jsfile)
2366 outputs.file(zjsfile)
2369 // _stevesoft core. add any cores without a classlist here (and the inputs and outputs)
2370 def stevesoftClasslistName = "_stevesoft"
2371 def stevesoftClasslist = [
2372 'jsfile': "${outputDir}/core${stevesoftClasslistName}.js",
2373 'zjsfile': "${outputDir}/core${stevesoftClasslistName}.z.js",
2374 'list': fileTree(dir: j2sDir, include: "com/stevesoft/pat/**/*.js"),
2375 'name': stevesoftClasslistName
2377 jalviewjsCoreClasslists += stevesoftClasslist
2378 inputs.files(stevesoftClasslist['list'])
2379 outputs.file(stevesoftClasslist['jsfile'])
2380 outputs.file(stevesoftClasslist['zjsfile'])
2383 def allClasslistName = "_all"
2384 def allJsFiles = fileTree(dir: j2sDir, include: "**/*.js")
2385 allJsFiles += fileTree(
2389 // these exlusions are files that the closure-compiler produces errors for. Should fix them
2390 "**/org/jmol/jvxl/readers/IsoIntersectFileReader.js",
2391 "**/org/jmol/export/JSExporter.js"
2394 allJsFiles += fileTree(
2398 // these exlusions are files that the closure-compiler produces errors for. Should fix them
2399 "**/sun/misc/Unsafe.js",
2400 "**/swingjs/jquery/jquery-editable-select.js",
2401 "**/swingjs/jquery/j2sComboBox.js",
2402 "**/sun/misc/FloatingDecimal.js"
2405 def allClasslist = [
2406 'jsfile': "${outputDir}/core${allClasslistName}.js",
2407 'zjsfile': "${outputDir}/core${allClasslistName}.z.js",
2409 'name': allClasslistName
2411 // not including this version of "all" core at the moment
2412 //jalviewjsCoreClasslists += allClasslist
2413 inputs.files(allClasslist['list'])
2414 outputs.file(allClasslist['jsfile'])
2415 outputs.file(allClasslist['zjsfile'])
2418 def logOutFile = file("${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_closure_stdout}")
2419 logOutFile.getParentFile().mkdirs()
2420 logOutFile.createNewFile()
2421 logOutFile.write(getDate("yyyy-MM-dd HH:mm:ss")+" jalviewjsBuildAllCores\n----\n")
2423 jalviewjsCoreClasslists.each {
2424 jalviewjsCallCore(it.name, it.list, prefixFile, suffixFile, it.jsfile, it.zjsfile, logOutFile, jalviewjs_j2s_to_console.equals("true"))
2431 def jalviewjsPublishCoreTemplate(String coreName, String templateName, File inputFile, String outputFile) {
2434 into file(outputFile).getParentFile()
2435 rename { filename ->
2436 if (filename.equals(inputFile.getName())) {
2437 return file(outputFile).getName()
2441 filter(ReplaceTokens,
2445 'MAIN': '"'+mainClass+'"',
2447 'NAME': jalviewjsJalviewTemplateName+" [core ${coreName}]",
2448 'COREKEY': jalviewjs_core_key,
2449 'CORENAME': coreName
2456 task jalviewjsPublishCoreTemplates {
2457 dependsOn jalviewjsBuildAllCores
2458 def inputFileName = "${jalviewDir}/${j2s_coretemplate_html}"
2459 def inputFile = file(inputFileName)
2460 def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
2462 def outputFiles = []
2463 jalviewjsCoreClasslists.each { cl ->
2464 def outputFile = "${outputDir}/${jalviewjsJalviewTemplateName}_${cl.name}.html"
2465 cl['outputfile'] = outputFile
2466 outputFiles += outputFile
2470 jalviewjsCoreClasslists.each { cl ->
2471 jalviewjsPublishCoreTemplate(cl.name, jalviewjsJalviewTemplateName, inputFile, cl.outputfile)
2474 inputs.file(inputFile)
2475 outputs.files(outputFiles)
2479 task jalviewjsSyncCore (type: Sync) {
2480 dependsOn jalviewjsBuildAllCores
2481 dependsOn jalviewjsPublishCoreTemplates
2482 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteCoreDir}")
2483 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
2487 def outputFiles = []
2488 rename { filename ->
2489 outputFiles += "${outputDir}/${filename}"
2495 outputs.files outputFiles
2496 inputs.files inputFiles
2500 // this Copy version of TransferSiteJs will delete anything else in the target dir
2501 task jalviewjsCopyTransferSiteJs(type: Copy) {
2502 dependsOn jalviewjsTranspile
2503 from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
2504 into "${jalviewDir}/${jalviewjsSiteDir}"
2508 // this Sync version of TransferSite is used by buildship to keep the website automatically up to date when a file changes
2509 task jalviewjsSyncTransferSiteJs(type: Sync) {
2510 from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
2512 into "${jalviewDir}/${jalviewjsSiteDir}"
2519 jalviewjsSyncAllLibs.mustRunAfter jalviewjsCopyTransferSiteJs
2520 jalviewjsSyncResources.mustRunAfter jalviewjsCopyTransferSiteJs
2521 jalviewjsSyncSiteResources.mustRunAfter jalviewjsCopyTransferSiteJs
2522 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsCopyTransferSiteJs
2524 jalviewjsSyncAllLibs.mustRunAfter jalviewjsSyncTransferSiteJs
2525 jalviewjsSyncResources.mustRunAfter jalviewjsSyncTransferSiteJs
2526 jalviewjsSyncSiteResources.mustRunAfter jalviewjsSyncTransferSiteJs
2527 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsSyncTransferSiteJs
2530 task jalviewjsPrepareSite {
2532 description "Prepares the website folder including unzipping files and copying resources"
2533 dependsOn jalviewjsSyncAllLibs
2534 dependsOn jalviewjsSyncResources
2535 dependsOn jalviewjsSyncSiteResources
2536 dependsOn jalviewjsSyncBuildProperties
2537 dependsOn jalviewjsSyncCore
2541 task jalviewjsBuildSite {
2543 description "Builds the whole website including transpiled code"
2544 dependsOn jalviewjsCopyTransferSiteJs
2545 dependsOn jalviewjsPrepareSite
2549 task cleanJalviewjsTransferSite {
2551 delete "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
2552 delete "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
2553 delete "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
2554 delete "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
2559 task cleanJalviewjsSite {
2560 dependsOn cleanJalviewjsTransferSite
2562 delete "${jalviewDir}/${jalviewjsSiteDir}"
2567 task jalviewjsSiteTar(type: Tar) {
2569 description "Creates a tar.gz file for the website"
2570 dependsOn jalviewjsBuildSite
2571 def outputFilename = "jalviewjs-site-${JALVIEW_VERSION}.tar.gz"
2573 archiveFileName = outputFilename
2574 } catch (Exception e) {
2575 archiveName = outputFilename
2578 compression Compression.GZIP
2580 from "${jalviewDir}/${jalviewjsSiteDir}"
2581 into jalviewjs_site_dir // this is inside the tar file
2583 inputs.dir("${jalviewDir}/${jalviewjsSiteDir}")
2587 task jalviewjsServer {
2589 def filename = "jalviewjsTest.html"
2590 description "Starts a webserver on localhost to test the website. See ${filename} to access local site on most recently used port."
2591 def htmlFile = "${jalviewDirAbsolutePath}/${filename}"
2594 SimpleHttpFileServerFactory factory = new SimpleHttpFileServerFactory()
2595 def port = Integer.valueOf(jalviewjs_server_port)
2600 while(port < start+1000 && !running) {
2602 def doc_root = new File("${jalviewDirAbsolutePath}/${jalviewjsSiteDir}")
2603 jalviewjsServer = factory.start(doc_root, port)
2605 url = jalviewjsServer.getResourceUrl(jalviewjs_server_resource)
2606 println("SERVER STARTED with document root ${doc_root}.")
2607 println("Go to "+url+" . Run gradle --stop to stop (kills all gradle daemons).")
2608 println("For debug: "+url+"?j2sdebug")
2609 println("For verbose: "+url+"?j2sverbose")
2610 } catch (Exception e) {
2615 <p><a href="${url}">JalviewJS Test. <${url}></a></p>
2616 <p><a href="${url}?j2sdebug">JalviewJS Test with debug. <${url}?j2sdebug></a></p>
2617 <p><a href="${url}?j2sverbose">JalviewJS Test with verbose. <${url}?j2sdebug></a></p>
2619 jalviewjsCoreClasslists.each { cl ->
2620 def urlcore = jalviewjsServer.getResourceUrl(file(cl.outputfile).getName())
2622 <p><a href="${urlcore}">${jalviewjsJalviewTemplateName} [core ${cl.name}]. <${urlcore}></a></p>
2624 println("For core ${cl.name}: "+urlcore)
2627 file(htmlFile).text = htmlText
2630 outputs.file(htmlFile)
2631 outputs.upToDateWhen({false})
2635 task cleanJalviewjsAll {
2637 description "Delete all configuration and build artifacts to do with JalviewJS build"
2638 dependsOn cleanJalviewjsSite
2639 dependsOn jalviewjsEclipsePaths
2642 delete "${jalviewDir}/${jalviewjsBuildDir}"
2643 delete "${jalviewDir}/${eclipse_bin_dir}"
2644 if (eclipseWorkspace != null && file(eclipseWorkspace.getAbsolutePath()+"/.metadata").exists()) {
2645 delete file(eclipseWorkspace.getAbsolutePath()+"/.metadata")
2647 delete "${jalviewDir}/${jalviewjs_j2s_settings}"
2650 outputs.upToDateWhen( { false } )
2654 task jalviewjsIDE_checkJ2sPlugin {
2655 group "00 JalviewJS in Eclipse"
2656 description "Compare the swingjs/net.sf.j2s.core(-j11)?.jar file with the Eclipse IDE's plugin version (found in the 'dropins' dir)"
2659 def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
2660 def j2sPluginFile = file(j2sPlugin)
2661 def eclipseHome = System.properties["eclipse.home.location"]
2662 if (eclipseHome == null || ! IN_ECLIPSE) {
2663 throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. Skipping J2S Plugin Check.")
2665 def eclipseJ2sPlugin = "${eclipseHome}/dropins/${j2sPluginFile.getName()}"
2666 def eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
2667 if (!eclipseJ2sPluginFile.exists()) {
2668 def msg = "Eclipse J2S Plugin is not installed (could not find '${eclipseJ2sPlugin}')\nTry running task jalviewjsIDE_copyJ2sPlugin"
2669 System.err.println(msg)
2670 throw new StopExecutionException(msg)
2673 def digest = MessageDigest.getInstance("MD5")
2675 digest.update(j2sPluginFile.text.bytes)
2676 def j2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
2678 digest.update(eclipseJ2sPluginFile.text.bytes)
2679 def eclipseJ2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
2681 if (j2sPluginMd5 != eclipseJ2sPluginMd5) {
2682 def msg = "WARNING! Eclipse J2S Plugin '${eclipseJ2sPlugin}' is different to this commit's version '${j2sPlugin}'"
2683 System.err.println(msg)
2684 throw new StopExecutionException(msg)
2686 def msg = "Eclipse J2S Plugin is the same as '${j2sPlugin}' (this is good)"
2692 task jalviewjsIDE_copyJ2sPlugin {
2693 group "00 JalviewJS in Eclipse"
2694 description "Copy the swingjs/net.sf.j2s.core(-j11)?.jar file into the Eclipse IDE's 'dropins' dir"
2697 def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
2698 def j2sPluginFile = file(j2sPlugin)
2699 def eclipseHome = System.properties["eclipse.home.location"]
2700 if (eclipseHome == null || ! IN_ECLIPSE) {
2701 throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. NOT copying J2S Plugin.")
2703 def eclipseJ2sPlugin = "${eclipseHome}/dropins/${j2sPluginFile.getName()}"
2704 def eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
2705 def msg = "WARNING! Copying this commit's j2s plugin '${j2sPlugin}' to Eclipse J2S Plugin '${eclipseJ2sPlugin}'\n* May require an Eclipse restart"
2706 System.err.println(msg)
2709 eclipseJ2sPluginFile.getParentFile().mkdirs()
2710 into eclipseJ2sPluginFile.getParent()
2716 task jalviewjsIDE_j2sFile {
2717 group "00 JalviewJS in Eclipse"
2718 description "Creates the .j2s file"
2719 dependsOn jalviewjsCreateJ2sSettings
2723 task jalviewjsIDE_SyncCore {
2724 group "00 JalviewJS in Eclipse"
2725 description "Build the core js lib closures listed in the classlists dir and publish core html from template"
2726 dependsOn jalviewjsSyncCore
2730 task jalviewjsIDE_SyncSiteAll {
2731 dependsOn jalviewjsSyncAllLibs
2732 dependsOn jalviewjsSyncResources
2733 dependsOn jalviewjsSyncSiteResources
2734 dependsOn jalviewjsSyncBuildProperties
2738 cleanJalviewjsTransferSite.mustRunAfter jalviewjsIDE_SyncSiteAll
2741 task jalviewjsIDE_PrepareSite {
2742 group "00 JalviewJS in Eclipse"
2743 description "Sync libs and resources to site dir, but not closure cores"
2745 dependsOn jalviewjsIDE_SyncSiteAll
2746 dependsOn cleanJalviewjsTransferSite
2750 task jalviewjsIDE_AssembleSite {
2751 group "00 JalviewJS in Eclipse"
2752 description "Assembles unzipped supporting zipfiles, resources, site resources and closure cores into the Eclipse transpiled site"
2753 dependsOn jalviewjsPrepareSite
2757 task jalviewjsIDE_SiteClean {
2758 group "00 JalviewJS in Eclipse"
2759 description "Deletes the Eclipse transpiled site"
2760 dependsOn cleanJalviewjsSite
2764 task jalviewjsIDE_Server {
2765 group "00 JalviewJS in Eclipse"
2766 description "Starts a webserver on localhost to test the website"
2767 dependsOn jalviewjsServer
2771 // buildship runs this at import or gradle refresh
2772 task eclipseSynchronizationTask {
2773 //dependsOn eclipseSetup
2774 dependsOn createBuildProperties
2776 dependsOn jalviewjsIDE_j2sFile
2777 dependsOn jalviewjsIDE_checkJ2sPlugin
2778 dependsOn jalviewjsIDE_PrepareSite
2783 // buildship runs this at build time or project refresh
2784 task eclipseAutoBuildTask {
2785 //dependsOn jalviewjsIDE_checkJ2sPlugin
2786 //dependsOn jalviewjsIDE_PrepareSite
2792 description "Build the site"
2793 dependsOn jalviewjsBuildSite