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         def cssDir = file("$buildDir/classes/main/javafx")
1553         jvmArgs "-Djava.ext.dirs=", "-Djavafx.toolkit=com.sun.javafx.pgstub.StubToolkit",
1554             "-DCSS_META_DATA_TEST_DIR=$cssDir"
1555         enableAssertions = true
1556         testLogging.exceptionFormat = "full"
1557         scanForTestClasses = false
1558         include "**/*Test.*"
1559         if (BUILD_CLOSED && DO_JCOV) {
1560             addJCov(project, test)
1561         }
1562     }
1563 
1564     // To enable the IDEs to all be happy (no red squiggles) we need to have the libraries
1565     // available in some known location. Maybe in the future the Gradle plugins to each
1566     // of the IDEs will be good enough that we won't need this hack anymore.
1567     classes << {
1568         // Copy all of the download libraries to the libs directory for the sake of the IDEs
1569         File libsDir = rootProject.file("build/libs");
1570         
1571         // In some IDEs (Eclipse for example), touching these libraries cauese a full build
1572         // within the IDE.  When gradle is used outside of the IDE, for example to build the
1573         // native code, a full rebuild is caused within the IDE.  The fix is to check for the 
1574         // lib directory and not copy the files
1575         //
1576         // This means that in order to update the dependent libraries for the IDE's, a clean
1577         // build is required
1578         //
1579         if (libsDir.exists()) return;
1580         libsDir.mkdirs();
1581         for (File f : [configurations.compile.files, configurations.antlr3.files].flatten()) {
1582             copy {
1583                 into libsDir
1584                 from f.getParentFile()
1585                 include "**/antlr-3.1.3.jar"
1586                 include "**/stringtemplate-3.2.jar"
1587                 include "**/antlr-runtime-3.1.3.jar"
1588                 includeEmptyDirs = false
1589             }
1590             // Have to rename the swt jar because it is some platform specific name but
1591             // for the sake of the IDEs we need to have a single stable name that works
1592             // on every platform
1593             copy {
1594                 into libsDir
1595                 from f.getParentFile()
1596                 include "**/*swt*.jar"
1597                 includeEmptyDirs = false
1598                 rename ".*swt.*jar", "swt-debug\\.jar"
1599             }
1600         }
1601     }
1602 }
1603 
1604 project(":controls") {
1605     dependencies {
1606         compile BUILD_SRC, project(":base"), project(":graphics"), project(":designTime")
1607         // TODO not sure how to specify this? processResources project(":base"), project(":graphics")
1608         testCompile project(":graphics").sourceSets.test.output
1609         testCompile project(":base").sourceSets.test.output
1610     }
1611 
1612     test {
1613         def cssDir = file("$buildDir/classes/main/javafx")
1614         jvmArgs "-Djavafx.toolkit=com.sun.javafx.pgstub.StubToolkit",
1615             "-DCSS_META_DATA_TEST_DIR=$cssDir"        
1616     }
1617 
1618     // TODO Css2Bin really should be moved out and put into buildSrc if it can be
1619     // TODO could change script to dynamically locate all .css files and create bss for them, probably better
1620     // TODO also not sure there is any benefit to having css files in the jfxrt.jar at all
1621     processResources << {
1622         ["$buildDir/resources/main/com/sun/javafx/scene/control/skin/caspian/caspian.css",
1623         "$buildDir/resources/main/com/sun/javafx/scene/control/skin/caspian/caspian-no-transparency.css",
1624         "$buildDir/resources/main/com/sun/javafx/scene/control/skin/caspian/embedded-qvga.css",
1625         "$buildDir/resources/main/com/sun/javafx/scene/control/skin/caspian/embedded.css",
1626         "$buildDir/resources/main/com/sun/javafx/scene/control/skin/caspian/fxvk.css",
1627         "$buildDir/resources/main/com/sun/javafx/scene/control/skin/caspian/highcontrast.css",
1628         "$buildDir/resources/main/com/sun/javafx/scene/control/skin/modena/modena.css",
1629         "$buildDir/resources/main/com/sun/javafx/scene/control/skin/modena/modena-no-transparency.css",
1630         "$buildDir/resources/main/com/sun/javafx/scene/control/skin/modena/touch.css"].each { css ->
1631             javaexec {
1632                 executable = JAVA
1633                 workingDir = "modules/controls"
1634                 classpath files("$buildDir/classes/main",
1635                         project(":graphics").sourceSets.main.output,
1636                         project(":base").sourceSets.main.output)
1637                 main = "com.sun.javafx.css.parser.Css2Bin"
1638                 args css
1639                 jvmArgs "-Djava.ext.dirs="
1640             }
1641         }
1642     }
1643 }
1644 
1645 project(":extensions") {
1646     dependencies {
1647         compile BUILD_SRC, project(":base"), project(":graphics")
1648     }
1649 }
1650 
1651 project(":swing") {
1652     /* should not be built, but needed in builders and JMX
1653     tasks.all {
1654         if (!COMPILE_SWING) it.enabled = false
1655     }
1656     */
1657     dependencies {
1658         compile BUILD_SRC, project(":base"), project(":graphics")
1659     }
1660 }
1661 
1662 project(":swt") {
1663     tasks.all {
1664         if (!COMPILE_SWT) it.enabled = false
1665     }
1666     dependencies {
1667         compile BUILD_SRC, project(":base"), project(":graphics")
1668         compile name: SWT_FILE_NAME
1669     }
1670 }
1671 
1672 project(":fxml") {
1673     dependencies {
1674         compile BUILD_SRC, project(":base"), project(":graphics"),
1675                 project(":controls"), project(":swt"), project(":swing")
1676         testCompile project(":graphics").sourceSets.test.output
1677     }
1678     test {
1679         // StubToolkit is not *really* needed here, but because some code inadvertently invokes performance
1680         // tracker and this attempts to fire up the toolkit and this looks for native libraries and fails,
1681         // we have to use the stub toolkit for now.
1682         jvmArgs "-Djavafx.toolkit=com.sun.javafx.pgstub.StubToolkit"
1683         classpath += files("$JDK_HOME/jre/lib/ext/nashorn.jar")
1684     }
1685 }
1686 
1687 project(":builders") {
1688     sourceCompatibility = 1.7
1689 
1690     if (!COMPILE_SWING) sourceSets.main.java.exclude ("**/swing/**")
1691     if (!COMPILE_SWT)   sourceSets.main.java.exclude ("**/swt/**")
1692 
1693     dependencies {
1694         compile BUILD_SRC, project(":base"), project(":graphics"),
1695                 project(":controls"), project(":swt"), project(":swing"), project(":media"), project(":web")
1696         testCompile project(":graphics").sourceSets.test.output
1697     }
1698     test {
1699         // StubToolkit is not *really* needed here, but because some code inadvertently invokes performance
1700         // tracker and this attempts to fire up the toolkit and this looks for native libraries and fails,
1701         // we have to use the stub toolkit for now.
1702         jvmArgs "-Djavafx.toolkit=com.sun.javafx.pgstub.StubToolkit"
1703     }
1704 }
1705 
1706 project(":designTime") {
1707     tasks.all {
1708         if (!COMPILE_DESIGN_TIME) it.enabled = false
1709     }
1710     dependencies {
1711         compile project(":graphics")
1712     }
1713     // impossible to run tests on designTime when not compiling SDK and designTime subproject
1714     // need to disable test and compileTestJava tasks and remove their dependencies
1715     if (!DO_BUILD_SDK_FOR_TEST) {
1716         [test, compileTestJava].each {
1717             it.dependsOn = []
1718             it.enabled = false
1719         }
1720     }
1721 }
1722 
1723 project(":jmx") {
1724     dependencies {
1725         compile project(":base")
1726         compile project(":graphics")
1727         compile project(":swing")
1728         compile project(":media")
1729     }
1730 
1731     // Tests are disabled until RT-33926 can be fixed
1732     test.enabled = false
1733 
1734     if (!DO_BUILD_SDK_FOR_TEST) {
1735        def javafxMxJar = new File(TEST_SDK_DIR, "lib/javafx-mx.jar")
1736        [test, compileTestJava].each {
1737            it.classpath = files(javafxMxJar) + it.classpath
1738        }
1739     }
1740 }
1741 
1742 // This project is for system tests that need to run with a full SDK.
1743 // Most of them display a stage or do other things that preclude running
1744 // them in a shared JVM or as part of the "smoke test" run (which must
1745 // not pop up any windows or use audio). As such, they are only enabled
1746 // when FULL_TEST is specified, and each test runs in its own JVM
1747 project(":systemTests") {
1748     test {
1749         enabled = IS_FULL_TEST
1750         if (!IS_USE_ROBOT) {
1751             // Disable all robot-based visual tests
1752             exclude("**/helloworld/*.*");
1753             exclude("**/javafx/embed/swing/*.*");
1754             exclude("**/javafx/scene/layout/*.*");
1755             exclude("**/test3d/*.*");
1756             exclude("**/painttest/*.*");
1757             exclude("**/renderlock/*.*");
1758         }
1759         if (!IS_AWT_TEST) {
1760             // Disable all AWT-based tests
1761             exclude("**/javafx/embed/swing/*.*");
1762             exclude("**/com/sun/javafx/application/Swing*.*");
1763         }
1764         
1765         forkEvery = 1
1766     }
1767 }
1768 
1769 project(":fxpackager") {
1770     tasks.all {
1771         if (!COMPILE_FXPACKAGER) it.enabled = false
1772     }
1773     // fxpackager has a dependency on ant in order to build the ant jar,
1774     // and as such needs to point to the apache binary repository
1775     if (!BUILD_CLOSED) {
1776         repositories {
1777             maven {
1778                 url "https://repository.apache.org"
1779             }
1780         }
1781     }
1782 
1783     dependencies {
1784         compile group: "org.apache.ant", name: "ant", version: "1.8.2"
1785     }
1786 
1787     // When producing the jar, we need to relocate a few class files
1788     // from their normal location to a resources/classes or resources/web-files
1789     // location
1790     jar {
1791         includeEmptyDirs = false
1792         archiveName = "ant-javafx.jar"
1793         eachFile { FileCopyDetails details ->
1794             if (details.path.startsWith("com/javafx/main")) {
1795                 details.path = "resources/classes/$details.path"
1796             }
1797         }
1798     }
1799 
1800     // The "man" task will create a $buildDir/man containing the man
1801     // files for the system being built
1802     task man(type: Copy) {
1803         includeEmptyDirs = false
1804         enabled = (IS_LINUX || IS_MAC) && COMPILE_FXPACKAGER
1805         from "src/main/man"
1806         into "$buildDir/man"
1807         exclude "**/*.html"
1808         if (IS_MAC) exclude "**/ja_JP.UTF-8/**"
1809     }
1810     processResources.dependsOn man
1811 
1812     // Compile the native launchers. These are included in ant-javafx.jar.
1813     if (IS_WINDOWS && COMPILE_FXPACKAGER) {
1814         task buildWinLauncher(type: CCTask, group: "Build") {
1815             description = "Compiles native sources for the application co-bundle launcher";
1816             matches = "WinLauncher\\.cpp";
1817             params.addAll(WIN.launcher.ccFlags);
1818             output(file("$buildDir/native/WinLauncher"));
1819             source(file("src/main/native/launcher/win"));
1820             compiler = WIN.launcher.compiler
1821             exe = true;
1822             linkerOptions.addAll(WIN.launcher.linkFlags);
1823             doLast {
1824                 copy {
1825                     from "$buildDir/native/WinLauncher/WinLauncher.exe"
1826                     from "$MSVCR"
1827                     from "$MSVCP"
1828                     into "$buildDir/classes/main/com/oracle/tools/packager/windows"
1829                 }
1830             }
1831         }
1832         task compileWinLibrary(type: CCTask, group: "Build") {
1833             description = "Compiles native sources for the application co-bundle launcher library";
1834             matches = ".*\\.cpp"
1835             source(file("src/main/native/library/common"));
1836             params.addAll(WIN.launcherlibrary.ccFlags)
1837             output(file("$buildDir/native/WinLauncher/obj"));
1838             compiler = WIN.launcherlibrary.compiler
1839         }
1840         task linkWinLibrary(type: LinkTask, group: "Build", dependsOn: compileWinLibrary) {
1841             description = "Links native sources for the application co-bundle launcher library";
1842             objectDir = file("$buildDir/native/WinLauncher/obj")
1843             linkParams.addAll(WIN.launcherlibrary.linkFlags);
1844             lib = file("$buildDir/native/WinLauncher/packager.dll")
1845             linker = WIN.launcherlibrary.linker
1846             doLast {
1847                 copy {
1848                     from "$buildDir/native/WinLauncher/packager.dll"
1849                     into "$buildDir/classes/main/com/oracle/tools/packager/windows"
1850                 }
1851             }
1852         }
1853         task buildWinLauncherSvc(type: CCTask, group: "Build") {
1854             description = "Compiles native sources for the application co-bundle launcher";
1855             matches = "WinLauncherSvc\\.cpp";
1856             params.addAll(WIN.launcher.ccFlags);
1857             output(file("$buildDir/native/WinLauncherSvc"));
1858             source(file("src/main/native/service/win"));
1859             compiler = WIN.launcher.compiler
1860             exe = true;
1861             linkerOptions.addAll(WIN.launcher.linkFlags);
1862             doLast {
1863                 copy {
1864                     from "$buildDir/native/WinLauncherSvc/WinLauncherSvc.exe"
1865                     into "$buildDir/classes/main/com/oracle/tools/packager/windows"
1866                 }
1867             }
1868         }
1869         task buildIconSwap(type: CCTask, group: "Build") {
1870             description = "Compiles native sources for the application co-bundle launcher"
1871             matches = "IconSwap\\.cpp"
1872             params.addAll(WIN.iconLauncher.ccFlags)
1873             output(file("$buildDir/native/IconSwap"))
1874             source file("src/main/native/tools/win")
1875             compiler = WIN.launcher.compiler
1876             exe = true
1877             linkerOptions.addAll(WIN.iconLauncher.linkFlags)
1878             doLast {
1879                 copy {
1880                     from "$buildDir/native/IconSwap/IconSwap.exe"
1881                     into "$buildDir/classes/main/com/oracle/tools/packager/windows"
1882                 }
1883             }
1884         }
1885         task compileLauncher(dependsOn: [buildWinLauncher, linkWinLibrary, buildWinLauncherSvc, buildIconSwap])
1886         jar.dependsOn compileLauncher;
1887     } else if (IS_MAC && COMPILE_FXPACKAGER) {
1888         task buildMacLauncher(type: CCTask, group: "Build") {
1889             description = "Compiles native sources for the application co-bundle launcher"
1890             matches = ".*\\.m"
1891             source file("src/main/native/launcher/mac")
1892             params.addAll(MAC.launcher.ccFlags)
1893             compiler = MAC.launcher.compiler
1894             output(file("$buildDir/classes/main/com/oracle/tools/packager/mac"))
1895             eachOutputFile = { f ->
1896                 return new File(f.getParent(), "JavaAppLauncher")
1897             }
1898         }
1899         task compileMacLibrary(type: CCTask, group: "Build") {
1900             description = "Compiles native sources for the application co-bundle launcher library"
1901             matches = ".*\\.cpp|.*\\.mm"
1902             source file("src/main/native/library/common");
1903             params.addAll(MAC.launcherlibrary.ccFlags)
1904             compiler = MAC.launcherlibrary.compiler
1905             output(file("$buildDir/native/maclauncher/obj"))
1906         }
1907         task linkMacLibrary(type: LinkTask, group: "Build", dependsOn: compileMacLibrary) {
1908             description = "Links native sources for the application co-bundle launcher library"
1909             objectDir = file("$buildDir/native/maclauncher/obj")
1910             linkParams.addAll(MAC.launcherlibrary.linkFlags)
1911             linker = MAC.launcherlibrary.linker
1912             lib = file("$buildDir/classes/main/com/oracle/tools/packager/mac/libpackager.dylib")
1913         }
1914         task compileLauncher(dependsOn: [buildMacLauncher, linkMacLibrary])
1915         jar.dependsOn compileLauncher;
1916     } else if (IS_LINUX && COMPILE_FXPACKAGER) {
1917         task compileLinuxLauncher(type: CCTask, group: "Build") {
1918             description = "Compiles native sources for the application co-bundle launcher"
1919             matches = ".*\\.cpp"
1920             source file("src/main/native/launcher/linux")
1921             params.addAll(LINUX.launcher.ccFlags)
1922             compiler = LINUX.launcher.compiler
1923             output(file("$buildDir/native/linuxlauncher/launcherobj"))
1924         }
1925         task linkLinuxLauncher(type: LinkTask, dependsOn: compileLinuxLauncher, group: "Build") {
1926             description = "Links native dynamic library for the application co-bundle launcher"
1927             objectDir = file("$buildDir/native/linuxlauncher/launcherobj")
1928             linkParams.addAll(LINUX.launcher.linkFlags)
1929             linker = LINUX.launcher.linker
1930             lib = file("$buildDir/classes/main/com/oracle/tools/packager/linux/JavaAppLauncher")
1931         }
1932         task compileLinuxLibrary(type: CCTask, group: "Build") {
1933             description = "Compiles native sources for the application co-bundle launcher library"
1934             matches = ".*\\.cpp"
1935             source file("src/main/native/library/common")
1936             params.addAll(LINUX.launcherlibrary.ccFlags)
1937             compiler = LINUX.launcherlibrary.compiler
1938             output(file("$buildDir/native/linuxlauncher/obj"))
1939         }
1940         task linkLinuxLibrary(type: LinkTask, dependsOn: compileLinuxLibrary, group: "Build") {
1941             description = "Links native dynamic library for the application co-bundle launcher library"
1942             objectDir = file("$buildDir/native/linuxlauncher/obj")
1943             linkParams.addAll(LINUX.launcherlibrary.linkFlags)
1944             linker = LINUX.launcherlibrary.linker
1945             lib = file("$buildDir/classes/main/com/oracle/tools/packager/linux/libpackager.so")
1946         }
1947         task compileLauncher(dependsOn: [linkLinuxLauncher, linkLinuxLibrary])
1948         jar.dependsOn compileLauncher;
1949     }
1950 
1951     // Builds the javapackager executable. For everything other than windows,
1952     // this is simply moving the existing shell script and ensuring it has proper
1953     // permissions. For Windows, this includes compiling the native executable
1954     if (IS_WINDOWS && COMPILE_FXPACKAGER){
1955         task buildJavaPackager(type: CCTask, group: "Build") {
1956             description = "Compiles native sources for javapackager.exe"
1957             matches = "javapackager\\.cpp"
1958             params.addAll(WIN.fxpackager.ccFlags)
1959             compiler = WIN.fxpackager.compiler
1960             output(file("$buildDir/native/javapackager"))
1961             source WIN.fxpackager.nativeSource
1962             doFirst {
1963                 copy {
1964                     mkdir "$buildDir/native"
1965                     mkdir "$buildDir/native/javapackager"
1966                     from file("src/main/native/javapackager/win/javapackager.manifest")
1967                     into file("$buildDir/native/javapackager")
1968                     filter { line->
1969                         line = line.replace("FXVERSION", "${RAW_VERSION}.${HUDSON_BUILD_NUMBER}");
1970                     }
1971                 }
1972             }
1973             doLast {
1974                 mkdir "$buildDir/native"
1975                 exec({
1976                     commandLine("$RC", "/nologo", "/l", "0x409", "/r", "/dJFX_DVERSION=8", "/dJFX_VERSION=8",
1977                             "/fo$buildDir/native/javapackager/javapackager.res",
1978                             "src/main/native/javapackager/win/javapackager.rc");
1979                     environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT);
1980                 });
1981             }
1982             doLast {
1983                 mkdir "$buildDir/javapackager"
1984                 exec({
1985                     commandLine("$WIN.fxpackager.linker", "/nologo", "/opt:REF", "/incremental:no", "/manifest", "kernel32.lib", "advapi32.lib",
1986                             "/out:$buildDir/native/javapackager/javapackager.exe",
1987                             "$buildDir/native/javapackager/javapackager.obj",
1988                             "$buildDir/native/javapackager/javapackager.res")
1989                     environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
1990                 })
1991             }
1992             doLast {
1993                 exec({
1994                     commandLine("$MC", "-manifest",
1995                                        "$buildDir/native/javapackager/javapackager.manifest",
1996                                        "-outputresource:$buildDir/native/javapackager/javapackager.exe")
1997                     environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
1998                 })
1999                 copy {
2000                     from file("$buildDir/native/javapackager/javapackager.exe")
2001                     into file("$buildDir/javapackager")
2002                 }
2003                 copy {
2004                     from file("$buildDir/native/javapackager/javapackager.exe")
2005                     into file("$buildDir/javapackager")
2006                     rename ('javapackager', 'javafxpackager')
2007                 }
2008             }
2009         }
2010     } else {
2011         task buildJavaPackager(group: "Build") {
2012             enabled = COMPILE_FXPACKAGER
2013             doLast {
2014                 copy {
2015                     from "src/main/native/javapackager/shell"
2016                     into "$buildDir/javapackager"
2017                     fileMode = 0755
2018                 }
2019                 copy {
2020                     from "src/main/native/javapackager/shell"
2021                     into "$buildDir/javapackager"
2022                     rename ('javapackager', 'javafxpackager')
2023                     fileMode = 0755
2024                 }
2025             }
2026         }
2027     }
2028 
2029     task packagerJar(type: Jar) {
2030         group = "Basic"
2031         description = "Creates the packager.jar"
2032         archiveName = "packager.jar";
2033         includeEmptyDirs = false
2034         from("$buildDir/classes/main");
2035         from("$buildDir/resources/main");
2036         include('jdk/packager/**')
2037 
2038         dependsOn(buildJavaPackager);
2039     }
2040 
2041     jar.dependsOn buildJavaPackager
2042     jar.dependsOn packagerJar
2043 
2044     classes << {
2045         // Copy all of the download libraries to libs directory for the sake of the IDEs
2046         File libsDir = rootProject.file("build/libs");
2047         File antLib = new File(libsDir, "ant-1.8.2.jar")
2048         libsDir.mkdirs();
2049         for (File f : configurations.compile.files) {
2050             copy {
2051                 into libsDir
2052                 from f.getParentFile()
2053                 include "**/ant-1.8.2.jar"
2054                 includeEmptyDirs = false
2055             }
2056         }
2057     }
2058 
2059     task packagerFakeJar(type: Jar) {
2060         dependsOn compileTestJava
2061         from compileTestJava.destinationDir
2062         include "hello/**"
2063 
2064         destinationDir project.file("build/tmp/tests/appResources")
2065         archiveName "mainApp.jar"
2066 
2067         manifest {
2068             attributes(
2069                     "Main-Class": "hello.HelloRectangle",
2070                     "Custom-Attribute": " Is it stripped?"
2071             )
2072         }
2073 
2074         doFirst {
2075             copy {
2076                 from "$projectDir/src/main/resources/com/oracle/tools/packager/linux/javalogo_white_48.png"
2077                 from "$projectDir/src/main/resources/com/oracle/tools/packager/mac/GenericAppHiDPI.icns"
2078                 from "$projectDir/src/main/resources/com/oracle/tools/packager/windows/javalogo_white_48.ico"
2079                 from "$projectDir/src/test/resources/hello/java-logo2.gif"
2080                 from "$projectDir/src/test/resources/hello/small.ico"
2081                 from "$projectDir/src/test/resources/hello/test.icns"
2082                 from "$projectDir/../../LICENSE"
2083                 from "$projectDir/build/libs/packager.jar"
2084                 into project.file("$projectDir/build/tmp/tests/appResources")
2085             }
2086             copy {
2087                 from "$projectDir/../../LICENSE"
2088                 into project.file("$projectDir/build/tmp/tests/appResources")
2089                 rename '(.*)LICENSE', '$1LICENSE2'
2090             }
2091         }
2092     }
2093 
2094     task packagerFXPackagedJar(type: Jar) {
2095         dependsOn packagerFakeJar
2096         from compileTestJava.destinationDir
2097         include "hello/**"
2098 
2099         destinationDir project.file("build/tmp/tests/appResources")
2100         archiveName "packagedMainApp.jar"
2101 
2102         manifest {
2103             attributes(
2104                 "JavaFX-Application-Class": "hello.TestPackager",
2105             )
2106         }
2107     }
2108 
2109     if (!DO_BUILD_SDK_FOR_TEST) {
2110         def antJavafxJar = new File(TEST_SDK_DIR, "lib/ant-javafx.jar")
2111         [compileTestJava, test].each {
2112             it.classpath = files(antJavafxJar) + it.classpath
2113         }
2114     }
2115 
2116     test {
2117         dependsOn packagerFXPackagedJar
2118         systemProperty "RETAIN_PACKAGER_TESTS", RETAIN_PACKAGER_TESTS
2119         systemProperty "TEST_PACKAGER_DMG", TEST_PACKAGER_DMG
2120         systemProperty "FULL_TEST", FULL_TEST
2121     }
2122 
2123     def packagerDevOpts = []
2124     try {
2125         packagerDevOpts.addAll(PACKAGER_DEV_OPTS.split(' '))
2126     } catch (MissingPropertyException ignore) {
2127         packagerDevOpts.addAll("image")
2128     }
2129     
2130     task packagerDev(dependsOn: [jar, packagerFakeJar], type:JavaExec) {
2131         workingDir = project.file("build/tmp/tests/appResources/")
2132         classpath = project.files("build/libs/ant-javafx.jar", "build/classes/test", "build/resources/test")
2133         main = "hello.SimpleBundle"
2134         args = [
2135                 "-o", "$projectDir/build/dev",
2136                 "-all",
2137                 packagerDevOpts
2138         ].flatten()
2139     }
2140 }
2141 
2142 project(":media") {
2143     configurations {
2144         media
2145     }
2146 
2147     dependencies {
2148         compile BUILD_SRC, project(":base"), project(":graphics")
2149     }
2150 
2151     sourceSets {
2152         tools {
2153             java.srcDir "src/tools/java"
2154         }
2155     }
2156 
2157     compileToolsJava {
2158         enabled = IS_COMPILE_MEDIA
2159         classpath = sourceSets.main.output;
2160     }
2161 
2162     project.ext.makeJobsFlag = IS_WINDOWS && IS_DEBUG_NATIVE ? "-j1" : "-j5";
2163     project.ext.buildType = IS_DEBUG_NATIVE ? "Debug" : "Release";
2164 
2165     def nativeSrcDir = file("${projectDir}/src/main/native")
2166     def generatedHeadersDir = file("${buildDir}/generated-src/headers")
2167     
2168     task generateHeaders(dependsOn: compileJava) {
2169         enabled = IS_COMPILE_MEDIA
2170         doLast {
2171             def classpath = sourceSets.main.output;
2172             mkdir generatedHeadersDir;
2173 
2174             def classesList = ["com.sun.media.jfxmedia.logging.Logger",
2175                              "com.sun.media.jfxmedia.track.AudioTrack",
2176                              "com.sun.media.jfxmedia.control.VideoDataBuffer",
2177                              "com.sun.media.jfxmedia.control.VideoFormat\$FormatTypes",
2178                              "com.sun.media.jfxmediaimpl.NativeAudioClip",
2179                              "com.sun.media.jfxmediaimpl.NativeMediaPlayer",
2180                              "com.sun.media.jfxmediaimpl.NativeVideoBuffer",
2181                              "com.sun.media.jfxmediaimpl.platform.gstreamer.GSTPlatform",
2182                              "com.sun.media.jfxmediaimpl.platform.gstreamer.GSTMedia",
2183                              "com.sun.media.jfxmediaimpl.platform.gstreamer.GSTMediaPlayer",
2184                              "com.sun.media.jfxmediaimpl.NativeAudioEqualizer",
2185                              "com.sun.media.jfxmediaimpl.NativeEqualizerBand",
2186                              "com.sun.media.jfxmediaimpl.NativeAudioSpectrum"]
2187             if (IS_MAC) {
2188                 classesList.addAll( ["com.sun.media.jfxmediaimpl.platform.osx.OSXPlatform",
2189                                      "com.sun.media.jfxmediaimpl.platform.osx.OSXMedia",
2190                                      "com.sun.media.jfxmediaimpl.platform.osx.OSXMediaPlayer"] );
2191             }
2192             exec {
2193                 commandLine ("${JAVAH}", "-J-Djava.ext.dirs=", "-d", "${generatedHeadersDir}", "-classpath", "${classpath.asPath}");
2194                 args classesList;
2195             }
2196         }
2197     }
2198     
2199     task generateMediaErrorHeader(dependsOn: [compileToolsJava, compileJava]) {
2200         enabled = IS_COMPILE_MEDIA
2201         doLast {
2202             def classpath = files(sourceSets.main.output, sourceSets.tools.output);
2203             def sourcepath = sourceSets.main.java.srcDirs;
2204             def headerpath = file("$generatedHeadersDir/jfxmedia_errors.h");
2205             def srcRoot = (sourcepath.toArray())[0];
2206 
2207             mkdir generatedHeadersDir;
2208 
2209             exec {
2210                 commandLine("$JAVA", "-Djava.ext.dirs=", "-classpath", "${classpath.asPath}");
2211                 args("headergen.HeaderGen", "$headerpath", "$srcRoot");
2212             }
2213         }
2214     }
2215 
2216     task buildNativeTargets {
2217         enabled = IS_COMPILE_MEDIA
2218     }
2219     
2220     compileTargets { t->        
2221         def targetProperties = project.rootProject.ext[t.upper]
2222         def nativeOutputDir = file("${buildDir}/native/${t.name}")
2223         def projectDir = t.name.startsWith("arm") ? "linux" : t.name
2224         def mediaProperties = targetProperties.media
2225         // Makefile for OSX needs to know if we're building for parfait
2226         def compileParfait = IS_COMPILE_PARFAIT ? "true" : "false"
2227         
2228         def buildNative = task("build${t.capital}Native", dependsOn: [generateHeaders, generateMediaErrorHeader]) {
2229             enabled = targetProperties.compileMediaNative
2230             if (!targetProperties.compileMediaNative) {
2231                 println("Not compiling native Media for ${t.name} per configuration request");
2232             } 
2233 
2234             doLast {
2235                 exec {
2236                     commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/jfxmedia/projects/${projectDir}")
2237                     args("JAVA_HOME=${JDK_HOME}", "GENERATED_HEADERS_DIR=${generatedHeadersDir}",
2238                          "OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}", "BASE_NAME=jfxmedia",
2239                          "COMPILE_PARFAIT=${compileParfait}")
2240 
2241                     if (t.name == "win") {
2242                         environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
2243                         args(IS_64 ? "ARCH=x64" : "ARCH=x32", "RESOURCE=${nativeOutputDir}/${buildType}/${WIN.media.jfxmediaRcFile}")
2244                     } else {
2245                         args ("CC=${mediaProperties.compiler}", "LINK=${mediaProperties.linker}", "LIB=${mediaProperties.lib}")
2246 
2247                         if (t.name.startsWith("arm")) {
2248                             args("EXTRA_CFLAGS=${mediaProperties.extra_cflags}", "EXTRA_LDFLAGS=${mediaProperties.extra_ldflags}")
2249                         } else {
2250                             args("HOST_COMPILE=1")
2251                         }
2252                     }
2253                 }
2254             }
2255         }        
2256         
2257         // check for the property disable${name} = true
2258         def boolean disabled = targetProperties.containsKey('disableMedia') ? targetProperties.get('disableMedia') : false
2259         if (!disabled) {
2260             // Building GStreamer
2261             def buildGStreamer = task("build${t.capital}GStreamer") {
2262                 enabled = IS_COMPILE_MEDIA
2263                 doLast {
2264                     exec {
2265                         commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/gstreamer/projects/${projectDir}/gstreamer-lite")
2266                         args("OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}", "BASE_NAME=gstreamer-lite")
2267 
2268                         if (t.name == "win") {
2269                             environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
2270                             args(IS_64 ? "ARCH=x64" : "ARCH=x32", "RESOURCE=${nativeOutputDir}/${buildType}/${WIN.media.gstreamerRcFile}")
2271                         } else
2272                             args ("CC=${mediaProperties.compiler}", "LINK=${mediaProperties.linker}", "LIB=${mediaProperties.lib}")
2273                     }
2274                 }
2275             }
2276 
2277             def buildPlugins = task("build${t.capital}Plugins", dependsOn: buildGStreamer) {
2278                 enabled = IS_COMPILE_MEDIA
2279 
2280                 if (!project.ext.properties.containsKey("ON2_SRCDIR")) {
2281                     project.ext.ON2_SRCDIR = "";
2282                 }
2283 
2284                 if (!project.ext.properties.containsKey("ON2_LIB")) {
2285                     project.ext.ON2_LIB = "";
2286                 }
2287 
2288                 doLast {
2289                     exec {
2290                         commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/gstreamer/projects/${projectDir}/fxplugins")
2291                         args("OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}", "BASE_NAME=fxplugins", 
2292                              "ON2_SRCDIR=${project.ext.ON2_SRCDIR}", "ON2_LIB=${project.ext.ON2_LIB}")
2293 
2294                         if (t.name == "win") {
2295                             Map winEnv = new HashMap(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
2296 
2297                             String sdkDir = System.getenv("BASECLASSES_SDK_DIR");
2298                             if (sdkDir == null) {
2299                                 sdkDir = "C:/Program Files/Microsoft SDKs/Windows/v7.1" // Default value
2300                                 winEnv["BASECLASSES_SDK_DIR"] = sdkDir
2301                             }
2302                             environment(winEnv)
2303 
2304                             args(IS_64 ? "ARCH=x64" : "ARCH=x32", "RESOURCE=${nativeOutputDir}/${buildType}/${WIN.media.fxpluginsRcFile}")
2305                         } else
2306                             args ("CC=${mediaProperties.compiler}", "LINK=${mediaProperties.linker}", "LIB=${mediaProperties.lib}")
2307                     }
2308                 }
2309             }
2310             
2311             buildNative.dependsOn buildPlugins
2312 
2313             if (t.name == "linux") {
2314                 def buildAVPlugin = task( "buildAVPlugin", dependsOn: [buildPlugins]) {
2315                     enabled = IS_COMPILE_MEDIA
2316 
2317                     doLast {
2318                         if (project.ext.properties.containsKey("libav")) {
2319                             project.ext.libav.versions.each { version ->
2320                                 def libavDir = "${project.ext.libav.basedir}-${version}"
2321                                 File dir = file(libavDir)
2322                                 if (dir.exists()) {
2323                                     exec {
2324                                         commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/gstreamer/projects/linux/avplugin")
2325                                         args("CC=${mediaProperties.compiler}", "OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}", 
2326                                              "BASE_NAME=avplugin", "VERSION=${version}", "LIBAV_DIR=${libavDir}")
2327                                     }
2328                                 }
2329                             }
2330                         } else {
2331                             // Building fxavcodec plugin (libav plugin)
2332                             exec {
2333                                 commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/gstreamer/projects/linux/avplugin")
2334                                 args("CC=${mediaProperties.compiler}", "OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}", 
2335                                      "BASE_NAME=avplugin")
2336                             }
2337                         }
2338                     }
2339                 }
2340                 buildNative.dependsOn buildAVPlugin
2341             }
2342 
2343             if (t.name == "win") {
2344                 def buildResources = task("buildResources") << {
2345                     def rcOutputDir = "${nativeOutputDir}/${buildType}"
2346                     mkdir rcOutputDir
2347                     exec {
2348                         environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
2349                         commandLine (WIN.media.rcCompiler)
2350                         args(WIN.media.glibRcFlags)
2351                         args("/Fo${rcOutputDir}/${WIN.media.glibRcFile}", WIN.media.rcSource)
2352                     }
2353 
2354                     exec {
2355                         environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
2356                         commandLine (WIN.media.rcCompiler)
2357                         args(WIN.media.gstreamerRcFlags)
2358                         args("/Fo${rcOutputDir}/${WIN.media.gstreamerRcFile}", WIN.media.rcSource)
2359                     }
2360 
2361                     exec {
2362                         environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
2363                         commandLine (WIN.media.rcCompiler)
2364                         args(WIN.media.fxpluginsRcFlags)
2365                         args("/Fo${rcOutputDir}/${WIN.media.fxpluginsRcFile}", WIN.media.rcSource)
2366                     }
2367 
2368                     exec {
2369                         environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
2370                         commandLine (WIN.media.rcCompiler)
2371                         args(WIN.media.jfxmediaRcFlags)
2372                         args("/Fo${rcOutputDir}/${WIN.media.jfxmediaRcFile}", WIN.media.rcSource)
2373                     }
2374                 }
2375                 
2376                 def buildGlib = task("build${t.capital}Glib", dependsOn: [buildResources]) {
2377                     enabled = IS_COMPILE_MEDIA
2378                     doLast {
2379                         exec {
2380                             environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
2381                             commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/gstreamer/projects/${projectDir}/glib-lite")
2382                             args("OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}", "BASE_NAME=glib-lite",
2383                                  IS_64 ? "ARCH=x64" : "ARCH=x32", "RESOURCE=${nativeOutputDir}/${buildType}/${WIN.media.glibRcFile}")
2384                         }
2385                     }
2386                 }
2387                 buildGStreamer.dependsOn buildGlib
2388                 
2389             } else if (t.name == "mac") {
2390                 def buildGlib = task("build${t.capital}Glib") {
2391                     enabled = IS_COMPILE_MEDIA
2392                     doLast {
2393                         exec {
2394                             commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/gstreamer/projects/${projectDir}/glib-lite")
2395                             args("OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}", "BASE_NAME=glib-lite")
2396                             args ("CC=${mediaProperties.compiler}", "LINK=${mediaProperties.linker}", "LIB=${mediaProperties.lib}")
2397                         }
2398                     }
2399                 }
2400                 buildGStreamer.dependsOn buildGlib
2401             }
2402         }
2403         
2404         buildNativeTargets.dependsOn buildNative
2405     }
2406  
2407     jar {
2408         exclude("headergen/**")
2409 
2410         dependsOn compileJava
2411         if (IS_COMPILE_MEDIA) {
2412             dependsOn buildNativeTargets
2413         }
2414     }
2415 }
2416 
2417 project(":web") {
2418     configurations {
2419         webkit
2420     }
2421     dependencies {
2422         compile project(":base"), project(":graphics"), project(":controls"), project(":media")
2423     }
2424     
2425     compileJava {
2426         if (IS_COMPILE_WEBKIT) {
2427             // These classes will be generated by native build
2428             sourceSets.main.java.exclude("com/sun/webkit/dom/**")
2429         }
2430     }
2431     
2432     task generateHeaders(dependsOn: compileJava) {
2433         doLast {
2434             def classpath = files("$buildDir/classes/main",
2435                                   project(":graphics").sourceSets.main.output.classesDir)
2436             def dest = file("$buildDir/generated-src/headers");
2437             mkdir dest;
2438             exec {
2439                 commandLine("$JAVAH", "-J-Djava.ext.dirs=", "-d", "$dest",
2440                             "-classpath", "${classpath.asPath}");
2441                 args("java.lang.Character",
2442                      "java.net.IDN",
2443                      "com.sun.webkit.ContextMenu",
2444                      "com.sun.webkit.ContextMenuItem",
2445                      "com.sun.webkit.CursorManager",
2446                      "com.sun.webkit.PageCache",
2447                      "com.sun.webkit.PopupMenu",
2448                      "com.sun.webkit.SharedBuffer",
2449                      "com.sun.webkit.WatchdogTimer",
2450                      "com.sun.webkit.WebPage",
2451                      "com.sun.webkit.LoadListenerClient",
2452                      "com.sun.webkit.event.WCFocusEvent",
2453                      "com.sun.webkit.event.WCKeyEvent",
2454                      "com.sun.webkit.event.WCMouseEvent",
2455                      "com.sun.webkit.event.WCMouseWheelEvent",
2456                      "com.sun.webkit.graphics.GraphicsDecoder",
2457                      "com.sun.webkit.graphics.RenderMediaControls",
2458                      "com.sun.webkit.graphics.RenderTheme",
2459                      "com.sun.webkit.graphics.ScrollBarTheme",
2460                      "com.sun.webkit.graphics.WCMediaPlayer",
2461                      "com.sun.webkit.graphics.WCGraphicsManager",
2462                      "com.sun.webkit.graphics.WCRenderQueue",
2463                      "com.sun.webkit.graphics.WCPath",
2464                      "com.sun.webkit.graphics.WCPathIterator",
2465                      "com.sun.webkit.Timer",
2466                      "com.sun.webkit.WCFrameView",
2467                      "com.sun.webkit.WCPasteboard",
2468                      "com.sun.webkit.WCPluginWidget",
2469                      "com.sun.webkit.dom.JSObject",
2470                      "com.sun.webkit.network.SocketStreamHandle",
2471                      "com.sun.webkit.network.URLLoader",
2472                      "com.sun.webkit.text.TextBreakIterator",
2473                      "com.sun.webkit.text.TextNormalizer");
2474             }
2475         }
2476     }
2477 
2478     task compileGenerated()
2479 
2480     compileTargets { t ->
2481         def targetProperties = project.rootProject.ext[t.upper]
2482         def classifier = (t.name != "linux" && t.name != "win") ? t.name :
2483                           IS_64 ? "${t.name}-amd64" : "${t.name}-i586"
2484         dependencies {
2485             webkit group: "com.sun.webkit", name: "webview-deps",
2486                    version: "1.2", classifier: "$classifier", ext: "zip"
2487         }
2488 
2489         def webkitOutputDir = "$buildDir/${t.name}"
2490         def webkitConfig = IS_DEBUG_NATIVE ? "Debug" : "Release"
2491 
2492         def compileNativeTask = task("compileNative${t.capital}", dependsOn: generateHeaders) << {
2493             println "Building Webkit configuration /$webkitConfig/ into $webkitOutputDir"
2494             
2495             def dependencyFile = configurations.webkit.filter(
2496                     { File f -> f.getName().contains(classifier) }
2497                 ).getSingleFile()
2498             ant.unzip(src:  dependencyFile,
2499                       dest: webkitOutputDir)
2500 
2501             exec {
2502                 workingDir("$projectDir/src/main/native")
2503                 commandLine("perl", "Tools/Scripts/set-webkit-configuration", "--$webkitConfig")
2504                 environment(["WEBKITOUTPUTDIR" : webkitOutputDir])
2505             }
2506 
2507             exec {
2508                 workingDir("$projectDir/src/main/native")
2509                 if (t.name == "win") {
2510                     String qtDir = cygpath(System.getenv().get("QTSDK_DIR"))
2511                     String parfaitPath = IS_COMPILE_PARFAIT ? System.getenv().get("PARFAIT_PATH") + ";" : "";
2512                     Map environmentSettings = new HashMap(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
2513                     environmentSettings["PATH"] = parfaitPath + "$WINDOWS_VS_PATH;$qtDir/bin;$qtDir/qt/bin"
2514                     environmentSettings["QMAKESPEC"] = "win32-msvc2008"
2515                     environment(environmentSettings)
2516                     /* To build with ICU:
2517                     1. Download http://javaweb.us.oracle.com/jcg/fx-webrevs/RT-17164/WebKitLibrariesICU.zip
2518                     and unzip it to WebKitLibraries folder.
2519                     2. Copy DLLs from
2520                     WebKitLibrariesICU.zip\WebKitLibraries\import\runtime
2521                     to %windir%\system32
2522                     3. Uncomment the line below
2523                      */
2524                     // args("--icu-unicode")
2525                 } else if (t.name == "mac") {
2526                     environment([
2527                         "QMAKESPEC"      : "macx-g++",
2528                         "QMAKE_CFLAGS"   : "-m64",
2529                         "QMAKE_LFLAGS"   : "-m64",
2530                     ])
2531                 } else if (t.name.startsWith("arm")) {
2532                     // ARM cross build
2533                     def webkitProperties = project.rootProject.ext[t.upper].webkit
2534                     def qmakeSpecDir = "$webkitOutputDir/qws/linux-cross-${t.name}-g++"
2535                     mkdir qmakeSpecDir
2536                     File qmakeSpec = new File("$qmakeSpecDir/qmake.conf")
2537                     qmakeSpec.append(
2538 """TARGET_PLATFORM         = unix
2539 include(/usr/share/qt4/mkspecs/common/linux.conf)
2540 include(/usr/share/qt4/mkspecs/common/g++.conf)
2541 include(/usr/share/qt4/mkspecs/common/qws.conf)
2542 QMAKE_CC                = $webkitProperties.compiler
2543 QMAKE_CXX               = $webkitProperties.linker
2544 QMAKE_LINK              = $webkitProperties.linker
2545 QMAKE_LINK_SHLIB        = $webkitProperties.linker
2546 QMAKE_AR                = $webkitProperties.ar cqs
2547 QMAKE_OBJCOPY           = $webkitProperties.objcopy
2548 QMAKE_STRIP             = $webkitProperties.strip
2549 QMAKE_CXXFLAGS          = $webkitProperties.ccFlags
2550 QMAKE_LFLAGS            = $webkitProperties.linkFlags
2551 load(qt_config)""")
2552                     environment([
2553                         "QMAKESPEC" : file(qmakeSpecDir).getAbsolutePath(),
2554                         "PATH"      : "$System.env.PATH:$webkitProperties.binDir",
2555                     ])
2556                     args("--nocache")
2557                 }
2558                 environment([
2559                     "JAVA_HOME"       : JDK_HOME,
2560                     "WEBKITOUTPUTDIR" : webkitOutputDir,
2561                 ])
2562 
2563                 if (IS_COMPILE_PARFAIT) {
2564                     environment([
2565                         "CC"        : "parfait-gcc",
2566                         "QMAKE_CC"  : "parfait-gcc",
2567                         "CXX"       : "parfait-g++",
2568                         "QMAKE_CXX" : "parfait-g++",
2569                         "CPP"       : "parfait-g++",
2570                         "cc"        : "parfait-gcc",
2571                         "LINK"      : "parfait-g++",
2572                         "QMAKE_LINK": "parfait-g++",
2573                     ])
2574                 }
2575                 commandLine("perl", "Tools/Scripts/build-webkit", "--java", "--imageio")
2576             }
2577 
2578             def library = rootProject.ext[t.upper].library
2579             copy {
2580                 from "$webkitOutputDir/$webkitConfig/lib/${library('jfxwebkit')}"
2581                 into "$buildDir/libs/${t.name}"
2582             }
2583             copy {
2584                 from "$webkitOutputDir/$webkitConfig/lib/${library('DumpRenderTreeJava')}"
2585                 into "$buildDir/test/${t.name}"
2586             }
2587         }
2588     
2589         if (IS_WINDOWS && t.name == "win") {
2590             def webkitProperties = project.rootProject.ext[t.upper].webkit
2591             def rcTask = project.task("rc${t.capital}", type: CompileResourceTask) {
2592                 compiler = webkitProperties.rcCompiler
2593                 source(webkitProperties.rcSource)
2594                 if (webkitProperties.rcFlags) {
2595                     rcParams.addAll(webkitProperties.rcFlags)
2596                 }
2597                 output(file("$webkitOutputDir/$webkitConfig/WebCore/obj"))
2598             }
2599             compileNativeTask.dependsOn rcTask
2600         }
2601         
2602         def compileGeneratedTask = task("compileGenerated${t.capital}", type: JavaCompile, dependsOn: compileNativeTask) {
2603             def gensrcDir = "$webkitOutputDir/$webkitConfig/WebCore/generated/java"
2604             doFirst {
2605                 copy {
2606                     from "$projectDir/src/main/java/com/sun/webkit/dom/EventListenerImpl.java"
2607                     into "$gensrcDir/com/sun/webkit/dom"
2608                 }
2609             }
2610             classpath = files(project(":graphics").sourceSets.main.output) // for JSObject
2611             source gensrcDir
2612             destinationDir = file("$buildDir/classes/main")
2613         }
2614 
2615         compileGenerated.dependsOn compileGeneratedTask
2616             
2617         if (!targetProperties.compileWebnodeNative) {
2618             println("Not compiling native Webkit for ${t.name} per configuration request");
2619             compileNativeTask.enabled = false
2620         }
2621     }
2622     
2623     def drtClasses = "com/sun/javafx/webkit/drt/**"
2624     jar.exclude(drtClasses)
2625     task drtJar(type: Jar, dependsOn: compileJava) {
2626         archiveName = "drt.jar"
2627         destinationDir = file("$buildDir/test")
2628         from "$buildDir/classes/main"
2629         include drtClasses
2630     }
2631 
2632     if (IS_COMPILE_WEBKIT) {
2633         jar.dependsOn compileGenerated, drtJar
2634     }
2635 }
2636 
2637 allprojects {
2638     // The following block is a workaround for the fact that presently Gradle
2639     // can't set the -XDignore.symbol.file flag, because it appears that the
2640     // javac API is lacking support for it. So what we'll do is find any Compile
2641     // task and manually provide the options necessary to fire up the
2642     // compiler with the right settings.
2643     //
2644     // Also, we need to remove jfxrt.jar from the ext classpath (if it is there)
2645     tasks.withType(Compile) { compile ->
2646         // It looks like we have to use ant to compile instead of the built-in gradle
2647         // compiler stuff because otherwise it won't compile on CYGWIN
2648         // TODO need to file issue with Gradle
2649         compile.options.useAnt = true
2650         compile.options.debug = true // we always generate debugging info in the class files
2651         compile.options.debugOptions.debugLevel = IS_DEBUG_JAVA ? "source,lines,vars" : "source,lines"
2652         compile.options.fork = true
2653         compile.options.forkOptions.executable = JAVAC
2654         compile.options.warnings = IS_LINT
2655         compile.options.useDepend = IS_USE_DEPEND
2656         compile.options.compilerArgs = ["-Djava.ext.dirs=", "-XDignore.symbol.file", "-encoding", "UTF-8"]
2657         if (!DO_BUILD_SDK_FOR_TEST) {
2658             compile.classpath = files(jfxrtJarFromSdk) + compile.classpath
2659         }
2660 
2661         // Add in the -Xlint options
2662         if (IS_LINT) {
2663             LINT.split("[, ]").each { s ->
2664                 compile.options.compilerArgs += "-Xlint:$s"
2665             }
2666         }
2667     }
2668 
2669     // Some tasks should be disabled not to compile SDK, when running only the tests
2670     disabledTasks.each {
2671         project.getTasksByName(it, false)*.enabled = false
2672     }
2673 }
2674 
2675 /******************************************************************************
2676  *                                                                            *
2677  *                             Top Level Tasks                                *
2678  *                                                                            *
2679  *  These are the tasks which are defined only for the top level project and  *
2680  *  not for any sub projects. These are generally the entry point that is     *
2681  *  used by Hudson and by the continuous build system.                        *
2682  *                                                                            *
2683  *****************************************************************************/
2684 
2685 task clean() {
2686     group = "Basic"
2687     description = "Deletes the build directory and the build directory of all sub projects"
2688     getSubprojects().each { subProject ->
2689         dependsOn(subProject.getTasksByName("clean", true));
2690     }
2691     doLast {
2692         delete(buildDir);
2693     }
2694 }
2695 
2696 task cleanAll() {
2697     group = "Basic"
2698     description = "Scrubs the repo of build artifacts"
2699     dependsOn(clean)
2700     doLast {
2701         //delete(".gradle"); This causes problems on windows.
2702         delete("buildSrc/build");
2703     }
2704 }
2705 
2706 task javadoc(type: Javadoc) {
2707     enabled = IS_BUILD_JAVADOC
2708     group = "Basic"
2709     description = "Generates the JavaDoc for all the public API"
2710     executable = JAVADOC
2711     def projectsToDocument = [
2712             project(":base"), project(":graphics"), project(":controls"), project(":media"),
2713             project(":swing"), project(":swt"), project(":fxml"), project(":web")]
2714     source(projectsToDocument.collect({
2715         [it.sourceSets.main.java, "$it.buildDir/generated-src/builders"]
2716     }));
2717     setDestinationDir(new File(buildDir, 'javadoc'));
2718     // Might need a classpath
2719     classpath = files(projectsToDocument.collect { project ->
2720         project.sourceSets.main.compileClasspath
2721     });
2722     classpath += files(projectsToDocument.collect { project ->
2723         project.sourceSets.main.output
2724     });
2725     exclude("com/**/*", "javafx/scene/ParentDesignInfo*", "Compile*", "javafx/builder/**/*", "javafx/scene/accessibility/**/*");
2726     options.windowTitle("${javadocTitle}")
2727     options.header("${javadocHeader}")
2728     options.bottom("${javadocBottom}")
2729     if (BUILD_CLOSED) {
2730         options.linksOffline(JDK_DOCS, JDK_DOCS_CLOSED);
2731     } else {
2732         options.links(JDK_DOCS);
2733     }
2734     options.addBooleanOption("XDignore.symbol.file").setValue(true);
2735     options.addBooleanOption("Xdoclint:none").setValue(!IS_DOC_LINT);
2736     options.addBooleanOption("javafx").setValue(true);
2737     options.addBooleanOption("use").setValue(true);
2738     doLast {
2739         projectsToDocument.each { p ->
2740             copy {
2741                 from "$p.projectDir/src/main/docs"
2742                 into "$buildDir/javadoc"
2743             }
2744         }
2745     }
2746 
2747     dependsOn(projectsToDocument.collect { project -> project.getTasksByName("classes", true)});
2748 }
2749 
2750 task jfxrt() {
2751     if (DO_BUILD_SDK_FOR_TEST) {
2752         rootProject.getTasksByName("compileTestJava", true).each { t ->
2753             if (t.enabled) t.dependsOn(jfxrt)
2754         }
2755     }
2756 }
2757 
2758 task sdk() {
2759     dependsOn(checkJfxrtJar)
2760 
2761     if (DO_BUILD_SDK_FOR_TEST) {
2762         rootProject.getTasksByName("test", true).each { t ->
2763             if (t.enabled) t.dependsOn(sdk)
2764         }
2765     }
2766 }
2767 
2768 task appsjar() {
2769     dependsOn(sdk)
2770     // Note: the jar dependencies get added elsewhere see project(":apps")
2771 }
2772 
2773 // these are empty tasks, allowing us to depend on the task, which may have other
2774 // real work items added later.
2775 task copyAppsArtifacts() {
2776     dependsOn(appsjar)
2777 }
2778 
2779 task apps() {
2780     dependsOn(sdk)
2781     dependsOn(appsjar)
2782     dependsOn(copyAppsArtifacts)
2783 }
2784 
2785 task findbugs() {
2786     dependsOn(sdk)
2787 
2788     doLast {
2789         if (!BUILD_CLOSED) {
2790             println "findbugs task is only run for a closed build"
2791         }
2792     }
2793 }
2794 
2795 // The following tasks are for the closed build only. They are a no-op for the open build
2796 
2797 task checkCache() {
2798     dependsOn(updateCacheIfNeeded)
2799 }
2800 
2801 // TODO: consider moving the "public-sdk" portion of this task here
2802 task publicExports() {
2803     doFirst {
2804         if (!IS_BUILD_JAVADOC) {
2805             fail("publicExports task requires: -PBUILD_JAVADOC=true")
2806         }
2807     }
2808     dependsOn(sdk)
2809     doLast {
2810         if (!BUILD_CLOSED) {
2811             println "publicExports task is only run for a closed build"
2812         }
2813     }
2814 }
2815 
2816 task perf() {
2817     dependsOn(sdk,apps)
2818     doLast {
2819         if (!BUILD_CLOSED) {
2820             println "perf task is only run for a closed build"
2821         }
2822     }
2823 }
2824 
2825 task zips() {
2826     doFirst {
2827         if (!IS_BUILD_JAVADOC) {
2828             fail("zips task requires: -PBUILD_JAVADOC=true")
2829         }
2830     }
2831     dependsOn(sdk,publicExports,apps,perf)
2832     doLast {
2833         if (!BUILD_CLOSED) {
2834             println "zips task is only run for a closed build"
2835         }
2836     }
2837 }
2838 
2839 task copySources(type: Copy) {
2840     enabled = IS_BUILD_SRC_ZIP
2841     def projectsToCopy = [
2842             project(":base"), project(":graphics"), project(":controls"),
2843             project(":swing"), project(":swt"), project(":fxml"),
2844             project(":builders"), project(":media"), project(":web")]
2845     from(projectsToCopy.collect({ proj ->
2846         files(proj.sourceSets.main.java.srcDirs)
2847     }))
2848     include "**/*.java"
2849     into "${buildDir}/javafx-src"
2850 }
2851 
2852 task zipSources(type: Zip) {
2853     enabled = IS_BUILD_SRC_ZIP
2854     dependsOn(copySources)
2855     archiveName = "javafx-src.zip"
2856     destinationDir = file("$buildDir")
2857     includeEmptyDirs = false
2858     from "${buildDir}/javafx-src"
2859 }
2860 
2861 task src {
2862     enabled = IS_BUILD_SRC_ZIP
2863     description = "Created the javafx-src.zip bundle"
2864     dependsOn(zipSources)
2865 }
2866 
2867 task all() {
2868     dependsOn(sdk,publicExports,apps,perf,zips)
2869 }
2870 
2871 compileTargets { t ->
2872     def targetProperties = project.ext[t.upper]
2873     def sdkDirName = targetProperties.sdkDirName
2874     def library = targetProperties.library
2875     // The jfxrt task is responsible for creating the jfxrt.jar. A developer may
2876     // have multiple SDK's on their system at any one time, depending on which
2877     // cross compiles they have done. For example, I might have:
2878     //      build/ios-sdk/rt/lib/ext/jfxrt.jar
2879     //      build/armhf-sdk/rt/lib/ext/jfxrt.jar
2880     // and so forth. The default host build will always install into 'sdk' 
2881     // allowing for uses where a known sdk path is needed (like IDEs)
2882     //      build/sdk/rt/lib/ext/jfxrt.jar
2883     // This arrangement allows for multiple independent SDKs to
2884     // exist on a developer's system.
2885     def jfxrtTask = task("jfxrt$t.capital", type: Jar) {
2886         group = "Basic"
2887         description = "Creates the jfxrt.jar for the $t.name target"
2888         archiveName = "build/${sdkDirName}/rt/lib/ext/jfxrt.jar";
2889         includeEmptyDirs = false
2890         from("modules/base/build/classes/main",
2891              "modules/base/build/resources/main",
2892              "modules/builders/build/classes/main",
2893              "modules/graphics/build/classes/main",
2894              "modules/graphics/build/resources/main",
2895              "modules/controls/build/classes/main",
2896              "modules/controls/build/resources/main",
2897              "modules/fxml/build/classes/main",
2898              "modules/fxml/build/resources/main",
2899              "modules/graphics/build/classes/jsl-decora",
2900              "modules/graphics/build/resources/jsl-decora",
2901              "modules/graphics/build/classes/jsl-prism",
2902              "modules/graphics/build/resources/jsl-prism",
2903              "modules/media/build/classes/main",
2904              "modules/media/build/resources/main")
2905         if (COMPILE_SWING) from ("modules/swing/build/classes/main", "modules/swing/build/resources/main")
2906 
2907         if (!IS_MAC) {
2908             exclude ("modules/media/build/classes/main/com/sun/media/jfxmediaimpl/platform/osx/**",
2909                      "com/sun/prism/es2/MacGL*",
2910                      "com/sun/glass/events/mac",
2911                      "com/sun/glass/ui/mac",
2912                      "com/sun/prism/es2/gl/mac"
2913                      )
2914         }
2915         if (!IS_WINDOWS) {
2916             exclude ("**/*.hlsl",
2917                      "com/sun/glass/ui/win",
2918                      "com/sun/prism/d3d",
2919                      "com/sun/prism/es2/gl/win",
2920                      "com/sun/prism/es2/WinGL*",
2921                      "com/sun/scenario/effect/impl/hw/d3d"
2922                      )
2923         }
2924         if (!targetProperties.includeGTK) { //usually IS_LINUX 
2925             exclude (
2926                      "com/sun/glass/ui/gtk",
2927                      "com/sun/prism/es2/EGL*",
2928                      "com/sun/prism/es2/gl/eglfb",
2929                      "com/sun/prism/es2/gl/eglx11",
2930                      "com/sun/prism/es2/gl/x11",
2931                      "com/sun/prism/es2/X11GL*"
2932                      )
2933         }
2934         if (!targetProperties.includeEGL) {
2935             exclude ("com/sun/prism/es2/EGL*")
2936         }
2937         if (!targetProperties.includeLens) {
2938             exclude ("com/sun/glass/ui/lens")
2939         }
2940         /* Note: Monocle is used in the test harness, and so should
2941          * not be excluded until the deploy phase
2942         if (!targetProperties.includeMonocle) {
2943             exclude ("com/sun/glass/ui/monocle")
2944         }
2945         */
2946         if (!targetProperties.includeNull3d) {
2947             // "com/sun/prism/null3d", // TODO This is used in dev builds but not the final sdk
2948             exclude ("com/sun/prism/null3d")
2949         }
2950         if (t.name != 'ios') {
2951             exclude ("modules/media/build/classes/main/com/sun/media/jfxmediaimpl/platform/ios/**",
2952                      "com/sun/glass/ui/ios",
2953                      "com/sun/prism/es2/IOS*"
2954                      )
2955         }
2956         if (t.name != 'android' && t.name != 'dalvik') {
2957             exclude ("com/sun/glass/ui/android/*")
2958         }
2959 
2960         if (t.name == 'android') {
2961             from ("modules/web/build/classes/android",
2962                   "modules/web/build/resources/android",
2963                   "modules/controls/build/classes/android",
2964                   "modules/controls/build/resources/android")
2965         } else if (t.name == 'ios') {
2966             from ("modules/web/build/classes/ios",
2967                   "modules/web/build/resources/ios",
2968                   "modules/extensions/build/classes/ios")
2969         } else {
2970             from ("modules/web/build/classes/main", "modules/web/build/resources/main")
2971         }
2972 
2973         exclude("**/javafx/embed/swt/**")
2974 
2975         if (!targetProperties.includeSWT) {
2976             exclude("com/sun/glass/ui/swt")
2977         }
2978 
2979         if (!targetProperties.includeSwing) {
2980             exclude("javafx/embed/swing")
2981         }
2982         exclude("js/**/*", // er...
2983                 "PrismLoaderBackend*", // More decora stuff
2984                 "**/*.stg",    // any glue files for decora must be excluded
2985                 "**/*.java");  // Builder java files are in build/classes and should be excluded
2986 
2987         // Filter out platform specific Java sources (glass) when compiling for other targets
2988         if (targetProperties.containsKey('jfxrtJarExcludes')) {
2989             exclude(targetProperties.jfxrtJarExcludes)
2990         }
2991 
2992         dependsOn(subprojects.collect { project -> project.getTasksByName("assemble", true)});
2993     }
2994     def jfxrtIndexTask = task("jfxrtIndex$t.capital") {
2995         //the following is a workaround for the lack of indexing in gradle 1.4 through 1.7
2996         dependsOn(jfxrtTask)
2997 
2998         doLast() {
2999             ant.jar (update: true, index: true, destfile: jfxrtTask.archiveName)
3000         }
3001     }
3002     jfxrt.dependsOn(jfxrtIndexTask)
3003 
3004     def jfxswtTask = task("jfxswt$t.capital", type: Jar) {
3005         enabled = COMPILE_SWT
3006         group = "Basic"
3007         description = "Creates the jfxswt.jar for the $t.name target"
3008         archiveName = "build/${sdkDirName}/rt/lib/jfxswt.jar";
3009         includeEmptyDirs = false
3010         from("modules/swt/build/classes/main");
3011         from("modules/builders/build/classes/main");
3012         include("**/javafx/embed/swt/**")
3013         exclude("**/*.java");  // Builder java files are in build/classes and should be excluded
3014 
3015         dependsOn(subprojects.collect { project -> project.getTasksByName("assemble", true)});
3016     }
3017     def jfxswtIndexTask = task("jfxswtIndex$t.capital") {
3018         //the following is a workaround for the lack of indexing in gradle 1.4 through 1.7
3019         dependsOn(jfxswtTask)
3020 
3021         doLast() {
3022             ant.jar (update: true, index: true, destfile: jfxswtTask.archiveName)
3023         }
3024     }
3025     jfxrt.dependsOn(jfxswtIndexTask)
3026 
3027     def jmxTask = task ("jmx${t.capital}", type: Jar) {
3028         group = "Basic"
3029         description = "Creates the javafx-mx.jar"
3030         archiveName = "build/${sdkDirName}/lib/javafx-mx.jar";
3031         includeEmptyDirs = false
3032         from "modules/jmx/build/classes/main"
3033         from "modules/jmx/build/resources/main"
3034         dependsOn project(":jmx").assemble
3035     }
3036 
3037     // The 'sdk' task will build the rest of the SDK, and depends on the 'jfxrtTask' task. After
3038     // executing this task the sdk bundle for the current COMPILE_TARGETS will be fully created.
3039     def sdkTask = task("sdk$t.capital") {
3040         group = "Basic"
3041         description = "Creates the SDK for $t.name"
3042         doLast {
3043             // TODO instead of using copy everywhere, I probably want to use "sync" instead?
3044             // Copy all of the .dll / .so / .dylib native libraries into build/sdk/rt/lib/
3045             copy {
3046                 def useLipo = targetProperties.containsKey('useLipo') ? targetProperties.useLipo : false
3047                 from("modules/graphics/build/libs/jsl-decora/${t.name}/${library(targetProperties.decora.lib)}")
3048                 def libs = ['font', 'prism', 'prismSW', 'prismES2', 'glass', 'iio']
3049                 if (IS_COMPILE_PANGO) {
3050                     libs += ['fontFreetype', 'fontPango'];
3051                 }
3052                 libs.each { lib ->
3053                     def variants = targetProperties[lib].containsKey('variants') && !useLipo ? targetProperties[lib].variants : [null]
3054                     variants.each { variant ->
3055                         def variantProperties = variant ? targetProperties[lib][variant] : targetProperties[lib]
3056                         println "modules/graphics/build/libs/$lib/$t.name/${library(variantProperties.lib)}"
3057                         from ("modules/graphics/build/libs/$lib/$t.name/${library(variantProperties.lib)}")
3058                     }
3059                 }
3060                 if (IS_WINDOWS) {
3061                     from ("modules/graphics/build/libs/prismD3D/${t.name}/${library(targetProperties.prismD3D.lib)}");
3062                 }
3063                 if (IS_COMPILE_WEBKIT) {
3064                     from ("modules/web/build/libs/${t.name}/${library('jfxwebkit')}")
3065                 } else {
3066                     if (t.name != "android" && t.name != "ios") {
3067                         from ("$LIBRARY_STUB/${library('jfxwebkit')}")
3068                     }
3069                 }
3070 
3071                 def mediaBuildType = project(":media").ext.buildType
3072                 if (IS_COMPILE_MEDIA) {
3073                     [ "fxplugins", "gstreamer-lite", "jfxmedia" ].each { name ->
3074                         from ("modules/media/build/native/${t.name}/${mediaBuildType}/${library(name)}") }
3075 
3076                     if (t.name == "mac") {
3077                         // OSX media natives
3078                         [ "jfxmedia_qtkit", "jfxmedia_avf", "glib-lite" ].each { name ->
3079                             from ("modules/media/build/native/${t.name}/${mediaBuildType}/${library(name)}") }
3080                     } else if (t.name == "linux") {
3081                         from("modules/media/build/native/${t.name}/${mediaBuildType}") { include "libavplugin*.so" }
3082                     } else from ("modules/media/build/native/${t.name}/${mediaBuildType}/${library("glib-lite")}")
3083                 } else {
3084                     [ "fxplugins", "gstreamer-lite", "jfxmedia" ].each { name ->
3085                         from ("$LIBRARY_STUB/${library(name)}") }
3086 
3087                     if (t.name == "mac") {
3088                         // copy libjfxmedia_{avf,qtkit}.dylib if they exist
3089                         [ "jfxmedia_qtkit", "jfxmedia_avf", "glib-lite" ].each { name ->
3090                             from ("$LIBRARY_STUB/${library(name)}") }
3091                     } else if (t.name == "linux") {
3092                         from(LIBRARY_STUB) { include "libavplugin*.so" }
3093                     }
3094                     else from ("$LIBRARY_STUB/${library("glib-lite")}")
3095                 }
3096                 
3097                 def libDest = targetProperties.libDest
3098                 into ("build/${sdkDirName}/rt/$libDest")
3099             }
3100 
3101             // Create the javafx.properties file
3102             final File javafxProperties = file("build/${sdkDirName}/rt/lib/javafx.properties")
3103             javafxProperties.delete()
3104             javafxProperties << "javafx.runtime.version=$RAW_VERSION";
3105             javafxProperties << "\n"
3106             // Include any properties that have been defined (most likely in
3107             // one of the various platform gradle files)
3108             if (targetProperties.containsKey("javafxProperties")) {
3109                 javafxProperties << targetProperties.javafxProperties
3110                 javafxProperties << "\n"
3111             }
3112 
3113             // Embedded builds define this file as well
3114             if (targetProperties.containsKey("javafxPlatformProperties")) {
3115                 final File javafxPlatformProperties = file("build/${sdkDirName}/rt/lib/javafx.platform.properties")
3116                 javafxPlatformProperties.delete()
3117                 javafxPlatformProperties << targetProperties.javafxPlatformProperties
3118                 javafxPlatformProperties << "\n"
3119             }
3120 
3121             // Copy over the javadocs that were generated. This is done rather than just generating
3122             // the docs into the "right place" because for a cross-compile you only need one set of
3123             // docs but need to have a copy in each created sdk
3124             if (IS_BUILD_JAVADOC) {
3125                 copy {
3126                     from "build/javadoc"
3127                     into "build/${sdkDirName}/docs/api"
3128                 }
3129             }
3130 
3131             // Copy over the javafx-src bundle
3132             if (IS_BUILD_SRC_ZIP) {
3133                 copy {
3134                     from "build/javafx-src.zip"
3135                     into "build/${sdkDirName}"
3136                 }
3137             }
3138 
3139             // Copy over the fxpackager and rename as ant-javafx.jar
3140             copy {
3141                 from "modules/fxpackager/build/libs"
3142                 into "build/${sdkDirName}/lib"
3143             }
3144 
3145             // Copy over the FXPackager man files
3146             copy {
3147                 from "modules/fxpackager/build/man"
3148                 into "build/${sdkDirName}/man"
3149             }
3150 
3151             // Copy over the javapackager executable
3152             if (t.name == "win" || t.name == "linux" || t.name == "mac") {
3153                 copy {
3154                     from "modules/fxpackager/build/javapackager"
3155                     into "build/${sdkDirName}/bin"
3156                 }
3157             }
3158         }
3159         dependsOn(jmxTask);
3160         dependsOn(jfxrtIndexTask)
3161         dependsOn(jfxswtIndexTask)
3162         dependsOn(javadoc)
3163         dependsOn(src)
3164     }
3165 
3166     def generateSymbols = targetProperties.containsKey('generateSymbols') ? targetProperties.generateSymbols : false
3167     if (generateSymbols) {
3168         def exportedSymbolsTask = project.task("exportedSymbols${t.capital}", type: ExportedSymbolsTask, dependsOn: sdkTask, group: "Build") {
3169             description = "Generates exported symbols file for iOS build (from .a libraries)"
3170             def libDirName = "build/${sdkDirName}/rt/$targetProperties.libDest"
3171             libDir = file("$libDirName")
3172             outputFile = file("$libDirName/exported.symbols")
3173             excludes = targetProperties.generateSymbolsExcludes
3174         }
3175         sdk.dependsOn(exportedSymbolsTask)
3176     }
3177 
3178     sdk.dependsOn(sdkTask)
3179 }
3180 
3181     //task integrationCheck {
3182     //    group = "Basic"
3183     //    description = "Performs all the tasks necessary to ensure that the current build is ready for integration."
3184     //    dependsOn sdk
3185     //    dependsOn subprojects.collect { project -> project.getTasksByName("check", true)}
3186     //}
3187 
3188 /*
3189  * This clause changes the way we handle a build.gradle within ./apps
3190  * It does a few things:
3191  *   modifies the classpath used to include the built runttime classes
3192  *   provides for copying the build applications to the artifacts tree
3193  *
3194  * The applications to be built will be under ./apps, but also must
3195  * be listed in the applications listed in the setting variable: JFXApplications
3196  */
3197 ext.JFXRT_CP =
3198     files(
3199         project(":base").sourceSets.main.output.classesDir,
3200         project(":graphics").sourceSets.main.output.classesDir,
3201         project(":controls").sourceSets.main.output.classesDir,
3202         project(":fxml").sourceSets.main.output.classesDir,
3203         project(":swing").sourceSets.main.output.classesDir, //NOTE - used by 3Dviewer
3204         project(":builders").sourceSets.main.output.classesDir,
3205             "modules/media/build/classes/main",
3206             "modules/web/build/classes/main",
3207     )
3208 
3209 project(":apps") {
3210     // The apps build is Ant based, and gradle lets us "import" ant build.xml
3211     // into our configuration.
3212 
3213     ant.importBuild 'build.xml'
3214 
3215     compileTargets { t ->
3216         // The apps build is Ant based, and gradle lets us "import" ant apps/build.xml
3217         // into our configuration.
3218 
3219         // override the apps build.xml with an explicit pointer to our jar.
3220         def sdkDirName = rootProject.ext[t.upper].sdkDirName
3221         def jfxrtJar = "${rootProject.buildDir}/${sdkDirName}/rt/lib/ext/jfxrt.jar"
3222 
3223         def appsJar = project.task("appsJar${t.capital}") {
3224             doLast() {
3225               ant.properties['targetBld'] = "$t.name"
3226               if (!rootProject.ext[t.upper].compileSwing) {
3227                 ant.properties['JFX_CORE_ONLY'] = 'true'
3228               }
3229               ant.properties['jfxbuild.jfxrt.jar'] = jfxrtJar
3230               ant.properties['platforms.JDK_1.8.home'] = "${rootProject.ext.JDK_HOME}"
3231               ant.project.executeTarget("sampleAppsJar")
3232               ant.project.executeTarget("scenebuilderSampleAppsJar")
3233               if (!t.name.startsWith("arm")) {
3234                 ant.project.executeTarget("scenebuilderAppJar")
3235               }
3236             }
3237         }
3238         rootProject.appsjar.dependsOn(appsJar)
3239 
3240         def appsClean = project.task("appsClean${t.capital}") {
3241             doLast() {
3242               ant.properties['targetBld'] = "$t.name"
3243               ant.properties['platforms.JDK_1.8.home'] = "${rootProject.ext.JDK_HOME}"
3244               ant.project.executeTarget("sampleAppsClean")
3245               ant.project.executeTarget("scenebuilderSampleAppsClean")
3246               if (!t.name.startsWith("arm")) {
3247                 ant.project.executeTarget("scenebuilderAppClean")
3248               }
3249             }
3250         }
3251         rootProject.clean.dependsOn(appsClean)
3252     }
3253 }
3254 
3255 /******************************************************************************
3256  *                                                                            *
3257  *                              BUILD_CLOSED                                  *
3258  *                                                                            *
3259  * This next section should remain at the end of the build script. It allows  *
3260  * for a "supplemental" gradle file to be used to extend the normal build     *
3261  * structure. For example, this is used for passing a supplemental gradle     *
3262  * file for producing official JavaFX builds.                                 *
3263  *                                                                            *
3264  *****************************************************************************/
3265 
3266 if (BUILD_CLOSED) {
3267     apply from: supplementalBuildFile
3268 }
3269 
3270 task showFlags {
3271 }
3272 
3273 compileTargets { t ->
3274     // Every platform must define these variables
3275     def props = project.ext[t.upper];
3276     showFlags.dependsOn(
3277         project.task("showFlags$t.upper") {
3278             doLast() {
3279                 println "Properties set for $t.upper"
3280                 props.each { println it }
3281             }
3282         }
3283     )
3284 }