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