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         testCompile project(":controls").sourceSets.test.output
2879         testCompile project(":swing").sourceSets.test.output
2880     }
2881 
2882     Set<String> testInclude = [ "test/**" ]
2883     configureJDK9tests(project, [ "base", "graphics", "controls", "swing", "fxml", "web" ],
2884         null, testInclude,
2885         project.projectDir.path + "/src/test/addExports"
2886     )
2887 
2888     test {
2889         enabled = IS_FULL_TEST
2890         if (!IS_USE_ROBOT) {
2891             // Disable all robot-based visual tests
2892             exclude("test/robot/**");
2893         }
2894         if (!IS_AWT_TEST) {
2895             // Disable all AWT-based tests
2896             exclude("**/javafx/embed/swing/*.*");
2897             exclude("**/com/sun/javafx/application/Swing*.*");
2898         }
2899 
2900         forkEvery = 1
2901     }
2902 }
2903 
2904 allprojects {
2905     // The following block is a workaround for the fact that presently Gradle
2906     // can't set the -XDignore.symbol.file flag, because it appears that the
2907     // javac API is lacking support for it. So what we'll do is find any Compile
2908     // task and manually provide the options necessary to fire up the
2909     // compiler with the right settings.
2910     //
2911     // Also, we need to remove jfxrt.jar from the ext classpath (if it is there)
2912     tasks.withType(JavaCompile) { compile ->
2913         if (compile.options.hasProperty("useAnt")) {
2914             compile.options.useAnt = true
2915             compile.options.useDepend = IS_USE_DEPEND
2916         } else if (compile.options.hasProperty("incremental")) {
2917             compile.options.incremental = IS_INCREMENTAL
2918         }
2919         compile.options.debug = true // we always generate debugging info in the class files
2920         compile.options.debugOptions.debugLevel = IS_DEBUG_JAVA ? "source,lines,vars" : "source,lines"
2921         compile.options.fork = true
2922         compile.options.forkOptions.executable = JAVAC
2923         compile.options.warnings = IS_LINT
2924         compile.options.compilerArgs = ["-XDignore.symbol.file", "-encoding", "UTF-8"]
2925         if (!DO_BUILD_SDK_FOR_TEST) {
2926             compile.classpath = files(jfxrtJarFromSdk) + compile.classpath
2927         }
2928 
2929         // Add in the -Xlint options
2930         if (IS_LINT) {
2931             LINT.split("[, ]").each { s ->
2932                 compile.options.compilerArgs += "-Xlint:$s"
2933             }
2934         }
2935     }
2936 
2937     // Some tasks should be disabled not to compile SDK, when running only the tests
2938     disabledTasks.each {
2939         project.getTasksByName(it, false)*.enabled = false
2940     }
2941 }
2942 
2943 // fxpackager requires JDK 9 to compile
2944 project(":fxpackager") {
2945     tasks.withType(JavaCompile) { compile ->
2946         compile.options.forkOptions.executable = JAVAC9
2947         compile.options.compilerArgs = [
2948                 "-XaddExports:java.base/sun.security.pkcs=ALL-UNNAMED,"
2949                         + "java.base/sun.security.timestamp=ALL-UNNAMED,"
2950                         + "java.base/sun.security.x509=ALL-UNNAMED,"
2951                         + "jdk.jdeps/com.sun.tools.jdeps=ALL-UNNAMED",
2952                 "-encoding", "UTF-8"]
2953     }
2954 }
2955 
2956 /******************************************************************************
2957  *                                                                            *
2958  *                             Top Level Tasks                                *
2959  *                                                                            *
2960  *  These are the tasks which are defined only for the top level project and  *
2961  *  not for any sub projects. These are generally the entry point that is     *
2962  *  used by Hudson and by the continuous build system.                        *
2963  *                                                                            *
2964  *****************************************************************************/
2965 
2966 task clean() {
2967     group = "Basic"
2968     description = "Deletes the build directory and the build directory of all sub projects"
2969     getSubprojects().each { subProject ->
2970         dependsOn(subProject.getTasksByName("clean", true));
2971     }
2972     doLast {
2973         delete(buildDir);
2974     }
2975 }
2976 
2977 task cleanAll() {
2978     group = "Basic"
2979     description = "Scrubs the repo of build artifacts"
2980     dependsOn(clean)
2981     doLast {
2982         //delete(".gradle"); This causes problems on windows.
2983         delete("buildSrc/build");
2984     }
2985 }
2986 
2987 task javadoc(type: Javadoc) {
2988     enabled = IS_BUILD_JAVADOC
2989     group = "Basic"
2990     description = "Generates the JavaDoc for all the public API"
2991     executable = JAVADOC
2992     def projectsToDocument = [
2993             project(":base"), project(":graphics"), project(":controls"), project(":media"),
2994             project(":swing"), /*project(":swt"),*/ project(":fxml"), project(":web")]
2995     source(projectsToDocument.collect({
2996         [it.sourceSets.main.java]
2997     }));
2998     setDestinationDir(new File(buildDir, 'javadoc'));
2999     // FIXME: The following is a workaround for JDK-8151191; it should be
3000     // reverted once that bug is fixed
3001     classpath = rootProject.BUILD_SRC
3002     classpath += files(projectsToDocument.collect { project ->
3003         project.sourceSets.main.java.srcDirs
3004     });
3005     /*
3006     // Might need a classpath
3007     classpath = files(projectsToDocument.collect { project ->
3008         project.sourceSets.main.compileClasspath
3009     });
3010     classpath += files(projectsToDocument.collect { project ->
3011         project.sourceSets.main.output
3012     });
3013     */
3014     exclude("com/**/*", "Compile*", "javafx/builder/**/*", "javafx/scene/accessibility/**/*");
3015     options.windowTitle("${javadocTitle}")
3016     options.header("${javadocHeader}")
3017     options.bottom("${javadocBottom}")
3018     if (BUILD_CLOSED) {
3019         options.linksOffline(JDK_DOCS, JDK_DOCS_CLOSED);
3020     } else {
3021         options.links(JDK_DOCS);
3022     }
3023     options.addBooleanOption("XDignore.symbol.file").setValue(true);
3024     options.addBooleanOption("Xdoclint:none").setValue(!IS_DOC_LINT);
3025     options.addBooleanOption("javafx").setValue(true);
3026     options.addBooleanOption("use").setValue(true);
3027     doLast {
3028         projectsToDocument.each { p ->
3029             copy {
3030                 from "$p.projectDir/src/main/docs"
3031                 into "$buildDir/javadoc"
3032             }
3033         }
3034     }
3035 
3036     dependsOn(projectsToDocument.collect { project -> project.getTasksByName("classes", true)});
3037 }
3038 
3039 task jfxrt() {
3040     if (DO_BUILD_SDK_FOR_TEST) {
3041         rootProject.getTasksByName("compileTestJava", true).each { t ->
3042             if (t.enabled) t.dependsOn(jfxrt)
3043         }
3044     }
3045 }
3046 
3047 task sdk() {
3048     dependsOn(checkJfxrtJar)
3049 
3050     if (DO_BUILD_SDK_FOR_TEST) {
3051         rootProject.getTasksByName("test", true).each { t ->
3052             if (t.enabled) t.dependsOn(sdk)
3053         }
3054     }
3055 }
3056 
3057 task appsjar() {
3058     dependsOn(sdk)
3059     // Note: the jar dependencies get added elsewhere see project(":apps")
3060 }
3061 
3062 // these are empty tasks, allowing us to depend on the task, which may have other
3063 // real work items added later.
3064 task copyAppsArtifacts() {
3065     dependsOn(appsjar)
3066 }
3067 
3068 task apps() {
3069     dependsOn(sdk)
3070     dependsOn(appsjar)
3071     dependsOn(copyAppsArtifacts)
3072 }
3073 
3074 task findbugs() {
3075     dependsOn(sdk)
3076 
3077     doLast {
3078         if (!BUILD_CLOSED) {
3079             println "findbugs task is only run for a closed build"
3080         }
3081     }
3082 }
3083 
3084 // The following tasks are for the closed build only. They are a no-op for the open build
3085 
3086 task checkCache() {
3087     dependsOn(updateCacheIfNeeded)
3088 }
3089 
3090 // TODO: consider moving the "public-sdk" portion of this task here
3091 task publicExports() {
3092     doFirst {
3093         if (BUILD_CLOSED && !IS_BUILD_JAVADOC) {
3094             fail("publicExports task requires: -PBUILD_JAVADOC=true")
3095         }
3096     }
3097     dependsOn(sdk)
3098 }
3099 
3100 task perf() {
3101     dependsOn(sdk,apps)
3102     doLast {
3103         if (!BUILD_CLOSED) {
3104             println "perf task is only run for a closed build"
3105         }
3106     }
3107 }
3108 
3109 task zips() {
3110     doFirst {
3111         if (BUILD_CLOSED && !IS_BUILD_JAVADOC) {
3112             fail("zips task requires: -PBUILD_JAVADOC=true")
3113         }
3114     }
3115     dependsOn(sdk,publicExports,apps,perf)
3116 }
3117 
3118 task copySources(type: Copy) {
3119     enabled = IS_BUILD_SRC_ZIP
3120     def projectsToCopy = [
3121             project(":base"), project(":graphics"), project(":controls"),
3122             project(":swing"), project(":swt"), project(":fxml"),
3123             project(":media"), project(":web")]
3124     from(projectsToCopy.collect({ proj ->
3125         files(proj.sourceSets.main.java.srcDirs)
3126     }))
3127     include "**/*.java"
3128     into "${buildDir}/javafx-src"
3129 }
3130 
3131 task zipSources(type: Zip) {
3132     enabled = IS_BUILD_SRC_ZIP
3133     dependsOn(copySources)
3134     archiveName = "javafx-src.zip"
3135     destinationDir = file("$buildDir")
3136     includeEmptyDirs = false
3137     from "${buildDir}/javafx-src"
3138 }
3139 
3140 task src {
3141     enabled = IS_BUILD_SRC_ZIP
3142     description = "Created the javafx-src.zip bundle"
3143     dependsOn(zipSources)
3144 }
3145 
3146 task all() {
3147     dependsOn(sdk,publicExports,apps,perf,zips)
3148 }
3149 
3150 
3151 // Construct list of subprojects that are modules
3152 ext.moduleProjList = []
3153 subprojects {
3154     if (project.hasProperty("buildModule") && project.ext.buildModule) {
3155         rootProject.ext.moduleProjList += project
3156         println "module: $project (buildModule=YES)"
3157     } else {
3158         println "module: $project (buildModule=NO)"
3159     }
3160 }
3161 
3162 
3163 // Create the legacy sdk from the modular-sdk
3164 
3165 compileTargets { t ->
3166     def targetProperties = project.ext[t.upper]
3167     def platformPrefix = targetProperties.platformPrefix
3168     def sdkDirName = "${platformPrefix}sdk"
3169     def modularSdkDirName = "${platformPrefix}modular-sdk"
3170     def modularSdkDir = "${rootProject.buildDir}/${modularSdkDirName}"
3171     def modulesDir = "${modularSdkDir}/modules"
3172     def modulesCmdsDir = "${modularSdkDir}/modules_cmds"
3173     def modulesLibsDir = "${modularSdkDir}/modules_libs"
3174 
3175     // The jfxrt task is responsible for creating the legacy jfxrt.jar. A developer may
3176     // have multiple SDK's on their system at any one time, depending on which
3177     // cross compiles they have done. For example, I might have:
3178     //      build/ios-sdk/lib/jfxrt.jar
3179     //      build/armhf-sdk/lib/jfxrt.jar
3180     // and so forth. The default host build will always install into 'sdk'
3181     // allowing for uses where a known sdk path is needed (like IDEs)
3182     //      build/sdk/lib/jfxrt.jar
3183     // This arrangement allows for multiple independent SDKs to
3184     // exist on a developer's system.
3185     def jfxrtTask = task("jfxrt$t.capital", type: Jar) {
3186         group = "Basic"
3187         description = "Creates the jfxrt.jar for the $t.name target"
3188         archiveName = "build/${sdkDirName}/lib/jfxrt.jar";
3189         includeEmptyDirs = false
3190 
3191         moduleProjList.each { project ->
3192             if (project.ext.moduleRuntime) {
3193                 from("${modulesDir}/${project.ext.moduleName}");
3194             }
3195         }
3196 
3197         dependsOn(subprojects.collect { project -> project.getTasksByName("assemble", true)});
3198     }
3199 
3200     def jfxrtIndexTask = task("jfxrtIndex$t.capital") {
3201         //the following is a workaround for the lack of indexing in gradle 1.4 through 1.7
3202         dependsOn(jfxrtTask)
3203 
3204         doLast() {
3205             ant.jar (update: true, index: true, destfile: jfxrtTask.archiveName)
3206         }
3207     }
3208     jfxrt.dependsOn(jfxrtIndexTask)
3209 
3210     // FIXME: update this for modules
3211     def jfxswtTask = task("jfxswt$t.capital", type: Jar) {
3212         enabled = COMPILE_SWT
3213         group = "Basic"
3214         description = "Creates the jfxswt.jar for the $t.name target"
3215         archiveName = "build/${sdkDirName}/lib/jfxswt.jar";
3216         includeEmptyDirs = false
3217         from("modules/swt/build/classes/main");
3218         include("**/javafx/embed/swt/**")
3219         exclude("**/*.java");  // Builder java files are in build/classes and should be excluded
3220 
3221         dependsOn(subprojects.collect { project -> project.getTasksByName("assemble", true)});
3222     }
3223 
3224     def jfxswtIndexTask = task("jfxswtIndex$t.capital") {
3225         //the following is a workaround for the lack of indexing in gradle 1.4 through 1.7
3226         dependsOn(jfxswtTask)
3227 
3228         doLast() {
3229             ant.jar (update: true, index: true, destfile: jfxswtTask.archiveName)
3230         }
3231     }
3232     jfxrt.dependsOn(jfxswtIndexTask)
3233 
3234     def jmxTask = task ("jmx${t.capital}", type: Jar) {
3235         group = "Basic"
3236         description = "Creates the javafx-mx.jar"
3237         archiveName = "build/${sdkDirName}/lib/javafx-mx.jar";
3238         includeEmptyDirs = false
3239         from "modules/jmx/build/classes/main"
3240         from "modules/jmx/build/resources/main"
3241         dependsOn project(":jmx").assemble
3242     }
3243 
3244     // The 'sdk' task will build the rest of the legacy SDK, and depends
3245     // on the 'jfxrtTask' task. After executing this task the sdk bundle for
3246     // the current COMPILE_TARGETS will be fully created.
3247     def sdkTask = task("sdk$t.capital") {
3248         group = "Basic"
3249         description = "Creates the SDK for $t.name"
3250         doLast {
3251             copy {
3252                 moduleProjList.each { project ->
3253                     from "${modulesLibsDir}/${project.ext.moduleName}"
3254                 }
3255                 into "build/${sdkDirName}/lib"
3256             }
3257 
3258             copy {
3259                 moduleProjList.each { project ->
3260                     from "${modulesCmdsDir}/${project.ext.moduleName}"
3261                 }
3262                 into "build/${sdkDirName}/bin"
3263             }
3264 
3265             // FIXME: update this for modules
3266             // Copy over the javadocs that were generated. This is done rather than just generating
3267             // the docs into the "right place" because for a cross-compile you only need one set of
3268             // docs but need to have a copy in each created sdk
3269             if (IS_BUILD_JAVADOC) {
3270                 copy {
3271                     from "build/javadoc"
3272                     into "build/${sdkDirName}/docs/api"
3273                 }
3274             }
3275 
3276             // FIXME: update this for modules
3277             // Copy over the javafx-src bundle
3278             if (IS_BUILD_SRC_ZIP) {
3279                 copy {
3280                     from "build/javafx-src.zip"
3281                     into "build/${sdkDirName}"
3282                 }
3283             }
3284 
3285             // FIXME: update this for modules
3286             // Copy over the javapackager man files
3287             copy {
3288                 from "modules/fxpackager/build/man"
3289                 into "build/${sdkDirName}/man"
3290             }
3291         }
3292         dependsOn(jmxTask);
3293         dependsOn(jfxrtIndexTask)
3294         dependsOn(jfxswtIndexTask)
3295         dependsOn(javadoc)
3296         dependsOn(src)
3297     }
3298 
3299     def generateSymbols = targetProperties.containsKey('generateSymbols') ? targetProperties.generateSymbols : false
3300     if (generateSymbols) {
3301         def exportedSymbolsTask = project.task("exportedSymbols${t.capital}", type: ExportedSymbolsTask, dependsOn: sdkTask, group: "Build") {
3302             description = "Generates exported symbols file for iOS build (from .a libraries)"
3303             def libDirName = "build/${sdkDirName}/$targetProperties.libDest"
3304             libDir = file("$libDirName")
3305             outputFile = file("$libDirName/exported.symbols")
3306             excludes = targetProperties.generateSymbolsExcludes
3307         }
3308         sdk.dependsOn(exportedSymbolsTask)
3309     }
3310 
3311     sdk.dependsOn(sdkTask)
3312 }
3313 
3314 /*
3315  * This clause changes the way we handle a build.gradle within ./apps
3316  * It does a few things:
3317  *   modifies the classpath used to include the built runttime classes
3318  *   provides for copying the build applications to the artifacts tree
3319  *
3320  * The applications to be built will be under ./apps, but also must
3321  * be listed in the applications listed in the setting variable: JFXApplications
3322  */
3323 ext.JFXRT_CP =
3324     files(
3325         project(":base").sourceSets.main.output.classesDir,
3326         project(":graphics").sourceSets.main.output.classesDir,
3327         project(":controls").sourceSets.main.output.classesDir,
3328         project(":fxml").sourceSets.main.output.classesDir,
3329         project(":swing").sourceSets.main.output.classesDir, //NOTE - used by 3Dviewer
3330             "modules/media/build/classes/main",
3331             "modules/web/build/classes/main",
3332     )
3333 
3334 project(":apps") {
3335     // The apps build is Ant based, and gradle lets us "import" ant build.xml
3336     // into our configuration.
3337 
3338     ant.importBuild 'build.xml'
3339 
3340     compileTargets { t ->
3341         // The apps build is Ant based, and gradle lets us "import" ant apps/build.xml
3342         // into our configuration.
3343 
3344         // override the apps build.xml with an explicit pointer to our jar.
3345         def platformPrefix = rootProject.ext[t.upper].platformPrefix
3346         def sdkDirName = "${platformPrefix}sdk"
3347         def jfxrtJar = "${rootProject.buildDir}/${sdkDirName}/lib/jfxrt.jar"
3348 
3349         def appsJar = project.task("appsJar${t.capital}") {
3350             dependsOn(sdk)
3351             doLast() {
3352               ant.properties['targetBld'] = "$t.name"
3353               if (!rootProject.ext[t.upper].compileSwing) {
3354                 ant.properties['JFX_CORE_ONLY'] = 'true'
3355               }
3356               ant.properties['jfxbuild.jfxrt.jar'] = jfxrtJar
3357               ant.properties['platforms.JDK_1.8.home'] = "${rootProject.ext.JDK_HOME}"
3358               ant.project.executeTarget("sampleAppsJar")
3359               ant.project.executeTarget("scenebuilderSampleAppsJar")
3360               if (!t.name.startsWith("arm")) {
3361                 ant.project.executeTarget("scenebuilderAppJar")
3362               }
3363             }
3364         }
3365         rootProject.appsjar.dependsOn(appsJar)
3366 
3367         def appsClean = project.task("appsClean${t.capital}") {
3368             doLast() {
3369               ant.properties['targetBld'] = "$t.name"
3370               ant.properties['platforms.JDK_1.8.home'] = "${rootProject.ext.JDK_HOME}"
3371               ant.project.executeTarget("sampleAppsClean")
3372               ant.project.executeTarget("scenebuilderSampleAppsClean")
3373               if (!t.name.startsWith("arm")) {
3374                 ant.project.executeTarget("scenebuilderAppClean")
3375               }
3376             }
3377         }
3378         rootProject.clean.dependsOn(appsClean)
3379     }
3380 }
3381 
3382 
3383 /******************************************************************************
3384  *                                                                            *
3385  *                               Modules                                      *
3386  *                                                                            *
3387  *****************************************************************************/
3388 
3389 ext.moduleDependencies = [file("dependencies")]
3390 
3391 task buildModules {
3392 }
3393 
3394 // Combine the classes, lib, and bin for each module
3395 compileTargets { t ->
3396     def targetProperties = project.ext[t.upper]
3397 
3398     def platformPrefix = targetProperties.platformPrefix
3399     def modularSdkDirName = "${platformPrefix}modular-sdk"
3400     def modularSdkDir = "${rootProject.buildDir}/${modularSdkDirName}"
3401     def modulesDir = "${modularSdkDir}/modules"
3402     def modulesCmdsDir = "${modularSdkDir}/modules_cmds"
3403     def modulesLibsDir = "${modularSdkDir}/modules_libs"
3404     def modulesSrcDir = "${modularSdkDir}/modules_src"
3405     def modulesConfDir = "${modularSdkDir}/modules_conf"
3406     def modulesMakeDir = "${modularSdkDir}/make"
3407 
3408     def zipTask = project.task("buildModuleZip$t.capital", type: Zip, group: "Build") {
3409         // FIXME: this should be moved to a sub-directory so we can keep the same name
3410         def jfxBundle = "${platformPrefix}javafx-exports.zip"
3411 
3412         doFirst() {
3413             file("${rootProject.buildDir}/${jfxBundle}").delete()
3414         }
3415 
3416         archiveName = jfxBundle
3417         destinationDir = file("${rootProject.buildDir}")
3418         includeEmptyDirs = false
3419         from "${modularSdkDir}"
3420     }
3421     buildModules.dependsOn(zipTask)
3422 
3423     def buildModulesTask = task("buildModules$t.capital", group: "Build") {
3424         doLast {
3425             moduleProjList.each { project ->
3426 
3427                 // Copy classes, bin, and lib directories
3428 
3429                 def moduleName = project.ext.moduleName
3430                 def buildDir = project.buildDir
3431 
3432                 def srcClassesDir = "${buildDir}/${platformPrefix}module-classes"
3433                 def dstClassesDir = "${modulesDir}/${moduleName}"
3434                 copy {
3435                     from srcClassesDir
3436                     into dstClassesDir
3437                 }
3438 
3439                 def srcCmdsDir = "${buildDir}/${platformPrefix}module-bin"
3440                 def dstCmdsDir = "${modulesCmdsDir}/${moduleName}"
3441                 copy {
3442                     from srcCmdsDir
3443                     into dstCmdsDir
3444                 }
3445 
3446                 def srcLibsDir = "${buildDir}/${platformPrefix}module-lib"
3447                 def dstLibsDir = "${modulesLibsDir}/${moduleName}"
3448                 copy {
3449                     from srcLibsDir
3450                     into dstLibsDir
3451                 }
3452 
3453                 // Copy module-info.java
3454                 def srcModuleInfoDir = "${project.projectDir}/src/main/module-info"
3455                 def dstModuleInfoDir = "${modulesSrcDir}/${moduleName}"
3456                 copy {
3457                     from srcModuleInfoDir
3458                     into dstModuleInfoDir
3459                     if (!IS_COMPILE_JFR && project.name.equals("base")) {
3460                         filter { line-> line.contains("requires jdk.jfr;") ? "" : line }
3461                     }
3462                 }
3463 
3464                 // Copy make/build.properties
3465                 def srcMakeDir = "${project.projectDir}/make"
3466                 def dstMakeDir = "${modulesMakeDir}/${moduleName}"
3467                 copy {
3468                     from srcMakeDir
3469                     into dstMakeDir
3470                 }
3471             }
3472 
3473             // Copy dependencies/*/module-info.java.extra
3474             def dependencyRoots = moduleDependencies
3475             if (rootProject.hasProperty("closedModuleDepedencies")) {
3476                 dependencyRoots = [dependencyRoots, closedModuleDepedencies].flatten()
3477             }
3478             copy {
3479                 dependencyRoots.each { root ->
3480                     from root
3481                 }
3482                 into modulesSrcDir
3483             }
3484 
3485             // concatecate java.policy files into a single file
3486             //
3487             def outputPolicyDir = "${modulesConfDir}/java.base/security"
3488             def outputPolicyFile = file("${outputPolicyDir}/java.policy.extra")
3489             mkdir outputPolicyDir
3490             outputPolicyFile.delete()
3491             moduleProjList.each { project ->
3492                 def policyDir = "${project.projectDir}/src/main/conf/security"
3493                 def policyFile = file("${policyDir}/java.policy")
3494                 if (policyFile.exists()) outputPolicyFile << policyFile.text
3495             }
3496         }
3497     }
3498     zipTask.dependsOn(buildModulesTask);
3499     buildModules.dependsOn(buildModulesTask)
3500 
3501     def isWindows = IS_WINDOWS && t.name == "win";
3502     def isMac = IS_MAC && t.name == "mac";
3503 
3504     // Create layout for modular classes
3505     moduleProjList.each { project ->
3506         def buildModuleClassesTask = project.task("buildModule$t.capital", group: "Build") {
3507             dependsOn(project.assemble)
3508             def buildDir = project.buildDir
3509             def sourceBuildDirs = [
3510                 "${buildDir}/classes/main",
3511                 "${buildDir}/resources/main"
3512             ]
3513             if (project.hasProperty("extraBuildDirs")) {
3514                 sourceBuildDirs += project.ext.extraBuildDirs
3515             }
3516             doLast {
3517                 def moduleClassesDir = "$buildDir/${platformPrefix}module-classes"
3518                 copy {
3519                     includeEmptyDirs = false
3520                     sourceBuildDirs.each { d ->
3521                         from d
3522                     }
3523                     into moduleClassesDir
3524 
3525                     // Exclude obsolete, experimental, or non-shipping code
3526                     exclude("version.rc")
3527                     exclude("com/sun/glass/ui/swt")
3528                     exclude("com/sun/javafx/tools/ant")
3529                     exclude("com/javafx/main")
3530                     if (!IS_INCLUDE_NULL3D) {
3531                         exclude ("com/sun/prism/null3d")
3532                     }
3533                     if (!IS_INCLUDE_ES2) {
3534                            exclude("com/sun/prism/es2",
3535                                    "com/sun/scenario/effect/impl/es2")
3536                     }
3537 
3538                     // Exclude platform-specific classes for other platforms
3539 
3540                     if (!isMac) {
3541                         exclude ("com/sun/media/jfxmediaimpl/platform/osx",
3542                                  "com/sun/prism/es2/MacGL*",
3543                                  "com/sun/glass/events/mac",
3544                                  "com/sun/glass/ui/mac",
3545                                  )
3546                     }
3547 
3548                     if (!isWindows) {
3549                         exclude ("**/*.hlsl",
3550                                  "com/sun/glass/ui/win",
3551                                  "com/sun/prism/d3d",
3552                                  "com/sun/prism/es2/WinGL*",
3553                                  "com/sun/scenario/effect/impl/hw/d3d"
3554                                  )
3555                     }
3556 
3557                     if (!targetProperties.includeGTK) { //usually IS_LINUX
3558                         exclude (
3559                                  "com/sun/glass/ui/gtk",
3560                                  "com/sun/prism/es2/EGL*",
3561                                  "com/sun/prism/es2/X11GL*"
3562                                  )
3563                     }
3564 
3565                     if (!targetProperties.includeEGL) {
3566                         exclude ("com/sun/prism/es2/EGL*")
3567                     }
3568 
3569                     if (!targetProperties.includeLens) {
3570                         exclude ("com/sun/glass/ui/lens")
3571                     }
3572 
3573                     // FIXME: Figure out what to do with Monocle
3574                     /*
3575                     if (!targetProperties.includeMonocle) {
3576                         exclude ("com/sun/glass/ui/monocle")
3577                         exclude("com/sun/prism/es2/Monocle*")
3578                     }
3579                     */
3580 
3581                     if (t.name != 'ios') {
3582                         exclude ("com/sun/media/jfxmediaimpl/platform/ios",
3583                                  "com/sun/glass/ui/ios",
3584                                  "com/sun/prism/es2/IOS*"
3585                                  )
3586                     }
3587 
3588                     if (t.name != 'android' && t.name != 'dalvik') {
3589                         exclude ("com/sun/glass/ui/android")
3590                     }
3591 
3592                     // Filter out other platform-specific classes
3593                     if (targetProperties.containsKey('jfxrtJarExcludes')) {
3594                         exclude(targetProperties.jfxrtJarExcludes)
3595                     }
3596 
3597                     /* FIXME: handle this in the module itself
3598                     if (t.name == 'android') {
3599                         from ("modules/web/build/classes/android",
3600                               "modules/web/build/resources/android",
3601                               "modules/controls/build/classes/android",
3602                               "modules/controls/build/resources/android")
3603                     } else if (t.name == 'ios') {
3604                         from ("modules/web/build/classes/ios",
3605                               "modules/web/build/resources/ios",
3606                               "modules/extensions/build/classes/ios")
3607                     } else {
3608                         from ("modules/web/build/classes/main", "modules/web/build/resources/main")
3609                     }
3610                     */
3611                 }
3612             }
3613         }
3614         buildModulesTask.dependsOn(buildModuleClassesTask)
3615     }
3616 
3617 
3618     def buildModuleLibsTask = task("buildModuleLibs$t.capital") {
3619         group = "Basic"
3620 
3621         def graphicsProject = project(":graphics");
3622         dependsOn(graphicsProject.assemble)
3623 
3624         def mediaProject = project(":media");
3625         dependsOn(mediaProject.assemble)
3626 
3627         def webProject = project(":web");
3628         dependsOn(webProject.assemble)
3629 
3630         def packagerProject = project(":fxpackager");
3631         //dependsOn(packagerProject.assemble)
3632         dependsOn(packagerProject.jar)
3633         dependsOn(project(":fxpackagerservices").jar)
3634 
3635         doLast {
3636 
3637             def library = targetProperties.library
3638 
3639             // javafx.base (lib/javafx.properties)
3640 
3641             def baseProject = project(":base");
3642             def moduleLibDir = "${baseProject.buildDir}/${platformPrefix}module-lib"
3643             mkdir moduleLibDir
3644             final File javafxProperties = file("${moduleLibDir}/javafx.properties")
3645             javafxProperties.delete()
3646             javafxProperties << "javafx.version=$RELEASE_VERSION_SHORT";
3647             javafxProperties << "\n"
3648             javafxProperties << "javafx.runtime.version=$RELEASE_VERSION_LONG";
3649             javafxProperties << "\n"
3650             javafxProperties << "javafx.runtime.build=$PROMOTED_BUILD_NUMBER";
3651             javafxProperties << "\n"
3652             // Include any properties that have been defined (most likely in
3653             // one of the various platform gradle files)
3654             if (targetProperties.containsKey("javafxProperties")) {
3655                 javafxProperties << targetProperties.javafxProperties
3656                 javafxProperties << "\n"
3657             }
3658 
3659             // Embedded builds define this file as well
3660             if (targetProperties.containsKey("javafxPlatformProperties")) {
3661                 final File javafxPlatformProperties = file("${moduleLibDir}/javafx.platform.properties")
3662                 javafxPlatformProperties.delete()
3663                 javafxPlatformProperties << targetProperties.javafxPlatformProperties
3664                 javafxPlatformProperties << "\n"
3665             }
3666 
3667 
3668             def useLipo = targetProperties.containsKey('useLipo') ? targetProperties.useLipo : false
3669             def libDest = targetProperties.libDest
3670             def moduleNativeDirName = "${platformPrefix}module-$libDest"
3671 
3672             // javafx.graphics native libraries
3673 
3674             copy {
3675                 into "${graphicsProject.buildDir}/${moduleNativeDirName}"
3676 
3677                 from("modules/graphics/build/libs/jsl-decora/${t.name}/${library(targetProperties.decora.lib)}")
3678                 def libs = ['font', 'prism', 'prismSW', 'glass', 'iio']
3679                 if (IS_INCLUDE_ES2) {
3680                     libs += ['prismES2'];
3681                 }
3682                 if (IS_COMPILE_PANGO) {
3683                     libs += ['fontFreetype', 'fontPango'];
3684                 }
3685                 libs.each { lib ->
3686                     def variants = targetProperties[lib].containsKey('variants') && !useLipo ? targetProperties[lib].variants : [null]
3687                     variants.each { variant ->
3688                         def variantProperties = variant ? targetProperties[lib][variant] : targetProperties[lib]
3689                         from ("modules/graphics/build/libs/$lib/$t.name/${library(variantProperties.lib)}")
3690                     }
3691                 }
3692                 if (IS_WINDOWS) {
3693                     from ("modules/graphics/build/libs/prismD3D/${t.name}/${library(targetProperties.prismD3D.lib)}");
3694                 }
3695             }
3696 
3697 
3698             // javafx.media native libraries
3699 
3700             copy {
3701                 into "${mediaProject.buildDir}/${moduleNativeDirName}"
3702 
3703                 def mediaBuildType = project(":media").ext.buildType
3704                 if (IS_COMPILE_MEDIA) {
3705                     [ "fxplugins", "gstreamer-lite", "jfxmedia" ].each { name ->
3706                         from ("modules/media/build/native/${t.name}/${mediaBuildType}/${library(name)}") }
3707 
3708                     if (t.name == "mac") {
3709                         // OSX media natives
3710                         [ "jfxmedia_qtkit", "jfxmedia_avf", "glib-lite" ].each { name ->
3711                             from ("modules/media/build/native/${t.name}/${mediaBuildType}/${library(name)}") }
3712                     } else if (t.name == "linux") {
3713                         from("modules/media/build/native/${t.name}/${mediaBuildType}") { include "libavplugin*.so" }
3714                     } else from ("modules/media/build/native/${t.name}/${mediaBuildType}/${library("glib-lite")}")
3715                 } else {
3716                     if (t.name != "android"  && t.name != "dalvik" ) {
3717                         [ "fxplugins", "gstreamer-lite", "jfxmedia" ].each { name ->
3718                             from ("$LIBRARY_STUB/${library(name)}") }
3719                     }
3720 
3721                     if (t.name == "mac") {
3722                         // copy libjfxmedia_{avf,qtkit}.dylib if they exist
3723                         [ "jfxmedia_qtkit", "jfxmedia_avf", "glib-lite" ].each { name ->
3724                             from ("$LIBRARY_STUB/${library(name)}") }
3725                     } else if (t.name == "linux") {
3726                         from(LIBRARY_STUB) { include "libavplugin*.so" }
3727                     }
3728                     else if (t.name != "android"  && t.name != "dalvik" ) {
3729                         from ("$LIBRARY_STUB/${library("glib-lite")}")
3730                     }
3731                 }
3732             }
3733 
3734 
3735             // javafx.web native libraries
3736 
3737             copy {
3738                 into "${webProject.buildDir}/${moduleNativeDirName}"
3739 
3740                 if (IS_COMPILE_WEBKIT) {
3741                     from ("modules/web/build/libs/${t.name}/${library('jfxwebkit')}")
3742                 } else {
3743                     if (t.name != "android" && t.name != "ios" && t.name != "dalvik") {
3744                         from ("$LIBRARY_STUB/${library('jfxwebkit')}")
3745                     }
3746                 }
3747             }
3748 
3749 
3750             // javafx.packager libraries and executable
3751 
3752             // Copy over the javapackager libs
3753             copy {
3754                 from "modules/fxpackager/build/libs"
3755                 into "${packagerProject.buildDir}/${platformPrefix}module-lib"
3756             }
3757 
3758             // Copy over the javapackager executable
3759             if (t.name == "win" || t.name == "linux" || t.name == "mac") {
3760                 copy {
3761                     from "modules/fxpackager/build/javapackager"
3762                     into "${packagerProject.buildDir}/${platformPrefix}module-bin"
3763                 }
3764             }
3765 
3766         }
3767     }
3768     buildModulesTask.dependsOn(buildModuleLibsTask)
3769 
3770     def sdkTask = tasks.getByName("sdk${t.capital}");
3771     sdkTask.dependsOn(buildModulesTask)
3772 }
3773 sdk.dependsOn(buildModules)
3774 
3775 void configureJDK9tests(
3776         Project p,
3777         List<String> moduleDeps,
3778         Set<String> patchInc,
3779         Set<String> testsInc,
3780         String addExportsFile
3781         ) {
3782 
3783     if(!IS_JDK9_TEST) {
3784         return
3785     }
3786 
3787     p.configurations {
3788         jdk9test
3789     }
3790 
3791     p.dependencies {
3792         jdk9test group: "junit", name: "junit", version: "4.8.2"
3793     }
3794 
3795     compileTargets { t ->
3796 
3797         def targetProperties = project.rootProject.ext[t.upper]
3798 
3799         def modularSdkDirName = "${targetProperties.platformPrefix}modular-sdk"
3800         def modularSdkDir = "${rootProject.buildDir}/${modularSdkDirName}"
3801         def modulesDir = "${modularSdkDir}/modules"
3802 
3803         boolean useModule = true
3804         String moduleName
3805         if(!p.hasProperty('moduleName')) {
3806             useModule = false
3807             moduleName = "systemTests"
3808         } else {
3809             moduleName = p.moduleName
3810         }
3811 
3812         logger.info("configuring $p.name for modular test copy");
3813 
3814         def testingDir = "${rootProject.buildDir}/${targetProperties.platformPrefix}testing";
3815         def patchesDir = new File("${testingDir}/modules");
3816         File patchPolicyFile = new File("${testingDir}/java.patch.policy");
3817 
3818         String javaLibraryPath = "${rootProject.buildDir}/sdk/$targetProperties.libDest"
3819 
3820         def jdk9patchesBaseDir = new File("${testingDir}/modules/$moduleName");
3821         def jdk9patchesTestDir = new File("${testingDir}/tests/$moduleName");
3822 
3823         p.files(patchPolicyFile);
3824 
3825         def srcClassesDir = "${p.buildDir}/${targetProperties.platformPrefix}module-classes"
3826         Task classes =  p.task("jdk9CopyClasses${t.capital}", type: Copy, dependsOn: [p.classes]) {
3827 
3828             enabled = useModule
3829 
3830             from srcClassesDir
3831             into jdk9patchesBaseDir
3832         }
3833 
3834         Task shims =  p.task("jdk9CopyShims${t.capital}", type: Copy, dependsOn: [p.testClasses]) {
3835             //from p.sourceSets.test.output.classesDir
3836 
3837             enabled = useModule
3838 
3839             from p.sourceSets.test.output
3840             into jdk9patchesBaseDir
3841             if (patchInc != null) {
3842                 include patchInc
3843             } else {
3844                 include "**/*"
3845             }
3846             if (testsInc != null) {
3847                 exclude testsInc
3848             }
3849             includeEmptyDirs = false
3850             doLast() {
3851                 logger.info("project $p.name finished jdk9CopyShims to $jdk9patchesBaseDir");
3852             }
3853         }
3854 
3855         Task alltests =  p.task("jdk9CopyTests${t.capital}", type: Copy, dependsOn: [p.testClasses]) {
3856             from p.sourceSets.test.output
3857             into jdk9patchesTestDir
3858             if (patchInc != null) {
3859                 exclude patchInc
3860             }
3861             if (testsInc != null) {
3862                 include testsInc
3863             } else {
3864                 include "**/*"
3865             }
3866             includeEmptyDirs = false
3867             doLast() {
3868                 logger.info("project $p.name finished jdk9CopyTests to $jdk9patchesTestDir");
3869             }
3870         }
3871 
3872         // create & use just one of these per platform
3873         String nameis = "moduleTestPatchPolicy${t.capital}"
3874         Task patchPerms = null
3875         if (rootProject.hasProperty(nameis)) {
3876             patchPerms = rootProject.tasks[nameis]
3877         } else {
3878             patchPerms = rootProject.task(nameis) {
3879                 outputs.file(patchPolicyFile)
3880                 doLast() {
3881                     logger.info("Creating test patch.policy file ${patchPolicyFile}")
3882 
3883                     delete(patchPolicyFile)
3884                     mkdir(testingDir)
3885 
3886                     [ "base", "graphics", "controls", "fxml", "swing", "web", ].each { mn ->
3887                         String themod = file("${patchesDir}/javafx.${mn}").toURI()
3888                         patchPolicyFile <<  "grant codeBase \"${themod}\" {\n" +
3889                         "    permission java.security.AllPermission;\n" +
3890                         "};\n"
3891                     }
3892                 }
3893             }
3894         }
3895 
3896         Task jdk9testsTask =  p.task("jdk9tests${t.capital}", dependsOn: [classes, shims, alltests, patchPerms ]) {
3897             doLast() {
3898                 logger.info("project $p.name finished jdk9tests${t.capital}");
3899             }
3900         }
3901 
3902         FileCollection testclasspath = p.files(p.configurations.jdk9test)
3903 
3904         p.test.dependsOn jdk9testsTask
3905 
3906         if (moduleDeps != null) {
3907             moduleDeps.each() {s->
3908                 logger.info("adding dep to project $p.name $s");
3909                 Project pdep = rootProject.project(s);
3910                 def jdk9Task = pdep.tasks.getByName("jdk9tests${t.capital}");
3911                 jdk9testsTask.dependsOn jdk9Task;
3912 
3913                 testclasspath += p.files(pdep.ext.jdk9patchesTestDir);
3914             }
3915         }
3916 
3917         testclasspath += p.files(jdk9patchesTestDir);
3918 
3919         p.ext.jdk9testClasspath = testclasspath
3920         p.ext.jdk9patchesTestDir = jdk9patchesTestDir
3921         p.ext.jdk9testClasses = jdk9testsTask
3922 
3923         p.ext.argclasspathFile = "$testingDir/classpath_"+p.name+".txt"
3924 
3925         p.test {
3926             if (IS_FORCE_TESTS) {
3927                 dependsOn 'cleanTest'
3928             }
3929 
3930             scanForTestClasses = false
3931             include("**/*Test.*")
3932 
3933             if (IS_JDK9_TEST) {
3934                 dependsOn jdk9testsTask
3935 
3936                 doFirst {
3937                     classpath = testclasspath
3938                     p.sourceSets.test.runtimeClasspath = testclasspath
3939                 }
3940 
3941                 String bcp = "-Xbootclasspath/a:" + rootProject.projectDir.path + "/buildSrc/build/libs/buildSrc.jar"
3942 
3943                 systemProperties 'worker.debug': false
3944                 systemProperties 'worker.library.path': cygpath(javaLibraryPath)
3945                 systemProperties 'worker.xpatch.dir': cygpath(patchesDir.path)
3946                 if (addExportsFile != null) {
3947                     systemProperties 'worker.exports.file': cygpath(addExportsFile)
3948                 }
3949                 systemProperties 'worker.classpath.file': cygpath(p.ext.argclasspathFile)
3950                 systemProperties 'worker.java.cmd': JAVA9
3951 
3952                 systemProperties 'worker.isJDK9': true
3953 
3954                 systemProperties 'worker.patch.policy': cygpath(patchPolicyFile.path)
3955 
3956                 //systemProperties 'prism.order': 'sw'
3957                 //systemProperties 'glass.platform': 'Monocle'
3958                 //systemProperties
'glass.len': 'headless'
3959 
3960                 jvmArgs bcp, "workaround.GradleJUnitWorker"
3961 
3962                 environment("JDK_HOME", JDK9_HOME);
3963                 executable (JAVA9);
3964 
3965               }
3966         }
3967 
3968     }
3969 
3970 }
3971 
3972 task checkrepo() {
3973     doLast {
3974         logger.info("checking for whitespace (open)");
3975         exec {
3976             if (IS_WINDOWS) {
3977                 commandLine  'bash', 'tools/scripts/checkWhiteSpace'
3978             } else {
3979                 commandLine  'bash', 'tools/scripts/checkWhiteSpace', '-x'
3980             }
3981         }
3982     }
3983 }
3984 
3985 task checkrepoall() {
3986     doLast {
3987         logger.info("checking for all whitespace (open)");
3988         exec {
3989             if (IS_WINDOWS) {
3990                 commandLine  'bash', 'tools/scripts/checkWhiteSpace', '-a'
3991             } else {
3992                 commandLine  'bash', 'tools/scripts/checkWhiteSpace', '-x', '-a'
3993             }
3994         }
3995     }
3996 }
3997 
3998 /******************************************************************************
3999  *                                                                            *
4000  *                              BUILD_CLOSED                                  *
4001  *                                                                            *
4002  * This next section should remain at the end of the build script. It allows  *
4003  * for a "supplemental" gradle file to be used to extend the normal build     *
4004  * structure. For example, this is used for passing a supplemental gradle     *
4005  * file for producing official JavaFX builds.                                 *
4006  *                                                                            *
4007  *****************************************************************************/
4008 
4009 if (BUILD_CLOSED) {
4010     apply from: supplementalBuildFile
4011 }
4012 
4013 task showFlags {
4014 }
4015 
4016 compileTargets { t ->
4017     // Every platform must define these variables
4018     def props = project.ext[t.upper];
4019     showFlags.dependsOn(
4020         project.task("showFlags$t.upper") {
4021             doLast() {
4022                 println "Properties set for $t.upper"
4023                 props.each { println it }
4024             }
4025         }
4026     )
4027 
4028 }
4029