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