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