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