build.gradle 20.2 KB
Newer Older
1 2
import com.badlogic.gdx.graphics.Texture
import com.badlogic.gdx.tools.texturepacker.TexturePacker
3
import edu.sc.seis.launch4j.tasks.Launch4jLibraryTask
4
import groovy.io.FileType
5
import org.apache.tools.ant.filters.ReplaceTokens
6

7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/*
 * Copyright (C) 2016 CZ.NIC, z.s.p.o. (http://www.nic.cz/)
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

24
apply plugin: "java"
25
apply plugin: 'edu.sc.seis.launch4j'
26
apply plugin: "edu.sc.seis.macAppBundle"
27

28
sourceCompatibility = 1.8
29 30 31 32 33 34 35
sourceSets {
    main {
        java {
            srcDir 'src/main'
        }
    }
    iTest {
36
        java.srcDirs = ['src/iTest/', '../itest/src/']
37 38 39
        compileClasspath += sourceSets.main.runtimeClasspath
    }
}
40

41 42
project.ext.mainLauncherClassName = "cz.nic.tablexia.desktop.DesktopLauncher"
project.ext.iTestLauncherClassName = "cz.nic.tablexia.desktop.DesktopITestLauncher"
43 44 45
project.ext.assetsDir = new File("../android/assets");

task run(dependsOn: classes, type: JavaExec) {
46
    main = project.mainLauncherClassName
47 48 49 50 51 52
    classpath = sourceSets.main.runtimeClasspath
    standardInput = System.in
    workingDir = project.assetsDir
    ignoreExitValue = true
}

53 54 55 56 57 58 59 60 61
task runITest(dependsOn: [classes, iTestClasses], type: JavaExec) {
    main = project.iTestLauncherClassName
    classpath += sourceSets.main.runtimeClasspath
    classpath += sourceSets.iTest.runtimeClasspath
    standardInput = System.in
    workingDir = project.assetsDir
    ignoreExitValue = true
}

62
task iTestJar(dependsOn: [classes, iTestClasses, ':util:checksum:runChecksum'], type: Jar) {
63
    baseName = tablexiaAppName + "-iTest"
64 65 66 67 68 69 70 71 72
    from files(sourceSets.iTest.output.classesDir)
    from files(sourceSets.main.output.classesDir)
    from files(sourceSets.main.output.resourcesDir)
    from {configurations.compile.collect {zipTree(it)}}
    from files(project.assetsDir);

    doFirst {
        manifest {
            attributes 'Main-Class': project.iTestLauncherClassName
73
            attributes 'Build-Type': 'iTest'
74 75 76 77 78 79
            attributes 'Version-Name': tablexiaVersionName
            attributes 'Assets-Cheksums': getMapConvertedToString(rootProject.ext.assetsChecksum)
        }
    }
}

80
task debugJar(dependsOn: [classes, ':util:checksum:runChecksum'], type: Jar) {
81
    baseName = tablexiaAppName + "-debug"
82 83 84 85
    from files(sourceSets.main.output.classesDir)
    from files(sourceSets.main.output.resourcesDir)
    from {configurations.compile.collect {zipTree(it)}}
    from files(project.assetsDir);
86

87 88
    doFirst {
        manifest {
89
            attributes 'Main-Class': project.mainLauncherClassName
90 91
            attributes 'Build-Type': 'debug'
            attributes 'Version-Name': tablexiaVersionName
92
            attributes 'Assets-Cheksums': getMapConvertedToString(rootProject.ext.assetsChecksum)
93
            attributes 'Sentry-DSN': project.sentryDSN
94
        }
95 96 97
    }
}

98
task releaseJar(dependsOn: [classes, ':util:checksum:runChecksum'], type: Jar) {
99
    baseName = tablexiaAppName + "-release"
100 101 102 103 104
    from files(sourceSets.main.output.classesDir)
    from files(sourceSets.main.output.resourcesDir)
    from {configurations.compile.collect {zipTree(it)}}
    from files(project.assetsDir);

105 106
    doFirst {
        manifest {
107
            attributes 'Main-Class': project.mainLauncherClassName
108 109
            attributes 'Build-Type': 'release'
            attributes 'Version-Name': tablexiaVersionName
110
            attributes 'Assets-Cheksums': getMapConvertedToString(rootProject.ext.assetsChecksum)
111
            attributes 'Sentry-DSN': project.sentryDSN
112
        }
113 114 115
    }
}

116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
task runITestBundle(dependsOn: iTestJar) {
    doLast {
        int testsCount = 0;
        int successfulTestsCount = 0;

        def iTestOutputPath = "${libsDir}/iTest_results/"
        def iTestOutputFile = new File(iTestOutputPath)
        if (iTestOutputFile.exists()) {
            println "[iTest] REMOVING OLD iTest OUTPUT DIRECTORY"
            iTestOutputFile.deleteDir()
        }

        new File(project(':itest').bundleFilePath).eachLine { iTestName ->
            testsCount++;
            runItest(iTestName)
        }

        iTestOutputFile.traverse(type : FileType.FILES, nameFilter: ~/OK_.*\.log/) { iTestLog ->
            successfulTestsCount++;
        }
        if (testsCount != successfulTestsCount) throw new GradleException("Failed to complete all iTests! Check iTest log files in: \'${iTestOutputPath}\'")
    }
}

def runItest(String iTestName) {
    println "[iTest] STARTING TEST: " + iTestName
    def stdout = new ByteArrayOutputStream()
    exec {
        ignoreExitValue true
        workingDir libsDir
        commandLine 'java', '-jar', tablexiaAppName + "-iTest-" + tablexiaVersionName + ".jar", iTestName
        standardOutput = stdout
    }
    println "[iTest] TEST: " + iTestName + " FINISHED"
}

152 153 154 155 156
/***************************
 * Windows Desktop Version *
 ***************************/

def download(String remoteUrl, String localUrl) {
Drahomír Karchňák's avatar
Drahomír Karchňák committed
157
    File localFile = new File(localUrl)
158
    if(!localFile.exists()) {
159
        localFile.getParentFile().mkdirs()
160 161
        localFile.createNewFile()
    }
162 163

    localFile.withOutputStream { out ->
164 165 166 167
        new URL(remoteUrl).withInputStream { from ->  out << from; }
    }
}

168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
/**
 * Task to create an exe file from jar
 */
class exeTask extends Launch4jLibraryTask {
    @Input
    String buildTypeInput = "debug" //Default value

    @Override
    def run() {
        setMainClassName('cz.nic.tablexia.desktop.DesktopLauncher')
        setOutputDir('bin')
        setBundledJrePath('../jre')
        setIcon('../../assets/icons/desktop_icon_' + buildTypeInput + '_128.png.ico')
        setJar('../libs/' + project.tablexiaAppName + '-' + buildTypeInput + '-' + project.tablexiaVersionName + '.jar')

        setOutfile('Tablexia.exe') //installer_script.nsi expects the file to be named like this.
        return super.run()
185
    }
186
}
187

188 189 190 191 192 193 194 195 196 197 198 199 200
/**
 * This task takes /bin/Tablexia.exe and creates an installer file
 */
class SetupExeTask extends exeTask {
    def log(String message) {
        logger.lifecycle(':' + project.name + ':' + name + ' ' + message)
    }

    @TaskAction
    def run() {
        super.run();

        log("Creating temporary folder for installer files")
201 202 203
        def installerDir = new File(project.buildDir.absolutePath + '/installer')
        if(installerDir.exists()) installerDir.mkdir()

204 205
        log("Copying jre/ folder to temporary installer folder")
        project.copy {
206 207 208
            from project.buildDir.absolutePath + '/jre'
            into installerDir.absolutePath + '/jre'
        }
209

210 211
        log("Copying bin/ folder to temporary installer folder")
        project.copy {
212 213
            from project.buildDir.absolutePath + '/bin'
            into installerDir.absolutePath + '/bin'
214
            exclude 'TablexiaSetup.exe'
215
        }
216

217 218 219
        log("Copying icon folder to temporary installer folder")
        project.copy {
            from project.projectDir.absolutePath + '/assets/icons/desktop_icon_' + buildTypeInput + '_128.png.ico'
220 221
            into installerDir.absolutePath
            rename '.*', 'logo.ico'
222 223 224 225 226
        }

        def stdout = new ByteArrayOutputStream()

        //Launch makensis
227
        project.exec {
228
            commandLine 'makensis', '-V2', 'installer_script.nsi'
229 230
            standardOutput = stdout
        }
231

232 233 234 235
        //print output of previous exec command
        def output = stdout.toString().trim()
        if(!output.isEmpty()) println output

236
        log("Creating outputs folder")
237 238 239
        def outputsFile = new File(project.buildDir.absolutePath + '/outputs/')
        if(!outputsFile.exists()) outputsFile.mkdir();

240 241
        log("Moving built .exe installer to outputs folder.")
        project.copy {
242
            from project.buildDir.absolutePath + '/bin/TablexiaSetup.exe'
243 244
            into outputsFile
            rename '.*', project.tablexiaAppName + '-' + getBuildTypeInput() + '-' + project.tablexiaVersionName + '-Setup.exe'
245 246
        }

247
        log("Deleting temporary installer folder")
248
        installerDir.deleteDir()
249
    }
250 251
}

252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282

task handleJreTask() {
    def jreFileName = '/jre.tar.gz'

    File jreFolder = new File(project.buildDir.absolutePath + '/jre/')
    boolean forceJreDownload = project.hasProperty('TABLEXIA_JRE_FORCE_DOWNLOAD') ? project.property('TABLEXIA_JRE_FORCE_DOWNLOAD') : false;

    doFirst {
        if (!jreFolder.exists() || forceJreDownload) {
            logger.lifecycle("Downloading JRE.")

            //Download JRE
            download(project.property('TABLEXIA_JRE_DOWNLOAD_MIRROR'), project.buildDir.absolutePath + jreFileName)

            //Byte buffer to store stdout
            def stdout = new ByteArrayOutputStream()

            //Extract JRE to desktop/build/
            exec {
                commandLine 'tar', '-xf', project.buildDir.absolutePath + jreFileName, '-C', project.buildDir.absolutePath
                standardOutput = stdout
            }

            //print output of previous exec command
            def output = stdout.toString().trim()
            if (!output.isEmpty()) println output
        }
    }
}


283 284 285 286
/**
 * Debug and Release implementation of the task above
 * buildTypeInput is used to name our .exe setup file
 */
287
task releaseExe(dependsOn: [classes, handleJreTask, releaseJar], type: SetupExeTask) {
288 289 290
    setBuildTypeInput('release')
}

291
task debugExe(dependsOn: [classes, handleJreTask, debugJar], type: SetupExeTask) {
292 293 294
    setBuildTypeInput('debug')
}

295

296 297
task releaseDeb (dependsOn: [classes, releaseJar]){
    def version="release"
298
    doLast {
299 300
        prepareFiles("$version")
        createDebPackage("$version")
301
    }
302
}
303

304
task debugDeb (dependsOn: [classes, debugJar]) {
305
    def version="debug"
306
    doLast {
307 308
        prepareFiles("$version")
        createDebPackage("$version")
309 310
    }
}
311

312
def prepareFiles(String version) {
313 314
    delete "build/debian/$version"

315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346
    def debianFolder = new File("desktop/build/debian/$version");
    debianFolder.mkdirs();

    def ver
    if("$version"=="release") ver=""
    else ver="-$version"

    def controlFile = new File("$debianFolder/control")
    controlFile.createNewFile()
    controlFile.text =  "Package: tablexia$ver\n" +
                        "Priority: optional\n" +
                        "Version: $tablexiaVersionName\n" +
                        "Section: web\n" +
                        "Architecture: all\n" +
                        "Depends: java8-runtime, openjfx\n" +
                        "Maintainer: cz.nic\n" +
                        "Homepage: http://tablexia.cz/\n" +
                        "Description: \n" +
                        " Tablexia is a modern educational application aiming to support the development of\n" +
                        " cognitive abilities. It is designed primarily for children with dyslexia in secondary\n" +
                        " schools. It should find its use in schools to supplement the standard teaching,\n" +
                        " as well as in pedagogical-psychological counseling offices and other counseling\n" +
                        " facilities for pupils with learning difficulties.\n" +
                        " .\n" +
                        " Also available for Android, iOS and Windows.\n"

    def tablexiaFile = new File("$debianFolder" + "/tablexia$ver")
    tablexiaFile.createNewFile()
    tablexiaFile.text = "#!/bin/sh\n" +
                        "\n" +
                        "java -jar /lib/tablexia$ver" + "/Tablexia.jar"

347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370
    String changelogMessage
    def fileOfChanges = new File("desktop/change-log")
    if(fileOfChanges.exists()){
        changelogMessage = new File('desktop/change-log').text
    }
    else{
        changelogMessage = "Updated to version $tablexiaVersionName"
        println 'File change-log in tablexia/deskop does not exists. ' +
                'If you want to write down news into changelog, please, create tablexia/desktop/change-log with description of what is new.'
    }

    def changelogFile = new File("$debianFolder/changelog")
    changelogFile.createNewFile()
    changelogFile.text =    "Tablexia trusty; urgency low\n" +
                            "* Rebuild\n" +
                            "CZ.NIC, z.s.p.o. (http://www.nic.cz/)\n" +
                            "$changelogMessage\n"

    exec {
        commandLine = ['gzip',"changelog"]
        workingDir = "build/debian/$version/"
    }


371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386
    if("$version" == "release") version=""
    else version = "$version" + "_"
    def tablexiaDesktop = new File("$debianFolder" + "/tablexia$ver" + ".desktop")
    tablexiaDesktop.createNewFile()
    tablexiaDesktop.text =  "[Desktop Entry]\n" +
                            "Encoding=UTF-8\n" +
                            "Name=Tablexia\n" +
                            "Comment=Educational application\n" +
                            "Exec=/usr/bin/tablexia$ver\n" +
                            "Icon=/usr/share/doc/tablexia$ver" + "/desktop_icon_$version" + "128.png\n" +
                            "Terminal=false\n" +
                            "Type=Application\n" +
                            "Categories=GNOME, Application\n" +
                            "StartupNotify=true"
}

387
def createDebPackage(String version) {
388 389 390 391 392
    def ver
    if("$version"=="release") ver=""
    else ver="-$version"

    def tablexiaPackage = "tablexia$ver"
393
    def tablexiaApp = tablexiaAppName + "-$version-" + tablexiaVersionName
394 395
    def packageFolder = new File("/desktop/build/libs/$tablexiaApp")
    packageFolder.mkdirs()
396

397
    new File("$packageFolder/DEBIAN").mkdirs()  // control
398
    new File("$packageFolder/lib/$tablexiaPackage").mkdirs()    // .jar
399
    new File("$packageFolder/usr/bin").mkdirs() //exec tablexia
400
    new File("$packageFolder/usr/share/applications").mkdirs()  //tablexia.desktop
401
    new File("$packageFolder/usr/share/doc/$tablexiaPackage").mkdirs()  // copyright, icon, changelog
402

403
    //copy .jar file
404 405
    copy {
        from "../desktop/build/libs/$tablexiaApp" + ".jar"
406
        into "../$packageFolder/lib/$tablexiaPackage" + "/"
407 408 409 410 411 412 413 414

        rename { String fileName ->
            fileName.replace("$tablexiaApp" + ".jar", "Tablexia.jar")
        }
    }

    //copy executable tablexia file
    copy {
415
        from "../desktop/build/debian/" + "$version" + "/tablexia$ver"
416 417 418 419 420
        into "../$packageFolder/usr/bin/"
    }

    //add tablexia file rights for execute
    exec {
421
        commandLine = ['chmod',"+x","tablexia$ver"]
422
        workingDir = "../$packageFolder/usr/bin/"
423
    }
424

425
    //copy control file
426
    copy {
427
        from "../desktop/build/debian/" + "$version" + "/control"
428
        into "../$packageFolder/DEBIAN/"
429
    }
430

431 432
    //copy copyright file
    copy {
433
        from "../desktop/copyright"
434
        into "../$packageFolder/usr/share/doc/$tablexiaPackage" + "/"
435 436 437 438
    }

    //copy tablexia.desktop
    copy {
439
        from "../desktop/build/debian/" + "$version" + "/tablexia$ver" + ".desktop"
440 441 442
        into "../$packageFolder/usr/share/applications/"
    }

443
    // copy changelog
444
    copy {
445
        from "../desktop/build/debian/$version" + "/changelog.gz"
446
        into "../$packageFolder/usr/share/doc/$tablexiaPackage" + "/"
447
    }
448

449 450 451 452 453 454 455 456
    //copy icon
    if("$version"=="release") ver=""
    else ver="$version" + "_"
    copy {
        from "../android/assets/icon/desktop_icon_$ver" + "128.png"
        into "../$packageFolder/usr/share/doc/$tablexiaPackage" + "/"
    }

457 458 459 460 461 462
    exec {
        commandLine = ['dpkg-deb',"--build","$tablexiaApp"]
        workingDir = "../desktop/build/libs"
    }

    delete "../$packageFolder"
463
    delete "build/debian"
464 465
}

466 467
macAppBundle {
    mainClassName = project.mainLauncherClassName
468
    icon = project.projectDir.absolutePath + '/assets/icons/mac_icon_release.icns'
469 470
    bundleJRE = true
    appName = 'Tablexia'
471 472
}

473 474 475
createDmg.enabled = false
createAppZip.enabled = false

476
task debugMac(dependsOn: [debugJar, createApp]) {
477 478
    doLast {
        setupMacApp('debug', applicationIdDebug)
479
    }
480 481
}

482
task releaseMac(dependsOn: [releaseJar, createApp]) {
483 484
    doLast {
        setupMacApp('release', applicationIdRelease)
485
    }
486 487
}

488
def setupMacApp(String buildType, String applicationId) {
489
    def appFolderName = project.tablexiaAppName + '-' + buildType + '-' + project.tablexiaVersionName + '.app'
490
    def iconName = 'mac_icon_' + buildType + '.icns'
491

492
    def outputDir = new File(project.buildDir.absolutePath + '/outputApp')
493
    if (!outputDir.exists()) {
Lukas Marik's avatar
Lukas Marik committed
494
        //create output directory
495 496
        outputDir.mkdir()
    }
497

Lukas Marik's avatar
Lukas Marik committed
498
    //copy default app to output app build directory
499 500 501 502
    project.copy {
        from project.buildDir.absolutePath + '/macApp/Tablexia.app'
        into project.buildDir.absolutePath + '/outputApp/' + appFolderName
    }
503

Lukas Marik's avatar
Lukas Marik committed
504
    //copy jar file to app
505 506
    project.copy {
        from project.buildDir.absolutePath + '/libs/' + project.tablexiaAppName + '-' + buildType + '-' + project.tablexiaVersionName + '.jar'
507 508 509 510 511 512 513 514 515 516 517 518 519
        into project.buildDir.absolutePath + '/outputApp/' + appFolderName + '/Contents/Java'
    }

    //delete old plist
    file(project.buildDir.absolutePath + '/outputApp/' + appFolderName + '/Contents/Info.plist').delete()

    //set properties
    updateMacProperties(buildType, applicationId, iconName)

    //config plist
    project.copy {
        from 'macapp_plist.xml'
        into project.buildDir.absolutePath + '/outputApp/' + appFolderName + '/Contents/'
Lukas Marik's avatar
Lukas Marik committed
520
        rename '.*', 'Info.plist'
521 522 523 524 525 526

        def myProps = new Properties()
        file("macapp_prop.properties").withInputStream {
            myProps.load(it);
        }
        filter(ReplaceTokens, tokens: myProps)
527
    }
528 529


Lukas Marik's avatar
Lukas Marik committed
530
    if (!buildType.equalsIgnoreCase('release')) {
531 532 533 534
        //remove release icon from resources folder
        file(project.buildDir.absolutePath + '/outputApp/' + appFolderName + '/Contents/Resources/mac_icon_release.icns').delete()

        //copy icns by build type to resources folder
Lukas Marik's avatar
Lukas Marik committed
535
        project.copy {
536 537 538
            from project.projectDir.absolutePath + '/assets/icons/' + iconName
            into project.buildDir.absolutePath + '/outputApp/' + appFolderName + '/Contents/Resources/'
        }
539
    }
540 541
}

542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557
def updateMacProperties(String buildType, String applicationId, String iconName) {
    Properties props = new Properties()
    def propsFile = file('macapp_prop.properties')

    if (!propsFile.exists()) {
        propsFile.createNewFile();
    }

    props.load(propsFile.newDataInputStream())
    props.setProperty('app.name', tablexiaAppName)
    props.setProperty('app.icon', iconName)
    props.setProperty('app.id', applicationId)
    props.setProperty('app.mainclass', mainLauncherClassName)
    props.setProperty('app.version', tablexiaModelVersionName)
    props.setProperty('app.build', '' + tablexiaVersionCode)
    props.setProperty('app.buildtype', buildType)
558
    props.setProperty('app.executable', 'JavaAppLauncher')
559 560 561 562 563
    props.setProperty('app.sentryDSN', sentryDSNFallbackValue)

    props.store(propsFile.newDataOutputStream(), '')
}

564
task cleanMacAppDir(dependsOn: [debugMac, releaseMac]) {
565
    doLast {
566 567 568
        file(project.buildDir.absolutePath + "/macApp").deleteDir()
    }
}
569

570 571 572 573 574 575
if (project.hasProperty('TABLEXIA_DESKTOP_ARTEFACTS') && Boolean.valueOf(project.property('TABLEXIA_DESKTOP_ARTEFACTS')).booleanValue()) {
    assemble.dependsOn([debugJar, debugDeb, debugExe, debugMac, releaseJar, releaseDeb, releaseExe, releaseMac, iTestJar, cleanMacAppDir])
}
else {
    assemble.dependsOn([debugJar, releaseJar, iTestJar])
}
576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593
jar.enabled = false

eclipse {
    project {
        name = appName + "-desktop"
        linkedResource name: 'assets', type: '2', location: 'PARENT-1-PROJECT_LOC/android/assets'
    }
}

task afterEclipseImport(description: "Post processing after project generation", group: "IDE") {
  doLast {
    def classpath = new XmlParser().parse(file(".classpath"))
    new Node(classpath, "classpathentry", [ kind: 'src', path: 'assets' ]);
    def writer = new FileWriter(file(".classpath"))
    def printer = new XmlNodePrinter(new PrintWriter(writer))
    printer.setPreserveWhitespace(true)
    printer.print(classpath)
  }
594
}