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