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