1 /*
   2  * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 /**
  27  * The main build script for JavaFX.
  28  *
  29  * MUST FIX tasks to complete:
  30  *  - build check -- making sure the final artifact has the right bits
  31  *      - some things worth automatically sanity checking:
  32  *          - are there images in the javadocs?
  33  *          - are all of the expected dylibs etc there?
  34  *          - is jfxrt.jar there?
  35  *          - does jfxrt.jar contain stuff it shouldn't (doc-files, iml, etc)
  36  *          - does jfxrt.jar contain stuff it should (bss files, etc)
  37  *  - Perform sanity checking to make sure a JDK exists with javac, javah, etc
  38  *  - Support building with no known JDK location, as long as javac, javah, etc are on the path
  39  *  - Check all of the native flags. We're adding weight to some libs that don't need it, and so forth.
  40  *
  41  * Additional projects to work on as we go:
  42  *  - Add "developer debug". This is where the natives do not have debug symbols, but the Java code does
  43  *  - The genVSproperties.bat doesn't find the directory where RC.exe lives. So it is hard coded. Might be a problem.
  44  *  - special tasks for common needs, such as:
  45  *      - updating copyright headers
  46  *      - stripping trailing whitespace (?)
  47  *  - checkstyle
  48  *  - findbugs
  49  *  - re needs?
  50  *  - sqe testing
  51  *  - API change check
  52  *  - Pushing results to a repo?
  53  *  - ServiceWithSecurityManagerTest fails to complete when run from gradle.
  54  *  - Integrate Parfait reports for C code
  55  *  - FXML Project tests are not running
  56  */
  57 defaultTasks = ["sdk"]
  58 
  59 import java.util.concurrent.CountDownLatch
  60 import java.util.concurrent.ExecutorService
  61 import java.util.concurrent.Executors
  62 import java.util.concurrent.Future
  63 
  64 /******************************************************************************
  65  *                              Utility methods                               *
  66  *****************************************************************************/
  67 
  68 /**
  69  * If the given named property is not defined, then this method will define
  70  * it with the given defaultValue. Any properties defined by this method can
  71  * be substituted on the command line by using -P, or by specifying a
  72  * gradle.properties file in the user home dir
  73  *
  74  * @param name The name of the property to define
  75  * @param defaultValue The default value to assign the property
  76  */
  77 void defineProperty(String name, String defaultValue) {
  78     if (!project.hasProperty(name)) {
  79         project.ext.set(name, defaultValue);
  80     }
  81 }
  82 
  83 /**
  84  * If the given named property is not defined, then this method will attempt to
  85  * look up the property in the props map, and use the defaultValue if it cannot be found.
  86  *
  87  * @param name The name of the property to look up and/or define
  88  * @param props The properties to look for the named property in, if it has not already been defined
  89  * @param defaultValue The default value if the property has not been defined and the
  90  *                     props map does not contain the named property
  91  */
  92 void defineProperty(String name, Properties props, String defaultValue) {
  93     if (!project.hasProperty(name)) {
  94         project.ext.set(name, props.getProperty(name, defaultValue));
  95     }
  96 }
  97 
  98 /**
  99  * Converts cygwin style paths to windows style paths, but with a forward slash.
 100  * This method is safe to call from any platform, and will only do work if
 101  * called on Windows (in all other cases it simply returns the supplied path.
 102  * In the future I would like to modify this so that it only does work if
 103  * cygwin is installed, as I hope one day to remove the requirement to build
 104  * with cygwin, but at present (due to GStreamer / Webkit) cygwin is needed
 105  * anyway.
 106  *
 107  * @param path the path to convert
 108  * @return the path converted to windows style, if on windows, otherwise it
 109  *         is the supplied path.
 110  */
 111 String cygpath(String path) {
 112     if (!IS_WINDOWS) return path;
 113     if (path == null || "".equals(path)) return path;
 114     ByteArrayOutputStream out = new ByteArrayOutputStream();
 115     logger.info("Converting path '$path' via cygpath")
 116     exec {
 117         standardOutput = out
 118         commandLine "cmd", "/c", "cygpath", "-m", path
 119     }
 120     return out.toString().trim();
 121 }
 122 
 123 void loadProperties(String sourceFileName) {
 124     def config = new Properties()
 125     def propFile = new File(sourceFileName)
 126     if (propFile.canRead()) {
 127         config.load(new FileInputStream(propFile))
 128         for (java.util.Map.Entry property in config) {
 129             def keySplit = property.key.split("\\.");
 130             def key = keySplit[0];
 131             for (int i = 1; i < keySplit.length; i++) {
 132                 key = key + keySplit[i].capitalize();
 133             }
 134             ext[key] = property.value;
 135         }
 136     }
 137 }
 138 
 139 /**
 140  * Struct used to contain some information passed to the closure
 141  * passed to compileTargets.
 142  */
 143 class CompileTarget {
 144     String name;
 145     String upper;
 146     String capital;
 147 }
 148 
 149 /**
 150  * Iterates over each of the compile targets, passing the given closure
 151  * a CompileTarget instance.
 152  *
 153  * @param c The closure to call
 154  */
 155 void compileTargets(Closure c) {
 156     if (COMPILE_TARGETS == "") {
 157         return
 158     }
 159     COMPILE_TARGETS.split(",").each { target ->
 160         CompileTarget ct = new CompileTarget();
 161         ct.name = target;
 162         ct.upper = target.trim().toUpperCase(Locale.ROOT)
 163         ct.capital = target.trim().capitalize()
 164         c(ct)
 165     }
 166 }
 167 
 168 /**
 169  * Manages the execution of some closure which is responsible for producing
 170  * content for a properties file built at build time and stored in the
 171  * root project's $buildDir, and then loading that properties file and
 172  * passing it to the processor closure.
 173  *
 174  * This is used on windows to produce a properties file containing all the
 175  * windows visual studio paths and environment variables, and on Linux
 176  * for storing the results of pkg-config calls.
 177  *
 178  * @param name the name of the file to produce
 179  * @param loader a closure which is invoked, given the properties file. This
 180  *        closure is invoked only if the properties file needs to be created
 181  *        and is responsible for populating the properties file.
 182  * @param processor a closure which is invoked every time this method is
 183  *        called and which will be given a Properties object, fully populated.
 184  *        The processor is then responsible for doing whatever it is that it
 185  *        must do with those properties (such as setting up environment
 186  *        variables used in subsequent native builds, or whatnot).
 187  */
 188 void setupTools(String name, Closure loader, Closure processor) {
 189     // Check to see whether $buildDir/$name.properties file exists. If not,
 190     // then generate it. Once generated, we need to read the properties file to
 191     // help us define the defaults for this block of properties
 192     File propFile = file("$buildDir/${name}.properties");
 193     if (!propFile.exists()) {
 194         // Create the properties file
 195         propFile.getParentFile().mkdirs();
 196         propFile.createNewFile();
 197         loader(propFile);
 198     }
 199 
 200     // Try reading the properties in order to define the properties. If the property file cannot
 201     // be located, then we will throw an exception because we cannot guess these values
 202     InputStream propStream = null;
 203     try {
 204         Properties properties = new Properties();
 205         propStream = new FileInputStream(propFile);
 206         properties.load(propStream);
 207         processor(properties);
 208     } finally {
 209         try { propStream.close() } catch (Exception e) { }
 210     }
 211 }
 212 
 213 /**
 214  * Fails the build with the specified error message
 215  *
 216  * @param msg the reason for the failure
 217  */
 218 void fail(String msg) {
 219     throw new GradleException("FAIL: " + msg);
 220 }
 221 
 222 /******************************************************************************
 223  *                                                                            *
 224  *                   Definition of project properties                         *
 225  *                                                                            *
 226  *  All properties defined using ext. are immediately available throughout    *
 227  *  the script as variables that can be used. These variables are attached    *
 228  *  to the root project (whereas if they were defined as def variables then   *
 229  *  they would only be available within the root project scope).              *
 230  *                                                                            *
 231  *  All properties defined using the "defineProperty" method can be replaced  *
 232  *  on the command line by using the -P flag. For example, to override the    *
 233  *  location of the binary plug, you would specify -PBINARY_PLUG=some/where   *
 234  *                                                                            *
 235  *****************************************************************************/
 236 
 237 // If the ../rt-closed directory exists, then we are doing a closed build.
 238 // In this case, build and property files will be read from
 239 // ../rt-closed/closed-build.gradle and ../rt-closed/closed-properties.gradle
 240 // respectively
 241 
 242 def closedDir = file("../rt-closed")
 243 def buildClosed = closedDir.isDirectory()
 244 ext.BUILD_CLOSED = buildClosed
 245 
 246 // These variables indicate what platform is running the build. Is
 247 // this build running on a Mac, Windows, or Linux machine? 32 or 64 bit?
 248 ext.OS_NAME = System.getProperty("os.name").toLowerCase()
 249 ext.OS_ARCH = System.getProperty("os.arch")
 250 ext.IS_64 = OS_ARCH.toLowerCase().contains("64")
 251 ext.IS_MAC = OS_NAME.contains("mac") || OS_NAME.contains("darwin")
 252 ext.IS_WINDOWS = OS_NAME.contains("windows")
 253 ext.IS_LINUX = OS_NAME.contains("linux")
 254 
 255 // Get the JDK_HOME automatically based on the version of Java used to execute gradle. Or, if specified,
 256 // use a user supplied JDK_HOME, STUB_RUNTIME, JAVAC, and/or JAVAH, all of which may be specified
 257 // independently (or we'll try to get the right one based on other supplied info). Sometimes the
 258 // JRE might be the thing that is being used instead of the JRE embedded in the JDK, such as:
 259 //    c:\Program Files (x86)\Java\jdk1.8.0\jre
 260 //    c:\Program Files (x86)\Java\jre8\
 261 // Because of this, you may sometimes get the jdk's JRE (in which case the logic we used to have here
 262 // was correct and consistent with all other platforms), or it might be the standalone JRE (for the love!).
 263 def envJavaHome = cygpath(System.getenv("JDK_HOME"))
 264 if (envJavaHome == null || envJavaHome.equals("")) envJavaHome = cygpath(System.getenv("JAVA_HOME"))
 265 def javaHome = envJavaHome == null || envJavaHome.equals("") ? System.getProperty("java.home") : envJavaHome
 266 def javaHomeFile = file(javaHome)
 267 defineProperty("JDK_HOME",
 268         javaHomeFile.name == "jre" ?
 269         javaHomeFile.getParent().toString() :
 270         javaHomeFile.name.startsWith("jre") ?
 271         new File(javaHomeFile.getParent(), "jdk1.${javaHomeFile.name.substring(3)}.0").toString() :
 272         javaHome) // we have to bail and set it to something and this is as good as any!
 273 ext.JAVA_HOME = JDK_HOME
 274 defineProperty("JAVA", cygpath("$JDK_HOME/bin/java${IS_WINDOWS ? '.exe' : ''}"))
 275 defineProperty("JAVAC", cygpath("$JDK_HOME/bin/javac${IS_WINDOWS ? '.exe' : ''}"))
 276 defineProperty("JAVAH", cygpath("$JDK_HOME/bin/javah${IS_WINDOWS ? '.exe' : ''}"))
 277 defineProperty("JAVADOC", cygpath("$JDK_HOME/bin/javadoc${IS_WINDOWS ? '.exe' : ''}"))
 278 defineProperty("JDK_DOCS", "https://docs.oracle.com/javase/8/docs/api/")
 279 
 280 defineProperty("javaRuntimeVersion", System.getProperty("java.runtime.version"))
 281 defineProperty("javaVersion", javaRuntimeVersion.split("-")[0])
 282 defineProperty("javaBuildNumber", javaRuntimeVersion.substring(javaRuntimeVersion.lastIndexOf("-b") + 2))
 283 
 284 loadProperties("$projectDir/build.properties")
 285 
 286 def String closedCacheStubRuntime = cygpath("$projectDir") + "/../caches/sdk/rt"
 287 defineProperty("STUB_RUNTIME", BUILD_CLOSED ? closedCacheStubRuntime : cygpath("$JDK_HOME/jre"))
 288 defineProperty("LIBRARY_STUB", IS_MAC ? "$STUB_RUNTIME/lib" :
 289                                IS_WINDOWS ? "$STUB_RUNTIME/bin" :
 290                                "$STUB_RUNTIME/lib/$OS_ARCH")
 291 defineProperty("UPDATE_STUB_CACHE", (STUB_RUNTIME.equals(closedCacheStubRuntime) ? 'true' : 'false'))
 292 
 293 def supplementalPreBuildFile = file("$closedDir/closed-pre-build.gradle");
 294 def supplementalBuildFile = file("$closedDir/closed-build.gradle");
 295 
 296 if (BUILD_CLOSED) {
 297     apply from: supplementalPreBuildFile
 298 }
 299 
 300 // GRADLE_VERSION_CHECK specifies whether to fail the build if the
 301 // gradle version check fails
 302 defineProperty("GRADLE_VERSION_CHECK", "true")
 303 ext.IS_GRADLE_VERSION_CHECK = Boolean.parseBoolean(GRADLE_VERSION_CHECK)
 304 
 305 // COMPILE_WEBKIT specifies whether to build all of webkit.
 306 defineProperty("COMPILE_WEBKIT", "false")
 307 ext.IS_COMPILE_WEBKIT = Boolean.parseBoolean(COMPILE_WEBKIT)
 308 
 309 // COMPILE_MEDIA specifies whether to build all of media.
 310 defineProperty("COMPILE_MEDIA", "false")
 311 ext.IS_COMPILE_MEDIA = Boolean.parseBoolean(COMPILE_MEDIA)
 312 
 313 // COMPILE_PANGO specifies whether to build javafx_font_pango.
 314 defineProperty("COMPILE_PANGO", "${IS_LINUX}")
 315 ext.IS_COMPILE_PANGO = Boolean.parseBoolean(COMPILE_PANGO)
 316 
 317 // COMPILE_HARFBUZZ specifies whether to use Harfbuzz.
 318 defineProperty("COMPILE_HARFBUZZ", "false")
 319 ext.IS_COMPILE_HARFBUZZ = Boolean.parseBoolean(COMPILE_HARFBUZZ)
 320 
 321 // COMPILE_PARFAIT specifies whether to build parfait
 322 defineProperty("COMPILE_PARFAIT", "false")
 323 ext.IS_COMPILE_PARFAIT = Boolean.parseBoolean(COMPILE_PARFAIT)
 324 
 325 // COMPILE_JFR specifies whether to build code that logs to JRockit Flight Recorder
 326 defineProperty("COMPILE_JFR", Boolean.toString(file("$JDK_HOME/jre/lib/jfr.jar").exists()))
 327 ext.IS_COMPILE_JFR = Boolean.parseBoolean(COMPILE_JFR)
 328 
 329 // RETAIN_PACKAGER_TESTS specifies whether the tests in fxpackager should
 330 // keep generated files instead of attempting to automatically delete them
 331 defineProperty("RETAIN_PACKAGER_TESTS", "false")
 332 ext.IS_RETAIN_PACKAGER_TESTS = Boolean.parseBoolean(RETAIN_PACKAGER_TESTS)
 333 
 334 // TEST_PACKAGER_DMG whether tests that create DMG files via hdiutil
 335 // should be run.  On OSX 10.7 this tends to hang automated builds
 336 defineProperty("TEST_PACKAGER_DMG", "false")
 337 ext.IS_TEST_PACKAGER_DMG = Boolean.parseBoolean(TEST_PACKAGER_DMG)
 338 
 339 // Define the SWT.jar that we are going to have to download during the build process based
 340 // on what platform we are compiling from (not based on our target).
 341 ext.SWT_FILE_NAME = IS_MAC ? "org.eclipse.swt.cocoa.macosx.x86_64_3.7.2.v3740f" :
 342     IS_WINDOWS && IS_64 ? "org.eclipse.swt.win32.win32.x86_64_3.7.2.v3740f" :
 343     IS_WINDOWS && !IS_64 ? "org.eclipse.swt.win32.win32.x86_3.7.2.v3740f" :
 344     IS_LINUX && IS_64 ? "org.eclipse.swt.gtk.linux.x86_64_3.7.2.v3740f" :
 345     IS_LINUX && !IS_64 ? "org.eclipse.swt.gtk.linux.x86_3.7.2.v3740f" : ""
 346 
 347 // Build javadocs only if BUILD_JAVADOC=true
 348 defineProperty("BUILD_JAVADOC", "false")
 349 ext.IS_BUILD_JAVADOC = Boolean.parseBoolean(BUILD_JAVADOC)
 350 
 351 // Specifies whether to build the javafx-src bundle
 352 defineProperty("BUILD_SRC_ZIP", "false")
 353 ext.IS_BUILD_SRC_ZIP = Boolean.parseBoolean(BUILD_SRC_ZIP)
 354 
 355 // Specifies whether to run full tests (true) or smoke tests (false)
 356 defineProperty("FULL_TEST", "false")
 357 ext.IS_FULL_TEST = Boolean.parseBoolean(FULL_TEST);
 358 
 359 // Specifies whether to run robot-based visual tests (only used when FULL_TEST is also enabled)
 360 defineProperty("USE_ROBOT", "false")
 361 ext.IS_USE_ROBOT = Boolean.parseBoolean(USE_ROBOT);
 362 
 363 // Specified whether to run tests in headless mode
 364 defineProperty("HEADLESS_TEST", "false")
 365 ext.IS_HEADLESS_TEST = Boolean.parseBoolean(HEADLESS_TEST);
 366 
 367 // Specifies whether to run system tests that depend on AWT (only used when FULL_TEST is also enabled)
 368 defineProperty("AWT_TEST", "true")
 369 ext.IS_AWT_TEST = Boolean.parseBoolean(AWT_TEST);
 370 
 371 // Specify the build configuration (Release, Debug, or DebugNative)
 372 defineProperty("CONF", "Debug")
 373 ext.IS_DEBUG_JAVA = CONF == "Debug" || CONF == "DebugNative"
 374 ext.IS_DEBUG_NATIVE = CONF == "DebugNative"
 375 
 376 // Defines the compiler warning levels to use. If empty, then no warnings are generated. If
 377 // not empty, then the expected syntax is as a space or comma separated list of names, such
 378 // as defined in the javac documentation.
 379 defineProperty("LINT", "none")
 380 ext.IS_LINT = LINT != "none"
 381 
 382 defineProperty("DOC_LINT", "none")
 383 ext.IS_DOC_LINT = DOC_LINT != "none"
 384 
 385 // Specifies whether to use the "useDepend" option when compiling Java sources
 386 defineProperty("USE_DEPEND", "true")
 387 ext.IS_USE_DEPEND = Boolean.parseBoolean(USE_DEPEND)
 388 
 389 // Specifies whether to use the "incremental" option when compiling Java sources
 390 defineProperty("INCREMENTAL", "false")
 391 ext.IS_INCREMENTAL = Boolean.parseBoolean(INCREMENTAL)
 392 
 393 // Specifies whether to generate code coverage statistics when running tests
 394 defineProperty("JCOV", "false")
 395 ext.DO_JCOV = Boolean.parseBoolean(JCOV)
 396 
 397 // Define the number of threads to use when compiling (specifically for native compilation)
 398 // On Mac we limit it to 1 by default due to problems running gcc in parallel
 399 if (IS_MAC) {
 400     defineProperty("NUM_COMPILE_THREADS", "1")
 401 } else {
 402     defineProperty("NUM_COMPILE_THREADS", "${Runtime.runtime.availableProcessors()}")
 403 }
 404 
 405 //
 406 // The next three sections of properties are used to generate the
 407 // VersionInfo class, and the Windows DLL manifest.
 408 //
 409 
 410 // The following properties should be left alone by developers and set only from Hudson.
 411 defineProperty("HUDSON_JOB_NAME", "not_hudson")
 412 defineProperty("HUDSON_BUILD_NUMBER","0000")
 413 defineProperty("PROMOTED_BUILD_NUMBER", "00")
 414 
 415 // The following properties define the product name for Oracle JDK and OpenJDK
 416 // for VersionInfo and the DLL manifest.
 417 if (BUILD_CLOSED) {
 418     defineProperty("PRODUCT_NAME", "Java(TM)")
 419     defineProperty("COMPANY_NAME", "Oracle Corporation")
 420     defineProperty("PLATFORM_NAME", "Platform SE")
 421 } else {
 422     defineProperty("PRODUCT_NAME", "OpenJFX")
 423     defineProperty("COMPANY_NAME", "N/A")
 424     defineProperty("PLATFORM_NAME", "Platform")
 425 }
 426 
 427 // The following properties are set based on properties defined in
 428 // build.properties. The release number or milestone number should be updated
 429 // in that file.
 430 def jfxReleaseVersion = "${jfxReleaseMajorVersion}.${jfxReleaseMinorVersion}.${jfxReleaseMicroVersion}"
 431 defineProperty("RAW_VERSION", jfxReleaseVersion)
 432 defineProperty("RELEASE_NAME", jfxReleaseName)
 433 defineProperty("RELEASE_MILESTONE", jfxReleaseMilestone)
 434 
 435 // Check whether the COMPILE_TARGETS property has been specified (if so, it was done by
 436 // the user and not by this script). If it has not been defined then default
 437 // to building the normal desktop build for this machine
 438 project.ext.set("defaultHostTarget", IS_MAC ? "mac" : IS_WINDOWS ? "win" : IS_LINUX ? "linux" : "");
 439 defineProperty("COMPILE_TARGETS", "$defaultHostTarget")
 440 
 441 // Flag indicating whether to import cross compile tools
 442 def importCrossTools = BUILD_CLOSED ? true : false;
 443 if (!importCrossTools && hasProperty("IMPORT_CROSS_TOOLS")) {
 444     importCrossTools = Boolean.parseBoolean(IMPORT_CROSS_TOOLS);
 445 }
 446 ext.IS_IMPORT_CROSS_TOOLS = importCrossTools
 447 
 448 // Location of the cross compile tools
 449 def crossToolsDir = "../crosslibs"
 450 if (hasProperty("CROSS_TOOLS_DIR")) {
 451     crossToolsDir = CROSS_TOOLS_DIR
 452 }
 453 ext.CROSS_TOOLS_DIR = file(crossToolsDir)
 454 
 455 // Specifies whether to run tests with the present jfxrt.jar instead of compiling the new one
 456 defineProperty("BUILD_SDK_FOR_TEST", "true")
 457 ext.DO_BUILD_SDK_FOR_TEST = Boolean.parseBoolean(BUILD_SDK_FOR_TEST)
 458 
 459 // Specifies the location to point at SDK build when DO_BUILD_SDK_FOR_TEST set to false
 460 // Used to get location of jfxrt.jar, ant-javafx.jar and javafx-mx.jar
 461 defineProperty("TEST_SDK", JDK_HOME)
 462 ext.TEST_SDK_DIR = file(TEST_SDK)
 463 
 464 def rtDir = new File(TEST_SDK_DIR, "rt")
 465 if (!rtDir.directory) {
 466     rtDir = new File(TEST_SDK_DIR, "jre")
 467 }
 468 ext.jfxrtJarFromSdk = new File(rtDir, "lib/ext/jfxrt.jar").absolutePath
 469 if (!DO_BUILD_SDK_FOR_TEST && !file(jfxrtJarFromSdk).exists()) {
 470     fail ("BUILD_SDK_FOR_TEST is set to false, but there\'s no jfxrt.jar at the expected paths in TEST_SDK($TEST_SDK_DIR)\n"
 471             + "TEST_SDK should point at either JavaFX SDK location or JDK location\n"
 472             + "Please, set the correct TEST_SDK")
 473 }
 474 
 475 // These tasks would be disabled when running with DO_BUILD_SDK_FOR_TEST=false as they're unneeded for running tests
 476 def disabledTasks = DO_BUILD_SDK_FOR_TEST ? [] : ["compileJava", "processResources", "classes", // all projects
 477          "generateDecoraShaders", "generatePrismShaders",
 478          "compilePrismCompilers", "compilePrismJavaShaders", "compileDecoraCompilers", // :graphics
 479          "processDecoraShaders", "processPrismShaders"]
 480 
 481 /**
 482  * Fetch/Check that external tools are present for the build. This method
 483  * will conditionally download the packages from project defined ivy repositories
 484  * and unpack them into the specified destdir
 485  *
 486  * @param configName A unique name to distinguish the configuration (ie "ARMSFV6")
 487  * @param packages A list of required packages (with extensions .tgz, .zip)
 488  * @param destdir where the packages should be unpacked
 489  * @param doFetch if true, the named packages will be download
 490  */
 491 void fetchExternalTools(String configName, List packages, File destdir, boolean doFetch) {
 492     if (doFetch) {
 493         // create a unique configuration for this fetch
 494         def String fetchToolsConfig = "fetchTools$configName"
 495         rootProject.configurations.create(fetchToolsConfig)
 496 
 497         def List<String> fetchedPackages = []
 498         def int fetchCount = 0
 499 
 500         packages.each { pkgname->
 501             def int dotdex = pkgname.lastIndexOf('.')
 502             def int dashdex = pkgname.lastIndexOf('-')
 503             def String basename = pkgname.substring(0,dashdex)
 504             def String ver = pkgname.substring(dashdex+1,dotdex)
 505             def String ext = pkgname.substring(dotdex+1)
 506             def File pkgdir = file("$destdir/$basename-$ver")
 507 
 508             if (!pkgdir.isDirectory()) {
 509                 rootProject.dependencies.add(fetchToolsConfig, "javafx:$basename:$ver", {
 510                     artifact {
 511                         name = basename
 512                         version = ver
 513                         type = ext
 514                     }
 515                 })
 516                 println "adding $pkgname as a downloadable item did not find $pkgdir"
 517                 fetchedPackages.add(pkgname)
 518                 fetchCount++
 519             }
 520         }
 521 
 522         //fetch all the missing packages
 523         if (fetchedPackages.size > 0) {
 524             destdir.mkdirs()
 525 
 526             logger.quiet "fetching missing packages $fetchedPackages"
 527             copy {
 528                 from rootProject.configurations[fetchToolsConfig]
 529                 into destdir
 530             }
 531 
 532             // unpack the fetched packages
 533             fetchedPackages.each { pkgname->
 534                 logger.quiet "expanding the package $pkgname"
 535                 def srcball = file("${destdir}/${pkgname}")
 536 
 537                 if (!srcball.exists()) {
 538                     throw new GradleException("Failed to fetch $pkgname");
 539                 }
 540 
 541                 def String basename = pkgname.substring(0,pkgname.lastIndexOf("."))
 542                 def File pkgdir = file("$destdir/$basename")
 543 
 544                 if (pkgname.endsWith(".tgz")) {
 545                     if (IS_LINUX || IS_MAC) {
 546                         // use native tar to support symlinks
 547                         pkgdir.mkdirs()
 548                         exec {
 549                             workingDir pkgdir
 550                             commandLine "tar", "zxf", "${srcball}"
 551                          }
 552                     } else {
 553                         copy {
 554                             from tarTree(resources.gzip("${srcball}"))
 555                             into pkgdir
 556                         }
 557                     }
 558                 } else if (pkgname.endsWith(".zip")) {
 559                      copy {
 560                          from zipTree("${srcball}")
 561                          into pkgdir
 562                      }
 563                 } else {
 564                     throw new GradleException("Unhandled package type for compile package ${pkgname}")
 565                 }
 566                 srcball.deleteOnExit();
 567             }
 568         } else {
 569             logger.quiet "all tool packages are present $packages"
 570         }
 571     } else { // !doFetch - so just check they are present
 572         // check that all the dirs are really there
 573         def List<String> errors = []
 574         packages.each { pkgname->
 575             def String basename = pkgname.substring(0,pkgname.lastIndexOf("."))
 576             def File pkgdir = file("$destdir/$basename")
 577 
 578             if (!pkgdir.isDirectory()) {
 579                 errors.add(pkgname)
 580             }
 581         }
 582         if (errors.size > 0) {
 583             throw new GradleException("Error: missing tool packages: $errors")
 584         } else {
 585             logger.quiet "all tool packages are present $packages"
 586         }
 587     }
 588 }
 589 
 590 // Now we need to define the native compilation tasks. The set of parameters to
 591 // native compilation depends on the target platform (and also to some extent what platform
 592 // you are compiling on). These settings are contained in various gradle files
 593 // such as mac.gradle and linux.gradle and armhf.gradle. Additionally, the developer
 594 // can specify COMPILE_FLAGS_FILE to be a URL or path to a different gradle file
 595 // that will contain the appropriate flags.
 596 defineProperty("COMPILE_FLAGS_FILES", COMPILE_TARGETS.split(",").collect {"buildSrc/${it.trim()}.gradle"}.join(","))
 597 if (COMPILE_TARGETS == "all") {
 598     def tmp = []
 599     File buildSrcDir = file("buildSrc")
 600     buildSrcDir.listFiles().each { File f ->
 601         if (f.isFile() && f.name.endsWith(".gradle") && !f.name.equals("build.gradle")) {
 602             def target = f.name.substring(0, f.name.lastIndexOf('.gradle')).toUpperCase(Locale.ROOT)
 603             apply from: f
 604             if (project.ext["${target}"].canBuild) {
 605                 tmp.add(target)
 606             }
 607         }
 608     }
 609     COMPILE_FLAGS_FILES = tmp.collect { "buildSrc/${it}.gradle"}.join(",")
 610     COMPILE_TARGETS = tmp.collect { "${it.toLowerCase()}"}.join(",")
 611 } else {
 612     COMPILE_FLAGS_FILES.split(",").each {
 613         logger.info("Applying COMPILE_FLAGS_FILE '$it'")
 614         apply from: it
 615     }
 616 }
 617 
 618 if (COMPILE_TARGETS != "") {
 619     def tmp = []
 620     COMPILE_TARGETS.split(",").each {target ->
 621         if (project.ext["${target.toUpperCase(Locale.ROOT)}"].canBuild) {
 622             tmp.add(target)
 623         }
 624     }
 625     COMPILE_TARGETS = tmp.collect { "${it.toLowerCase()}"}.join(",")
 626 }
 627 
 628 // Sanity check the expected properties all exist
 629 compileTargets { t ->
 630     // Every platform must define these variables
 631     if (!project.hasProperty(t.upper)) throw new Exception("ERROR: Incorrectly configured compile flags file, missing ${t.name} property")
 632     def props = project.ext[t.upper];
 633     ["compileSwing", "compileSWT", "compileFXPackager", "libDest"].each { prop ->
 634         if (!props.containsKey(prop)) throw new Exception("ERROR: Incorrectly configured compile flags file, missing ${prop} property on ${t.name}")
 635     }
 636 }
 637 
 638 // Various build flags may be set by the different target files, such as
 639 // whether to build Swing, SWT, FXPackager, etc. We iterate over all
 640 // compile targets and look for these settings in our properties. Note that
 641 // these properties cannot be set from the command line, but are set by
 642 // the target build files such as armv6hf.gradle or mac.gradle.
 643 ext.COMPILE_SWING = false;
 644 ext.COMPILE_SWT = false;
 645 ext.COMPILE_FXPACKAGER = false;
 646 compileTargets { t ->
 647     def targetProperties = project.rootProject.ext[t.upper]
 648 
 649     if (targetProperties.compileSwing) COMPILE_SWING = true
 650     if (targetProperties.compileSWT) COMPILE_SWT = true
 651     if (targetProperties.compileFXPackager) COMPILE_FXPACKAGER = true
 652 
 653     if (!targetProperties.containsKey('compileWebnodeNative')) {
 654         // unless specified otherwise, we will compile native Webnode if IS_COMPILE_WEBKIT
 655         targetProperties.compileWebnodeNative = true
 656     }
 657 
 658     if (!targetProperties.containsKey('compileMediaNative')) {
 659         // unless specified otherwise, we will compile native Media if IS_COMPILE_MEDIA
 660         targetProperties.compileMediaNative = true
 661     }
 662 
 663     if (!targetProperties.containsKey('includeSWT')) targetProperties.includeSWT = true
 664     if (!targetProperties.containsKey('includeSwing')) targetProperties.includeSwing = true
 665     if (!targetProperties.containsKey('includeNull3d')) targetProperties.includeNull3d = true
 666     if (!targetProperties.containsKey('includeLens')) targetProperties.includeLens = false
 667     if (!targetProperties.containsKey('includeMonocle')) targetProperties.includeMonocle = false
 668     if (!targetProperties.containsKey('includeEGL')) targetProperties.includeEGL = false
 669 
 670     if (!targetProperties.containsKey('includeGTK')) targetProperties.includeGTK = IS_LINUX
 671 
 672     // This value is used to under ./build/${sdkDirName} to allow for
 673     // a common name for the hosted build (for use when building apps)
 674     // and a unique name for cross builds.
 675     if (rootProject.defaultHostTarget.equals(t.name)) {
 676         // use a simple common default for the "host" build
 677         targetProperties.sdkDirName="sdk"
 678         targetProperties.exportDirName="export"
 679         targetProperties.bundleDirName="bundles"
 680     } else {
 681         // and a more complex one for cross builds
 682         targetProperties.sdkDirName="${t.name}-sdk"
 683         targetProperties.exportDirName="${t.name}-export"
 684         targetProperties.bundleDirName="${t.name}-bundles"
 685     }
 686 }
 687 
 688 /******************************************************************************
 689  *                                                                            *
 690  *                         Build Setup Sanity Checks                          *
 691  *                                                                            *
 692  *  Here we do a variety of checks so that if the version of Java you are     *
 693  *  building with is misconfigured, or you are using the wrong version of     *
 694  *  gradle, etc you will get some kind of helpful error / warning message     *
 695  *                                                                            *
 696  *****************************************************************************/
 697 
 698 // Verify that the architecture & OS are supported configurations. Note that
 699 // at present building on PI is not supported, but we would only need to make
 700 // some changes on assumptions on what should be built (like SWT / Swing) and
 701 // such and we could probably make it work.
 702 if (!IS_MAC && !IS_WINDOWS && !IS_LINUX) logger.error("Unsupported build OS ${OS_NAME}")
 703 if (IS_WINDOWS && OS_ARCH != "x86" && OS_ARCH != "amd64") {
 704     throw new Exception("Unknown and unsupported build architecture: $OS_ARCH")
 705 } else if (IS_MAC && OS_ARCH != "x86_64") {
 706     throw new Exception("Unknown and unsupported build architecture: $OS_ARCH")
 707 } else if (IS_LINUX && OS_ARCH != "i386" && OS_ARCH != "amd64") {
 708     throw new Exception("Unknown and unsupported build architecture: $OS_ARCH")
 709 }
 710 
 711 // Sanity check that we actually have a list of compile targets to execute
 712 if (COMPILE_TARGETS == null || COMPILE_TARGETS == "") {
 713     throw new Exception("Unable to determine compilation platform, must specify valid COMPILE_TARGETS!")
 714 }
 715 
 716 // Make sure JDK_HOME/bin/java exists
 717 if (!file(JAVA).exists()) throw new Exception("Missing or incorrect path to 'java': '$JAVA'. Perhaps bad JDK_HOME? $JDK_HOME")
 718 if (!file(JAVAC).exists()) throw new Exception("Missing or incorrect path to 'javac': '$JAVAC'. Perhaps bad JDK_HOME? $JDK_HOME")
 719 if (!file(JAVAH).exists()) throw new Exception("Missing or incorrect path to 'javah': '$JAVAH'. Perhaps bad JDK_HOME? $JDK_HOME")
 720 if (!file(JAVADOC).exists()) throw new Exception("Missing or incorrect path to 'javadoc': '$JAVADOC'. Perhaps bad JDK_HOME? $JDK_HOME")
 721 
 722 
 723 // Determine the verion of Java in JDK_HOME. It looks like this:
 724 //
 725 // $ java -version
 726 // java version "1.7.0_45"
 727 // Java(TM) SE Runtime Environment (build 1.7.0_45-b18)
 728 // Java HotSpot(TM) 64-Bit Server VM (build 24.45-b08, mixed mode)
 729 //
 730 // We need to parse the second line
 731 def inStream = new java.io.BufferedReader(new java.io.InputStreamReader(new java.lang.ProcessBuilder(JAVA, "-version").start().getErrorStream()));
 732 try {
 733     if (inStream.readLine() != null) {
 734         String v = inStream.readLine();
 735         if (v != null) {
 736             int ib = v.indexOf(" (build ");
 737             if (ib != -1) {
 738                 String ver = v.substring(ib + 8, v.size() - 1);
 739 
 740                 defineProperty("jdkRuntimeVersion", ver)
 741                 defineProperty("jdkVersion", jdkRuntimeVersion.split("-")[0])
 742                 defineProperty("jdkBuildNumber", jdkRuntimeVersion.substring(jdkRuntimeVersion.lastIndexOf("-b") + 2))
 743             }
 744         }
 745     }
 746 } finally {
 747     inStream.close();
 748 }
 749 if (!project.hasProperty("jdkRuntimeVersion")) throw new Exception("Unable to determine the version of Java in JDK_HOME at $JDK_HOME");
 750 
 751 
 752 
 753 // Verify that CONF is something useful
 754 if (CONF != "Release" && CONF != "Debug" && CONF != "DebugNative") {
 755     logger.warn("Unknown configuration CONF='$CONF'. Treating as 'Release'")
 756 }
 757 
 758 // If the number of compile threads is less than 1 then we have a problem!
 759 if (Integer.parseInt(NUM_COMPILE_THREADS.toString()) < 1) {
 760     logger.warn("NUM_COMPILE_THREADS was specified as '$NUM_COMPILE_THREADS' which is less than the minimum value of 1. " +
 761             "Building with a value of 1 instead.")
 762     NUM_COMPILE_THREADS = 1
 763 }
 764 
 765 // Check that Gradle 1.8 is in use.
 766 if (gradle.gradleVersion != "1.8") {
 767     def ver = gradle.gradleVersion.split("[\\.]");
 768     def gradleMajor = Integer.parseInt(ver[0]);
 769     def gradleMinor = Integer.parseInt(ver[1]);
 770     def err = "";
 771     if (gradleMajor == 1) {
 772         if (gradleMinor < 8) {
 773             err = "Gradle version too old: ${gradle.gradleVersion}; must be at least 1.8"
 774         }
 775 
 776         // Blacklisted versions of gradle
 777         if (gradleMinor == 11) {
 778             err = "JavaFX fails to build with Gradle ${gradle.gradleVersion}; supported version is 1.8"
 779         }
 780     }
 781 
 782     if (IS_GRADLE_VERSION_CHECK && err != "") {
 783         fail(err);
 784     }
 785 
 786     logger.warn("*****************************************************************");
 787     logger.warn("Unsupported gradle version $gradle.gradleVersion in use.");
 788     logger.warn("Only version 1.8 is supported. Use this version at your own risk");
 789     if ( err != "") logger.warn(err);
 790     logger.warn("*****************************************************************");
 791 }
 792 
 793 /******************************************************************************
 794  *                                                                            *
 795  *                      Logging of Properties and Settings                    *
 796  *                                                                            *
 797  *  Log some of the settings we've determined. We could log more here, it     *
 798  *  doesn't really hurt.                                                      *
 799  *                                                                            *
 800  *****************************************************************************/
 801 
 802 logger.quiet("OS_NAME: $OS_NAME")
 803 logger.quiet("OS_ARCH: $OS_ARCH")
 804 logger.quiet("JAVA_HOME: $JAVA_HOME")
 805 logger.quiet("JDK_HOME: $JDK_HOME")
 806 logger.quiet("java.runtime.version: ${javaRuntimeVersion}")
 807 logger.quiet("java version: ${javaVersion}")
 808 logger.quiet("java build number: ${javaBuildNumber}")
 809 logger.quiet("jdk.runtime.version: ${jdkRuntimeVersion}")
 810 logger.quiet("jdk version: ${jdkVersion}")
 811 logger.quiet("jdk build number: ${jdkBuildNumber}")
 812 logger.quiet("minimum java build number: ${jfxBuildJdkBuildnumMin}")
 813 logger.quiet("CONF: $CONF")
 814 logger.quiet("NUM_COMPILE_THREADS: $NUM_COMPILE_THREADS")
 815 logger.quiet("COMPILE_TARGETS: $COMPILE_TARGETS")
 816 logger.quiet("COMPILE_FLAGS_FILES: $COMPILE_FLAGS_FILES")
 817 logger.quiet("HUDSON_JOB_NAME: $HUDSON_JOB_NAME")
 818 logger.quiet("HUDSON_BUILD_NUMBER: $HUDSON_BUILD_NUMBER")
 819 logger.quiet("PROMOTED_BUILD_NUMBER: $PROMOTED_BUILD_NUMBER")
 820 logger.quiet("PRODUCT_NAME: $PRODUCT_NAME")
 821 logger.quiet("RAW_VERSION: $RAW_VERSION")
 822 logger.quiet("RELEASE_NAME: $RELEASE_NAME")
 823 logger.quiet("RELEASE_MILESTONE: $RELEASE_MILESTONE")
 824 
 825 if (UPDATE_STUB_CACHE) {
 826     logger.quiet("UPDATE_STUB_CACHE: $UPDATE_STUB_CACHE")
 827 }
 828 
 829 /******************************************************************************
 830  *                                                                            *
 831  *                Definition of Native Code Compilation Tasks                 *
 832  *                                                                            *
 833  *    - JavaHeaderTask is used to run javah. The JAVAH property will point at *
 834  *      the version of javah to be used (i.e.: a path to javah)               *
 835  *    - CCTask compiles native code. Specifically it will compile .m, .c,     *
 836  *      .cpp, or .cc files. It uses the headers provided by the               *
 837  *      JavaHeaderTask plus additional platform specific headers. It will     *
 838  *      compile into .obj files.                                              *
 839  *    - LinkTask will perform native linking and create the .dll / .so /      *
 840  *      .dylib as necessary.                                                  *
 841  *                                                                            *
 842  *****************************************************************************/
 843 
 844 // Save a reference to the buildSrc.jar file because we need it for actually
 845 // compiling things, not just for the sake of this build script
 846 // (such as generating the builders, JSL files, etc)
 847 ext.BUILD_SRC = rootProject.files("buildSrc/build/libs/buildSrc.jar")
 848 
 849 /**
 850  * Convenience method for creating javah, cc, link, and "native" tasks in the given project. These
 851  * tasks are parameterized by name, so that we can produce, for example, javahGlass, ccGlass, etc
 852  * named tasks.
 853  *
 854  * @param project The project to add tasks to
 855  * @param name The name of the project, such as "prism-common". This name is used
 856  *        in the name of the generated task, such as ccPrismCommon, and also
 857  *        in the name of the final library, such as libprism-common.dylib.
 858  */
 859 void addNative(Project project, String name) {
 860     // TODO if we want to handle 32/64 bit windows in the same build,
 861     // Then we will need to modify the win compile target to be win32 or win64
 862     def capitalName = name.split("-").collect{it.capitalize()}.join()
 863     def nativeTask = project.task("native$capitalName", group: "Build") {
 864         description = "Generates JNI headers, compiles, and builds native dynamic library for $name for all compile targets"
 865     }
 866     def cleanTask = project.task("cleanNative$capitalName", type: Delete, group: "Build") {
 867         description = "Clean native objects for $name"
 868     }
 869     if (project.hasProperty("nativeAllTask")) project.nativeAllTask.dependsOn nativeTask
 870     project.assemble.dependsOn(nativeTask)
 871     if (project.hasProperty("cleanNativeAllTask")) project.cleanNativeAllTask.dependsOn cleanTask
 872 
 873     // Each of the different compile targets will be placed in a sub directory
 874     // of these root dirs, with the name of the dir being the name of the target
 875     def headerRootDir = project.file("$project.buildDir/generated-src/headers/$name")
 876     def nativeRootDir = project.file("$project.buildDir/native/$name")
 877     def libRootDir = project.file("$project.buildDir/libs/$name")
 878     // For each compile target, create a javah / cc / link triplet
 879     compileTargets { t ->
 880         def targetProperties = project.rootProject.ext[t.upper]
 881         def library = targetProperties.library
 882         def properties = targetProperties.get(name)
 883         def nativeDir = file("$nativeRootDir/${t.name}")
 884         def headerDir = file("$headerRootDir/${t.name}")
 885 
 886         // If there is not a library clause in the properties, assume it is not wanted
 887         if (!targetProperties.containsKey(name)) {
 888             println("Ignoring native library ${name}. Not defined in ${t.name} project properties");
 889             return
 890         }
 891 
 892         // check for the property disable${name} = true
 893         def String disableKey = "disable${name}"
 894         def boolean disabled = targetProperties.containsKey(disableKey) ? targetProperties.get(disableKey) : false
 895         if (disabled) {
 896             println("Native library ${name} disabled in ${t.name} project properties");
 897             return
 898         }
 899 
 900         def javahTask = project.task("javah${t.capital}${capitalName}", type: JavaHeaderTask, dependsOn: project.classes, group: "Build") {
 901             description = "Generates JNI Headers for ${name} for ${t.name}"
 902             if (properties.javahSource == null) {
 903                 source(project.sourceSets.main.output.classesDir)
 904             } else {
 905                 source(properties.javahSource)
 906             }
 907             if (properties.javahClasspath == null) {
 908                 classpath = project.files(project.sourceSets.main.output.classesDir)
 909                 classpath += project.sourceSets.main.compileClasspath
 910             } else {
 911                 classpath = project.files(properties.javahClasspath)
 912             }
 913             output = headerDir
 914             include(properties.javahInclude)
 915             cleanTask.delete headerDir
 916         }
 917 
 918         def variants = properties.containsKey("variants") ? properties.variants : [""];
 919         variants.each { variant ->
 920             def variantProperties = variant == "" ? properties : properties.get(variant)
 921             def capitalVariant = variant.capitalize()
 922             def ccOutput = variant == "" ? nativeDir : file("$nativeDir/$variant")
 923             def ccTask = project.task("cc${t.capital}$capitalName$capitalVariant", type: CCTask, dependsOn: javahTask, group: "Build") {
 924                 description = "Compiles native sources for ${name} for ${t.name}${capitalVariant != '' ? ' for variant ' + capitalVariant : ''}"
 925                 matches = ".*\\.c|.*\\.cpp|.*\\.m|.*\\.cc"
 926                 headers = headerDir
 927                 output(ccOutput)
 928                 params.addAll(variantProperties.ccFlags)
 929                 compiler = variantProperties.compiler
 930                 source(variantProperties.nativeSource)
 931                 cleanTask.delete ccOutput
 932             }
 933             def linkTask = project.task("link${t.capital}$capitalName$capitalVariant", type: LinkTask, dependsOn: ccTask, group: "Build") {
 934                 description = "Creates native dynamic library for $name for ${t.name}${capitalVariant != '' ? ' for variant ' + capitalVariant : ''}"
 935                 objectDir = ccOutput
 936                 linkParams.addAll(variantProperties.linkFlags)
 937                 lib = file("$libRootDir/${t.name}/${variant == '' ? library(properties.lib) : library(variantProperties.lib)}")
 938                 linker = variantProperties.linker
 939                 cleanTask.delete "$libRootDir/${t.name}"
 940             }
 941             nativeTask.dependsOn(linkTask)
 942             if (IS_WINDOWS && t.name == "win") {
 943                 def rcTask = project.task("rc$capitalName$capitalVariant", type: CompileResourceTask, dependsOn: javahTask, group: "Build") {
 944                     description = "Compiles native sources for $name"
 945                     matches = ".*\\.rc"
 946                     compiler = variantProperties.rcCompiler
 947                     source(variantProperties.rcSource)
 948                     if (variantProperties.rcFlags) {
 949                         rcParams.addAll(variantProperties.rcFlags)
 950                     }
 951                     output(ccOutput)
 952                 }
 953                 linkTask.dependsOn rcTask;
 954             }
 955         }
 956 
 957         def useLipo = targetProperties.containsKey('useLipo') ? targetProperties.useLipo : false
 958         if (useLipo) {
 959             def lipoTask = project.task("lipo${t.capital}$capitalName", type: LipoTask, dependsOn: javahTask, group: "Build") {
 960                 description = "Creates native fat library for $name for ${t.name}"
 961                 libDir = file("$libRootDir/${t.name}")
 962                 lib = file("$libRootDir/${t.name}/${library(properties.lib)}")
 963             }
 964             nativeTask.dependsOn(lipoTask)
 965         }
 966     }
 967 }
 968 
 969 void addJSL(Project project, String name, String pkg, Closure compile) {
 970     def lowerName = name.toLowerCase()
 971 
 972     def compileCompilers = project.task("compile${name}Compilers", type: JavaCompile, dependsOn: project.compileJava) {
 973         description = "Compile the $name JSL Compilers"
 974         classpath = project.files(project.sourceSets.main.output.classesDir) +
 975                 rootProject.BUILD_SRC +
 976                 project.configurations.antlr3
 977         source = [project.file("src/main/jsl-$lowerName")]
 978         destinationDir = project.file("$project.buildDir/classes/jsl-compilers/$lowerName")
 979     }
 980 
 981     def generateShaders = project.task("generate${name}Shaders", dependsOn: compileCompilers) {
 982         description = "Generate $name shaders from JSL"
 983         def sourceDir = project.file("src/main/jsl-$lowerName")
 984         def destinationDir = project.file("$project.buildDir/generated-src/jsl-$lowerName")
 985         inputs.dir sourceDir
 986         outputs.dir destinationDir
 987         doLast {
 988             compile(sourceDir, destinationDir)
 989         }
 990     }
 991 
 992     project.task("compile${name}JavaShaders", type: JavaCompile, dependsOn: generateShaders) {
 993         description = "Compile the Java $name JSL shaders"
 994         classpath = project.files(project.sourceSets.main.output.classesDir) + rootProject.BUILD_SRC
 995         source = [project.file("$project.buildDir/generated-src/jsl-$lowerName")]
 996         destinationDir = project.file("$project.buildDir/classes/jsl-$lowerName")
 997     }
 998 
 999     def compileHLSLShaders = project.task("compile${name}HLSLShaders", dependsOn: generateShaders, type: CompileHLSLTask) {
1000         enabled = IS_WINDOWS
1001         description = "Compile $name HLSL files into .obj files"
1002         matches = ".*\\.hlsl"
1003         output project.file("$project.buildDir/hlsl/$name/$pkg")
1004         source project.file("$project.buildDir/generated-src/jsl-$lowerName/$pkg")
1005     }
1006 
1007     project.task("process${name}Shaders", dependsOn: [generateShaders, compileHLSLShaders], type: Copy, description: "Copy hlsl / frag shaders to build/resources/jsl-$lowerName") {
1008         from("$project.buildDir/hlsl/$name") {
1009             include "**/*.obj"
1010         }
1011         from("$project.buildDir/generated-src/jsl-$lowerName") {
1012             include("**/*.frag")
1013         }
1014         into "$project.buildDir/resources/jsl-$lowerName"
1015     }
1016 }
1017 
1018 /**
1019  * Parses a JDK version string. The string must be in one of the following
1020  * two formats:
1021  *
1022  *     major.minor.subminor
1023  * or
1024  *     major.minor.subminor_update
1025  *
1026  * In both cases a list of 4 integers is returned, with element 3 set to
1027  * 0 in the former case.
1028  */
1029 List parseJdkVersion(String version) {
1030     def arr = version.split("[_\\.]");
1031     def intArr = [];
1032     arr.each { s -> intArr += Integer.parseInt(s); }
1033     if (intArr.size() < 4) intArr += 0;
1034     return intArr;
1035 }
1036 
1037 /**
1038  * Returns -1, 0, or 1 depending on whether JDK version "a" is less than,
1039  * equal to, or grater than version "b".
1040  */
1041 int compareJdkVersion(String a, String b) {
1042     def aIntArr = parseJdkVersion(a);
1043     def bIntArr = parseJdkVersion(b);
1044 
1045     for (int i = 0; i < 4; i++) {
1046         if (aIntArr[i] < bIntArr[i]) return -1;
1047         if (aIntArr[i] > bIntArr[i]) return  1;
1048     }
1049     return 0;
1050 }
1051 
1052 // Task to verify the minimum level of Java needed to build JavaFX
1053 task verifyJava() {
1054     doLast {
1055         def status = compareJdkVersion(jdkVersion, jfxBuildJdkVersion);
1056         if (status < 0) {
1057             fail("java version mismatch: JDK version (${jdkVersion}) < minimum version (${jfxBuildJdkVersion})")
1058         } else if (status == 0) {
1059             def buildNum = Integer.parseInt(jdkBuildNumber)
1060             def minBuildNum = Integer.parseInt(jfxBuildJdkBuildnumMin)
1061             if (buildNum < minBuildNum) {
1062                 fail("JDK build number ($buildNum) < minimum build number ($minBuildNum)")
1063             }
1064         }
1065     }
1066 }
1067 
1068 // Task to check whether jfxrt.jar is present in the JDK
1069 task checkJfxrtJar {
1070     doLast {
1071         def jfxrtFile = new File("$JDK_HOME/jre/lib/ext/jfxrt.jar");
1072         if (jfxrtFile.exists()) {
1073             fail("$jfxrtFile must be removed before building sdk")
1074         }
1075     }
1076 }
1077 
1078 task updateCacheIfNeeded() {
1079     // an empty task we can add to as needed for UPDATE_STUB_CACHE
1080 }
1081 
1082 /*****************************************************************************
1083 *        Project definitions (dependencies, etc)                             *
1084 *****************************************************************************/
1085 
1086 void addJCov(p, test) {
1087     test.doFirst {
1088         def jcovJVMArgument =
1089                 "include=javafx," +
1090                 "include=com.sun.javafx," +
1091                 "include=com.sun.glass," +
1092                 "include=com.sun.openpisces," +
1093                 "include=com.sun.pisces," +
1094                 "include=com.sun.prism," +
1095                 "include=com.sun.scenario," +
1096                 "include=com.sun.webkit," +
1097                 "exclude=com," +
1098                 "exclude=java," +
1099                 "exclude=javax," +
1100                 "exclude=\"**.test\"," +
1101                 "exclude=\"**.*Test\"," +
1102                 "file=build/reports/jcov/report.xml," +
1103                 "merge=merge";
1104         test.jvmArgs("-javaagent:${p.configurations.testCompile.files.find { it.name.startsWith('jcov') }}=$jcovJVMArgument");
1105         p.mkdir p.file("build/reports/jcov")
1106     }
1107     test.doLast {
1108         def reportFile = p.file("build/reports/jcov/report.xml")
1109         if (reportFile.exists()) {
1110             p.javaexec {
1111                 workingDir = p.file("build/reports/jcov")
1112                 classpath = p.files(p.configurations.testCompile.files.find { it.name.startsWith('jcov') })
1113                 main = "com.sun.tdk.jcov.Helper"
1114                 args = [
1115                         "RepGen",
1116                         "-exclude", "\"**.test\"",
1117                         "-exclude", "\"**.*Test\"",
1118                         "-output", ".",
1119                         "-source", p.sourceSets.main.java.srcDirs.collect{p.file(it)}.join(":"),
1120                         "report.xml"
1121                 ]
1122             }
1123         }
1124     }
1125 }
1126 
1127 allprojects {
1128     // We want to configure all projects as java projects and use the same compile settings
1129     // etc, except for the root project which we just want to ignore (and for now media)
1130     if (project == rootProject) {
1131        return
1132     }
1133     if (project.path.startsWith(":apps")) {
1134         // Lets handle the apps tree differently, as it is a collection of ant builds,
1135         // and the ant importer collides with the 'apply plugin:java'
1136         return
1137     }
1138     // All of our projects are java projects
1139     apply plugin: "java"
1140     sourceCompatibility = 1.8
1141 
1142     // Setup the repositories that we'll download libraries from. Maven Central is
1143     // just easy for most things. The custom "ivy" repo is for downloading SWT. The way it
1144     // works is to setup the download URL such that it will resolve to the actual jar file
1145     // to download. See SWT_FILE_NAME for the name of the jar that will be used as the
1146     // "artifact" in the pattern below. Note that the closed builds use different repositories
1147     // so if you are debugging a closed-build artifact related build issue, check out the
1148     // closed gradle file instead.
1149     if (!BUILD_CLOSED) {
1150         repositories {
1151             mavenCentral()
1152             ivy {
1153                 url "http://download.eclipse.org/eclipse/updates/3.7/R-3.7.2-201202080800/plugins/"
1154                 layout "pattern", {
1155                     artifact "[artifact].[ext]"
1156                 }
1157             }
1158         }
1159     }
1160 
1161     // By default all of our projects require junit for testing so we can just
1162     // setup this dependency here.
1163     dependencies {
1164         testCompile group: "junit", name: "junit", version: "4.8.2"
1165         if (BUILD_CLOSED && DO_JCOV)  {
1166             testCompile name: "jcov"
1167         }
1168     }
1169 
1170     // Compile and run tests against the jfxrt.jar in the built sdk of the host machine
1171     def sdkDir = "${rootProject.buildDir}/sdk"
1172     def jfxrtJar = "$sdkDir/rt/lib/ext/jfxrt.jar"
1173     def testJfxrtJar = DO_BUILD_SDK_FOR_TEST ? jfxrtJar : jfxrtJarFromSdk
1174 
1175     // At the moment the ASM library shipped with Gradle that is used to
1176     // discover the different test classes fails on Java 8, so in order
1177     // to have sourceCompatibility set to 1.8 I have to also turn scanForClasses off
1178     // and manually specify the includes / excludes. At the moment we use
1179     // Java 7 but when we switch to 8 this will be needed, and probably again when
1180     // we start building with Java 9.
1181     test {
1182         jvmArgs("-Djava.ext.dirs=");
1183         executable = JAVA;
1184         enableAssertions = true;
1185         testLogging.exceptionFormat = "full";
1186         scanForTestClasses = false;
1187         include("**/*Test.*");
1188         if (BUILD_CLOSED && DO_JCOV) {
1189             addJCov(project, test)
1190         }
1191         classpath = files(testJfxrtJar) + classpath
1192         if (IS_HEADLESS_TEST) {
1193             systemProperty 'glass.platform', 'Monocle'
1194             systemProperty 'monocle.platform', 'Headless'
1195             systemProperty 'prism.order', 'sw'
1196             systemProperty 'com.sun.javafx.gestures.zoom', 'true'
1197             systemProperty 'com.sun.javafx.gestures.rotate', 'true'
1198             systemProperty 'com.sun.javafx.gestures.scroll', 'true'
1199         }
1200     }
1201 
1202     compileTestJava {
1203         classpath = files(testJfxrtJar) + classpath
1204     }
1205 
1206     // Exclude any non-public-API classes from having javadoc generated. This block is used
1207     // when generating JavaDocs for a specific project. When generating the JavaDocs for the
1208     // entire SDK, a different javadoc command is used (see the javadoc task on the top level)
1209     javadoc {
1210         enabled = IS_BUILD_JAVADOC
1211         exclude("com/**/*", "Compile*", "javafx/builder/**/*", "javafx/scene/accessibility/**/*");
1212         executable = JAVADOC;
1213         options.windowTitle("JavaFX Project ${project.name} ${RELEASE_NAME}")
1214         if (BUILD_CLOSED) {
1215             options.linksOffline(JDK_DOCS, JDK_DOCS_CLOSED);
1216         } else {
1217             options.links(JDK_DOCS);
1218         }
1219         options.addBooleanOption("XDignore.symbol.file").setValue(true);
1220         options.addBooleanOption("Xdoclint:none").setValue(!IS_DOC_LINT);
1221         options.addBooleanOption("javafx").setValue(true);
1222         options.addBooleanOption("use").setValue(true);
1223         // All doc-files are located in src/main/docs because Gradle's javadoc doesn't copy
1224         // over the doc-files if they are embedded with the sources. I find this arrangement
1225         // somewhat cleaner anyway (never was a fan of mixing javadoc files with the sources)
1226         doLast {
1227             copy {
1228                 from "src/main/docs"
1229                 into "$buildDir/docs/javadoc"
1230             }
1231         }
1232     }
1233 }
1234 
1235 // The "base" project is our first module and the most basic one required for
1236 // all other modules. It is useful even for non-GUI applications.
1237 project(":base") {
1238     dependencies {
1239         compile BUILD_SRC
1240     }
1241 
1242     // We need to take the VersionInfo.java file and replace the various
1243     // properties within it
1244     def replacements = [
1245         "BUILD_TIMESTAMP": new java.util.Date(),
1246         "HUDSON_JOB_NAME": HUDSON_JOB_NAME,
1247         "HUDSON_BUILD_NUMBER": HUDSON_BUILD_NUMBER,
1248         "PROMOTED_BUILD_NUMBER": PROMOTED_BUILD_NUMBER,
1249         "PRODUCT_NAME": PRODUCT_NAME,
1250         "RAW_VERSION": RAW_VERSION,
1251         "RELEASE_NAME": RELEASE_NAME,
1252         "RELEASE_MILESTONE": RELEASE_MILESTONE];
1253     task processVersionInfo(type: Copy, description: "Replace params in VersionInfo and copy file to destination") {
1254         doFirst { mkdir "$buildDir/generated-src/version-info" }
1255         from "src/main/version-info"
1256         into "$buildDir/generated-src/version-info/com/sun/javafx/runtime"
1257         filter {line->
1258             replacements.each() {k, v ->
1259                 line = line.replace("@$k@", v.toString());
1260             }
1261             line
1262         }
1263     }
1264 
1265     compileJava.dependsOn updateCacheIfNeeded
1266     compileJava.dependsOn verifyJava
1267 
1268     // Make sure to include $buildDir/generated-src/version-info that we previously created.
1269     // We DO NOT want to include src/main/version-info
1270     if (System.getProperty("jfx.build.jdk.defenders", "true").equals("true")) {
1271         sourceSets.main.java.srcDirs += "src/main/java8"
1272     } else {
1273         sourceSets.main.java.srcDirs += "src/main/java7"
1274     }
1275 
1276     if (IS_COMPILE_JFR) {
1277         sourceSets.main.java.srcDirs += "src/main/java-jfr"
1278     }
1279 
1280     sourceSets.main.java.srcDirs += "$buildDir/generated-src/version-info"
1281 
1282     compileJava.dependsOn processVersionInfo
1283 }
1284 
1285 // The graphics module is needed for any graphical JavaFX application. It requires
1286 // the base module and includes the scene graph, layout, css, prism, windowing, etc.
1287 // This is a fairly complicated module. There are many different types of native components
1288 // that all need to be compiled.
1289 project(":graphics") {
1290     // Workaround for lack of Antlr 3 support in Gradle. By defining a configuration,
1291     // we can then give it a class path and use that classpath to execute a java command
1292     getConfigurations().create("antlr3");
1293 
1294     sourceSets {
1295         main
1296         test
1297         stub
1298     }
1299 
1300     dependencies {
1301         compile project(":base"), BUILD_SRC
1302         compile name: SWT_FILE_NAME
1303         stubCompile group: "junit", name: "junit", version: "4.8.2",
1304         project(":base").sourceSets.test.output, sourceSets.main.output
1305         antlr3 group: "org.antlr", name: "antlr", version: "3.1.3"
1306         antlr3 group: "org.antlr", name: "antlr-runtime",  version: "3.1.3"
1307         antlr3 group: "org.antlr", name: "stringtemplate", version: "3.2"
1308     }
1309 
1310     // Create a single "native" task which will depend on all the individual native tasks for graphics
1311     project.ext.nativeAllTask = task("native", group: "Build", description: "Compiles and Builds all native libraries for Graphics");
1312     project.ext.cleanNativeAllTask = task("cleanNative", group: "Build", description: "Clean all native libraries and objects for Graphics");
1313 
1314     // Add tasks for native compilation
1315     addNative(project, "glass");
1316     addNative(project, "prism")
1317     addNative(project, "prismSW")
1318     addNative(project, "font")
1319     addNative(project, "iio")
1320     addNative(project, "prismES2")
1321 
1322     if (IS_COMPILE_PANGO) {
1323         addNative(project, "fontFreetype")
1324         addNative(project, "fontPango")
1325     }
1326 
1327     if (IS_WINDOWS) {
1328         addNative(project, "prismD3D")
1329         // TODO need to hook this up to be executed only if PassThroughVS.h is missing or PassThroughVS.hlsl is changed
1330         task generateD3DHeaders(group: "Build") {
1331             enabled = IS_WINDOWS
1332             dependsOn javahWinPrismD3D
1333             inputs.file "src/main/native-prism-d3d/hlsl/Mtl1PS.hlsl"
1334             inputs.file "src/main/native-prism-d3d/hlsl/Mtl1VS.hlsl"
1335             inputs.file "src/main/native-prism-d3d/PassThroughVS.hlsl"
1336             outputs.dir "$buildDir/headers/PrismD3D/"
1337             outputs.dir "$buildDir/headers/PrismD3D/hlsl/"
1338             description = "Generate headers by compiling hlsl files"
1339             doLast {
1340                 mkdir file("$buildDir/headers/PrismD3D/hlsl")
1341                 def PS_3D_SRC = file("src/main/native-prism-d3d/hlsl/Mtl1PS.hlsl")
1342                 def VS_3D_SRC = file("src/main/native-prism-d3d/hlsl/Mtl1VS.hlsl")
1343                 def PASSTHROUGH_VS_SRC = file("src/main/native-prism-d3d/PassThroughVS.hlsl")
1344                 def jobs = [
1345                         ["$FXC", "/nologo", "/T", "vs_3_0", "/Fh", "$buildDir/headers/PrismD3D/PassThroughVS.h", "/E", "passThrough", "$PASSTHROUGH_VS_SRC"],
1346                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS.h", "/DSpec=0", "/DSType=0", "$PS_3D_SRC"],
1347                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_i.h", "/DSpec=0", "/DSType=0", "/DIllumMap=1", "$PS_3D_SRC"],
1348                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s1n.h", "/DSpec=1", "/DSType=0", "$PS_3D_SRC"],
1349                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s2n.h", "/DSpec=2", "/DSType=0", "$PS_3D_SRC"],
1350                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s3n.h", "/DSpec=3", "/DSType=0", "$PS_3D_SRC"],
1351                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s1t.h", "/DSpec=1", "/DSType=1", "$PS_3D_SRC"],
1352                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s2t.h", "/DSpec=2", "/DSType=1", "$PS_3D_SRC"],
1353                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s3t.h", "/DSpec=3", "/DSType=1", "$PS_3D_SRC"],
1354                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s1c.h", "/DSpec=1", "/DSType=2", "$PS_3D_SRC"],
1355                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s2c.h", "/DSpec=2", "/DSType=2", "$PS_3D_SRC"],
1356                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s3c.h", "/DSpec=3", "/DSType=2", "$PS_3D_SRC"],
1357                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s1m.h", "/DSpec=1", "/DSType=3", "$PS_3D_SRC"],
1358                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s2m.h", "/DSpec=2", "/DSType=3", "$PS_3D_SRC"],
1359                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s3m.h", "/DSpec=3", "/DSType=3", "$PS_3D_SRC"],
1360                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b1n.h", "/DSpec=1", "/DSType=0", "/DBump=1", "$PS_3D_SRC"],
1361                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b2n.h", "/DSpec=2", "/DSType=0", "/DBump=1", "$PS_3D_SRC"],
1362                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b3n.h", "/DSpec=3", "/DSType=0", "/DBump=1", "$PS_3D_SRC"],
1363                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b1t.h", "/DSpec=1", "/DSType=1", "/DBump=1", "$PS_3D_SRC"],
1364                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b2t.h", "/DSpec=2", "/DSType=1", "/DBump=1", "$PS_3D_SRC"],
1365                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b3t.h", "/DSpec=3", "/DSType=1", "/DBump=1", "$PS_3D_SRC"],
1366                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b1c.h", "/DSpec=1", "/DSType=2", "/DBump=1", "$PS_3D_SRC"],
1367                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b2c.h", "/DSpec=2", "/DSType=2", "/DBump=1", "$PS_3D_SRC"],
1368                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b3c.h", "/DSpec=3", "/DSType=2", "/DBump=1", "$PS_3D_SRC"],
1369                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b1m.h", "/DSpec=1", "/DSType=3", "/DBump=1", "$PS_3D_SRC"],
1370                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b2m.h", "/DSpec=2", "/DSType=3", "/DBump=1", "$PS_3D_SRC"],
1371                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b3m.h", "/DSpec=3", "/DSType=3", "/DBump=1", "$PS_3D_SRC"],
1372                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s1ni.h", "/DSpec=1", "/DSType=0", "/DIllumMap=1", "$PS_3D_SRC"],
1373                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s2ni.h", "/DSpec=2", "/DSType=0", "/DIllumMap=1", "$PS_3D_SRC"],
1374                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s3ni.h", "/DSpec=3", "/DSType=0", "/DIllumMap=1", "$PS_3D_SRC"],
1375                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s1ti.h", "/DSpec=1", "/DSType=1", "/DIllumMap=1", "$PS_3D_SRC"],
1376                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s2ti.h", "/DSpec=2", "/DSType=1", "/DIllumMap=1", "$PS_3D_SRC"],
1377                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s3ti.h", "/DSpec=3", "/DSType=1", "/DIllumMap=1", "$PS_3D_SRC"],
1378                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s1ci.h", "/DSpec=1", "/DSType=2", "/DIllumMap=1", "$PS_3D_SRC"],
1379                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s2ci.h", "/DSpec=2", "/DSType=2", "/DIllumMap=1", "$PS_3D_SRC"],
1380                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s3ci.h", "/DSpec=3", "/DSType=2", "/DIllumMap=1", "$PS_3D_SRC"],
1381                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s1mi.h", "/DSpec=1", "/DSType=3", "/DIllumMap=1", "$PS_3D_SRC"],
1382                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s2mi.h", "/DSpec=2", "/DSType=3", "/DIllumMap=1", "$PS_3D_SRC"],
1383                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s3mi.h", "/DSpec=3", "/DSType=3", "/DIllumMap=1", "$PS_3D_SRC"],
1384                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b1ni.h", "/DSpec=1", "/DSType=0", "/DBump=1", "/DIllumMap=1", "$PS_3D_SRC"],
1385                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b2ni.h", "/DSpec=2", "/DSType=0", "/DBump=1", "/DIllumMap=1", "$PS_3D_SRC"],
1386                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b3ni.h", "/DSpec=3", "/DSType=0", "/DBump=1", "/DIllumMap=1", "$PS_3D_SRC"],
1387                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b1ti.h", "/DSpec=1", "/DSType=1", "/DBump=1", "/DIllumMap=1", "$PS_3D_SRC"],
1388                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b2ti.h", "/DSpec=2", "/DSType=1", "/DBump=1", "/DIllumMap=1", "$PS_3D_SRC"],
1389                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b3ti.h", "/DSpec=3", "/DSType=1", "/DBump=1", "/DIllumMap=1", "$PS_3D_SRC"],
1390                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b1ci.h", "/DSpec=1", "/DSType=2", "/DBump=1", "/DIllumMap=1", "$PS_3D_SRC"],
1391                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b2ci.h", "/DSpec=2", "/DSType=2", "/DBump=1", "/DIllumMap=1", "$PS_3D_SRC"],
1392                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b3ci.h", "/DSpec=3", "/DSType=2", "/DBump=1", "/DIllumMap=1", "$PS_3D_SRC"],
1393                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b1mi.h", "/DSpec=1", "/DSType=3", "/DBump=1", "/DIllumMap=1", "$PS_3D_SRC"],
1394                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b2mi.h", "/DSpec=2", "/DSType=3", "/DBump=1", "/DIllumMap=1", "$PS_3D_SRC"],
1395                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b3mi.h", "/DSpec=3", "/DSType=3", "/DBump=1", "/DIllumMap=1", "$PS_3D_SRC"],
1396                         ["$FXC", "/nologo", "/T", "vs_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1VS_Obj.h", "/DVertexType=ObjVertex", "$VS_3D_SRC"]
1397                 ]
1398                 final ExecutorService executor = Executors.newFixedThreadPool(Integer.parseInt(project.NUM_COMPILE_THREADS.toString()));
1399                 final CountDownLatch latch = new CountDownLatch(jobs.size());
1400                 List futures = new ArrayList<Future>();
1401                 jobs.each { cmd ->
1402                     futures.add(executor.submit(new Runnable() {
1403                         @Override public void run() {
1404                             try {
1405                                 exec {
1406                                     commandLine cmd
1407                                 }
1408                             } finally {
1409                                 latch.countDown();
1410                             }
1411                         }
1412                     }));
1413                 }
1414                 latch.await();
1415                 // Looking for whether an exception occurred while executing any of the futures.
1416                 // By calling "get()" on each future an exception will be thrown if one had occurred
1417                 // on the background thread.
1418                 futures.each {it.get();}
1419             }
1420         }
1421 
1422         ccWinPrismD3D.dependsOn generateD3DHeaders
1423     }
1424 
1425     // The Decora and Prism JSL files have to be generated in a very specific set of steps.
1426     //      1) Compile the *Compile.java classes. These live in src/main/jsl-* and will be
1427     //         output to $buildDir/classes/jsl-compilers/* (where * == decora or prism).
1428     //      2) Generate source files from the JSL files contained in src/main/jsl-*. These
1429     //         will be output to $buildDir/generated-src/jsl-*
1430     //      3) Compile the JSL Java sources in $buildDir/generated-src/jsl-* and put the output
1431     //         into classes/jsl-*
1432     //      4) Compile the native JSL sources in $buildDir/generated-src/jsl-* and put the obj
1433     //         files into native/jsl-* and the resulting library into libs/jsl-*.dll|so|dylib
1434     //      5) Modify the jar step to include classes/jsl-*
1435     // The native library must be copied over during SDK creation time in the "sdk" task. In
1436     // addition to these steps, the clean task is created. Note that I didn't bother to create
1437     // a new task for each of the decora files, preferring instead just to create a rule?? Also
1438     // need "clean" tasks for each compile task.
1439 
1440     addJSL(project, "Decora", "com/sun/scenario/effect/impl/hw/d3d/hlsl") { sourceDir, destinationDir ->
1441         [[fileName: "ColorAdjust", generator: "CompileJSL", outputs: "-all"],
1442          [fileName: "Brightpass", generator: "CompileJSL", outputs: "-all"],
1443          [fileName: "SepiaTone", generator: "CompileJSL", outputs: "-all"],
1444          [fileName: "PerspectiveTransform", generator: "CompileJSL", outputs: "-all"],
1445          [fileName: "DisplacementMap", generator: "CompileJSL", outputs: "-all"],
1446          [fileName: "InvertMask", generator: "CompileJSL", outputs: "-all"],
1447          [fileName: "Blend", generator: "CompileBlend", outputs: "-all"],
1448          [fileName: "PhongLighting", generator: "CompilePhong", outputs: "-all"],
1449          [fileName: "LinearConvolve", generator: "CompileLinearConvolve", outputs: "-hw"],
1450          [fileName: "LinearConvolveShadow", generator: "CompileLinearConvolve", outputs: "-hw"]].each { settings ->
1451             javaexec {
1452                 executable = JAVA
1453                 workingDir = "modules/graphics"
1454                 main = settings.generator
1455                 classpath = configurations.compile + configurations.antlr3
1456                 classpath += files("$buildDir/classes/main")
1457                 classpath += files("$buildDir/classes/jsl-compilers/decora")
1458                 args = ["-i", sourceDir, "-o", destinationDir, "-t", "-pkg", "com/sun/scenario/effect", "$settings.outputs", "$settings.fileName"]
1459                 jvmArgs "-Djava.ext.dirs="
1460             }
1461         }
1462     }
1463 
1464     task generateDecoraNativeHeaders(type: JavaHeaderTask, dependsOn: compileDecoraJavaShaders) {
1465         description = "Generates JNI Headers for Decora SSE Natives"
1466         source file("$buildDir/classes/jsl-decora")
1467         source file("$buildDir/classes/main")
1468         include("com/sun/scenario/effect/impl/sw/sse/*");
1469         classpath = files("$buildDir/classes/main", "$buildDir/classes/jsl-decora")
1470         output = file("$buildDir/generated-src/headers/jsl-decora")
1471     }
1472 
1473     task nativeDecora(dependsOn: compileDecoraHLSLShaders, group: "Build") {
1474         description = "Generates JNI headers, compiles, and builds native dynamic library for Decora"
1475     }
1476     task cleanNativeDecora(type: Delete, group: "Build") {
1477         description = "Clean native objects for Decora"
1478     }
1479 
1480     def headerDir = file("$buildDir/generated-src/headers/jsl-decora")
1481     def nativeRootDir = project.file("$project.buildDir/native/jsl-decora")
1482     def libRootDir = project.file("$project.buildDir/libs/jsl-decora")
1483     // For each compile target, create cc and link tasks
1484     compileTargets { t ->
1485         def target = t.name
1486         def upperTarget = t.upper
1487         def capitalTarget = t.capital
1488         def targetProperties = rootProject.ext[upperTarget];
1489         def library = targetProperties.library
1490         def properties = targetProperties.get('decora')
1491         def nativeDir = file("$nativeRootDir/$target");
1492 
1493         def variants = properties.containsKey("variants") ? properties.variants : [""];
1494         variants.each { variant ->
1495             def variantProperties = variant == "" ? properties : properties.get(variant)
1496             def capitalVariant = variant.capitalize()
1497             def ccOutput = variant == "" ? nativeDir : file("$nativeDir/$variant")
1498 
1499             def ccTask = task("compileDecoraNativeShaders$capitalTarget$capitalVariant", type: CCTask, dependsOn: generateDecoraNativeHeaders) {
1500                 description = "Compiles Decora SSE natives for ${t.name}${capitalVariant != '' ? ' for variant ' + capitalVariant : ''}"
1501                 matches = ".*\\.cc"
1502                 source file("$buildDir/generated-src/jsl-decora")
1503                 source file("modules/graphics/src/main/native-decora")
1504                 headers = headerDir
1505                 params.addAll(variantProperties.ccFlags)
1506                 output(ccOutput)
1507                 compiler = variantProperties.compiler
1508                 cleanNativeDecora.delete ccOutput
1509             }
1510 
1511             def linkTask = task("linkDecoraNativeShaders$capitalTarget$capitalVariant", type: LinkTask, dependsOn: ccTask) {
1512                 description = "Creates native dynamic library for Decora SSE ${t.name}${capitalVariant != '' ? ' for variant ' + capitalVariant : ''}"
1513                 objectDir = ccOutput
1514                 linkParams.addAll(variantProperties.linkFlags)
1515                 lib = file("$libRootDir/$t.name/${library(variantProperties.lib)}")
1516                 linker = variantProperties.linker
1517                 cleanNativeDecora.delete "$libRootDir/$t.name/"
1518             }
1519 
1520             if (IS_WINDOWS && target == "win") {
1521                 def rcTask = project.task("rcDecoraNativeShaders$capitalTarget$capitalVariant", type: CompileResourceTask, dependsOn: generateDecoraNativeHeaders) {
1522                     description = "Compiles native sources for Decora SSE"
1523                     matches = ".*\\.rc"
1524                     compiler = variantProperties.rcCompiler
1525                     source(variantProperties.rcSource)
1526                     if (variantProperties.rcFlags) {
1527                         rcParams.addAll(variantProperties.rcFlags)
1528                     }
1529                     output(ccOutput)
1530                 }
1531                 linkTask.dependsOn rcTask;
1532             }
1533 
1534             nativeDecora.dependsOn(linkTask)
1535         }
1536     }
1537 
1538     // Prism JSL
1539     addJSL(project, "Prism", "com/sun/prism/d3d/hlsl") { sourceDir, destinationDir ->
1540         def inputFiles = fileTree(dir: sourceDir)
1541         inputFiles.include "**/*.jsl"
1542         inputFiles.each { file ->
1543             javaexec {
1544                 executable = JAVA
1545                 workingDir = "modules/graphics"
1546                 main = "CompileJSL"
1547                 classpath = configurations.compile + configurations.antlr3
1548                 classpath += files("$buildDir/classes/jsl-compilers/prism", "modules/graphics/src/main/jsl-prism") // for the .stg
1549                 args = ["-i", sourceDir, "-o", destinationDir, "-t", "-pkg", "com/sun/prism", "-d3d", "-es2", "-name", "$file"]
1550                 jvmArgs "-Djava.ext.dirs="
1551             }
1552         }
1553     }
1554 
1555     classes.dependsOn compilePrismJavaShaders;
1556     nativePrism.dependsOn compilePrismHLSLShaders;
1557 
1558     project.nativeAllTask.dependsOn nativeDecora
1559     project.cleanNativeAllTask.dependsOn cleanNativeDecora
1560     assemble.dependsOn nativeDecora
1561     processResources.dependsOn processDecoraShaders, processPrismShaders
1562 
1563     test {
1564         def cssDir = file("$buildDir/classes/main/javafx")
1565         jvmArgs "-Djava.ext.dirs=", "-Djavafx.toolkit=com.sun.javafx.pgstub.StubToolkit",
1566             "-DCSS_META_DATA_TEST_DIR=$cssDir"
1567         enableAssertions = true
1568         testLogging.exceptionFormat = "full"
1569         scanForTestClasses = false
1570         include "**/*Test.*"
1571         if (BUILD_CLOSED && DO_JCOV) {
1572             addJCov(project, test)
1573         }
1574     }
1575 
1576     // To enable the IDEs to all be happy (no red squiggles) we need to have the libraries
1577     // available in some known location. Maybe in the future the Gradle plugins to each
1578     // of the IDEs will be good enough that we won't need this hack anymore.
1579     classes << {
1580         // Copy all of the download libraries to the libs directory for the sake of the IDEs
1581         File libsDir = rootProject.file("build/libs");
1582 
1583         // In some IDEs (Eclipse for example), touching these libraries cauese a full build
1584         // within the IDE.  When gradle is used outside of the IDE, for example to build the
1585         // native code, a full rebuild is caused within the IDE.  The fix is to check for the
1586         // lib directory and not copy the files
1587         //
1588         // This means that in order to update the dependent libraries for the IDE's, a clean
1589         // build is required
1590         //
1591         if (libsDir.exists()) return;
1592         libsDir.mkdirs();
1593         for (File f : [configurations.compile.files, configurations.antlr3.files].flatten()) {
1594             copy {
1595                 into libsDir
1596                 from f.getParentFile()
1597                 include "**/antlr-3.1.3.jar"
1598                 include "**/stringtemplate-3.2.jar"
1599                 include "**/antlr-runtime-3.1.3.jar"
1600                 includeEmptyDirs = false
1601             }
1602             // Have to rename the swt jar because it is some platform specific name but
1603             // for the sake of the IDEs we need to have a single stable name that works
1604             // on every platform
1605             copy {
1606                 into libsDir
1607                 from f.getParentFile()
1608                 include "**/*swt*.jar"
1609                 includeEmptyDirs = false
1610                 rename ".*swt.*jar", "swt-debug\\.jar"
1611             }
1612         }
1613     }
1614 }
1615 
1616 project(":controls") {
1617     dependencies {
1618         compile BUILD_SRC, project(":base"), project(":graphics")
1619         // TODO not sure how to specify this? processResources project(":base"), project(":graphics")
1620         testCompile project(":graphics").sourceSets.test.output
1621         testCompile project(":base").sourceSets.test.output
1622     }
1623 
1624     test {
1625         def cssDir = file("$buildDir/classes/main/javafx")
1626         jvmArgs "-Djavafx.toolkit=com.sun.javafx.pgstub.StubToolkit",
1627             "-DCSS_META_DATA_TEST_DIR=$cssDir"
1628     }
1629 
1630     // TODO Css2Bin really should be moved out and put into buildSrc if it can be
1631     // TODO could change script to dynamically locate all .css files and create bss for them, probably better
1632     // TODO also not sure there is any benefit to having css files in the jfxrt.jar at all
1633     processResources << {
1634         ["$buildDir/resources/main/com/sun/javafx/scene/control/skin/caspian/caspian.css",
1635         "$buildDir/resources/main/com/sun/javafx/scene/control/skin/caspian/caspian-no-transparency.css",
1636         "$buildDir/resources/main/com/sun/javafx/scene/control/skin/caspian/embedded-qvga.css",
1637         "$buildDir/resources/main/com/sun/javafx/scene/control/skin/caspian/embedded.css",
1638         "$buildDir/resources/main/com/sun/javafx/scene/control/skin/caspian/fxvk.css",
1639         "$buildDir/resources/main/com/sun/javafx/scene/control/skin/caspian/highcontrast.css",
1640         "$buildDir/resources/main/com/sun/javafx/scene/control/skin/modena/modena.css",
1641         "$buildDir/resources/main/com/sun/javafx/scene/control/skin/modena/modena-no-transparency.css",
1642         "$buildDir/resources/main/com/sun/javafx/scene/control/skin/modena/touch.css"].each { css ->
1643             javaexec {
1644                 executable = JAVA
1645                 workingDir = "modules/controls"
1646                 classpath files("$buildDir/classes/main",
1647                         project(":graphics").sourceSets.main.output,
1648                         project(":base").sourceSets.main.output)
1649                 main = "com.sun.javafx.css.parser.Css2Bin"
1650                 args css
1651                 jvmArgs "-Djava.ext.dirs="
1652             }
1653         }
1654     }
1655 }
1656 
1657 project(":extensions") {
1658     dependencies {
1659         compile BUILD_SRC, project(":base"), project(":graphics")
1660     }
1661 }
1662 
1663 project(":swing") {
1664     /* should not be built, but needed in builders and JMX
1665     tasks.all {
1666         if (!COMPILE_SWING) it.enabled = false
1667     }
1668     */
1669     dependencies {
1670         compile BUILD_SRC, project(":base"), project(":graphics")
1671     }
1672     test {
1673         enabled = IS_FULL_TEST && IS_AWT_TEST
1674     }
1675 }
1676 
1677 project(":swt") {
1678     tasks.all {
1679         if (!COMPILE_SWT) it.enabled = false
1680     }
1681     dependencies {
1682         compile BUILD_SRC, project(":base"), project(":graphics")
1683         compile name: SWT_FILE_NAME
1684     }
1685 }
1686 
1687 project(":fxml") {
1688     dependencies {
1689         compile BUILD_SRC, project(":base"), project(":graphics"),
1690                 project(":controls"), project(":swt"), project(":swing")
1691         testCompile project(":graphics").sourceSets.test.output
1692     }
1693     test {
1694         // StubToolkit is not *really* needed here, but because some code inadvertently invokes performance
1695         // tracker and this attempts to fire up the toolkit and this looks for native libraries and fails,
1696         // we have to use the stub toolkit for now.
1697         jvmArgs "-Djavafx.toolkit=com.sun.javafx.pgstub.StubToolkit"
1698         classpath += files("$JDK_HOME/jre/lib/ext/nashorn.jar")
1699     }
1700 }
1701 
1702 project(":builders") {
1703     sourceCompatibility = 1.7
1704 
1705     if (!COMPILE_SWING) sourceSets.main.java.exclude ("**/swing/**")
1706     if (!COMPILE_SWT)   sourceSets.main.java.exclude ("**/swt/**")
1707 
1708     dependencies {
1709         compile BUILD_SRC, project(":base"), project(":graphics"),
1710                 project(":controls"), project(":swt"), project(":swing"), project(":media"), project(":web")
1711         testCompile project(":graphics").sourceSets.test.output
1712     }
1713     test {
1714         // StubToolkit is not *really* needed here, but because some code inadvertently invokes performance
1715         // tracker and this attempts to fire up the toolkit and this looks for native libraries and fails,
1716         // we have to use the stub toolkit for now.
1717         jvmArgs "-Djavafx.toolkit=com.sun.javafx.pgstub.StubToolkit"
1718     }
1719 }
1720 
1721 project(":jmx") {
1722     dependencies {
1723         compile project(":base")
1724         compile project(":graphics")
1725         compile project(":swing")
1726         compile project(":media")
1727     }
1728 
1729     // Tests are disabled until RT-33926 can be fixed
1730     test.enabled = false
1731 
1732     if (!DO_BUILD_SDK_FOR_TEST) {
1733        def javafxMxJar = new File(TEST_SDK_DIR, "lib/javafx-mx.jar")
1734        [test, compileTestJava].each {
1735            it.classpath = files(javafxMxJar) + it.classpath
1736        }
1737     }
1738 }
1739 
1740 // This project is for system tests that need to run with a full SDK.
1741 // Most of them display a stage or do other things that preclude running
1742 // them in a shared JVM or as part of the "smoke test" run (which must
1743 // not pop up any windows or use audio). As such, they are only enabled
1744 // when FULL_TEST is specified, and each test runs in its own JVM
1745 project(":systemTests") {
1746     test {
1747         enabled = IS_FULL_TEST
1748         if (!IS_USE_ROBOT) {
1749             // Disable all robot-based visual tests
1750             exclude("**/helloworld/*.*");
1751             exclude("**/javafx/embed/swing/*.*");
1752             exclude("**/javafx/scene/layout/*.*");
1753             exclude("**/test3d/*.*");
1754             exclude("**/painttest/*.*");
1755             exclude("**/renderlock/*.*");
1756         }
1757         if (!IS_AWT_TEST) {
1758             // Disable all AWT-based tests
1759             exclude("**/javafx/embed/swing/*.*");
1760             exclude("**/com/sun/javafx/application/Swing*.*");
1761         }
1762 
1763         forkEvery = 1
1764     }
1765 }
1766 
1767 project(":fxpackager") {
1768     tasks.all {
1769         if (!COMPILE_FXPACKAGER) it.enabled = false
1770     }
1771     // fxpackager has a dependency on ant in order to build the ant jar,
1772     // and as such needs to point to the apache binary repository
1773     if (!BUILD_CLOSED) {
1774         repositories {
1775             maven {
1776                 url "https://repository.apache.org"
1777             }
1778         }
1779     }
1780 
1781     dependencies {
1782         compile group: "org.apache.ant", name: "ant", version: "1.8.2"
1783     }
1784 
1785     // When producing the jar, we need to relocate a few class files
1786     // from their normal location to a resources/classes or resources/web-files
1787     // location
1788     jar {
1789         includeEmptyDirs = false
1790         archiveName = "ant-javafx.jar"
1791         eachFile { FileCopyDetails details ->
1792             if (details.path.startsWith("com/javafx/main")) {
1793                 details.path = "resources/classes/$details.path"
1794             }
1795         }
1796     }
1797 
1798     // The "man" task will create a $buildDir/man containing the man
1799     // files for the system being built
1800     task man(type: Copy) {
1801         includeEmptyDirs = false
1802         enabled = (IS_LINUX || IS_MAC) && COMPILE_FXPACKAGER
1803         from "src/main/man"
1804         into "$buildDir/man"
1805         exclude "**/*.html"
1806         if (IS_MAC) exclude "**/ja_JP.UTF-8/**"
1807     }
1808     processResources.dependsOn man
1809 
1810     // Compile the native launchers. These are included in ant-javafx.jar.
1811     if (IS_WINDOWS && COMPILE_FXPACKAGER) {
1812         task buildWinLauncher(type: CCTask, group: "Build") {
1813             description = "Compiles native sources for the application co-bundle launcher";
1814             matches = "WinLauncher\\.cpp";
1815             params.addAll(WIN.launcher.ccFlags);
1816             output(file("$buildDir/native/WinLauncher"));
1817             source(file("src/main/native/launcher/win"));
1818             compiler = WIN.launcher.compiler
1819             exe = true;
1820             linkerOptions.addAll(WIN.launcher.linkFlags);
1821             doLast {
1822                 copy {
1823                     from "$buildDir/native/WinLauncher/WinLauncher.exe"
1824                     from "$MSVCR"
1825                     from "$MSVCP"
1826                     into "$buildDir/classes/main/com/oracle/tools/packager/windows"
1827                 }
1828             }
1829         }
1830         task compileWinLibrary(type: CCTask, group: "Build") {
1831             description = "Compiles native sources for the application co-bundle launcher library";
1832             matches = ".*\\.cpp"
1833             source(file("src/main/native/library/common"));
1834             params.addAll(WIN.launcherlibrary.ccFlags)
1835             output(file("$buildDir/native/WinLauncher/obj"));
1836             compiler = WIN.launcherlibrary.compiler
1837         }
1838         task linkWinLibrary(type: LinkTask, group: "Build", dependsOn: compileWinLibrary) {
1839             description = "Links native sources for the application co-bundle launcher library";
1840             objectDir = file("$buildDir/native/WinLauncher/obj")
1841             linkParams.addAll(WIN.launcherlibrary.linkFlags);
1842             lib = file("$buildDir/native/WinLauncher/packager.dll")
1843             linker = WIN.launcherlibrary.linker
1844             doLast {
1845                 copy {
1846                     from "$buildDir/native/WinLauncher/packager.dll"
1847                     into "$buildDir/classes/main/com/oracle/tools/packager/windows"
1848                 }
1849             }
1850         }
1851         task buildWinLauncherSvc(type: CCTask, group: "Build") {
1852             description = "Compiles native sources for the application co-bundle launcher";
1853             matches = "WinLauncherSvc\\.cpp";
1854             params.addAll(WIN.launcher.ccFlags);
1855             output(file("$buildDir/native/WinLauncherSvc"));
1856             source(file("src/main/native/service/win"));
1857             compiler = WIN.launcher.compiler
1858             exe = true;
1859             linkerOptions.addAll(WIN.launcher.linkFlags);
1860             doLast {
1861                 copy {
1862                     from "$buildDir/native/WinLauncherSvc/WinLauncherSvc.exe"
1863                     into "$buildDir/classes/main/com/oracle/tools/packager/windows"
1864                 }
1865             }
1866         }
1867         task buildIconSwap(type: CCTask, group: "Build") {
1868             description = "Compiles native sources for the application co-bundle launcher"
1869             matches = "IconSwap\\.cpp"
1870             params.addAll(WIN.iconLauncher.ccFlags)
1871             output(file("$buildDir/native/IconSwap"))
1872             source file("src/main/native/tools/win")
1873             compiler = WIN.launcher.compiler
1874             exe = true
1875             linkerOptions.addAll(WIN.iconLauncher.linkFlags)
1876             doLast {
1877                 copy {
1878                     from "$buildDir/native/IconSwap/IconSwap.exe"
1879                     into "$buildDir/classes/main/com/oracle/tools/packager/windows"
1880                 }
1881             }
1882         }
1883         task compileLauncher(dependsOn: [buildWinLauncher, linkWinLibrary, buildWinLauncherSvc, buildIconSwap])
1884         jar.dependsOn compileLauncher;
1885     } else if (IS_MAC && COMPILE_FXPACKAGER) {
1886         task buildMacLauncher(type: CCTask, group: "Build") {
1887             description = "Compiles native sources for the application co-bundle launcher"
1888             matches = ".*\\.m"
1889             source file("src/main/native/launcher/mac")
1890             params.addAll(MAC.launcher.ccFlags)
1891             compiler = MAC.launcher.compiler
1892             output(file("$buildDir/classes/main/com/oracle/tools/packager/mac"))
1893             eachOutputFile = { f ->
1894                 return new File(f.getParent(), "JavaAppLauncher")
1895             }
1896         }
1897         task compileMacLibrary(type: CCTask, group: "Build") {
1898             description = "Compiles native sources for the application co-bundle launcher library"
1899             matches = ".*\\.cpp|.*\\.mm"
1900             source file("src/main/native/library/common");
1901             params.addAll(MAC.launcherlibrary.ccFlags)
1902             compiler = MAC.launcherlibrary.compiler
1903             output(file("$buildDir/native/maclauncher/obj"))
1904         }
1905         task linkMacLibrary(type: LinkTask, group: "Build", dependsOn: compileMacLibrary) {
1906             description = "Links native sources for the application co-bundle launcher library"
1907             objectDir = file("$buildDir/native/maclauncher/obj")
1908             linkParams.addAll(MAC.launcherlibrary.linkFlags)
1909             linker = MAC.launcherlibrary.linker
1910             lib = file("$buildDir/classes/main/com/oracle/tools/packager/mac/libpackager.dylib")
1911         }
1912         task compileLauncher(dependsOn: [buildMacLauncher, linkMacLibrary])
1913         jar.dependsOn compileLauncher;
1914     } else if (IS_LINUX && COMPILE_FXPACKAGER) {
1915         task compileLinuxLauncher(type: CCTask, group: "Build") {
1916             description = "Compiles native sources for the application co-bundle launcher"
1917             matches = ".*\\.cpp"
1918             source file("src/main/native/launcher/linux")
1919             params.addAll(LINUX.launcher.ccFlags)
1920             compiler = LINUX.launcher.compiler
1921             output(file("$buildDir/native/linuxlauncher/launcherobj"))
1922         }
1923         task linkLinuxLauncher(type: LinkTask, dependsOn: compileLinuxLauncher, group: "Build") {
1924             description = "Links native dynamic library for the application co-bundle launcher"
1925             objectDir = file("$buildDir/native/linuxlauncher/launcherobj")
1926             linkParams.addAll(LINUX.launcher.linkFlags)
1927             linker = LINUX.launcher.linker
1928             lib = file("$buildDir/classes/main/com/oracle/tools/packager/linux/JavaAppLauncher")
1929         }
1930         task compileLinuxLibrary(type: CCTask, group: "Build") {
1931             description = "Compiles native sources for the application co-bundle launcher library"
1932             matches = ".*\\.cpp"
1933             source file("src/main/native/library/common")
1934             params.addAll(LINUX.launcherlibrary.ccFlags)
1935             compiler = LINUX.launcherlibrary.compiler
1936             output(file("$buildDir/native/linuxlauncher/obj"))
1937         }
1938         task linkLinuxLibrary(type: LinkTask, dependsOn: compileLinuxLibrary, group: "Build") {
1939             description = "Links native dynamic library for the application co-bundle launcher library"
1940             objectDir = file("$buildDir/native/linuxlauncher/obj")
1941             linkParams.addAll(LINUX.launcherlibrary.linkFlags)
1942             linker = LINUX.launcherlibrary.linker
1943             lib = file("$buildDir/classes/main/com/oracle/tools/packager/linux/libpackager.so")
1944         }
1945         task compileLauncher(dependsOn: [linkLinuxLauncher, linkLinuxLibrary])
1946         jar.dependsOn compileLauncher;
1947     }
1948 
1949     // Builds the javapackager executable. For everything other than windows,
1950     // this is simply moving the existing shell script and ensuring it has proper
1951     // permissions. For Windows, this includes compiling the native executable
1952     if (IS_WINDOWS && COMPILE_FXPACKAGER){
1953         task buildJavaPackager(type: CCTask, group: "Build") {
1954             description = "Compiles native sources for javapackager.exe"
1955             matches = "javapackager\\.cpp"
1956             params.addAll(WIN.fxpackager.ccFlags)
1957             compiler = WIN.fxpackager.compiler
1958             output(file("$buildDir/native/javapackager"))
1959             source WIN.fxpackager.nativeSource
1960             doFirst {
1961                 copy {
1962                     mkdir "$buildDir/native"
1963                     mkdir "$buildDir/native/javapackager"
1964                     from file("src/main/native/javapackager/win/javapackager.manifest")
1965                     into file("$buildDir/native/javapackager")
1966                     filter { line->
1967                         line = line.replace("FXVERSION", "${RAW_VERSION}.${HUDSON_BUILD_NUMBER}");
1968                     }
1969                 }
1970             }
1971             doLast {
1972                 mkdir "$buildDir/native"
1973                 exec {
1974                     environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
1975                     commandLine(WIN.fxpackager.rcCompiler)
1976                     args(WIN.fxpackager.rcFlags)
1977                     args("/fo$buildDir/native/javapackager/javapackager.res")
1978                     args(WIN.fxpackager.rcSource)
1979                 }
1980             }
1981             doLast {
1982                 mkdir "$buildDir/javapackager"
1983                 exec({
1984                     commandLine("$WIN.fxpackager.linker", "/nologo", "/opt:REF", "/incremental:no", "/manifest", "kernel32.lib", "advapi32.lib",
1985                             "/out:$buildDir/native/javapackager/javapackager.exe",
1986                             "$buildDir/native/javapackager/javapackager.obj",
1987                             "$buildDir/native/javapackager/javapackager.res")
1988                     environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
1989                 })
1990             }
1991             doLast {
1992                 exec({
1993                     commandLine("$MC", "-manifest",
1994                                        "$buildDir/native/javapackager/javapackager.manifest",
1995                                        "-outputresource:$buildDir/native/javapackager/javapackager.exe")
1996                     environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
1997                 })
1998                 copy {
1999                     from file("$buildDir/native/javapackager/javapackager.exe")
2000                     into file("$buildDir/javapackager")
2001                 }
2002                 copy {
2003                     from file("$buildDir/native/javapackager/javapackager.exe")
2004                     into file("$buildDir/javapackager")
2005                     rename ('javapackager', 'javafxpackager')
2006                 }
2007             }
2008         }
2009     } else {
2010         task buildJavaPackager(group: "Build") {
2011             enabled = COMPILE_FXPACKAGER
2012             doLast {
2013                 copy {
2014                     from "src/main/native/javapackager/shell"
2015                     into "$buildDir/javapackager"
2016                     fileMode = 0755
2017                 }
2018                 copy {
2019                     from "src/main/native/javapackager/shell"
2020                     into "$buildDir/javapackager"
2021                     rename ('javapackager', 'javafxpackager')
2022                     fileMode = 0755
2023                 }
2024             }
2025         }
2026     }
2027 
2028     task packagerJar(type: Jar) {
2029         group = "Basic"
2030         description = "Creates the packager.jar"
2031         archiveName = "packager.jar";
2032         includeEmptyDirs = false
2033         from("$buildDir/classes/main");
2034         from("$buildDir/resources/main");
2035         include('jdk/packager/**')
2036 
2037         dependsOn(buildJavaPackager);
2038     }
2039 
2040     jar.dependsOn buildJavaPackager
2041     jar.dependsOn packagerJar
2042 
2043     classes << {
2044         // Copy all of the download libraries to libs directory for the sake of the IDEs
2045         File libsDir = rootProject.file("build/libs");
2046         File antLib = new File(libsDir, "ant-1.8.2.jar")
2047         libsDir.mkdirs();
2048         for (File f : configurations.compile.files) {
2049             copy {
2050                 into libsDir
2051                 from f.getParentFile()
2052                 include "**/ant-1.8.2.jar"
2053                 includeEmptyDirs = false
2054             }
2055         }
2056     }
2057 
2058     task packagerFakeJar(type: Jar) {
2059         dependsOn compileTestJava
2060         from compileTestJava.destinationDir
2061         include "hello/**"
2062 
2063         destinationDir project.file("build/tmp/tests/appResources")
2064         archiveName "mainApp.jar"
2065 
2066         manifest {
2067             attributes(
2068                     "Main-Class": "hello.HelloRectangle",
2069                     "Custom-Attribute": " Is it stripped?"
2070             )
2071         }
2072 
2073         doFirst {
2074             copy {
2075                 from "$projectDir/src/main/resources/com/oracle/tools/packager/linux/javalogo_white_48.png"
2076                 from "$projectDir/src/main/resources/com/oracle/tools/packager/mac/GenericAppHiDPI.icns"
2077                 from "$projectDir/src/main/resources/com/oracle/tools/packager/windows/javalogo_white_48.ico"
2078                 from "$projectDir/src/test/resources/hello/java-logo2.gif"
2079                 from "$projectDir/src/test/resources/hello/small.ico"
2080                 from "$projectDir/src/test/resources/hello/test.icns"
2081                 from "$projectDir/src/test/resources/hello/LICENSE-RTF.rtf"
2082                 from "$projectDir/../../LICENSE"
2083                 from "$projectDir/build/libs/packager.jar"
2084                 into project.file("$projectDir/build/tmp/tests/appResources")
2085             }
2086             copy {
2087                 from "$projectDir/../../LICENSE"
2088                 into project.file("$projectDir/build/tmp/tests/appResources")
2089                 rename '(.*)LICENSE', '$1LICENSE2'
2090             }
2091         }
2092     }
2093 
2094     task packagerFXPackagedJar(type: Jar) {
2095         dependsOn packagerFakeJar
2096         from compileTestJava.destinationDir
2097         include "hello/**"
2098 
2099         destinationDir project.file("build/tmp/tests/appResources")
2100         archiveName "packagedMainApp.jar"
2101 
2102         manifest {
2103             attributes(
2104                 "JavaFX-Application-Class": "hello.TestPackager",
2105             )
2106         }
2107     }
2108 
2109     if (!DO_BUILD_SDK_FOR_TEST) {
2110         def antJavafxJar = new File(TEST_SDK_DIR, "lib/ant-javafx.jar")
2111         [compileTestJava, test].each {
2112             it.classpath = files(antJavafxJar) + it.classpath
2113         }
2114     }
2115 
2116     test {
2117         dependsOn packagerFXPackagedJar
2118         systemProperty "RETAIN_PACKAGER_TESTS", RETAIN_PACKAGER_TESTS
2119         systemProperty "TEST_PACKAGER_DMG", TEST_PACKAGER_DMG
2120         systemProperty "FULL_TEST", FULL_TEST
2121     }
2122 
2123     def packagerDevOpts = []
2124     try {
2125         packagerDevOpts.addAll(PACKAGER_DEV_OPTS.split(' '))
2126     } catch (MissingPropertyException ignore) {
2127         packagerDevOpts.addAll("image")
2128     }
2129 
2130     task packagerDev(dependsOn: [jar, packagerFakeJar], type:JavaExec) {
2131         workingDir = project.file("build/tmp/tests/appResources/")
2132         classpath = project.files("build/libs/ant-javafx.jar", "build/classes/test", "build/resources/test")
2133         main = "hello.SimpleBundle"
2134         args = [
2135                 "-o", "$projectDir/build/dev",
2136                 "-all",
2137                 packagerDevOpts
2138         ].flatten()
2139     }
2140 }
2141 
2142 project(":media") {
2143     configurations {
2144         media
2145     }
2146 
2147     dependencies {
2148         compile BUILD_SRC, project(":base"), project(":graphics")
2149     }
2150 
2151     sourceSets {
2152         tools {
2153             java.srcDir "src/tools/java"
2154         }
2155     }
2156 
2157     compileToolsJava {
2158         enabled = IS_COMPILE_MEDIA
2159         classpath = sourceSets.main.output;
2160     }
2161 
2162     project.ext.makeJobsFlag = IS_WINDOWS && IS_DEBUG_NATIVE ? "-j1" : "-j5";
2163     project.ext.buildType = IS_DEBUG_NATIVE ? "Debug" : "Release";
2164 
2165     def nativeSrcDir = file("${projectDir}/src/main/native")
2166     def generatedHeadersDir = file("${buildDir}/generated-src/headers")
2167 
2168     task generateHeaders(dependsOn: compileJava) {
2169         enabled = IS_COMPILE_MEDIA
2170         doLast {
2171             def classpath = sourceSets.main.output;
2172             mkdir generatedHeadersDir;
2173 
2174             def classesList = ["com.sun.media.jfxmedia.logging.Logger",
2175                              "com.sun.media.jfxmedia.track.AudioTrack",
2176                              "com.sun.media.jfxmedia.control.VideoDataBuffer",
2177                              "com.sun.media.jfxmedia.control.VideoFormat\$FormatTypes",
2178                              "com.sun.media.jfxmediaimpl.NativeAudioClip",
2179                              "com.sun.media.jfxmediaimpl.NativeMediaPlayer",
2180                              "com.sun.media.jfxmediaimpl.NativeVideoBuffer",
2181                              "com.sun.media.jfxmediaimpl.platform.gstreamer.GSTPlatform",
2182                              "com.sun.media.jfxmediaimpl.platform.gstreamer.GSTMedia",
2183                              "com.sun.media.jfxmediaimpl.platform.gstreamer.GSTMediaPlayer",
2184                              "com.sun.media.jfxmediaimpl.NativeAudioEqualizer",
2185                              "com.sun.media.jfxmediaimpl.NativeEqualizerBand",
2186                              "com.sun.media.jfxmediaimpl.NativeAudioSpectrum"]
2187             if (IS_MAC) {
2188                 classesList.addAll( ["com.sun.media.jfxmediaimpl.platform.osx.OSXPlatform",
2189                                      "com.sun.media.jfxmediaimpl.platform.osx.OSXMedia",
2190                                      "com.sun.media.jfxmediaimpl.platform.osx.OSXMediaPlayer"] );
2191             }
2192             exec {
2193                 commandLine ("${JAVAH}", "-J-Djava.ext.dirs=", "-d", "${generatedHeadersDir}", "-classpath", "${classpath.asPath}");
2194                 args classesList;
2195             }
2196         }
2197     }
2198 
2199     task generateMediaErrorHeader(dependsOn: [compileToolsJava, compileJava]) {
2200         enabled = IS_COMPILE_MEDIA
2201         doLast {
2202             def classpath = files(sourceSets.main.output, sourceSets.tools.output);
2203             def sourcepath = sourceSets.main.java.srcDirs;
2204             def headerpath = file("$generatedHeadersDir/jfxmedia_errors.h");
2205             def srcRoot = (sourcepath.toArray())[0];
2206 
2207             mkdir generatedHeadersDir;
2208 
2209             exec {
2210                 commandLine("$JAVA", "-Djava.ext.dirs=", "-classpath", "${classpath.asPath}");
2211                 args("headergen.HeaderGen", "$headerpath", "$srcRoot");
2212             }
2213         }
2214     }
2215 
2216     task buildNativeTargets {
2217         enabled = IS_COMPILE_MEDIA
2218     }
2219 
2220     compileTargets { t->
2221         def targetProperties = project.rootProject.ext[t.upper]
2222         def nativeOutputDir = file("${buildDir}/native/${t.name}")
2223         def projectDir = t.name.startsWith("arm") ? "linux" : t.name
2224         def mediaProperties = targetProperties.media
2225         // Makefile for OSX needs to know if we're building for parfait
2226         def compileParfait = IS_COMPILE_PARFAIT ? "true" : "false"
2227 
2228         def buildNative = task("build${t.capital}Native", dependsOn: [generateHeaders, generateMediaErrorHeader]) {
2229             enabled = targetProperties.compileMediaNative
2230             if (!targetProperties.compileMediaNative) {
2231                 println("Not compiling native Media for ${t.name} per configuration request");
2232             }
2233 
2234             doLast {
2235                 exec {
2236                     commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/jfxmedia/projects/${projectDir}")
2237                     args("JAVA_HOME=${JDK_HOME}", "GENERATED_HEADERS_DIR=${generatedHeadersDir}",
2238                          "OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}", "BASE_NAME=jfxmedia",
2239                          "COMPILE_PARFAIT=${compileParfait}")
2240 
2241                     if (t.name == "win") {
2242                         environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
2243                         args(IS_64 ? "ARCH=x64" : "ARCH=x32", "RESOURCE=${nativeOutputDir}/${buildType}/${WIN.media.jfxmediaRcFile}")
2244                     } else {
2245                         args ("CC=${mediaProperties.compiler}", "LINK=${mediaProperties.linker}", "LIB=${mediaProperties.lib}")
2246                         if (t.name == "linux") {
2247                             args(IS_64 ? "ARCH=x64" : "ARCH=x32")
2248                         }
2249 
2250                         if (t.name.startsWith("arm")) {
2251                             args("EXTRA_CFLAGS=${mediaProperties.extra_cflags}", "EXTRA_LDFLAGS=${mediaProperties.extra_ldflags}")
2252                         } else {
2253                             args("HOST_COMPILE=1")
2254                         }
2255                     }
2256                 }
2257             }
2258         }
2259 
2260         // check for the property disable${name} = true
2261         def boolean disabled = targetProperties.containsKey('disableMedia') ? targetProperties.get('disableMedia') : false
2262         if (!disabled) {
2263             // Building GStreamer
2264             def buildGStreamer = task("build${t.capital}GStreamer") {
2265                 enabled = IS_COMPILE_MEDIA
2266                 doLast {
2267                     exec {
2268                         commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/gstreamer/projects/${projectDir}/gstreamer-lite")
2269                         args("OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}", "BASE_NAME=gstreamer-lite")
2270 
2271                         if (t.name == "win") {
2272                             environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
2273                             args(IS_64 ? "ARCH=x64" : "ARCH=x32", "RESOURCE=${nativeOutputDir}/${buildType}/${WIN.media.gstreamerRcFile}")
2274                         } else {
2275                             args ("CC=${mediaProperties.compiler}", "LINK=${mediaProperties.linker}", "LIB=${mediaProperties.lib}")
2276                             if (t.name == "linux") {
2277                                 args(IS_64 ? "ARCH=x64" : "ARCH=x32")
2278                             }
2279                         }
2280                     }
2281                 }
2282             }
2283 
2284             def buildPlugins = task("build${t.capital}Plugins", dependsOn: buildGStreamer) {
2285                 enabled = IS_COMPILE_MEDIA
2286 
2287                 if (!project.ext.properties.containsKey("ON2_SRCDIR")) {
2288                     project.ext.ON2_SRCDIR = "";
2289                 }
2290 
2291                 if (!project.ext.properties.containsKey("ON2_LIB")) {
2292                     project.ext.ON2_LIB = "";
2293                 }
2294 
2295                 doLast {
2296                     exec {
2297                         commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/gstreamer/projects/${projectDir}/fxplugins")
2298                         args("OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}", "BASE_NAME=fxplugins",
2299                              "ON2_SRCDIR=${project.ext.ON2_SRCDIR}", "ON2_LIB=${project.ext.ON2_LIB}")
2300 
2301                         if (t.name == "win") {
2302                             Map winEnv = new HashMap(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
2303 
2304                             String sdkDir = System.getenv("BASECLASSES_SDK_DIR");
2305                             if (sdkDir == null) {
2306                                 sdkDir = "C:/Program Files/Microsoft SDKs/Windows/v7.1" // Default value
2307                                 winEnv["BASECLASSES_SDK_DIR"] = sdkDir
2308                             }
2309                             environment(winEnv)
2310 
2311                             args(IS_64 ? "ARCH=x64" : "ARCH=x32", "RESOURCE=${nativeOutputDir}/${buildType}/${WIN.media.fxpluginsRcFile}")
2312                         } else {
2313                             args ("CC=${mediaProperties.compiler}", "LINK=${mediaProperties.linker}", "LIB=${mediaProperties.lib}")
2314                             if (t.name == "linux") {
2315                                 args(IS_64 ? "ARCH=x64" : "ARCH=x32")
2316                             }
2317                         }
2318                     }
2319                 }
2320             }
2321 
2322             buildNative.dependsOn buildPlugins
2323 
2324             if (t.name == "linux") {
2325                 def buildAVPlugin = task( "buildAVPlugin", dependsOn: [buildPlugins]) {
2326                     enabled = IS_COMPILE_MEDIA
2327 
2328                     doLast {
2329                         if (project.ext.properties.containsKey("libav")) {
2330                             project.ext.libav.versions.each { version ->
2331                                 def libavDir = "${project.ext.libav.basedir}-${version}"
2332                                 File dir = file(libavDir)
2333                                 if (dir.exists()) {
2334                                     exec {
2335                                         commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/gstreamer/projects/linux/avplugin")
2336                                         args("CC=${mediaProperties.compiler}", "OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}",
2337                                              "BASE_NAME=avplugin", "VERSION=${version}", "LIBAV_DIR=${libavDir}",
2338                                              "SUFFIX=", IS_64 ? "ARCH=x64" : "ARCH=x32")
2339                                     }
2340                                 }
2341                             }
2342 
2343                             project.ext.libav.ffmpeg.versions.each { version ->
2344                                 def libavDir = "${project.ext.libav.ffmpeg.basedir}-${version}"
2345                                 File dir = file(libavDir)
2346                                 if (dir.exists()) {
2347                                     exec {
2348                                         commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/gstreamer/projects/linux/avplugin")
2349                                         args("CC=${mediaProperties.compiler}", "LINKER=${mediaProperties.linker}",
2350                                              "OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}",
2351                                              "BASE_NAME=avplugin", "VERSION=${version}", "LIBAV_DIR=${libavDir}",
2352                                              "SUFFIX=-ffmpeg", IS_64 ? "ARCH=x64" : "ARCH=x32")
2353                                     }
2354                                 }
2355                             }
2356                         } else {
2357                             // Building fxavcodec plugin (libav plugin)
2358                             exec {
2359                                 commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/gstreamer/projects/linux/avplugin")
2360                                 args("CC=${mediaProperties.compiler}", "OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}",
2361                                      "BASE_NAME=avplugin", IS_64 ? "ARCH=x64" : "ARCH=x32")
2362                             }
2363                         }
2364                     }
2365                 }
2366                 buildNative.dependsOn buildAVPlugin
2367             }
2368 
2369             if (t.name == "win") {
2370                 def buildResources = task("buildResources") << {
2371                     def rcOutputDir = "${nativeOutputDir}/${buildType}"
2372                     mkdir rcOutputDir
2373                     exec {
2374                         environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
2375                         commandLine (WIN.media.rcCompiler)
2376                         args(WIN.media.glibRcFlags)
2377                         args("/Fo${rcOutputDir}/${WIN.media.glibRcFile}", WIN.media.rcSource)
2378                     }
2379 
2380                     exec {
2381                         environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
2382                         commandLine (WIN.media.rcCompiler)
2383                         args(WIN.media.gstreamerRcFlags)
2384                         args("/Fo${rcOutputDir}/${WIN.media.gstreamerRcFile}", WIN.media.rcSource)
2385                     }
2386 
2387                     exec {
2388                         environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
2389                         commandLine (WIN.media.rcCompiler)
2390                         args(WIN.media.fxpluginsRcFlags)
2391                         args("/Fo${rcOutputDir}/${WIN.media.fxpluginsRcFile}", WIN.media.rcSource)
2392                     }
2393 
2394                     exec {
2395                         environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
2396                         commandLine (WIN.media.rcCompiler)
2397                         args(WIN.media.jfxmediaRcFlags)
2398                         args("/Fo${rcOutputDir}/${WIN.media.jfxmediaRcFile}", WIN.media.rcSource)
2399                     }
2400                 }
2401 
2402                 def buildGlib = task("build${t.capital}Glib", dependsOn: [buildResources]) {
2403                     enabled = IS_COMPILE_MEDIA
2404                     doLast {
2405                         exec {
2406                             environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
2407                             commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/gstreamer/projects/${projectDir}/glib-lite")
2408                             args("OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}", "BASE_NAME=glib-lite",
2409                                  IS_64 ? "ARCH=x64" : "ARCH=x32", "RESOURCE=${nativeOutputDir}/${buildType}/${WIN.media.glibRcFile}")
2410                         }
2411                     }
2412                 }
2413                 buildGStreamer.dependsOn buildGlib
2414 
2415             } else if (t.name == "mac") {
2416                 def buildGlib = task("build${t.capital}Glib") {
2417                     enabled = IS_COMPILE_MEDIA
2418                     doLast {
2419                         exec {
2420                             commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/gstreamer/projects/${projectDir}/glib-lite")
2421                             args("OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}", "BASE_NAME=glib-lite")
2422                             args ("CC=${mediaProperties.compiler}", "LINK=${mediaProperties.linker}", "LIB=${mediaProperties.lib}")
2423                         }
2424                     }
2425                 }
2426                 buildGStreamer.dependsOn buildGlib
2427             }
2428         }
2429 
2430         buildNativeTargets.dependsOn buildNative
2431     }
2432 
2433     jar {
2434         exclude("headergen/**")
2435 
2436         dependsOn compileJava
2437         if (IS_COMPILE_MEDIA) {
2438             dependsOn buildNativeTargets
2439         }
2440     }
2441 }
2442 
2443 project(":web") {
2444     configurations {
2445         webkit
2446     }
2447     dependencies {
2448         compile project(":base"), project(":graphics"), project(":controls"), project(":media")
2449     }
2450 
2451     task webArchiveJar(type: Jar) {
2452         from (project.file("$projectDir/src/test/resources/test/html")) {
2453             include "**/archive-*.*"
2454         }
2455         archiveName = "webArchiveJar.jar"
2456         destinationDir = file("$buildDir/testing/resources")
2457     }
2458 
2459     test {
2460         // Run web tests in headless mode
2461         systemProperty 'glass.platform', 'Monocle'
2462         systemProperty 'monocle.platform', 'Headless'
2463         systemProperty 'prism.order', 'sw'
2464         dependsOn webArchiveJar
2465         def testResourceDir = file("$buildDir/testing/resources")
2466         jvmArgs "-DWEB_ARCHIVE_JAR_TEST_DIR=$testResourceDir"
2467     }
2468 
2469     if (!IS_COMPILE_WEBKIT) {
2470         // Include wrapper classes that are otherwise generated by native build
2471         sourceSets.main.java.srcDirs += "src/main/java-wrappers"
2472     }
2473 
2474     task generateHeaders(dependsOn: compileJava) {
2475         doLast {
2476             def classpath = files("$buildDir/classes/main",
2477                                   project(":graphics").sourceSets.main.output.classesDir)
2478             def dest = file("$buildDir/generated-src/headers");
2479             mkdir dest;
2480             exec {
2481                 commandLine("$JAVAH", "-J-Djava.ext.dirs=", "-d", "$dest",
2482                             "-classpath", "${classpath.asPath}");
2483                 args("java.lang.Character",
2484                      "java.net.IDN",
2485                      "com.sun.webkit.ContextMenu",
2486                      "com.sun.webkit.ContextMenuItem",
2487                      "com.sun.webkit.CursorManager",
2488                      "com.sun.webkit.PageCache",
2489                      "com.sun.webkit.PopupMenu",
2490                      "com.sun.webkit.SharedBuffer",
2491                      "com.sun.webkit.WatchdogTimer",
2492                      "com.sun.webkit.WebPage",
2493                      "com.sun.webkit.LoadListenerClient",
2494                      "com.sun.webkit.event.WCFocusEvent",
2495                      "com.sun.webkit.event.WCKeyEvent",
2496                      "com.sun.webkit.event.WCMouseEvent",
2497                      "com.sun.webkit.event.WCMouseWheelEvent",
2498                      "com.sun.webkit.graphics.GraphicsDecoder",
2499                      "com.sun.webkit.graphics.RenderMediaControls",
2500                      "com.sun.webkit.graphics.RenderTheme",
2501                      "com.sun.webkit.graphics.ScrollBarTheme",
2502                      "com.sun.webkit.graphics.WCMediaPlayer",
2503                      "com.sun.webkit.graphics.WCGraphicsManager",
2504                      "com.sun.webkit.graphics.WCRenderQueue",
2505                      "com.sun.webkit.graphics.WCPath",
2506                      "com.sun.webkit.graphics.WCPathIterator",
2507                      "com.sun.webkit.Timer",
2508                      "com.sun.webkit.WCFrameView",
2509                      "com.sun.webkit.WCPasteboard",
2510                      "com.sun.webkit.WCPluginWidget",
2511                      "com.sun.webkit.dom.JSObject",
2512                      "com.sun.webkit.network.SocketStreamHandle",
2513                      "com.sun.webkit.network.URLLoader",
2514                      "com.sun.webkit.text.TextBreakIterator",
2515                      "com.sun.webkit.text.TextNormalizer");
2516             }
2517         }
2518     }
2519 
2520     task compileGenerated()
2521 
2522     compileTargets { t ->
2523         def targetProperties = project.rootProject.ext[t.upper]
2524         def classifier = (t.name != "linux" && t.name != "win") ? t.name :
2525                           IS_64 ? "${t.name}-amd64" : "${t.name}-i586"
2526         dependencies {
2527             webkit group: "com.sun.webkit", name: "webview-deps",
2528                    version: "1.3.1", classifier: "$classifier", ext: "zip"
2529         }
2530 
2531         def webkitOutputDir = cygpath("$buildDir/${t.name}")
2532         def webkitConfig = IS_DEBUG_NATIVE ? "Debug" : "Release"
2533 
2534         def compileNativeTask = task("compileNative${t.capital}", dependsOn: generateHeaders) << {
2535             println "Building Webkit configuration /$webkitConfig/ into $webkitOutputDir"
2536 
2537             def dependencyFile = configurations.webkit.filter(
2538                     { File f -> f.getName().contains(classifier) }
2539                 ).getSingleFile()
2540             ant.unzip(src:  dependencyFile,
2541                       dest: webkitOutputDir)
2542 
2543             exec {
2544                 workingDir("$projectDir/src/main/native")
2545                 commandLine("perl", "Tools/Scripts/set-webkit-configuration", "--$webkitConfig")
2546                 environment(["WEBKIT_OUTPUTDIR" : webkitOutputDir])
2547             }
2548 
2549             exec {
2550                 workingDir("$projectDir/src/main/native")
2551                 def cmakeArgs = "-DENABLE_TOOLS=1"
2552                 if (t.name == "win") {
2553                     String parfaitPath = IS_COMPILE_PARFAIT ? System.getenv().get("PARFAIT_PATH") + ";" : "";
2554                     Map environmentSettings = new HashMap(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
2555                     environmentSettings["PATH"] = parfaitPath + "$WINDOWS_VS_PATH"
2556                     /* To build with ICU:
2557                     1. Download http://javaweb.us.oracle.com/jcg/fx-webrevs/RT-17164/WebKitLibrariesICU.zip
2558                     and unzip it to WebKitLibraries folder.
2559                     2. Copy DLLs from
2560                     WebKitLibrariesICU.zip\WebKitLibraries\import\runtime
2561                     to %windir%\system32
2562                     3. Uncomment the line below
2563                      */
2564                     // args("--icu-unicode")
2565                 } else if (t.name == "mac") {
2566                     // Add any osx specific flags.
2567                 } else if (t.name == "linux") {
2568                     if (!IS_64) {
2569                         cmakeArgs = "-DCMAKE_C_FLAGS=-m32 -DCMAKE_CXX_FLAGS=-m32"
2570                     }
2571                 } else if (t.name.startsWith("arm")) {
2572                     fail("ARM target is not supported as of now.")
2573                 }
2574 
2575                 if (IS_COMPILE_PARFAIT) {
2576                     environment([
2577                         "COMPILE_PARFAIT" : "true"
2578                     ])
2579                     cmakeArgs = "-DCMAKE_C_COMPILER=parfait-gcc -DCMAKE_CXX_COMPILER=parfait-g++"
2580                 }
2581 
2582                 environment([
2583                     "JAVA_HOME"       : JDK_HOME,
2584                     "WEBKIT_OUTPUTDIR" : webkitOutputDir,
2585                 ])
2586 
2587                 def targetCpuBitDepthSwitch = ""
2588                 if (IS_64) {
2589                     targetCpuBitDepthSwitch = "--64-bit"
2590                 } else {
2591                     targetCpuBitDepthSwitch = "--32-bit"
2592                 }
2593 
2594                 commandLine("perl", "Tools/Scripts/build-webkit",
2595                     "--java", "--icu-unicode", targetCpuBitDepthSwitch,
2596                     "--cmakeargs=${cmakeArgs}")
2597             }
2598 
2599             def library = rootProject.ext[t.upper].library
2600             copy {
2601                 from "$webkitOutputDir/$webkitConfig/lib/${library('jfxwebkit')}"
2602                 into "$buildDir/libs/${t.name}"
2603             }
2604             copy {
2605                 from "$webkitOutputDir/$webkitConfig/lib/${library('DumpRenderTreeJava')}"
2606                 into "$buildDir/test/${t.name}"
2607             }
2608         }
2609 
2610         if (IS_WINDOWS && t.name == "win") {
2611             def webkitProperties = project.rootProject.ext[t.upper].webkit
2612             def rcTask = project.task("rc${t.capital}", type: CompileResourceTask) {
2613                 compiler = webkitProperties.rcCompiler
2614                 source(webkitProperties.rcSource)
2615                 if (webkitProperties.rcFlags) {
2616                     rcParams.addAll(webkitProperties.rcFlags)
2617                 }
2618                 output(file("$webkitOutputDir/$webkitConfig/WebCore/obj"))
2619             }
2620             compileNativeTask.dependsOn rcTask
2621         }
2622 
2623         def compileGeneratedTask = task("compileGenerated${t.capital}", type: JavaCompile, dependsOn: compileNativeTask) {
2624             def gensrcDir = "$webkitOutputDir/$webkitConfig/DerivedSources/WebCore/nativeJava/java"
2625             doFirst {
2626                 copy {
2627                     from "$projectDir/src/main/java-wrappers/com/sun/webkit/dom/EventListenerImpl.java"
2628                     into "$gensrcDir/com/sun/webkit/dom"
2629                 }
2630             }
2631             classpath = files(project.sourceSets.main.output.classesDir) +
2632                         files(project(":graphics").sourceSets.main.output) // for JSObject
2633             source gensrcDir
2634             destinationDir = file("$buildDir/classes/main")
2635         }
2636 
2637         compileGenerated.dependsOn compileGeneratedTask
2638 
2639         if (!targetProperties.compileWebnodeNative) {
2640             println("Not compiling native Webkit for ${t.name} per configuration request");
2641             compileNativeTask.enabled = false
2642         }
2643     }
2644 
2645     def drtClasses = "com/sun/javafx/webkit/drt/**"
2646     jar.exclude(drtClasses)
2647     task drtJar(type: Jar, dependsOn: compileJava) {
2648         archiveName = "drt.jar"
2649         destinationDir = file("$buildDir/test")
2650         from "$buildDir/classes/main"
2651         include drtClasses
2652     }
2653 
2654     if (IS_COMPILE_WEBKIT) {
2655         jar.dependsOn compileGenerated, drtJar
2656     }
2657 }
2658 
2659 allprojects {
2660     // The following block is a workaround for the fact that presently Gradle
2661     // can't set the -XDignore.symbol.file flag, because it appears that the
2662     // javac API is lacking support for it. So what we'll do is find any Compile
2663     // task and manually provide the options necessary to fire up the
2664     // compiler with the right settings.
2665     //
2666     // Also, we need to remove jfxrt.jar from the ext classpath (if it is there)
2667     tasks.withType(JavaCompile) { compile ->
2668         if (compile.options.hasProperty("useAnt")) {
2669             compile.options.useAnt = true
2670             compile.options.useDepend = IS_USE_DEPEND
2671         } else if (compile.options.hasProperty("incremental")) {
2672             compile.options.incremental = IS_INCREMENTAL
2673         }
2674         compile.options.debug = true // we always generate debugging info in the class files
2675         compile.options.debugOptions.debugLevel = IS_DEBUG_JAVA ? "source,lines,vars" : "source,lines"
2676         compile.options.fork = true
2677         compile.options.forkOptions.executable = JAVAC
2678         compile.options.warnings = IS_LINT
2679         compile.options.compilerArgs = ["-Djava.ext.dirs=", "-XDignore.symbol.file", "-encoding", "UTF-8"]
2680         if (!DO_BUILD_SDK_FOR_TEST) {
2681             compile.classpath = files(jfxrtJarFromSdk) + compile.classpath
2682         }
2683 
2684         // Add in the -Xlint options
2685         if (IS_LINT) {
2686             LINT.split("[, ]").each { s ->
2687                 compile.options.compilerArgs += "-Xlint:$s"
2688             }
2689         }
2690     }
2691 
2692     // Some tasks should be disabled not to compile SDK, when running only the tests
2693     disabledTasks.each {
2694         project.getTasksByName(it, false)*.enabled = false
2695     }
2696 }
2697 
2698 /******************************************************************************
2699  *                                                                            *
2700  *                             Top Level Tasks                                *
2701  *                                                                            *
2702  *  These are the tasks which are defined only for the top level project and  *
2703  *  not for any sub projects. These are generally the entry point that is     *
2704  *  used by Hudson and by the continuous build system.                        *
2705  *                                                                            *
2706  *****************************************************************************/
2707 
2708 task clean() {
2709     group = "Basic"
2710     description = "Deletes the build directory and the build directory of all sub projects"
2711     getSubprojects().each { subProject ->
2712         dependsOn(subProject.getTasksByName("clean", true));
2713     }
2714     doLast {
2715         delete(buildDir);
2716     }
2717 }
2718 
2719 task cleanAll() {
2720     group = "Basic"
2721     description = "Scrubs the repo of build artifacts"
2722     dependsOn(clean)
2723     doLast {
2724         //delete(".gradle"); This causes problems on windows.
2725         delete("buildSrc/build");
2726     }
2727 }
2728 
2729 task javadoc(type: Javadoc) {
2730     enabled = IS_BUILD_JAVADOC
2731     group = "Basic"
2732     description = "Generates the JavaDoc for all the public API"
2733     executable = JAVADOC
2734     def projectsToDocument = [
2735             project(":base"), project(":graphics"), project(":controls"), project(":media"),
2736             project(":swing"), project(":swt"), project(":fxml"), project(":web")]
2737     source(projectsToDocument.collect({
2738         [it.sourceSets.main.java, "$it.buildDir/generated-src/builders"]
2739     }));
2740     setDestinationDir(new File(buildDir, 'javadoc'));
2741     // Might need a classpath
2742     classpath = files(projectsToDocument.collect { project ->
2743         project.sourceSets.main.compileClasspath
2744     });
2745     classpath += files(projectsToDocument.collect { project ->
2746         project.sourceSets.main.output
2747     });
2748     exclude("com/**/*", "Compile*", "javafx/builder/**/*", "javafx/scene/accessibility/**/*");
2749     options.windowTitle("${javadocTitle}")
2750     options.header("${javadocHeader}")
2751     options.bottom("${javadocBottom}")
2752     if (BUILD_CLOSED) {
2753         options.linksOffline(JDK_DOCS, JDK_DOCS_CLOSED);
2754     } else {
2755         options.links(JDK_DOCS);
2756     }
2757     options.addBooleanOption("XDignore.symbol.file").setValue(true);
2758     options.addBooleanOption("Xdoclint:none").setValue(!IS_DOC_LINT);
2759     options.addBooleanOption("javafx").setValue(true);
2760     options.addBooleanOption("use").setValue(true);
2761     doLast {
2762         projectsToDocument.each { p ->
2763             copy {
2764                 from "$p.projectDir/src/main/docs"
2765                 into "$buildDir/javadoc"
2766             }
2767         }
2768     }
2769 
2770     dependsOn(projectsToDocument.collect { project -> project.getTasksByName("classes", true)});
2771 }
2772 
2773 task jfxrt() {
2774     if (DO_BUILD_SDK_FOR_TEST) {
2775         rootProject.getTasksByName("compileTestJava", true).each { t ->
2776             if (t.enabled) t.dependsOn(jfxrt)
2777         }
2778     }
2779 }
2780 
2781 task sdk() {
2782     dependsOn(checkJfxrtJar)
2783 
2784     if (DO_BUILD_SDK_FOR_TEST) {
2785         rootProject.getTasksByName("test", true).each { t ->
2786             if (t.enabled) t.dependsOn(sdk)
2787         }
2788     }
2789 }
2790 
2791 task appsjar() {
2792     dependsOn(sdk)
2793     // Note: the jar dependencies get added elsewhere see project(":apps")
2794 }
2795 
2796 // these are empty tasks, allowing us to depend on the task, which may have other
2797 // real work items added later.
2798 task copyAppsArtifacts() {
2799     dependsOn(appsjar)
2800 }
2801 
2802 task apps() {
2803     dependsOn(sdk)
2804     dependsOn(appsjar)
2805     dependsOn(copyAppsArtifacts)
2806 }
2807 
2808 task findbugs() {
2809     dependsOn(sdk)
2810 
2811     doLast {
2812         if (!BUILD_CLOSED) {
2813             println "findbugs task is only run for a closed build"
2814         }
2815     }
2816 }
2817 
2818 // The following tasks are for the closed build only. They are a no-op for the open build
2819 
2820 task checkCache() {
2821     dependsOn(updateCacheIfNeeded)
2822 }
2823 
2824 // TODO: consider moving the "public-sdk" portion of this task here
2825 task publicExports() {
2826     doFirst {
2827         if (BUILD_CLOSED && !IS_BUILD_JAVADOC) {
2828             fail("publicExports task requires: -PBUILD_JAVADOC=true")
2829         }
2830     }
2831     dependsOn(sdk)
2832 }
2833 
2834 task perf() {
2835     dependsOn(sdk,apps)
2836     doLast {
2837         if (!BUILD_CLOSED) {
2838             println "perf task is only run for a closed build"
2839         }
2840     }
2841 }
2842 
2843 task zips() {
2844     doFirst {
2845         if (BUILD_CLOSED && !IS_BUILD_JAVADOC) {
2846             fail("zips task requires: -PBUILD_JAVADOC=true")
2847         }
2848     }
2849     dependsOn(sdk,publicExports,apps,perf)
2850 }
2851 
2852 task copySources(type: Copy) {
2853     enabled = IS_BUILD_SRC_ZIP
2854     def projectsToCopy = [
2855             project(":base"), project(":graphics"), project(":controls"),
2856             project(":swing"), project(":swt"), project(":fxml"),
2857             project(":builders"), project(":media"), project(":web")]
2858     from(projectsToCopy.collect({ proj ->
2859         files(proj.sourceSets.main.java.srcDirs)
2860     }))
2861     include "**/*.java"
2862     into "${buildDir}/javafx-src"
2863 }
2864 
2865 task zipSources(type: Zip) {
2866     enabled = IS_BUILD_SRC_ZIP
2867     dependsOn(copySources)
2868     archiveName = "javafx-src.zip"
2869     destinationDir = file("$buildDir")
2870     includeEmptyDirs = false
2871     from "${buildDir}/javafx-src"
2872 }
2873 
2874 task src {
2875     enabled = IS_BUILD_SRC_ZIP
2876     description = "Created the javafx-src.zip bundle"
2877     dependsOn(zipSources)
2878 }
2879 
2880 task all() {
2881     dependsOn(sdk,publicExports,apps,perf,zips)
2882 }
2883 
2884 compileTargets { t ->
2885     def targetProperties = project.ext[t.upper]
2886     def sdkDirName = targetProperties.sdkDirName
2887     def library = targetProperties.library
2888     // The jfxrt task is responsible for creating the jfxrt.jar. A developer may
2889     // have multiple SDK's on their system at any one time, depending on which
2890     // cross compiles they have done. For example, I might have:
2891     //      build/ios-sdk/rt/lib/ext/jfxrt.jar
2892     //      build/armhf-sdk/rt/lib/ext/jfxrt.jar
2893     // and so forth. The default host build will always install into 'sdk'
2894     // allowing for uses where a known sdk path is needed (like IDEs)
2895     //      build/sdk/rt/lib/ext/jfxrt.jar
2896     // This arrangement allows for multiple independent SDKs to
2897     // exist on a developer's system.
2898     def jfxrtTask = task("jfxrt$t.capital", type: Jar) {
2899         group = "Basic"
2900         description = "Creates the jfxrt.jar for the $t.name target"
2901         archiveName = "build/${sdkDirName}/rt/lib/ext/jfxrt.jar";
2902         includeEmptyDirs = false
2903         from("modules/base/build/classes/main",
2904              "modules/base/build/resources/main",
2905              "modules/builders/build/classes/main",
2906              "modules/graphics/build/classes/main",
2907              "modules/graphics/build/resources/main",
2908              "modules/controls/build/classes/main",
2909              "modules/controls/build/resources/main",
2910              "modules/fxml/build/classes/main",
2911              "modules/fxml/build/resources/main",
2912              "modules/graphics/build/classes/jsl-decora",
2913              "modules/graphics/build/resources/jsl-decora",
2914              "modules/graphics/build/classes/jsl-prism",
2915              "modules/graphics/build/resources/jsl-prism",
2916              "modules/media/build/classes/main",
2917              "modules/media/build/resources/main")
2918         if (COMPILE_SWING) from ("modules/swing/build/classes/main", "modules/swing/build/resources/main")
2919 
2920         if (!IS_MAC) {
2921             exclude ("modules/media/build/classes/main/com/sun/media/jfxmediaimpl/platform/osx/**",
2922                      "com/sun/prism/es2/MacGL*",
2923                      "com/sun/glass/events/mac",
2924                      "com/sun/glass/ui/mac",
2925                      "com/sun/prism/es2/gl/mac"
2926                      )
2927         }
2928         if (!IS_WINDOWS) {
2929             exclude ("**/*.hlsl",
2930                      "com/sun/glass/ui/win",
2931                      "com/sun/prism/d3d",
2932                      "com/sun/prism/es2/gl/win",
2933                      "com/sun/prism/es2/WinGL*",
2934                      "com/sun/scenario/effect/impl/hw/d3d"
2935                      )
2936         }
2937         if (!targetProperties.includeGTK) { //usually IS_LINUX
2938             exclude (
2939                      "com/sun/glass/ui/gtk",
2940                      "com/sun/prism/es2/EGL*",
2941                      "com/sun/prism/es2/gl/eglfb",
2942                      "com/sun/prism/es2/gl/eglx11",
2943                      "com/sun/prism/es2/gl/x11",
2944                      "com/sun/prism/es2/X11GL*"
2945                      )
2946         }
2947         if (!targetProperties.includeEGL) {
2948             exclude ("com/sun/prism/es2/EGL*")
2949         }
2950         if (!targetProperties.includeLens) {
2951             exclude ("com/sun/glass/ui/lens")
2952         }
2953         /* Note: Monocle is used in the test harness, and so should
2954          * not be excluded until the deploy phase
2955         if (!targetProperties.includeMonocle) {
2956             exclude ("com/sun/glass/ui/monocle")
2957         }
2958         */
2959         if (!targetProperties.includeNull3d) {
2960             // "com/sun/prism/null3d", // TODO This is used in dev builds but not the final sdk
2961             exclude ("com/sun/prism/null3d")
2962         }
2963         if (t.name != 'ios') {
2964             exclude ("modules/media/build/classes/main/com/sun/media/jfxmediaimpl/platform/ios/**",
2965                      "com/sun/glass/ui/ios",
2966                      "com/sun/prism/es2/IOS*"
2967                      )
2968         }
2969         if (t.name != 'android' && t.name != 'dalvik') {
2970             exclude ("com/sun/glass/ui/android/*")
2971         }
2972 
2973         if (t.name == 'android') {
2974             from ("modules/web/build/classes/android",
2975                   "modules/web/build/resources/android",
2976                   "modules/controls/build/classes/android",
2977                   "modules/controls/build/resources/android")
2978         } else if (t.name == 'ios') {
2979             from ("modules/web/build/classes/ios",
2980                   "modules/web/build/resources/ios",
2981                   "modules/extensions/build/classes/ios")
2982         } else {
2983             from ("modules/web/build/classes/main", "modules/web/build/resources/main")
2984         }
2985 
2986         exclude("**/javafx/embed/swt/**")
2987 
2988         if (!targetProperties.includeSWT) {
2989             exclude("com/sun/glass/ui/swt")
2990         }
2991 
2992         if (!targetProperties.includeSwing) {
2993             exclude("javafx/embed/swing")
2994         }
2995         exclude("js/**/*", // er...
2996                 "PrismLoaderBackend*", // More decora stuff
2997                 "**/*.stg",    // any glue files for decora must be excluded
2998                 "**/*.java");  // Builder java files are in build/classes and should be excluded
2999 
3000         // Filter out platform specific Java sources (glass) when compiling for other targets
3001         if (targetProperties.containsKey('jfxrtJarExcludes')) {
3002             exclude(targetProperties.jfxrtJarExcludes)
3003         }
3004 
3005         dependsOn(subprojects.collect { project -> project.getTasksByName("assemble", true)});
3006     }
3007     def jfxrtIndexTask = task("jfxrtIndex$t.capital") {
3008         //the following is a workaround for the lack of indexing in gradle 1.4 through 1.7
3009         dependsOn(jfxrtTask)
3010 
3011         doLast() {
3012             ant.jar (update: true, index: true, destfile: jfxrtTask.archiveName)
3013         }
3014     }
3015     jfxrt.dependsOn(jfxrtIndexTask)
3016 
3017     def jfxswtTask = task("jfxswt$t.capital", type: Jar) {
3018         enabled = COMPILE_SWT
3019         group = "Basic"
3020         description = "Creates the jfxswt.jar for the $t.name target"
3021         archiveName = "build/${sdkDirName}/rt/lib/jfxswt.jar";
3022         includeEmptyDirs = false
3023         from("modules/swt/build/classes/main");
3024         from("modules/builders/build/classes/main");
3025         include("**/javafx/embed/swt/**")
3026         exclude("**/*.java");  // Builder java files are in build/classes and should be excluded
3027 
3028         dependsOn(subprojects.collect { project -> project.getTasksByName("assemble", true)});
3029     }
3030     def jfxswtIndexTask = task("jfxswtIndex$t.capital") {
3031         //the following is a workaround for the lack of indexing in gradle 1.4 through 1.7
3032         dependsOn(jfxswtTask)
3033 
3034         doLast() {
3035             ant.jar (update: true, index: true, destfile: jfxswtTask.archiveName)
3036         }
3037     }
3038     jfxrt.dependsOn(jfxswtIndexTask)
3039 
3040     def jmxTask = task ("jmx${t.capital}", type: Jar) {
3041         group = "Basic"
3042         description = "Creates the javafx-mx.jar"
3043         archiveName = "build/${sdkDirName}/lib/javafx-mx.jar";
3044         includeEmptyDirs = false
3045         from "modules/jmx/build/classes/main"
3046         from "modules/jmx/build/resources/main"
3047         dependsOn project(":jmx").assemble
3048     }
3049 
3050     // The 'sdk' task will build the rest of the SDK, and depends on the 'jfxrtTask' task. After
3051     // executing this task the sdk bundle for the current COMPILE_TARGETS will be fully created.
3052     def sdkTask = task("sdk$t.capital") {
3053         group = "Basic"
3054         description = "Creates the SDK for $t.name"
3055         doLast {
3056             // TODO instead of using copy everywhere, I probably want to use "sync" instead?
3057             // Copy all of the .dll / .so / .dylib native libraries into build/sdk/rt/lib/
3058             copy {
3059                 def useLipo = targetProperties.containsKey('useLipo') ? targetProperties.useLipo : false
3060                 from("modules/graphics/build/libs/jsl-decora/${t.name}/${library(targetProperties.decora.lib)}")
3061                 def libs = ['font', 'prism', 'prismSW', 'prismES2', 'glass', 'iio']
3062                 if (IS_COMPILE_PANGO) {
3063                     libs += ['fontFreetype', 'fontPango'];
3064                 }
3065                 libs.each { lib ->
3066                     def variants = targetProperties[lib].containsKey('variants') && !useLipo ? targetProperties[lib].variants : [null]
3067                     variants.each { variant ->
3068                         def variantProperties = variant ? targetProperties[lib][variant] : targetProperties[lib]
3069                         println "modules/graphics/build/libs/$lib/$t.name/${library(variantProperties.lib)}"
3070                         from ("modules/graphics/build/libs/$lib/$t.name/${library(variantProperties.lib)}")
3071                     }
3072                 }
3073                 if (IS_WINDOWS) {
3074                     from ("modules/graphics/build/libs/prismD3D/${t.name}/${library(targetProperties.prismD3D.lib)}");
3075 
3076                     // Copy VS2013 runtime libs to sdk
3077                     if ("${targetProperties.MSVCRTDIR}" != "") {
3078                         from("${targetProperties.MSVCRTDIR}") {
3079                             include "msvcr${WINDOWS_VS_VER}.dll",
3080                                     "msvcp${WINDOWS_VS_VER}.dll"
3081                         }
3082                     }
3083                 }
3084                 if (IS_COMPILE_WEBKIT) {
3085                     from ("modules/web/build/libs/${t.name}/${library('jfxwebkit')}")
3086                 } else {
3087                     if (t.name != "android" && t.name != "ios" && t.name != "dalvik") {
3088                         from ("$LIBRARY_STUB/${library('jfxwebkit')}")
3089                     }
3090                 }
3091 
3092                 def mediaBuildType = project(":media").ext.buildType
3093                 if (IS_COMPILE_MEDIA) {
3094                     [ "fxplugins", "gstreamer-lite", "jfxmedia" ].each { name ->
3095                         from ("modules/media/build/native/${t.name}/${mediaBuildType}/${library(name)}") }
3096 
3097                     if (t.name == "mac") {
3098                         // OSX media natives
3099                         [ "jfxmedia_qtkit", "jfxmedia_avf", "glib-lite" ].each { name ->
3100                             from ("modules/media/build/native/${t.name}/${mediaBuildType}/${library(name)}") }
3101                     } else if (t.name == "linux") {
3102                         from("modules/media/build/native/${t.name}/${mediaBuildType}") { include "libavplugin*.so" }
3103                     } else from ("modules/media/build/native/${t.name}/${mediaBuildType}/${library("glib-lite")}")
3104                 } else {
3105                     if (t.name != "android"  && t.name != "dalvik" ) {
3106                         [ "fxplugins", "gstreamer-lite", "jfxmedia" ].each { name ->
3107                             from ("$LIBRARY_STUB/${library(name)}") }
3108                     }
3109 
3110                     if (t.name == "mac") {
3111                         // copy libjfxmedia_{avf,qtkit}.dylib if they exist
3112                         [ "jfxmedia_qtkit", "jfxmedia_avf", "glib-lite" ].each { name ->
3113                             from ("$LIBRARY_STUB/${library(name)}") }
3114                     } else if (t.name == "linux") {
3115                         from(LIBRARY_STUB) { include "libavplugin*.so" }
3116                     }
3117                     else if (t.name != "android"  && t.name != "dalvik" ) {
3118                         from ("$LIBRARY_STUB/${library("glib-lite")}")
3119                     }
3120                 }
3121 
3122                 def libDest = targetProperties.libDest
3123                 into ("build/${sdkDirName}/rt/$libDest")
3124             }
3125 
3126             // Create the javafx.properties file
3127             final File javafxProperties = file("build/${sdkDirName}/rt/lib/javafx.properties")
3128             javafxProperties.delete()
3129             javafxProperties << "javafx.runtime.version=$RAW_VERSION";
3130             javafxProperties << "\n"
3131             javafxProperties << "javafx.runtime.build=b$PROMOTED_BUILD_NUMBER";
3132             javafxProperties << "\n"
3133             // Include any properties that have been defined (most likely in
3134             // one of the various platform gradle files)
3135             if (targetProperties.containsKey("javafxProperties")) {
3136                 javafxProperties << targetProperties.javafxProperties
3137                 javafxProperties << "\n"
3138             }
3139 
3140             // Embedded builds define this file as well
3141             if (targetProperties.containsKey("javafxPlatformProperties")) {
3142                 final File javafxPlatformProperties = file("build/${sdkDirName}/rt/lib/javafx.platform.properties")
3143                 javafxPlatformProperties.delete()
3144                 javafxPlatformProperties << targetProperties.javafxPlatformProperties
3145                 javafxPlatformProperties << "\n"
3146             }
3147 
3148             // Copy over the javadocs that were generated. This is done rather than just generating
3149             // the docs into the "right place" because for a cross-compile you only need one set of
3150             // docs but need to have a copy in each created sdk
3151             if (IS_BUILD_JAVADOC) {
3152                 copy {
3153                     from "build/javadoc"
3154                     into "build/${sdkDirName}/docs/api"
3155                 }
3156             }
3157 
3158             // Copy over the javafx-src bundle
3159             if (IS_BUILD_SRC_ZIP) {
3160                 copy {
3161                     from "build/javafx-src.zip"
3162                     into "build/${sdkDirName}"
3163                 }
3164             }
3165 
3166             // Copy over the fxpackager and rename as ant-javafx.jar
3167             copy {
3168                 from "modules/fxpackager/build/libs"
3169                 into "build/${sdkDirName}/lib"
3170             }
3171 
3172             // Copy over the FXPackager man files
3173             copy {
3174                 from "modules/fxpackager/build/man"
3175                 into "build/${sdkDirName}/man"
3176             }
3177 
3178             // Copy over the javapackager executable
3179             if (t.name == "win" || t.name == "linux" || t.name == "mac") {
3180                 copy {
3181                     from "modules/fxpackager/build/javapackager"
3182                     into "build/${sdkDirName}/bin"
3183                 }
3184             }
3185         }
3186         dependsOn(jmxTask);
3187         dependsOn(jfxrtIndexTask)
3188         dependsOn(jfxswtIndexTask)
3189         dependsOn(javadoc)
3190         dependsOn(src)
3191     }
3192 
3193     def generateSymbols = targetProperties.containsKey('generateSymbols') ? targetProperties.generateSymbols : false
3194     if (generateSymbols) {
3195         def exportedSymbolsTask = project.task("exportedSymbols${t.capital}", type: ExportedSymbolsTask, dependsOn: sdkTask, group: "Build") {
3196             description = "Generates exported symbols file for iOS build (from .a libraries)"
3197             def libDirName = "build/${sdkDirName}/rt/$targetProperties.libDest"
3198             libDir = file("$libDirName")
3199             outputFile = file("$libDirName/exported.symbols")
3200             excludes = targetProperties.generateSymbolsExcludes
3201         }
3202         sdk.dependsOn(exportedSymbolsTask)
3203     }
3204 
3205     sdk.dependsOn(sdkTask)
3206 }
3207 
3208     //task integrationCheck {
3209     //    group = "Basic"
3210     //    description = "Performs all the tasks necessary to ensure that the current build is ready for integration."
3211     //    dependsOn sdk
3212     //    dependsOn subprojects.collect { project -> project.getTasksByName("check", true)}
3213     //}
3214 
3215 /*
3216  * This clause changes the way we handle a build.gradle within ./apps
3217  * It does a few things:
3218  *   modifies the classpath used to include the built runttime classes
3219  *   provides for copying the build applications to the artifacts tree
3220  *
3221  * The applications to be built will be under ./apps, but also must
3222  * be listed in the applications listed in the setting variable: JFXApplications
3223  */
3224 ext.JFXRT_CP =
3225     files(
3226         project(":base").sourceSets.main.output.classesDir,
3227         project(":graphics").sourceSets.main.output.classesDir,
3228         project(":controls").sourceSets.main.output.classesDir,
3229         project(":fxml").sourceSets.main.output.classesDir,
3230         project(":swing").sourceSets.main.output.classesDir, //NOTE - used by 3Dviewer
3231         project(":builders").sourceSets.main.output.classesDir,
3232             "modules/media/build/classes/main",
3233             "modules/web/build/classes/main",
3234     )
3235 
3236 project(":apps") {
3237     // The apps build is Ant based, and gradle lets us "import" ant build.xml
3238     // into our configuration.
3239 
3240     ant.importBuild 'build.xml'
3241 
3242     compileTargets { t ->
3243         // The apps build is Ant based, and gradle lets us "import" ant apps/build.xml
3244         // into our configuration.
3245 
3246         // override the apps build.xml with an explicit pointer to our jar.
3247         def sdkDirName = rootProject.ext[t.upper].sdkDirName
3248         def jfxrtJar = "${rootProject.buildDir}/${sdkDirName}/rt/lib/ext/jfxrt.jar"
3249 
3250         def appsJar = project.task("appsJar${t.capital}") {
3251             doLast() {
3252               ant.properties['targetBld'] = "$t.name"
3253               if (!rootProject.ext[t.upper].compileSwing) {
3254                 ant.properties['JFX_CORE_ONLY'] = 'true'
3255               }
3256               ant.properties['jfxbuild.jfxrt.jar'] = jfxrtJar
3257               ant.properties['platforms.JDK_1.8.home'] = "${rootProject.ext.JDK_HOME}"
3258               ant.project.executeTarget("sampleAppsJar")
3259               ant.project.executeTarget("scenebuilderSampleAppsJar")
3260               if (!t.name.startsWith("arm")) {
3261                 ant.project.executeTarget("scenebuilderAppJar")
3262               }
3263             }
3264         }
3265         rootProject.appsjar.dependsOn(appsJar)
3266 
3267         def appsClean = project.task("appsClean${t.capital}") {
3268             doLast() {
3269               ant.properties['targetBld'] = "$t.name"
3270               ant.properties['platforms.JDK_1.8.home'] = "${rootProject.ext.JDK_HOME}"
3271               ant.project.executeTarget("sampleAppsClean")
3272               ant.project.executeTarget("scenebuilderSampleAppsClean")
3273               if (!t.name.startsWith("arm")) {
3274                 ant.project.executeTarget("scenebuilderAppClean")
3275               }
3276             }
3277         }
3278         rootProject.clean.dependsOn(appsClean)
3279     }
3280 }
3281 
3282 /******************************************************************************
3283  *                                                                            *
3284  *                              OpenExport                                    *
3285  *                                                                            *
3286  *****************************************************************************/
3287 
3288 task openExport() {
3289     if (!BUILD_CLOSED) {
3290         publicExports.dependsOn(openExport)
3291     }
3292 }
3293 
3294 task openZip() {
3295     if (!BUILD_CLOSED) {
3296         zips.dependsOn(openZip)
3297     }
3298 }
3299 
3300 compileTargets { t ->
3301     def targetProperties = project.ext[t.upper]
3302 
3303     def sdkDir = "${project.buildDir}/${targetProperties.sdkDirName}"
3304     def exportDir = "${project.buildDir}/${targetProperties.exportDirName}"
3305     def exportSDKDir = "${exportDir}/sdk"
3306     def bundleDir = "${project.buildDir}/${targetProperties.bundleDirName}"
3307     def jfxrtJar = "$sdkDir/rt/lib/ext/jfxrt.jar"
3308 
3309     def isWindows = false
3310     if (IS_WINDOWS && t.name == "win") {
3311         isWindows = true
3312     }
3313 
3314     def String compressJar = "false"
3315     if (targetProperties.containsKey('deploy') &&
3316         targetProperties.deploy.containsKey('compressBigJar')) {
3317         compressJar = targetProperties.deploy.compressBigJar
3318     }
3319 
3320     def exportTask = project.task("openExport$t.capital", group: "Build") {
3321         dependsOn("sdk$t.capital")
3322 
3323         doLast {
3324             def exportTmp = "${exportDir}/tmp/classes"
3325 
3326             // delete any old exports dir before rebuilding it
3327             file("${exportDir}").deleteDir()
3328 
3329             mkdir "${exportTmp}"
3330 
3331             copy {
3332                 from "${sdkDir}"
3333                 into "${exportSDKDir}"
3334                 exclude '**/jfxrt.jar'
3335 
3336                 if (isWindows) {
3337                     exclude '**/prism_es2.dll'
3338                 }
3339 
3340                 eachFile {details ->
3341                     if (details.path.startsWith('rt/')) {
3342                         details.path = 'jre/' + details.path.substring(3);
3343                     }
3344                 }
3345             }
3346 
3347             copy {
3348                 from zipTree("${jfxrtJar}")
3349                 into "${exportTmp}"
3350             }
3351 
3352             mkdir "${exportSDKDir}/jre/lib/ext"
3353 
3354             ant.jar(
3355                     destfile: "${exportSDKDir}/jre/lib/ext/jfxrt.jar",
3356                     index: true,
3357                     compress: compressJar
3358                 ) {
3359                     delegate.manifest {
3360                       attribute(name: 'Implementation-Title', value: 'OpenJavaFX')
3361                     }
3362 
3363                     fileset(dir: "${exportTmp}") {
3364                        exclude(name:'META-INF/*')
3365                        exclude(name:'com/sun/javafx/tools/ant/*')
3366 
3367                        //-- Obsolete or experimental code --
3368                        exclude(name:'com/sun/embeddedswing/**')
3369                        exclude(name:'com/sun/javafx/tk/glass/**')
3370                        exclude(name:'com/sun/javafx/tk/swing/**')
3371                        exclude(name:'com/sun/prism/null3d/**')
3372                        exclude(name:'com/sun/scenario/scenegraph/**')
3373                        exclude(name:'com/sun/scenario/utils/**')
3374                        exclude(name:'com/sun/webpane/sg/swing/**')
3375                        exclude(name:'com/sun/webpane/swing/**')
3376                        exclude(name:'com/sun/glass/ui/swt/**')
3377 
3378                        if (isWindows) {
3379                            //-- Strip ES2 pipeline on Windows platform only --
3380                            exclude(name:'com/sun/prism/es2/**')
3381                            exclude(name:'com/sun/scenario/effect/impl/es2/**')
3382                            exclude(name:'com/sun/scenario/effect/impl/hw/ogl/**')
3383                            exclude(name:'com/sun/scenario/effect/impl/j2d/jogl/**')
3384                            exclude(name:'com/sun/scenario/effect/impl/j2d/rsl/**')
3385                        }
3386 
3387                        if(!targetProperties.includeLens) {
3388                            exclude(name:'com/sun/glass/ui/lens/**')
3389                        }
3390 
3391                        if(!targetProperties.includeMonocle) {
3392                            exclude(name:'com/sun/glass/ui/monocle/**')
3393                            exclude(name:'com/sun/prism/es2/Monocle*')
3394                        }
3395                 }
3396             } // ant.jar
3397 
3398             // remove {exportTmp}
3399             file("${exportTmp}").deleteDir()
3400         }
3401     }
3402 
3403     def jfxBundle = 'javafx-sdk-overlay.zip'
3404 
3405     def zipTask = project.task("openZip$t.capital", type: Zip, group: "Build") {
3406 
3407         doFirst() {
3408             file("${bundleDir}/${jfxBundle}").delete()
3409         }
3410 
3411         archiveName = jfxBundle
3412         destinationDir = file("$bundleDir")
3413         includeEmptyDirs = false
3414         from "${exportSDKDir}"
3415 
3416         dependsOn(exportTask)
3417     }
3418 
3419     openExport.dependsOn(exportTask)
3420     openZip.dependsOn(zipTask)
3421 }
3422 
3423 task checkrepo() {
3424     doLast {
3425         logger.info("checking for whitespace (open)");
3426         exec {
3427             if (IS_WINDOWS) {
3428                 commandLine  'bash', 'tools/scripts/checkWhiteSpace'
3429             } else {
3430                 commandLine  'bash', 'tools/scripts/checkWhiteSpace', '-x'
3431             }
3432         }
3433     }
3434 }
3435 
3436 task checkrepoall() {
3437     doLast {
3438         logger.info("checking for all whitespace (open)");
3439         exec {
3440             if (IS_WINDOWS) {
3441                 commandLine  'bash', 'tools/scripts/checkWhiteSpace', '-a'
3442             } else {
3443                 commandLine  'bash', 'tools/scripts/checkWhiteSpace', '-x', '-a'
3444             }
3445         }
3446     }
3447 }
3448 
3449 /******************************************************************************
3450  *                                                                            *
3451  *                              BUILD_CLOSED                                  *
3452  *                                                                            *
3453  * This next section should remain at the end of the build script. It allows  *
3454  * for a "supplemental" gradle file to be used to extend the normal build     *
3455  * structure. For example, this is used for passing a supplemental gradle     *
3456  * file for producing official JavaFX builds.                                 *
3457  *                                                                            *
3458  *****************************************************************************/
3459 
3460 if (BUILD_CLOSED) {
3461     apply from: supplementalBuildFile
3462 }
3463 
3464 task showFlags {
3465 }
3466 
3467 compileTargets { t ->
3468     // Every platform must define these variables
3469     def props = project.ext[t.upper];
3470     showFlags.dependsOn(
3471         project.task("showFlags$t.upper") {
3472             doLast() {
3473                 println "Properties set for $t.upper"
3474                 props.each { println it }
3475             }
3476         }
3477     )
3478 }
3479