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     compileJava.dependsOn verifyJava
1268     compileJava.dependsOn checkJfxrtJar
1269 
1270     // Compile and run tests against the jfxrt.jar in the built sdk of the host machine
1271     def sdkDir = "${rootProject.buildDir}/sdk"
1272     def jfxrtJar = "$sdkDir/lib/jfxrt.jar"
1273     def testJfxrtJar = DO_BUILD_SDK_FOR_TEST ? jfxrtJar : jfxrtJarFromSdk
1274 
1275     // At the moment the ASM library shipped with Gradle that is used to
1276     // discover the different test classes fails on Java 8, so in order
1277     // to have sourceCompatibility set to 1.8 I have to also turn scanForClasses off
1278     // and manually specify the includes / excludes. At the moment we use
1279     // Java 7 but when we switch to 8 this will be needed, and probably again when
1280     // we start building with Java 9.
1281     test {
1282         executable = JAVA;
1283         enableAssertions = true;
1284         testLogging.exceptionFormat = "full";
1285         scanForTestClasses = false;
1286         include("**/*Test.*");
1287         if (BUILD_CLOSED && DO_JCOV) {
1288             addJCov(project, test)
1289         }
1290         classpath = files(testJfxrtJar) + classpath
1291         if (IS_HEADLESS_TEST) {
1292             systemProperty 'glass.platform', 'Monocle'
1293             systemProperty 'monocle.platform', 'Headless'
1294             systemProperty 'prism.order', 'sw'
1295             systemProperty 'com.sun.javafx.gestures.zoom', 'true'
1296             systemProperty 'com.sun.javafx.gestures.rotate', 'true'
1297             systemProperty 'com.sun.javafx.gestures.scroll', 'true'
1298         }
1299 
1300         systemProperty 'unstable.test', IS_UNSTABLE_TEST
1301     }
1302 
1303     compileTestJava {
1304         classpath = files(testJfxrtJar) + classpath
1305     }
1306 
1307     // Exclude any non-public-API classes from having javadoc generated. This block is used
1308     // when generating JavaDocs for a specific project. When generating the JavaDocs for the
1309     // entire SDK, a different javadoc command is used (see the javadoc task on the top level)
1310     javadoc {
1311         enabled = IS_BUILD_JAVADOC
1312         exclude("com/**/*", "Compile*", "javafx/builder/**/*", "javafx/scene/accessibility/**/*");
1313         executable = JAVADOC;
1314         options.windowTitle("JavaFX Project ${project.name} ${RELEASE_VERSION}")
1315         if (BUILD_CLOSED) {
1316             options.linksOffline(JDK_DOCS, JDK_DOCS_CLOSED);
1317         } else {
1318             options.links(JDK_DOCS);
1319         }
1320         options.addBooleanOption("XDignore.symbol.file").setValue(true);
1321         options.addBooleanOption("Xdoclint:none").setValue(!IS_DOC_LINT);
1322         options.addBooleanOption("javafx").setValue(true);
1323         options.addBooleanOption("use").setValue(true);
1324         // All doc-files are located in src/main/docs because Gradle's javadoc doesn't copy
1325         // over the doc-files if they are embedded with the sources. I find this arrangement
1326         // somewhat cleaner anyway (never was a fan of mixing javadoc files with the sources)
1327         doLast {
1328             copy {
1329                 from "src/main/docs"
1330                 into "$buildDir/docs/javadoc"
1331             }
1332         }
1333     }
1334 }
1335 
1336 // The "base" project is our first module and the most basic one required for
1337 // all other modules. It is useful even for non-GUI applications.
1338 project(":base") {
1339     project.ext.buildModule = true
1340     project.ext.moduleRuntime = true
1341     project.ext.moduleName = "javafx.base"
1342 
1343     Set<String> testInclude = [ "test/**" ]
1344     configureJigsawTests(project, null,
1345         null, testInclude,
1346         project.projectDir.path + "/src/test/addExports"
1347         )
1348 
1349     dependencies {
1350         compile BUILD_SRC
1351     }
1352 
1353     // We need to take the VersionInfo.java file and replace the various
1354     // properties within it
1355     def replacements = [
1356         "BUILD_TIMESTAMP": BUILD_TIMESTAMP,
1357         "HUDSON_JOB_NAME": HUDSON_JOB_NAME,
1358         "HUDSON_BUILD_NUMBER": HUDSON_BUILD_NUMBER,
1359         "PROMOTED_BUILD_NUMBER": PROMOTED_BUILD_NUMBER,
1360         "PRODUCT_NAME": PRODUCT_NAME,
1361         "RELEASE_VERSION": RELEASE_VERSION,
1362         "RELEASE_SUFFIX": RELEASE_SUFFIX];
1363     task processVersionInfo(type: Copy, description: "Replace params in VersionInfo and copy file to destination") {
1364         doFirst { mkdir "$buildDir/generated-src/version-info" }
1365         from "src/main/version-info"
1366         into "$buildDir/generated-src/version-info/com/sun/javafx/runtime"
1367         filter {line->
1368             replacements.each() {k, v ->
1369                 line = line.replace("@$k@", v.toString());
1370             }
1371             line
1372         }
1373     }
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     compileJava.dependsOn updateCacheIfNeeded
2317 
2318     sourceSets {
2319         tools {
2320             java.srcDir "src/tools/java"
2321         }
2322     }
2323 
2324     compileToolsJava {
2325         enabled = IS_COMPILE_MEDIA
2326         classpath = sourceSets.main.output;
2327     }
2328 
2329     project.ext.makeJobsFlag = IS_WINDOWS && IS_DEBUG_NATIVE ? "-j1" : "-j5";
2330     project.ext.buildType = IS_DEBUG_NATIVE ? "Debug" : "Release";
2331 
2332     def nativeSrcDir = file("${projectDir}/src/main/native")
2333     def generatedHeadersDir = file("${buildDir}/generated-src/headers")
2334 
2335     task generateHeaders(dependsOn: compileJava) {
2336         enabled = IS_COMPILE_MEDIA
2337         doLast {
2338             def classpath = sourceSets.main.output;
2339             mkdir generatedHeadersDir;
2340 
2341             def classesList = ["com.sun.media.jfxmedia.logging.Logger",
2342                              "com.sun.media.jfxmedia.track.AudioTrack",
2343                              "com.sun.media.jfxmedia.control.VideoDataBuffer",
2344                              "com.sun.media.jfxmedia.control.VideoFormat\$FormatTypes",
2345                              "com.sun.media.jfxmediaimpl.NativeAudioClip",
2346                              "com.sun.media.jfxmediaimpl.NativeMediaPlayer",
2347                              "com.sun.media.jfxmediaimpl.NativeVideoBuffer",
2348                              "com.sun.media.jfxmediaimpl.platform.gstreamer.GSTPlatform",
2349                              "com.sun.media.jfxmediaimpl.platform.gstreamer.GSTMedia",
2350                              "com.sun.media.jfxmediaimpl.platform.gstreamer.GSTMediaPlayer",
2351                              "com.sun.media.jfxmediaimpl.NativeAudioEqualizer",
2352                              "com.sun.media.jfxmediaimpl.NativeEqualizerBand",
2353                              "com.sun.media.jfxmediaimpl.NativeAudioSpectrum"]
2354             if (IS_MAC) {
2355                 classesList.addAll( ["com.sun.media.jfxmediaimpl.platform.osx.OSXPlatform",
2356                                      "com.sun.media.jfxmediaimpl.platform.osx.OSXMedia",
2357                                      "com.sun.media.jfxmediaimpl.platform.osx.OSXMediaPlayer"] );
2358             }
2359             exec {
2360                 commandLine ("${JAVAH}", "-d", "${generatedHeadersDir}", "-classpath", "${classpath.asPath}");
2361                 args classesList;
2362             }
2363         }
2364     }
2365 
2366     task generateMediaErrorHeader(dependsOn: [compileToolsJava, compileJava]) {
2367         enabled = IS_COMPILE_MEDIA
2368         doLast {
2369             def classpath = files(sourceSets.main.output, sourceSets.tools.output);
2370             def sourcepath = sourceSets.main.java.srcDirs;
2371             def headerpath = file("$generatedHeadersDir/jfxmedia_errors.h");
2372             def srcRoot = (sourcepath.toArray())[0];
2373 
2374             mkdir generatedHeadersDir;
2375 
2376             exec {
2377                 commandLine("$JAVA", "-classpath", "${classpath.asPath}");
2378                 args("headergen.HeaderGen", "$headerpath", "$srcRoot");
2379             }
2380         }
2381     }
2382 
2383     task buildNativeTargets {
2384         enabled = IS_COMPILE_MEDIA
2385     }
2386 
2387     compileTargets { t->
2388         def targetProperties = project.rootProject.ext[t.upper]
2389         def nativeOutputDir = file("${buildDir}/native/${t.name}")
2390         def projectDir = t.name.startsWith("arm") ? "linux" : t.name
2391         def mediaProperties = targetProperties.media
2392         // Makefile for OSX needs to know if we're building for parfait
2393         def compileParfait = IS_COMPILE_PARFAIT ? "true" : "false"
2394 
2395         def buildNative = task("build${t.capital}Native", dependsOn: [generateHeaders, generateMediaErrorHeader]) {
2396             enabled = targetProperties.compileMediaNative
2397             if (!targetProperties.compileMediaNative) {
2398                 println("Not compiling native Media for ${t.name} per configuration request");
2399             }
2400 
2401             doLast {
2402                 exec {
2403                     commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/jfxmedia/projects/${projectDir}")
2404                     args("JAVA_HOME=${JDK_HOME}", "GENERATED_HEADERS_DIR=${generatedHeadersDir}",
2405                          "OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}", "BASE_NAME=jfxmedia",
2406                          "COMPILE_PARFAIT=${compileParfait}",
2407                          IS_64 ? "ARCH=x64" : "ARCH=x32",
2408                         "CC=${mediaProperties.compiler}", "LINKER=${mediaProperties.linker}")
2409 
2410                     if (t.name == "win") {
2411                         environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
2412                         args( "RESOURCE=${nativeOutputDir}/${buildType}/${WIN.media.jfxmediaRcFile}")
2413                     } else {
2414                         if (t.name.startsWith("arm")) {
2415                             args("EXTRA_CFLAGS=${mediaProperties.extra_cflags}", "EXTRA_LDFLAGS=${mediaProperties.extra_ldflags}")
2416                         } else {
2417                             args("HOST_COMPILE=1")
2418                         }
2419                     }
2420                 }
2421             }
2422         }
2423 
2424         // check for the property disable${name} = true
2425         def boolean disabled = targetProperties.containsKey('disableMedia') ? targetProperties.get('disableMedia') : false
2426         if (!disabled) {
2427             // Building GStreamer
2428             def buildGStreamer = task("build${t.capital}GStreamer") {
2429                 enabled = IS_COMPILE_MEDIA
2430                 doLast {
2431                     exec {
2432                         commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/gstreamer/projects/${projectDir}/gstreamer-lite")
2433                         args("OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}", "BASE_NAME=gstreamer-lite",
2434                              IS_64 ? "ARCH=x64" : "ARCH=x32", "CC=${mediaProperties.compiler}",
2435                              "AR=${mediaProperties.ar}", "LINKER=${mediaProperties.linker}")
2436 
2437                         if (t.name == "win") {
2438                             environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
2439                             args("RESOURCE=${nativeOutputDir}/${buildType}/${WIN.media.gstreamerRcFile}")
2440                         }
2441                     }
2442                 }
2443             }
2444 
2445             def buildPlugins = task("build${t.capital}Plugins", dependsOn: buildGStreamer) {
2446                 enabled = IS_COMPILE_MEDIA
2447 
2448                 if (!project.ext.properties.containsKey("ON2_SRCDIR")) {
2449                     project.ext.ON2_SRCDIR = "";
2450                 }
2451 
2452                 if (!project.ext.properties.containsKey("ON2_LIB")) {
2453                     project.ext.ON2_LIB = "";
2454                 }
2455 
2456                 doLast {
2457                     exec {
2458                         commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/gstreamer/projects/${projectDir}/fxplugins")
2459                         args("OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}", "BASE_NAME=fxplugins",
2460                              "ON2_SRCDIR=${project.ext.ON2_SRCDIR}", "ON2_LIB=${project.ext.ON2_LIB}",
2461                              IS_64 ? "ARCH=x64" : "ARCH=x32",
2462                              "CC=${mediaProperties.compiler}", "AR=${mediaProperties.ar}", "LINKER=${mediaProperties.linker}")
2463 
2464                         if (t.name == "win") {
2465                             Map winEnv = new HashMap(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
2466 
2467                             String sdkDir = System.getenv("BASECLASSES_SDK_DIR");
2468                             if (sdkDir == null) {
2469                                 sdkDir = "C:/Program Files/Microsoft SDKs/Windows/v7.1" // Default value
2470                                 winEnv["BASECLASSES_SDK_DIR"] = sdkDir
2471                             }
2472                             environment(winEnv)
2473 
2474                             args("RESOURCE=${nativeOutputDir}/${buildType}/${WIN.media.fxpluginsRcFile}")
2475                         }
2476                     }
2477                 }
2478             }
2479 
2480             buildNative.dependsOn buildPlugins
2481 
2482             if (t.name == "linux") {
2483                 def buildAVPlugin = task( "buildAVPlugin", dependsOn: [buildPlugins]) {
2484                     enabled = IS_COMPILE_MEDIA
2485 
2486                     doLast {
2487                         if (project.ext.properties.containsKey("libav")) {
2488                             project.ext.libav.versions.each { version ->
2489                                 def libavDir = "${project.ext.libav.basedir}-${version}"
2490                                 File dir = file(libavDir)
2491                                 if (dir.exists()) {
2492                                     exec {
2493                                         commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/gstreamer/projects/linux/avplugin")
2494                                         args("CC=${mediaProperties.compiler}", "LINKER=${mediaProperties.linker}",
2495                                              "OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}",
2496                                              "BASE_NAME=avplugin", "VERSION=${version}", "LIBAV_DIR=${libavDir}",
2497                                              "SUFFIX=", IS_64 ? "ARCH=x64" : "ARCH=x32")
2498                                     }
2499                                 }
2500                             }
2501 
2502                             project.ext.libav.ffmpeg.versions.each { version ->
2503                                 def libavDir = "${project.ext.libav.ffmpeg.basedir}-${version}"
2504                                 File dir = file(libavDir)
2505                                 if (dir.exists()) {
2506                                     exec {
2507                                         commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/gstreamer/projects/linux/avplugin")
2508                                         args("CC=${mediaProperties.compiler}", "LINKER=${mediaProperties.linker}",
2509                                              "OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}",
2510                                              "BASE_NAME=avplugin", "VERSION=${version}", "LIBAV_DIR=${libavDir}",
2511                                              "SUFFIX=-ffmpeg", IS_64 ? "ARCH=x64" : "ARCH=x32")
2512                                     }
2513                                 }
2514                             }
2515                         } else {
2516                             // Building fxavcodec plugin (libav plugin)
2517                             exec {
2518                                 commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/gstreamer/projects/linux/avplugin")
2519                                 args("CC=${mediaProperties.compiler}", "LINKER=${mediaProperties.linker}",
2520                                      "OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}",
2521                                      "BASE_NAME=avplugin", IS_64 ? "ARCH=x64" : "ARCH=x32")
2522                             }
2523                         }
2524                     }
2525                 }
2526                 buildNative.dependsOn buildAVPlugin
2527             }
2528 
2529             if (t.name == "win") {
2530                 def buildResources = task("buildResources") << {
2531                     def rcOutputDir = "${nativeOutputDir}/${buildType}"
2532                     mkdir rcOutputDir
2533                     exec {
2534                         environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
2535                         commandLine (WIN.media.rcCompiler)
2536                         args(WIN.media.glibRcFlags)
2537                         args("/Fo${rcOutputDir}/${WIN.media.glibRcFile}", WIN.media.rcSource)
2538                     }
2539 
2540                     exec {
2541                         environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
2542                         commandLine (WIN.media.rcCompiler)
2543                         args(WIN.media.gstreamerRcFlags)
2544                         args("/Fo${rcOutputDir}/${WIN.media.gstreamerRcFile}", WIN.media.rcSource)
2545                     }
2546 
2547                     exec {
2548                         environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
2549                         commandLine (WIN.media.rcCompiler)
2550                         args(WIN.media.fxpluginsRcFlags)
2551                         args("/Fo${rcOutputDir}/${WIN.media.fxpluginsRcFile}", WIN.media.rcSource)
2552                     }
2553 
2554                     exec {
2555                         environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
2556                         commandLine (WIN.media.rcCompiler)
2557                         args(WIN.media.jfxmediaRcFlags)
2558                         args("/Fo${rcOutputDir}/${WIN.media.jfxmediaRcFile}", WIN.media.rcSource)
2559                     }
2560                 }
2561 
2562                 def buildGlib = task("build${t.capital}Glib", dependsOn: [buildResources]) {
2563                     enabled = IS_COMPILE_MEDIA
2564                     doLast {
2565                         exec {
2566                             environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
2567                             commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/gstreamer/projects/${projectDir}/glib-lite")
2568                             args("OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}", "BASE_NAME=glib-lite",
2569                                  IS_64 ? "ARCH=x64" : "ARCH=x32", "RESOURCE=${nativeOutputDir}/${buildType}/${WIN.media.glibRcFile}",
2570                                  "CC=${mediaProperties.compiler}", "AR=${mediaProperties.ar}", "LINKER=${mediaProperties.linker}")
2571                         }
2572                     }
2573                 }
2574                 buildGStreamer.dependsOn buildGlib
2575 
2576             } else if (t.name == "mac") {
2577                 def buildGlib = task("build${t.capital}Glib") {
2578                     enabled = IS_COMPILE_MEDIA
2579                     doLast {
2580                         exec {
2581                             commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/gstreamer/projects/${projectDir}/libffi")
2582                             args("OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}", "BASE_NAME=ffi")
2583                             args ("CC=${mediaProperties.compiler}", "LINKER=${mediaProperties.linker}", "AR=${mediaProperties.ar}")
2584                         }
2585 
2586                         exec {
2587                             commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/gstreamer/projects/${projectDir}/glib-lite")
2588                             args("OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}", "BASE_NAME=glib-lite")
2589                             args ("CC=${mediaProperties.compiler}", "LINKER=${mediaProperties.linker}")
2590                         }
2591                     }
2592                 }
2593                 buildGStreamer.dependsOn buildGlib
2594             }
2595         }
2596 
2597         buildNativeTargets.dependsOn buildNative
2598     }
2599 
2600     jar {
2601         exclude("headergen/**")
2602 
2603         dependsOn compileJava
2604         if (IS_COMPILE_MEDIA) {
2605             dependsOn buildNativeTargets
2606         }
2607     }
2608 }
2609 
2610 project(":web") {
2611     configurations {
2612         webkit
2613     }
2614     project.ext.buildModule = true
2615     project.ext.moduleRuntime = true
2616     project.ext.moduleName = "javafx.web"
2617 
2618     Set<String> testInclude = [ "test/**" ]
2619     configureJigsawTests(project, [ "base", "graphics" ],
2620         null, testInclude,
2621         project.projectDir.path + "/src/test/addExports"
2622         )
2623 
2624     dependencies {
2625         compile project(":base"), project(":graphics"), project(":controls"), project(":media")
2626     }
2627 
2628     compileJava.dependsOn updateCacheIfNeeded
2629 
2630     test {
2631         if (!IS_JIGSAW_TEST) {
2632         //TODO: support this in Jake
2633         // Run web tests in headless mode
2634         systemProperty 'glass.platform', 'Monocle'
2635         systemProperty 'monocle.platform', 'Headless'
2636         systemProperty 'prism.order', 'sw'
2637         }
2638     }
2639 
2640     if (!IS_COMPILE_WEBKIT) {
2641         // Include wrapper classes that are otherwise generated by native build
2642         sourceSets.main.java.srcDirs += "src/main/java-wrappers"
2643     }
2644 
2645     task generateHeaders(dependsOn: compileJava) {
2646         doLast {
2647             def classpath = files("$buildDir/classes/main",
2648                                   project(":graphics").sourceSets.main.output.classesDir)
2649             def dest = file("$buildDir/generated-src/headers");
2650             mkdir dest;
2651             exec {
2652                 commandLine("$JAVAH", "-d", "$dest",
2653                             "-classpath", "${classpath.asPath}");
2654                 args("java.lang.Character",
2655                      "java.net.IDN",
2656                      "com.sun.webkit.ContextMenu",
2657                      "com.sun.webkit.ContextMenuItem",
2658                      "com.sun.webkit.CursorManager",
2659                      "com.sun.webkit.PageCache",
2660                      "com.sun.webkit.PopupMenu",
2661                      "com.sun.webkit.SharedBuffer",
2662                      "com.sun.webkit.WatchdogTimer",
2663                      "com.sun.webkit.WebPage",
2664                      "com.sun.webkit.LoadListenerClient",
2665                      "com.sun.webkit.event.WCFocusEvent",
2666                      "com.sun.webkit.event.WCKeyEvent",
2667                      "com.sun.webkit.event.WCMouseEvent",
2668                      "com.sun.webkit.event.WCMouseWheelEvent",
2669                      "com.sun.webkit.graphics.GraphicsDecoder",
2670                      "com.sun.webkit.graphics.RenderMediaControls",
2671                      "com.sun.webkit.graphics.RenderTheme",
2672                      "com.sun.webkit.graphics.ScrollBarTheme",
2673                      "com.sun.webkit.graphics.WCMediaPlayer",
2674                      "com.sun.webkit.graphics.WCGraphicsManager",
2675                      "com.sun.webkit.graphics.WCRenderQueue",
2676                      "com.sun.webkit.graphics.WCPath",
2677                      "com.sun.webkit.graphics.WCPathIterator",
2678                      "com.sun.webkit.Timer",
2679                      "com.sun.webkit.WCFrameView",
2680                      "com.sun.webkit.WCPasteboard",
2681                      "com.sun.webkit.WCPluginWidget",
2682                      "com.sun.webkit.dom.JSObject",
2683                      "com.sun.webkit.network.SocketStreamHandle",
2684                      "com.sun.webkit.network.URLLoader",
2685                      "com.sun.webkit.text.TextBreakIterator",
2686                      "com.sun.webkit.text.TextNormalizer");
2687             }
2688         }
2689     }
2690 
2691     task compileGenerated()
2692 
2693     compileTargets { t ->
2694         def targetProperties = project.rootProject.ext[t.upper]
2695         def classifier = (t.name != "linux" && t.name != "win") ? t.name :
2696                           IS_64 ? "${t.name}-amd64" : "${t.name}-i586"
2697         dependencies {
2698             webkit group: "com.sun.webkit", name: "webview-deps",
2699                    version: "1.3", classifier: "$classifier", ext: "zip"
2700         }
2701 
2702         def webkitOutputDir = "$buildDir/${t.name}"
2703         def webkitConfig = IS_DEBUG_NATIVE ? "Debug" : "Release"
2704 
2705         def compileNativeTask = task("compileNative${t.capital}", dependsOn: generateHeaders) << {
2706             println "Building Webkit configuration /$webkitConfig/ into $webkitOutputDir"
2707 
2708             def dependencyFile = configurations.webkit.filter(
2709                     { File f -> f.getName().contains(classifier) }
2710                 ).getSingleFile()
2711             ant.unzip(src:  dependencyFile,
2712                       dest: webkitOutputDir)
2713 
2714             exec {
2715                 workingDir("$projectDir/src/main/native")
2716                 commandLine("perl", "Tools/Scripts/set-webkit-configuration", "--$webkitConfig")
2717                 environment(["WEBKIT_OUTPUTDIR" : webkitOutputDir])
2718             }
2719 
2720             exec {
2721                 workingDir("$projectDir/src/main/native")
2722                 if (t.name == "win") {
2723                     String qtDir = cygpath(System.getenv().get("QTSDK_DIR"))
2724                     String parfaitPath = IS_COMPILE_PARFAIT ? System.getenv().get("PARFAIT_PATH") + ";" : "";
2725                     Map environmentSettings = new HashMap(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
2726                     environmentSettings["PATH"] = parfaitPath + "$WINDOWS_VS_PATH;$qtDir/bin;$qtDir/qt/bin"
2727                     environmentSettings["QMAKESPEC"] = "win32-msvc2013"
2728                     environment(environmentSettings)
2729                     /* To build with ICU:
2730                     1. Download http://javaweb.us.oracle.com/jcg/fx-webrevs/RT-17164/WebKitLibrariesICU.zip
2731                     and unzip it to WebKitLibraries folder.
2732                     2. Copy DLLs from
2733                     WebKitLibrariesICU.zip\WebKitLibraries\import\runtime
2734                     to %windir%\system32
2735                     3. Uncomment the line below
2736                      */
2737                     // args("--icu-unicode")
2738                 } else if (t.name == "mac") {
2739                     environment([
2740                         "QMAKESPEC"      : "macx-clang",
2741                         "QMAKE_CFLAGS"   : "-m64",
2742                         "QMAKE_LFLAGS"   : "-m64",
2743                     ])
2744                 } else if (t.name == "linux") {
2745                     if (IS_64) {
2746                         environment([
2747                             "QMAKESPEC"      : "linux-g++-64",
2748                         ])
2749                     } else {
2750                         environment([
2751                             "QMAKESPEC"      : "linux-g++-32",
2752                             "QMAKE_CFLAGS"   : "-m32",
2753                             "QMAKE_LFLAGS"   : "-m32",
2754                         ])
2755                     }
2756                 } else if (t.name.startsWith("arm")) {
2757                     // ARM cross build
2758                     def webkitProperties = project.rootProject.ext[t.upper].webkit
2759                     def qmakeSpecDir = "$webkitOutputDir/qws/linux-cross-${t.name}-g++"
2760                     mkdir qmakeSpecDir
2761                     File qmakeSpec = new File("$qmakeSpecDir/qmake.conf")
2762                     qmakeSpec.append(
2763 """TARGET_PLATFORM         = unix
2764 include(/usr/share/qt4/mkspecs/common/linux.conf)
2765 include(/usr/share/qt4/mkspecs/common/g++.conf)
2766 include(/usr/share/qt4/mkspecs/common/qws.conf)
2767 QMAKE_CC                = $webkitProperties.compiler
2768 QMAKE_CXX               = $webkitProperties.linker
2769 QMAKE_LINK              = $webkitProperties.linker
2770 QMAKE_LINK_SHLIB        = $webkitProperties.linker
2771 QMAKE_AR                = $webkitProperties.ar cqs
2772 QMAKE_OBJCOPY           = $webkitProperties.objcopy
2773 QMAKE_STRIP             = $webkitProperties.strip
2774 QMAKE_CXXFLAGS          = $webkitProperties.ccFlags
2775 QMAKE_LFLAGS            = $webkitProperties.linkFlags
2776 load(qt_config)""")
2777                     environment([
2778                         "QMAKESPEC" : file(qmakeSpecDir).getAbsolutePath(),
2779                         "PATH"      : "$System.env.PATH:$webkitProperties.binDir",
2780                     ])
2781                     args("--nocache")
2782                 }
2783                 environment([
2784                     "JAVA_HOME"       : JDK_HOME,
2785                     "WEBKIT_OUTPUTDIR" : webkitOutputDir,
2786                 ])
2787 
2788                 if (IS_COMPILE_PARFAIT) {
2789                     environment([
2790                         "COMPILE_PARFAIT" : "true",
2791                         "QMAKE_CC"        : "parfait-gcc",
2792                         "QMAKE_CXX"       : "parfait-g++",
2793                         "QMAKE_LINK"      : "parfait-g++",
2794                     ])
2795                 }
2796                 commandLine("perl", "Tools/Scripts/build-webkit", "--java", "--imageio", "--icu-unicode")
2797             }
2798 
2799             def library = rootProject.ext[t.upper].library
2800             copy {
2801                 from "$webkitOutputDir/$webkitConfig/lib/${library('jfxwebkit')}"
2802                 into "$buildDir/libs/${t.name}"
2803             }
2804             copy {
2805                 from "$webkitOutputDir/$webkitConfig/lib/${library('DumpRenderTreeJava')}"
2806                 into "$buildDir/test/${t.name}"
2807             }
2808         }
2809 
2810         if (IS_WINDOWS && t.name == "win") {
2811             def webkitProperties = project.rootProject.ext[t.upper].webkit
2812             def rcTask = project.task("rc${t.capital}", type: CompileResourceTask) {
2813                 compiler = webkitProperties.rcCompiler
2814                 source(webkitProperties.rcSource)
2815                 if (webkitProperties.rcFlags) {
2816                     rcParams.addAll(webkitProperties.rcFlags)
2817                 }
2818                 output(file("$webkitOutputDir/$webkitConfig/WebCore/obj"))
2819             }
2820             compileNativeTask.dependsOn rcTask
2821         }
2822 
2823         def compileGeneratedTask = task("compileGenerated${t.capital}", type: JavaCompile, dependsOn: compileNativeTask) {
2824             def gensrcDir = "$webkitOutputDir/$webkitConfig/WebCore/generated/java"
2825             doFirst {
2826                 copy {
2827                     from "$projectDir/src/main/java-wrappers/com/sun/webkit/dom/EventListenerImpl.java"
2828                     into "$gensrcDir/com/sun/webkit/dom"
2829                 }
2830             }
2831             classpath = files(project.sourceSets.main.output.classesDir)
2832             source gensrcDir
2833             destinationDir = file("$buildDir/classes/main")
2834         }
2835 
2836         compileGenerated.dependsOn compileGeneratedTask
2837 
2838         if (!targetProperties.compileWebnodeNative) {
2839             println("Not compiling native Webkit for ${t.name} per configuration request");
2840             compileNativeTask.enabled = false
2841         }
2842     }
2843 
2844     def drtClasses = "com/sun/javafx/webkit/drt/**"
2845     jar.exclude(drtClasses)
2846     task drtJar(type: Jar, dependsOn: compileJava) {
2847         archiveName = "drt.jar"
2848         destinationDir = file("$buildDir/test")
2849         from "$buildDir/classes/main"
2850         include drtClasses
2851     }
2852 
2853     if (IS_COMPILE_WEBKIT) {
2854         jar.dependsOn compileGenerated, drtJar
2855     }
2856 }
2857 
2858 // This project is for system tests that need to run with a full SDK.
2859 // Most of them display a stage or do other things that preclude running
2860 // them in a shared JVM or as part of the "smoke test" run (which must
2861 // not pop up any windows or use audio). As such, they are only enabled
2862 // when FULL_TEST is specified, and each test runs in its own JVM
2863 project(":systemTests") {
2864 
2865     dependencies {
2866         testCompile project(":graphics").sourceSets.test.output
2867         testCompile project(":base").sourceSets.test.output
2868         testCompile project(":controls").sourceSets.test.output
2869         testCompile project(":swing").sourceSets.test.output
2870     }
2871 
2872     Set<String> testInclude = [ "test/**" ]
2873     configureJigsawTests(project, [ "base", "graphics", "controls", "swing", "fxml", "web" ],
2874         null, testInclude,
2875         project.projectDir.path + "/src/test/addExports"
2876     )
2877 
2878     test {
2879         enabled = IS_FULL_TEST
2880         if (!IS_USE_ROBOT) {
2881             // Disable all robot-based visual tests
2882             exclude("test/robot/**");
2883         }
2884         if (!IS_AWT_TEST) {
2885             // Disable all AWT-based tests
2886             exclude("**/javafx/embed/swing/*.*");
2887             exclude("**/com/sun/javafx/application/Swing*.*");
2888         }
2889 
2890         forkEvery = 1
2891     }
2892 }
2893 
2894 allprojects {
2895     // The following block is a workaround for the fact that presently Gradle
2896     // can't set the -XDignore.symbol.file flag, because it appears that the
2897     // javac API is lacking support for it. So what we'll do is find any Compile
2898     // task and manually provide the options necessary to fire up the
2899     // compiler with the right settings.
2900     //
2901     // Also, we need to remove jfxrt.jar from the ext classpath (if it is there)
2902     tasks.withType(JavaCompile) { compile ->
2903         if (compile.options.hasProperty("useAnt")) {
2904             compile.options.useAnt = true
2905             compile.options.useDepend = IS_USE_DEPEND
2906         } else if (compile.options.hasProperty("incremental")) {
2907             compile.options.incremental = IS_INCREMENTAL
2908         }
2909         compile.options.debug = true // we always generate debugging info in the class files
2910         compile.options.debugOptions.debugLevel = IS_DEBUG_JAVA ? "source,lines,vars" : "source,lines"
2911         compile.options.fork = true
2912         compile.options.forkOptions.executable = JAVAC
2913         compile.options.warnings = IS_LINT
2914         compile.options.compilerArgs = ["-XDignore.symbol.file", "-encoding", "UTF-8"]
2915         if (!DO_BUILD_SDK_FOR_TEST) {
2916             compile.classpath = files(jfxrtJarFromSdk) + compile.classpath
2917         }
2918 
2919         // Add in the -Xlint options
2920         if (IS_LINT) {
2921             LINT.split("[, ]").each { s ->
2922                 compile.options.compilerArgs += "-Xlint:$s"
2923             }
2924         }
2925     }
2926 
2927     // Some tasks should be disabled not to compile SDK, when running only the tests
2928     disabledTasks.each {
2929         project.getTasksByName(it, false)*.enabled = false
2930     }
2931 }
2932 
2933 // fxpackager requires JDK 9 to compile
2934 project(":fxpackager") {
2935     tasks.withType(JavaCompile) { compile ->
2936         compile.options.forkOptions.executable = JIGSAW_JAVAC
2937         compile.options.compilerArgs = [
2938                 "-XaddExports:java.base/sun.security.pkcs=ALL-UNNAMED,"
2939                         + "java.base/sun.security.timestamp=ALL-UNNAMED,"
2940                         + "java.base/sun.security.x509=ALL-UNNAMED,"
2941                         + "jdk.jdeps/com.sun.tools.jdeps=ALL-UNNAMED",
2942                 "-encoding", "UTF-8"]
2943     }
2944 }
2945 
2946 /******************************************************************************
2947  *                                                                            *
2948  *                             Top Level Tasks                                *
2949  *                                                                            *
2950  *  These are the tasks which are defined only for the top level project and  *
2951  *  not for any sub projects. These are generally the entry point that is     *
2952  *  used by Hudson and by the continuous build system.                        *
2953  *                                                                            *
2954  *****************************************************************************/
2955 
2956 task clean() {
2957     group = "Basic"
2958     description = "Deletes the build directory and the build directory of all sub projects"
2959     getSubprojects().each { subProject ->
2960         dependsOn(subProject.getTasksByName("clean", true));
2961     }
2962     doLast {
2963         delete(buildDir);
2964     }
2965 }
2966 
2967 task cleanAll() {
2968     group = "Basic"
2969     description = "Scrubs the repo of build artifacts"
2970     dependsOn(clean)
2971     doLast {
2972         //delete(".gradle"); This causes problems on windows.
2973         delete("buildSrc/build");
2974     }
2975 }
2976 
2977 task javadoc(type: Javadoc) {
2978     enabled = IS_BUILD_JAVADOC
2979     group = "Basic"
2980     description = "Generates the JavaDoc for all the public API"
2981     executable = JAVADOC
2982     def projectsToDocument = [
2983             project(":base"), project(":graphics"), project(":controls"), project(":media"),
2984             project(":swing"), /*project(":swt"),*/ project(":fxml"), project(":web")]
2985     source(projectsToDocument.collect({
2986         [it.sourceSets.main.java]
2987     }));
2988     setDestinationDir(new File(buildDir, 'javadoc'));
2989     // FIXME: The following is a workaround for JDK-8151191; it should be
2990     // reverted once that bug is fixed
2991     classpath = rootProject.BUILD_SRC
2992     classpath += files(projectsToDocument.collect { project ->
2993         project.sourceSets.main.java.srcDirs
2994     });
2995     /*
2996     // Might need a classpath
2997     classpath = files(projectsToDocument.collect { project ->
2998         project.sourceSets.main.compileClasspath
2999     });
3000     classpath += files(projectsToDocument.collect { project ->
3001         project.sourceSets.main.output
3002     });
3003     */
3004     exclude("com/**/*", "Compile*", "javafx/builder/**/*", "javafx/scene/accessibility/**/*");
3005     options.windowTitle("${javadocTitle}")
3006     options.header("${javadocHeader}")
3007     options.bottom("${javadocBottom}")
3008     if (BUILD_CLOSED) {
3009         options.linksOffline(JDK_DOCS, JDK_DOCS_CLOSED);
3010     } else {
3011         options.links(JDK_DOCS);
3012     }
3013     options.addBooleanOption("XDignore.symbol.file").setValue(true);
3014     options.addBooleanOption("Xdoclint:none").setValue(!IS_DOC_LINT);
3015     options.addBooleanOption("javafx").setValue(true);
3016     options.addBooleanOption("use").setValue(true);
3017     doLast {
3018         projectsToDocument.each { p ->
3019             copy {
3020                 from "$p.projectDir/src/main/docs"
3021                 into "$buildDir/javadoc"
3022             }
3023         }
3024     }
3025 
3026     dependsOn(projectsToDocument.collect { project -> project.getTasksByName("classes", true)});
3027 }
3028 
3029 task jfxrt() {
3030     if (DO_BUILD_SDK_FOR_TEST) {
3031         rootProject.getTasksByName("compileTestJava", true).each { t ->
3032             if (t.enabled) t.dependsOn(jfxrt)
3033         }
3034     }
3035 }
3036 
3037 task sdk() {
3038     if (DO_BUILD_SDK_FOR_TEST) {
3039         rootProject.getTasksByName("test", true).each { t ->
3040             if (t.enabled) t.dependsOn(sdk)
3041         }
3042     }
3043 }
3044 
3045 task appsjar() {
3046     dependsOn(sdk)
3047     // Note: the jar dependencies get added elsewhere see project(":apps")
3048 }
3049 
3050 // these are empty tasks, allowing us to depend on the task, which may have other
3051 // real work items added later.
3052 task copyAppsArtifacts() {
3053     dependsOn(appsjar)
3054 }
3055 
3056 task apps() {
3057     dependsOn(sdk)
3058     dependsOn(appsjar)
3059     dependsOn(copyAppsArtifacts)
3060 }
3061 
3062 task findbugs() {
3063     dependsOn(sdk)
3064 
3065     doLast {
3066         if (!BUILD_CLOSED) {
3067             println "findbugs task is only run for a closed build"
3068         }
3069     }
3070 }
3071 
3072 // The following tasks are for the closed build only. They are a no-op for the open build
3073 
3074 task checkCache() {
3075     dependsOn(updateCacheIfNeeded)
3076 }
3077 
3078 // TODO: consider moving the "public-sdk" portion of this task here
3079 task publicExports() {
3080     doFirst {
3081         if (BUILD_CLOSED && !IS_BUILD_JAVADOC) {
3082             fail("publicExports task requires: -PBUILD_JAVADOC=true")
3083         }
3084     }
3085     dependsOn(sdk)
3086 }
3087 
3088 task perf() {
3089     dependsOn(sdk,apps)
3090     doLast {
3091         if (!BUILD_CLOSED) {
3092             println "perf task is only run for a closed build"
3093         }
3094     }
3095 }
3096 
3097 task zips() {
3098     doFirst {
3099         if (BUILD_CLOSED && !IS_BUILD_JAVADOC) {
3100             fail("zips task requires: -PBUILD_JAVADOC=true")
3101         }
3102     }
3103     dependsOn(sdk,publicExports,apps,perf)
3104 }
3105 
3106 task copySources(type: Copy) {
3107     enabled = IS_BUILD_SRC_ZIP
3108     def projectsToCopy = [
3109             project(":base"), project(":graphics"), project(":controls"),
3110             project(":swing"), project(":swt"), project(":fxml"),
3111             project(":media"), project(":web")]
3112     from(projectsToCopy.collect({ proj ->
3113         files(proj.sourceSets.main.java.srcDirs)
3114     }))
3115     include "**/*.java"
3116     into "${buildDir}/javafx-src"
3117 }
3118 
3119 task zipSources(type: Zip) {
3120     enabled = IS_BUILD_SRC_ZIP
3121     dependsOn(copySources)
3122     archiveName = "javafx-src.zip"
3123     destinationDir = file("$buildDir")
3124     includeEmptyDirs = false
3125     from "${buildDir}/javafx-src"
3126 }
3127 
3128 task src {
3129     enabled = IS_BUILD_SRC_ZIP
3130     description = "Created the javafx-src.zip bundle"
3131     dependsOn(zipSources)
3132 }
3133 
3134 task all() {
3135     dependsOn(sdk,publicExports,apps,perf,zips)
3136 }
3137 
3138 
3139 // Construct list of subprojects that are modules
3140 ext.moduleProjList = []
3141 subprojects {
3142     if (project.hasProperty("buildModule") && project.ext.buildModule) {
3143         rootProject.ext.moduleProjList += project
3144         println "module: $project (buildModule=YES)"
3145     } else {
3146         println "module: $project (buildModule=NO)"
3147     }
3148 }
3149 
3150 
3151 // Create the legacy sdk from the modular-sdk
3152 
3153 compileTargets { t ->
3154     def targetProperties = project.ext[t.upper]
3155     def platformPrefix = targetProperties.platformPrefix
3156     def sdkDirName = "${platformPrefix}sdk"
3157     def modularSdkDirName = "${platformPrefix}modular-sdk"
3158     def modularSdkDir = "${rootProject.buildDir}/${modularSdkDirName}"
3159     def modulesDir = "${modularSdkDir}/modules"
3160     def modulesCmdsDir = "${modularSdkDir}/modules_cmds"
3161     def modulesLibsDir = "${modularSdkDir}/modules_libs"
3162 
3163     // The jfxrt task is responsible for creating the legacy jfxrt.jar. A developer may
3164     // have multiple SDK's on their system at any one time, depending on which
3165     // cross compiles they have done. For example, I might have:
3166     //      build/ios-sdk/lib/jfxrt.jar
3167     //      build/armhf-sdk/lib/jfxrt.jar
3168     // and so forth. The default host build will always install into 'sdk'
3169     // allowing for uses where a known sdk path is needed (like IDEs)
3170     //      build/sdk/lib/jfxrt.jar
3171     // This arrangement allows for multiple independent SDKs to
3172     // exist on a developer's system.
3173     def jfxrtTask = task("jfxrt$t.capital", type: Jar) {
3174         group = "Basic"
3175         description = "Creates the jfxrt.jar for the $t.name target"
3176         archiveName = "build/${sdkDirName}/lib/jfxrt.jar";
3177         includeEmptyDirs = false
3178 
3179         moduleProjList.each { project ->
3180             if (project.ext.moduleRuntime) {
3181                 from("${modulesDir}/${project.ext.moduleName}");
3182             }
3183         }
3184 
3185         dependsOn(subprojects.collect { project -> project.getTasksByName("assemble", true)});
3186     }
3187 
3188     def jfxrtIndexTask = task("jfxrtIndex$t.capital") {
3189         //the following is a workaround for the lack of indexing in gradle 1.4 through 1.7
3190         dependsOn(jfxrtTask)
3191 
3192         doLast() {
3193             ant.jar (update: true, index: true, destfile: jfxrtTask.archiveName)
3194         }
3195     }
3196     jfxrt.dependsOn(jfxrtIndexTask)
3197 
3198     // FIXME: JIGSAW -- update this for modules
3199     def jfxswtTask = task("jfxswt$t.capital", type: Jar) {
3200         enabled = COMPILE_SWT
3201         group = "Basic"
3202         description = "Creates the jfxswt.jar for the $t.name target"
3203         archiveName = "build/${sdkDirName}/lib/jfxswt.jar";
3204         includeEmptyDirs = false
3205         from("modules/swt/build/classes/main");
3206         include("**/javafx/embed/swt/**")
3207         exclude("**/*.java");  // Builder java files are in build/classes and should be excluded
3208 
3209         dependsOn(subprojects.collect { project -> project.getTasksByName("assemble", true)});
3210     }
3211 
3212     def jfxswtIndexTask = task("jfxswtIndex$t.capital") {
3213         //the following is a workaround for the lack of indexing in gradle 1.4 through 1.7
3214         dependsOn(jfxswtTask)
3215 
3216         doLast() {
3217             ant.jar (update: true, index: true, destfile: jfxswtTask.archiveName)
3218         }
3219     }
3220     jfxrt.dependsOn(jfxswtIndexTask)
3221 
3222     def jmxTask = task ("jmx${t.capital}", type: Jar) {
3223         group = "Basic"
3224         description = "Creates the javafx-mx.jar"
3225         archiveName = "build/${sdkDirName}/lib/javafx-mx.jar";
3226         includeEmptyDirs = false
3227         from "modules/jmx/build/classes/main"
3228         from "modules/jmx/build/resources/main"
3229         dependsOn project(":jmx").assemble
3230     }
3231 
3232     // The 'sdk' task will build the rest of the legacy SDK, and depends
3233     // on the 'jfxrtTask' task. After executing this task the sdk bundle for
3234     // the current COMPILE_TARGETS will be fully created.
3235     def sdkTask = task("sdk$t.capital") {
3236         group = "Basic"
3237         description = "Creates the SDK for $t.name"
3238         doLast {
3239             copy {
3240                 moduleProjList.each { project ->
3241                     from "${modulesLibsDir}/${project.ext.moduleName}"
3242                 }
3243                 into "build/${sdkDirName}/lib"
3244             }
3245 
3246             copy {
3247                 moduleProjList.each { project ->
3248                     from "${modulesCmdsDir}/${project.ext.moduleName}"
3249                 }
3250                 into "build/${sdkDirName}/bin"
3251             }
3252 
3253             // FIXME: JIGSAW -- update this for modules
3254             // Copy over the javadocs that were generated. This is done rather than just generating
3255             // the docs into the "right place" because for a cross-compile you only need one set of
3256             // docs but need to have a copy in each created sdk
3257             if (IS_BUILD_JAVADOC) {
3258                 copy {
3259                     from "build/javadoc"
3260                     into "build/${sdkDirName}/docs/api"
3261                 }
3262             }
3263 
3264             // FIXME: JIGSAW -- update this for modules
3265             // Copy over the javafx-src bundle
3266             if (IS_BUILD_SRC_ZIP) {
3267                 copy {
3268                     from "build/javafx-src.zip"
3269                     into "build/${sdkDirName}"
3270                 }
3271             }
3272 
3273             // FIXME: JIGSAW -- update this for modules
3274             // Copy over the javapackager man files
3275             copy {
3276                 from "modules/fxpackager/build/man"
3277                 into "build/${sdkDirName}/man"
3278             }
3279         }
3280         dependsOn(jmxTask);
3281         dependsOn(jfxrtIndexTask)
3282         dependsOn(jfxswtIndexTask)
3283         dependsOn(javadoc)
3284         dependsOn(src)
3285     }
3286 
3287     def generateSymbols = targetProperties.containsKey('generateSymbols') ? targetProperties.generateSymbols : false
3288     if (generateSymbols) {
3289         def exportedSymbolsTask = project.task("exportedSymbols${t.capital}", type: ExportedSymbolsTask, dependsOn: sdkTask, group: "Build") {
3290             description = "Generates exported symbols file for iOS build (from .a libraries)"
3291             def libDirName = "build/${sdkDirName}/$targetProperties.libDest"
3292             libDir = file("$libDirName")
3293             outputFile = file("$libDirName/exported.symbols")
3294             excludes = targetProperties.generateSymbolsExcludes
3295         }
3296         sdk.dependsOn(exportedSymbolsTask)
3297     }
3298 
3299     sdk.dependsOn(sdkTask)
3300 }
3301 
3302 /*
3303  * This clause changes the way we handle a build.gradle within ./apps
3304  * It does a few things:
3305  *   modifies the classpath used to include the built runttime classes
3306  *   provides for copying the build applications to the artifacts tree
3307  *
3308  * The applications to be built will be under ./apps, but also must
3309  * be listed in the applications listed in the setting variable: JFXApplications
3310  */
3311 ext.JFXRT_CP =
3312     files(
3313         project(":base").sourceSets.main.output.classesDir,
3314         project(":graphics").sourceSets.main.output.classesDir,
3315         project(":controls").sourceSets.main.output.classesDir,
3316         project(":fxml").sourceSets.main.output.classesDir,
3317         project(":swing").sourceSets.main.output.classesDir, //NOTE - used by 3Dviewer
3318             "modules/media/build/classes/main",
3319             "modules/web/build/classes/main",
3320     )
3321 
3322 project(":apps") {
3323     // The apps build is Ant based, and gradle lets us "import" ant build.xml
3324     // into our configuration.
3325 
3326     ant.importBuild 'build.xml'
3327 
3328     compileTargets { t ->
3329         // The apps build is Ant based, and gradle lets us "import" ant apps/build.xml
3330         // into our configuration.
3331 
3332         // override the apps build.xml with an explicit pointer to our jar.
3333         def platformPrefix = rootProject.ext[t.upper].platformPrefix
3334         def sdkDirName = "${platformPrefix}sdk"
3335         def jfxrtJar = "${rootProject.buildDir}/${sdkDirName}/lib/jfxrt.jar"
3336 
3337         def appsJar = project.task("appsJar${t.capital}") {
3338             dependsOn(sdk)
3339             doLast() {
3340               ant.properties['targetBld'] = "$t.name"
3341               if (!rootProject.ext[t.upper].compileSwing) {
3342                 ant.properties['JFX_CORE_ONLY'] = 'true'
3343               }
3344               ant.properties['jfxbuild.jfxrt.jar'] = jfxrtJar
3345               ant.properties['platforms.JDK_1.8.home'] = "${rootProject.ext.JDK_HOME}"
3346               ant.project.executeTarget("sampleAppsJar")
3347               ant.project.executeTarget("scenebuilderSampleAppsJar")
3348               if (!t.name.startsWith("arm")) {
3349                 ant.project.executeTarget("scenebuilderAppJar")
3350               }
3351             }
3352         }
3353         rootProject.appsjar.dependsOn(appsJar)
3354 
3355         def appsClean = project.task("appsClean${t.capital}") {
3356             doLast() {
3357               ant.properties['targetBld'] = "$t.name"
3358               ant.properties['platforms.JDK_1.8.home'] = "${rootProject.ext.JDK_HOME}"
3359               ant.project.executeTarget("sampleAppsClean")
3360               ant.project.executeTarget("scenebuilderSampleAppsClean")
3361               if (!t.name.startsWith("arm")) {
3362                 ant.project.executeTarget("scenebuilderAppClean")
3363               }
3364             }
3365         }
3366         rootProject.clean.dependsOn(appsClean)
3367     }
3368 }
3369 
3370 
3371 /******************************************************************************
3372  *                                                                            *
3373  *                               Modules                                      *
3374  *                                                                            *
3375  *****************************************************************************/
3376 
3377 ext.moduleDependencies = [file("dependencies")]
3378 
3379 task buildModules {
3380 }
3381 
3382 // Combine the classes, lib, and bin for each module
3383 compileTargets { t ->
3384     def targetProperties = project.ext[t.upper]
3385 
3386     def platformPrefix = targetProperties.platformPrefix
3387     def modularSdkDirName = "${platformPrefix}modular-sdk"
3388     def modularSdkDir = "${rootProject.buildDir}/${modularSdkDirName}"
3389     def modulesDir = "${modularSdkDir}/modules"
3390     def modulesCmdsDir = "${modularSdkDir}/modules_cmds"
3391     def modulesLibsDir = "${modularSdkDir}/modules_libs"
3392     def modulesSrcDir = "${modularSdkDir}/modules_src"
3393     def modulesConfDir = "${modularSdkDir}/modules_conf"
3394     def modulesMakeDir = "${modularSdkDir}/make"
3395 
3396     def zipTask = project.task("buildModuleZip$t.capital", type: Zip, group: "Build") {
3397         // FIXME: JIGSAW -- this should be moved to a sub-directory so we can keep the same name
3398         def jfxBundle = "${platformPrefix}javafx-exports.zip"
3399 
3400         doFirst() {
3401             file("${rootProject.buildDir}/${jfxBundle}").delete()
3402         }
3403 
3404         archiveName = jfxBundle
3405         destinationDir = file("${rootProject.buildDir}")
3406         includeEmptyDirs = false
3407         from "${modularSdkDir}"
3408     }
3409     buildModules.dependsOn(zipTask)
3410 
3411     def buildModulesTask = task("buildModules$t.capital", group: "Build") {
3412         doLast {
3413             moduleProjList.each { project ->
3414 
3415                 // Copy classes, bin, and lib directories
3416 
3417                 def moduleName = project.ext.moduleName
3418                 def buildDir = project.buildDir
3419 
3420                 def srcClassesDir = "${buildDir}/${platformPrefix}module-classes"
3421                 def dstClassesDir = "${modulesDir}/${moduleName}"
3422                 copy {
3423                     from srcClassesDir
3424                     into dstClassesDir
3425                 }
3426 
3427                 def srcCmdsDir = "${buildDir}/${platformPrefix}module-bin"
3428                 def dstCmdsDir = "${modulesCmdsDir}/${moduleName}"
3429                 copy {
3430                     from srcCmdsDir
3431                     into dstCmdsDir
3432                 }
3433 
3434                 def srcLibsDir = "${buildDir}/${platformPrefix}module-lib"
3435                 def dstLibsDir = "${modulesLibsDir}/${moduleName}"
3436                 copy {
3437                     from srcLibsDir
3438                     into dstLibsDir
3439                 }
3440 
3441                 // Copy module-info.java
3442                 def srcModuleInfoDir = "${project.projectDir}/src/main/module-info"
3443                 def dstModuleInfoDir = "${modulesSrcDir}/${moduleName}"
3444                 copy {
3445                     from srcModuleInfoDir
3446                     into dstModuleInfoDir
3447                     if (!IS_COMPILE_JFR && project.name.equals("base")) {
3448                         filter { line-> line.contains("requires jdk.jfr;") ? "" : line }
3449                     }
3450                 }
3451 
3452                 // Copy make/build.properties
3453                 def srcMakeDir = "${project.projectDir}/make"
3454                 def dstMakeDir = "${modulesMakeDir}/${moduleName}"
3455                 copy {
3456                     from srcMakeDir
3457                     into dstMakeDir
3458                 }
3459             }
3460 
3461             // Copy dependencies/*/module-info.java.extra
3462             def dependencyRoots = moduleDependencies
3463             if (rootProject.hasProperty("closedModuleDepedencies")) {
3464                 dependencyRoots = [dependencyRoots, closedModuleDepedencies].flatten()
3465             }
3466             copy {
3467                 dependencyRoots.each { root ->
3468                     from root
3469                 }
3470                 into modulesSrcDir
3471             }
3472 
3473             // concatecate java.policy files into a single file
3474             //
3475             def outputPolicyDir = "${modulesConfDir}/java.base/security"
3476             def outputPolicyFile = file("${outputPolicyDir}/java.policy.extra")
3477             mkdir outputPolicyDir
3478             outputPolicyFile.delete()
3479             moduleProjList.each { project ->
3480                 def policyDir = "${project.projectDir}/src/main/conf/security"
3481                 def policyFile = file("${policyDir}/java.policy")
3482                 if (policyFile.exists()) outputPolicyFile << policyFile.text
3483             }
3484         }
3485     }
3486     zipTask.dependsOn(buildModulesTask);
3487     buildModules.dependsOn(buildModulesTask)
3488 
3489     def isWindows = IS_WINDOWS && t.name == "win";
3490     def isMac = IS_MAC && t.name == "mac";
3491 
3492     // Create layout for modular classes
3493     moduleProjList.each { project ->
3494         def buildModuleClassesTask = project.task("buildModule$t.capital", group: "Build") {
3495             dependsOn(project.assemble)
3496             def buildDir = project.buildDir
3497             def sourceBuildDirs = [
3498                 "${buildDir}/classes/main",
3499                 "${buildDir}/resources/main"
3500             ]
3501             if (project.hasProperty("extraBuildDirs")) {
3502                 sourceBuildDirs += project.ext.extraBuildDirs
3503             }
3504             doLast {
3505                 def moduleClassesDir = "$buildDir/${platformPrefix}module-classes"
3506                 copy {
3507                     includeEmptyDirs = false
3508                     sourceBuildDirs.each { d ->
3509                         from d
3510                     }
3511                     into moduleClassesDir
3512 
3513                     // Exclude obsolete, experimental, or non-shipping code
3514                     exclude("version.rc")
3515                     exclude("com/sun/glass/ui/swt")
3516                     exclude("com/sun/javafx/tools/ant")
3517                     exclude("com/javafx/main")
3518                     if (!IS_INCLUDE_NULL3D) {
3519                         exclude ("com/sun/prism/null3d")
3520                     }
3521                     if (!IS_INCLUDE_ES2) {
3522                            exclude("com/sun/prism/es2",
3523                                    "com/sun/scenario/effect/impl/es2")
3524                     }
3525 
3526                     // Exclude platform-specific classes for other platforms
3527 
3528                     if (!isMac) {
3529                         exclude ("com/sun/media/jfxmediaimpl/platform/osx",
3530                                  "com/sun/prism/es2/MacGL*",
3531                                  "com/sun/glass/events/mac",
3532                                  "com/sun/glass/ui/mac",
3533                                  )
3534                     }
3535 
3536                     if (!isWindows) {
3537                         exclude ("**/*.hlsl",
3538                                  "com/sun/glass/ui/win",
3539                                  "com/sun/prism/d3d",
3540                                  "com/sun/prism/es2/WinGL*",
3541                                  "com/sun/scenario/effect/impl/hw/d3d"
3542                                  )
3543                     }
3544 
3545                     if (!targetProperties.includeGTK) { //usually IS_LINUX
3546                         exclude (
3547                                  "com/sun/glass/ui/gtk",
3548                                  "com/sun/prism/es2/EGL*",
3549                                  "com/sun/prism/es2/X11GL*"
3550                                  )
3551                     }
3552 
3553                     if (!targetProperties.includeEGL) {
3554                         exclude ("com/sun/prism/es2/EGL*")
3555                     }
3556 
3557                     if (!targetProperties.includeLens) {
3558                         exclude ("com/sun/glass/ui/lens")
3559                     }
3560 
3561                     // FIXME: JIGSAW -- Figure out what to do with Monocle
3562                     /*
3563                     if (!targetProperties.includeMonocle) {
3564                         exclude ("com/sun/glass/ui/monocle")
3565                         exclude("com/sun/prism/es2/Monocle*")
3566                     }
3567                     */
3568 
3569                     if (t.name != 'ios') {
3570                         exclude ("com/sun/media/jfxmediaimpl/platform/ios",
3571                                  "com/sun/glass/ui/ios",
3572                                  "com/sun/prism/es2/IOS*"
3573                                  )
3574                     }
3575 
3576                     if (t.name != 'android' && t.name != 'dalvik') {
3577                         exclude ("com/sun/glass/ui/android")
3578                     }
3579 
3580                     // Filter out other platform-specific classes
3581                     if (targetProperties.containsKey('jfxrtJarExcludes')) {
3582                         exclude(targetProperties.jfxrtJarExcludes)
3583                     }
3584 
3585                     /* FIXME: JIGSAW -- handle this in the module itself
3586                     if (t.name == 'android') {
3587                         from ("modules/web/build/classes/android",
3588                               "modules/web/build/resources/android",
3589                               "modules/controls/build/classes/android",
3590                               "modules/controls/build/resources/android")
3591                     } else if (t.name == 'ios') {
3592                         from ("modules/web/build/classes/ios",
3593                               "modules/web/build/resources/ios",
3594                               "modules/extensions/build/classes/ios")
3595                     } else {
3596                         from ("modules/web/build/classes/main", "modules/web/build/resources/main")
3597                     }
3598                     */
3599                 }
3600             }
3601         }
3602         buildModulesTask.dependsOn(buildModuleClassesTask)
3603     }
3604 
3605 
3606     def buildModuleLibsTask = task("buildModuleLibs$t.capital") {
3607         group = "Basic"
3608 
3609         def graphicsProject = project(":graphics");
3610         dependsOn(graphicsProject.assemble)
3611 
3612         def mediaProject = project(":media");
3613         dependsOn(mediaProject.assemble)
3614 
3615         def webProject = project(":web");
3616         dependsOn(webProject.assemble)
3617 
3618         def packagerProject = project(":fxpackager");
3619         //dependsOn(packagerProject.assemble)
3620         dependsOn(packagerProject.jar)
3621         dependsOn(project(":fxpackagerservices").jar)
3622 
3623         doLast {
3624 
3625             def library = targetProperties.library
3626 
3627             // javafx.base (lib/javafx.properties)
3628 
3629             def baseProject = project(":base");
3630             def moduleLibDir = "${baseProject.buildDir}/${platformPrefix}module-lib"
3631             mkdir moduleLibDir
3632             final File javafxProperties = file("${moduleLibDir}/javafx.properties")
3633             javafxProperties.delete()
3634             javafxProperties << "javafx.version=$RELEASE_VERSION_SHORT";
3635             javafxProperties << "\n"
3636             javafxProperties << "javafx.runtime.version=$RELEASE_VERSION_LONG";
3637             javafxProperties << "\n"
3638             javafxProperties << "javafx.runtime.build=$PROMOTED_BUILD_NUMBER";
3639             javafxProperties << "\n"
3640             // Include any properties that have been defined (most likely in
3641             // one of the various platform gradle files)
3642             if (targetProperties.containsKey("javafxProperties")) {
3643                 javafxProperties << targetProperties.javafxProperties
3644                 javafxProperties << "\n"
3645             }
3646 
3647             // Embedded builds define this file as well
3648             if (targetProperties.containsKey("javafxPlatformProperties")) {
3649                 final File javafxPlatformProperties = file("${moduleLibDir}/javafx.platform.properties")
3650                 javafxPlatformProperties.delete()
3651                 javafxPlatformProperties << targetProperties.javafxPlatformProperties
3652                 javafxPlatformProperties << "\n"
3653             }
3654 
3655 
3656             def useLipo = targetProperties.containsKey('useLipo') ? targetProperties.useLipo : false
3657             def libDest = targetProperties.libDest
3658             def moduleNativeDirName = "${platformPrefix}module-$libDest"
3659 
3660             // javafx.graphics native libraries
3661 
3662             copy {
3663                 into "${graphicsProject.buildDir}/${moduleNativeDirName}"
3664 
3665                 from("modules/graphics/build/libs/jsl-decora/${t.name}/${library(targetProperties.decora.lib)}")
3666                 def libs = ['font', 'prism', 'prismSW', 'glass', 'iio']
3667                 if (IS_INCLUDE_ES2) {
3668                     libs += ['prismES2'];
3669                 }
3670                 if (IS_COMPILE_PANGO) {
3671                     libs += ['fontFreetype', 'fontPango'];
3672                 }
3673                 libs.each { lib ->
3674                     def variants = targetProperties[lib].containsKey('variants') && !useLipo ? targetProperties[lib].variants : [null]
3675                     variants.each { variant ->
3676                         def variantProperties = variant ? targetProperties[lib][variant] : targetProperties[lib]
3677                         from ("modules/graphics/build/libs/$lib/$t.name/${library(variantProperties.lib)}")
3678                     }
3679                 }
3680                 if (IS_WINDOWS) {
3681                     from ("modules/graphics/build/libs/prismD3D/${t.name}/${library(targetProperties.prismD3D.lib)}");
3682                 }
3683             }
3684 
3685 
3686             // javafx.media native libraries
3687 
3688             copy {
3689                 into "${mediaProject.buildDir}/${moduleNativeDirName}"
3690 
3691                 def mediaBuildType = project(":media").ext.buildType
3692                 if (IS_COMPILE_MEDIA) {
3693                     [ "fxplugins", "gstreamer-lite", "jfxmedia" ].each { name ->
3694                         from ("modules/media/build/native/${t.name}/${mediaBuildType}/${library(name)}") }
3695 
3696                     if (t.name == "mac") {
3697                         // OSX media natives
3698                         [ "jfxmedia_qtkit", "jfxmedia_avf", "glib-lite" ].each { name ->
3699                             from ("modules/media/build/native/${t.name}/${mediaBuildType}/${library(name)}") }
3700                     } else if (t.name == "linux") {
3701                         from("modules/media/build/native/${t.name}/${mediaBuildType}") { include "libavplugin*.so" }
3702                     } else from ("modules/media/build/native/${t.name}/${mediaBuildType}/${library("glib-lite")}")
3703                 } else {
3704                     if (t.name != "android"  && t.name != "dalvik" ) {
3705                         [ "fxplugins", "gstreamer-lite", "jfxmedia" ].each { name ->
3706                             from ("$LIBRARY_STUB/${library(name)}") }
3707                     }
3708 
3709                     if (t.name == "mac") {
3710                         // copy libjfxmedia_{avf,qtkit}.dylib if they exist
3711                         [ "jfxmedia_qtkit", "jfxmedia_avf", "glib-lite" ].each { name ->
3712                             from ("$LIBRARY_STUB/${library(name)}") }
3713                     } else if (t.name == "linux") {
3714                         from(LIBRARY_STUB) { include "libavplugin*.so" }
3715                     }
3716                     else if (t.name != "android"  && t.name != "dalvik" ) {
3717                         from ("$LIBRARY_STUB/${library("glib-lite")}")
3718                     }
3719                 }
3720             }
3721 
3722 
3723             // javafx.web native libraries
3724 
3725             copy {
3726                 into "${webProject.buildDir}/${moduleNativeDirName}"
3727 
3728                 if (IS_COMPILE_WEBKIT) {
3729                     from ("modules/web/build/libs/${t.name}/${library('jfxwebkit')}")
3730                 } else {
3731                     if (t.name != "android" && t.name != "ios" && t.name != "dalvik") {
3732                         from ("$LIBRARY_STUB/${library('jfxwebkit')}")
3733                     }
3734                 }
3735             }
3736 
3737 
3738             // javafx.packager libraries and executable
3739 
3740             // Copy over the javapackager libs
3741             copy {
3742                 from "modules/fxpackager/build/libs"
3743                 into "${packagerProject.buildDir}/${platformPrefix}module-lib"
3744             }
3745 
3746             // Copy over the javapackager executable
3747             if (t.name == "win" || t.name == "linux" || t.name == "mac") {
3748                 copy {
3749                     from "modules/fxpackager/build/javapackager"
3750                     into "${packagerProject.buildDir}/${platformPrefix}module-bin"
3751                 }
3752             }
3753 
3754         }
3755     }
3756     buildModulesTask.dependsOn(buildModuleLibsTask)
3757 
3758     def sdkTask = tasks.getByName("sdk${t.capital}");
3759     sdkTask.dependsOn(buildModulesTask)
3760 }
3761 sdk.dependsOn(buildModules)
3762 
3763 void configureJigsawTests(
3764         Project p,
3765         List<String> moduleDeps,
3766         Set<String> patchInc,
3767         Set<String> testsInc,
3768         String addExportsFile
3769         ) {
3770 
3771     if(!IS_JIGSAW_TEST) {
3772         return
3773     }
3774 
3775     p.configurations {
3776         jigsawTest
3777     }
3778 
3779     p.dependencies {
3780         jigsawTest group: "junit", name: "junit", version: "4.8.2"
3781     }
3782 
3783     compileTargets { t ->
3784 
3785         def targetProperties = project.rootProject.ext[t.upper]
3786 
3787         def modularSdkDirName = "${targetProperties.platformPrefix}modular-sdk"
3788         def modularSdkDir = "${rootProject.buildDir}/${modularSdkDirName}"
3789         def modulesDir = "${modularSdkDir}/modules"
3790 
3791         boolean useModule = true
3792         String moduleName
3793         if(!p.hasProperty('moduleName')) {
3794             useModule = false
3795             moduleName = "systemTests"
3796         } else {
3797             moduleName = p.moduleName
3798         }
3799 
3800         logger.info("configuring $p.name for modular test copy");
3801 
3802         def testingDir = "${rootProject.buildDir}/${targetProperties.platformPrefix}testing";
3803         def patchesDir = new File("${testingDir}/modules");
3804         File patchPolicyFile = new File("${testingDir}/java.patch.policy");
3805 
3806         String javaLibraryPath = "${rootProject.buildDir}/sdk/$targetProperties.libDest"
3807 
3808         def jigsawPatchesBaseDir = new File("${testingDir}/modules/$moduleName");
3809         def jigsawPatchesTestDir = new File("${testingDir}/tests/$moduleName");
3810 
3811         p.files(patchPolicyFile);
3812 
3813         def srcClassesDir = "${p.buildDir}/${targetProperties.platformPrefix}module-classes"
3814         Task classes =  p.task("jigsawCopyClasses${t.capital}", type: Copy, dependsOn: [p.classes]) {
3815 
3816             enabled = useModule
3817 
3818             from srcClassesDir
3819             into jigsawPatchesBaseDir
3820         }
3821 
3822         Task shims =  p.task("jigsawCopyShims${t.capital}", type: Copy, dependsOn: [p.testClasses]) {
3823             //from p.sourceSets.test.output.classesDir
3824 
3825             enabled = useModule
3826 
3827             from p.sourceSets.test.output
3828             into jigsawPatchesBaseDir
3829             if (patchInc != null) {
3830                 include patchInc
3831             } else {
3832                 include "**/*"
3833             }
3834             if (testsInc != null) {
3835                 exclude testsInc
3836             }
3837             includeEmptyDirs = false
3838             doLast() {
3839                 logger.info("project $p.name finished jigsawCopyShims to $jigsawPatchesBaseDir");
3840             }
3841         }
3842 
3843         Task alltests =  p.task("jigsawCopyTests${t.capital}", type: Copy, dependsOn: [p.testClasses]) {
3844             from p.sourceSets.test.output
3845             into jigsawPatchesTestDir
3846             if (patchInc != null) {
3847                 exclude patchInc
3848             }
3849             if (testsInc != null) {
3850                 include testsInc
3851             } else {
3852                 include "**/*"
3853             }
3854             includeEmptyDirs = false
3855             doLast() {
3856                 logger.info("project $p.name finished jigsawCopyTests to $jigsawPatchesTestDir");
3857             }
3858         }
3859 
3860         // create & use just one of these per platform
3861         String nameis = "moduleTestPatchPolicy${t.capital}"
3862         Task patchPerms = null
3863         if (rootProject.hasProperty(nameis)) {
3864             patchPerms = rootProject.tasks[nameis]
3865         } else {
3866             patchPerms = rootProject.task(nameis) {
3867                 outputs.file(patchPolicyFile)
3868                 doLast() {
3869                     logger.info("Creating test patch.policy file ${patchPolicyFile}")
3870 
3871                     delete(patchPolicyFile)
3872                     mkdir(testingDir)
3873 
3874                     [ "base", "graphics", "controls", "fxml", "swing", "web", ].each { mn ->
3875                         String themod = file("${patchesDir}/javafx.${mn}").toURI()
3876                         patchPolicyFile <<  "grant codeBase \"${themod}\" {\n" +
3877                         "    permission java.security.AllPermission;\n" +
3878                         "};\n"
3879                     }
3880                 }
3881             }
3882         }
3883 
3884         Task jigsawTestsTask =  p.task("jigsawTests${t.capital}", dependsOn: [classes, shims, alltests, patchPerms ]) {
3885             doLast() {
3886                 logger.info("project $p.name finished jigsawTests${t.capital}");
3887             }
3888         }
3889 
3890         FileCollection testclasspath = p.files(p.configurations.jigsawTest)
3891 
3892         p.test.dependsOn jigsawTestsTask
3893 
3894         if (moduleDeps != null) {
3895             moduleDeps.each() {s->
3896                 logger.info("adding dep to project $p.name $s");
3897                 Project pdep = rootProject.project(s);
3898                 def jigsawTask = pdep.tasks.getByName("jigsawTests${t.capital}");
3899                 jigsawTestsTask.dependsOn jigsawTask;
3900 
3901                 testclasspath += p.files(pdep.ext.jigsawPatchesTestDir);
3902             }
3903         }
3904 
3905         testclasspath += p.files(jigsawPatchesTestDir);
3906 
3907         p.ext.jigsawTestClasspath = testclasspath
3908         p.ext.jigsawPatchesTestDir = jigsawPatchesTestDir
3909         p.ext.jigsawTestClasses = jigsawTestsTask
3910 
3911         p.ext.argclasspathFile = "$testingDir/classpath_"+p.name+".txt"
3912 
3913         p.test {
3914             if (IS_FORCE_TESTS) {
3915                 dependsOn 'cleanTest'
3916             }
3917 
3918             scanForTestClasses = false
3919             include("**/*Test.*")
3920 
3921             if (IS_JIGSAW_TEST) {
3922                 dependsOn jigsawTestsTask
3923 
3924                 doFirst {
3925                     classpath = testclasspath
3926                     p.sourceSets.test.runtimeClasspath = testclasspath
3927                 }
3928 
3929                 String bcp = "-Xbootclasspath/a:" + rootProject.projectDir.path + "/buildSrc/build/libs/buildSrc.jar"
3930 
3931                 systemProperties 'worker.debug': IS_WORKER_DEBUG
3932                 systemProperties 'worker.library.path': cygpath(javaLibraryPath)
3933                 systemProperties 'worker.xpatch.dir': cygpath(patchesDir.path)
3934                 if (addExportsFile != null) {
3935                     systemProperties 'worker.exports.file': cygpath(addExportsFile)
3936                 }
3937                 systemProperties 'worker.classpath.file': cygpath(p.ext.argclasspathFile)
3938                 systemProperties 'worker.java.cmd': JIGSAW_JAVA
3939 
3940                 systemProperties 'worker.isJigsaw': true
3941 
3942                 systemProperties 'worker.patch.policy': cygpath(patchPolicyFile.path)
3943 
3944                 //systemProperties 'prism.order': 'sw'
3945                 //systemProperties 'glass.platform': 'Monocle'
3946                 //systemProperties
'glass.len': 'headless'
3947 
3948                 jvmArgs bcp, "workaround.GradleJUnitWorker"
3949 
3950                 environment("JDK_HOME", JIGSAW_HOME);
3951                 executable (JIGSAW_JAVA);
3952 
3953               }
3954         }
3955 
3956     }
3957 
3958 }
3959 
3960 task checkrepo() {
3961     doLast {
3962         logger.info("checking for whitespace (open)");
3963         exec {
3964             if (IS_WINDOWS) {
3965                 commandLine  'bash', 'tools/scripts/checkWhiteSpace'
3966             } else {
3967                 commandLine  'bash', 'tools/scripts/checkWhiteSpace', '-x'
3968             }
3969         }
3970     }
3971 }
3972 
3973 task checkrepoall() {
3974     doLast {
3975         logger.info("checking for all whitespace (open)");
3976         exec {
3977             if (IS_WINDOWS) {
3978                 commandLine  'bash', 'tools/scripts/checkWhiteSpace', '-a'
3979             } else {
3980                 commandLine  'bash', 'tools/scripts/checkWhiteSpace', '-x', '-a'
3981             }
3982         }
3983     }
3984 }
3985 
3986 /******************************************************************************
3987  *                                                                            *
3988  *                              BUILD_CLOSED                                  *
3989  *                                                                            *
3990  * This next section should remain at the end of the build script. It allows  *
3991  * for a "supplemental" gradle file to be used to extend the normal build     *
3992  * structure. For example, this is used for passing a supplemental gradle     *
3993  * file for producing official JavaFX builds.                                 *
3994  *                                                                            *
3995  *****************************************************************************/
3996 
3997 if (BUILD_CLOSED) {
3998     apply from: supplementalBuildFile
3999 }
4000 
4001 task showFlags {
4002 }
4003 
4004 compileTargets { t ->
4005     // Every platform must define these variables
4006     def props = project.ext[t.upper];
4007     showFlags.dependsOn(
4008         project.task("showFlags$t.upper") {
4009             doLast() {
4010                 println "Properties set for $t.upper"
4011                 props.each { println it }
4012             }
4013         }
4014     )
4015 
4016 }
4017