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