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