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