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