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