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