1 /*
   2  * Copyright (c) 2013, 2018, 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  *  - Perform sanity checking to make sure a JDK exists with javac, etc
  35  *  - Support building with no known JDK location, as long as javac, etc are on the path
  36  *  - Check all of the native flags. We're adding weight to some libs that don't need it, and so forth.
  37  *
  38  * Additional projects to work on as we go:
  39  *  - Add "developer debug". This is where the natives do not have debug symbols, but the Java code does
  40  *  - The genVSproperties.bat doesn't find the directory where RC.exe lives. So it is hard coded. Might be a problem.
  41  *  - special tasks for common needs, such as:
  42  *      - updating copyright headers
  43  *      - stripping trailing whitespace (?)
  44  *  - checkstyle
  45  *  - findbugs
  46  *  - re needs?
  47  *  - sqe testing
  48  *  - API change check
  49  *  - Pushing results to a repo?
  50  *  - ServiceWithSecurityManagerTest fails to complete when run from gradle.
  51  *  - Integrate Parfait reports for C code
  52  *  - FXML Project tests are not running
  53  */
  54 defaultTasks = ["sdk"]
  55 
  56 import java.util.concurrent.CountDownLatch
  57 import java.util.concurrent.ExecutorService
  58 import java.util.concurrent.Executors
  59 import java.util.concurrent.Future
  60 
  61 /******************************************************************************
  62  *                              Utility methods                               *
  63  *****************************************************************************/
  64 
  65 /**
  66  * If the given named property is not defined, then this method will define
  67  * it with the given defaultValue. Any properties defined by this method can
  68  * be substituted on the command line by using -P, or by specifying a
  69  * gradle.properties file in the user home dir
  70  *
  71  * @param name The name of the property to define
  72  * @param defaultValue The default value to assign the property
  73  */
  74 void defineProperty(String name, String defaultValue) {
  75     if (!project.hasProperty(name)) {
  76         project.ext.set(name, defaultValue);
  77     }
  78 }
  79 
  80 /**
  81  * If the given named property is not defined, then this method will attempt to
  82  * look up the property in the props map, and use the defaultValue if it cannot be found.
  83  *
  84  * @param name The name of the property to look up and/or define
  85  * @param props The properties to look for the named property in, if it has not already been defined
  86  * @param defaultValue The default value if the property has not been defined and the
  87  *                     props map does not contain the named property
  88  */
  89 void defineProperty(String name, Properties props, String defaultValue) {
  90     if (!project.hasProperty(name)) {
  91         project.ext.set(name, props.getProperty(name, defaultValue));
  92     }
  93 }
  94 
  95 /**
  96  * Converts cygwin style paths to windows style paths, but with a forward slash.
  97  * This method is safe to call from any platform, and will only do work if
  98  * called on Windows (in all other cases it simply returns the supplied path.
  99  *
 100  * @param path the path to convert
 101  * @return the path converted to windows style, if on windows, otherwise it
 102  *         is the supplied path.
 103  */
 104 String cygpath(String path) {
 105     if (!IS_WINDOWS) return path;
 106     if (path == null || "".equals(path)) return path;
 107     String ret = path.replaceAll('\\\\', '/')
 108     logger.info("Converting path '$path' via cygpath to "+ret)
 109     return ret
 110 }
 111 
 112 /**
 113  * Converts cygwin file paths for java executables to windows style
 114  * executable paths by changing forward slashes to back slashes and
 115  * adding the '.exe' extension.
 116  * This method is safe to call from any platform, and will only do work if
 117  * called on Windows (in all other cases it simply returns the supplied path).
 118  *
 119  * @param path the path to convert
 120  * @return the path converted to windows style, if on windows, otherwise it
 121  *         is the supplied path.
 122  */
 123 String cygpathExe(String path) {
 124     if (!IS_WINDOWS) return path;
 125     if (path == null || "".equals(path)) return path;
 126     String ret = path.replaceAll('/', '\\\\')
 127     logger.info("Converting path '$path' via cygpath to "+ret)
 128     return ret + ".exe"
 129 }
 130 
 131 void loadProperties(String sourceFileName) {
 132     def config = new Properties()
 133     def propFile = new File(sourceFileName)
 134     if (propFile.canRead()) {
 135         config.load(new FileInputStream(propFile))
 136         for (java.util.Map.Entry property in config) {
 137             def keySplit = property.key.split("\\.");
 138             def key = keySplit[0];
 139             for (int i = 1; i < keySplit.length; i++) {
 140                 key = key + keySplit[i].capitalize();
 141             }
 142             ext[key] = property.value;
 143         }
 144     }
 145 }
 146 
 147 /**
 148  * Struct used to contain some information passed to the closure
 149  * passed to compileTargets.
 150  */
 151 class CompileTarget {
 152     String name;
 153     String upper;
 154     String capital;
 155 }
 156 
 157 /**
 158  * Iterates over each of the compile targets, passing the given closure
 159  * a CompileTarget instance.
 160  *
 161  * @param c The closure to call
 162  */
 163 void compileTargets(Closure c) {
 164     if (COMPILE_TARGETS == "") {
 165         return
 166     }
 167     COMPILE_TARGETS.split(",").each { target ->
 168         CompileTarget ct = new CompileTarget();
 169         ct.name = target;
 170         ct.upper = target.trim().toUpperCase(Locale.ROOT)
 171         ct.capital = target.trim().capitalize()
 172         c(ct)
 173     }
 174 }
 175 
 176 /**
 177  * Manages the execution of some closure which is responsible for producing
 178  * content for a properties file built at build time and stored in the
 179  * root project's $buildDir, and then loading that properties file and
 180  * passing it to the processor closure.
 181  *
 182  * This is used on windows to produce a properties file containing all the
 183  * windows visual studio paths and environment variables, and on Linux
 184  * for storing the results of pkg-config calls.
 185  *
 186  * @param name the name of the file to produce
 187  * @param loader a closure which is invoked, given the properties file. This
 188  *        closure is invoked only if the properties file needs to be created
 189  *        and is responsible for populating the properties file.
 190  * @param processor a closure which is invoked every time this method is
 191  *        called and which will be given a Properties object, fully populated.
 192  *        The processor is then responsible for doing whatever it is that it
 193  *        must do with those properties (such as setting up environment
 194  *        variables used in subsequent native builds, or whatnot).
 195  */
 196 void setupTools(String name, Closure loader, Closure processor) {
 197     // Check to see whether $buildDir/$name.properties file exists. If not,
 198     // then generate it. Once generated, we need to read the properties file to
 199     // help us define the defaults for this block of properties
 200     File propFile = file("$buildDir/${name}.properties");
 201     if (!propFile.exists()) {
 202         // Create the properties file
 203         propFile.getParentFile().mkdirs();
 204         propFile.createNewFile();
 205         loader(propFile);
 206     }
 207 
 208     // Try reading the properties in order to define the properties. If the property file cannot
 209     // be located, then we will throw an exception because we cannot guess these values
 210     InputStream propStream = null;
 211     try {
 212         Properties properties = new Properties();
 213         propStream = new FileInputStream(propFile);
 214         properties.load(propStream);
 215         processor(properties);
 216     } finally {
 217         try { propStream.close() } catch (Exception e) { }
 218     }
 219 }
 220 
 221 String[] parseJavaVersion(String jRuntimeVersion) {
 222     def jVersion = jRuntimeVersion.split("[-\\+]")[0]
 223     def tmpBuildNumber = "0"
 224     if (jVersion.startsWith("1.")) {
 225         // This is a pre-JEP-223 version string
 226         def dashbIdx = jRuntimeVersion.lastIndexOf("-b")
 227         if (dashbIdx != -1) {
 228             tmpBuildNumber = jRuntimeVersion.substring(dashbIdx + 2)
 229         }
 230     } else {
 231         // This is a post-JEP-223 version string
 232         def plusIdx = jRuntimeVersion.indexOf("+")
 233         if (plusIdx != -1) {
 234             tmpBuildNumber = jRuntimeVersion.substring(plusIdx + 1)
 235         }
 236     }
 237     def jBuildNumber = tmpBuildNumber.split("[-\\+]")[0]
 238     def versionInfo = new String[2];
 239     versionInfo[0] = jVersion
 240     versionInfo[1] = jBuildNumber
 241     return versionInfo
 242 }
 243 
 244 /**
 245  * Fails the build with the specified error message
 246  *
 247  * @param msg the reason for the failure
 248  */
 249 void fail(String msg) {
 250     throw new GradleException("FAIL: " + msg);
 251 }
 252 
 253 /******************************************************************************
 254  *                                                                            *
 255  *                   Definition of project properties                         *
 256  *                                                                            *
 257  *  All properties defined using ext. are immediately available throughout    *
 258  *  the script as variables that can be used. These variables are attached    *
 259  *  to the root project (whereas if they were defined as def variables then   *
 260  *  they would only be available within the root project scope).              *
 261  *                                                                            *
 262  *  All properties defined using the "defineProperty" method can be replaced  *
 263  *  on the command line by using the -P flag. For example, to override the    *
 264  *  location of the binary plug, you would specify -PBINARY_PLUG=some/where   *
 265  *                                                                            *
 266  *****************************************************************************/
 267 
 268 // If the ../rt-closed directory exists, then we are doing a closed build.
 269 // In this case, build and property files will be read from
 270 // ../rt-closed/closed-build.gradle and ../rt-closed/closed-properties.gradle
 271 // respectively
 272 
 273 def closedDir = file("../rt-closed")
 274 def buildClosed = closedDir.isDirectory()
 275 ext.BUILD_CLOSED = buildClosed
 276 
 277 ext.RUNARGSFILE = "run.args"
 278 ext.COMPILEARGSFILE = "compile.args"
 279 ext.RUNJAVAPOLICYFILE = 'run.java.policy'
 280 
 281 ext.TESTCOMPILEARGSFILE = "testcompile.args"
 282 ext.TESTRUNARGSFILE = "testrun.args"
 283 ext.TESTJAVAPOLICYFILE = 'test.java.policy'
 284 
 285 // the file containing "extra" --add-exports
 286 ext.EXTRAADDEXPORTS = 'buildSrc/addExports'
 287 
 288 ext.MODULESOURCEPATH = "modulesourcepath.args"
 289 
 290 // These variables indicate what platform is running the build. Is
 291 // this build running on a Mac, Windows, or Linux machine? 32 or 64 bit?
 292 ext.OS_NAME = System.getProperty("os.name").toLowerCase()
 293 ext.OS_ARCH = System.getProperty("os.arch")
 294 ext.IS_64 = OS_ARCH.toLowerCase().contains("64")
 295 ext.IS_MAC = OS_NAME.contains("mac") || OS_NAME.contains("darwin")
 296 ext.IS_WINDOWS = OS_NAME.contains("windows")
 297 ext.IS_LINUX = OS_NAME.contains("linux")
 298 
 299 ext.MAVEN_GROUP_ID = "org.openjfx"
 300 
 301 // Verify that the architecture & OS are supported configurations. Note that
 302 // at present building on PI is not supported, but we would only need to make
 303 // some changes on assumptions on what should be built (like SWT / Swing) and
 304 // such and we could probably make it work.
 305 if (!IS_MAC && !IS_WINDOWS && !IS_LINUX) fail("Unsupported build OS ${OS_NAME}")
 306 if (IS_WINDOWS && OS_ARCH != "x86" && OS_ARCH != "amd64") {
 307     fail("Unknown and unsupported build architecture: $OS_ARCH")
 308 } else if (IS_MAC && OS_ARCH != "x86_64") {
 309     fail("Unknown and unsupported build architecture: $OS_ARCH")
 310 } else if (IS_LINUX && OS_ARCH != "i386" && OS_ARCH != "amd64") {
 311     fail("Unknown and unsupported build architecture: $OS_ARCH")
 312 }
 313 
 314 
 315 // Get the JDK_HOME automatically based on the version of Java used to execute gradle. Or, if specified,
 316 // use a user supplied JDK_HOME, STUB_RUNTIME, JAVAC, all of which may be specified
 317 // independently (or we'll try to get the right one based on other supplied info). Sometimes the
 318 // JRE might be the thing that is being used instead of the JRE embedded in the JDK, such as:
 319 //    c:\Program Files (x86)\Java\jdk1.8.0\jre
 320 //    c:\Program Files (x86)\Java\jre8\
 321 // Because of this, you may sometimes get the jdk's JRE (in which case the logic we used to have here
 322 // was correct and consistent with all other platforms), or it might be the standalone JRE (for the love!).
 323 def envJavaHome = cygpath(System.getenv("JDK_HOME"))
 324 if (envJavaHome == null || envJavaHome.equals("")) envJavaHome = cygpath(System.getenv("JAVA_HOME"))
 325 def javaHome = envJavaHome == null || envJavaHome.equals("") ? System.getProperty("java.home") : envJavaHome
 326 def javaHomeFile = file(javaHome)
 327 defineProperty("JDK_HOME",
 328         javaHomeFile.name == "jre" ?
 329         javaHomeFile.getParent().toString() :
 330         javaHomeFile.name.startsWith("jre") ?
 331         new File(javaHomeFile.getParent(), "jdk1.${javaHomeFile.name.substring(3)}.0").toString() :
 332         javaHome) // we have to bail and set it to something and this is as good as any!
 333 ext.JAVA_HOME = JDK_HOME
 334 
 335 defineProperty("JAVA", cygpathExe("$JDK_HOME/bin/java"))
 336 defineProperty("JAVAC", cygpathExe("$JDK_HOME/bin/javac"))
 337 defineProperty("JAVADOC", cygpathExe("$JDK_HOME/bin/javadoc"))
 338 defineProperty("JMOD", cygpathExe("$JDK_HOME/bin/jmod"))
 339 defineProperty("JDK_DOCS", "https://docs.oracle.com/javase/10/docs/api/")
 340 defineProperty("JDK_JMODS", cygpath(System.getenv("JDK_JMODS")) ?: cygpath(System.getenv("JDK_HOME") + "/jmods"))
 341 
 342 defineProperty("javaRuntimeVersion", System.getProperty("java.runtime.version"))
 343 def javaVersionInfo = parseJavaVersion(javaRuntimeVersion)
 344 defineProperty("javaVersion", javaVersionInfo[0])
 345 defineProperty("javaBuildNumber", javaVersionInfo[1])
 346 
 347 defineProperty("libAVRepositoryURL", "https://libav.org/releases/")
 348 defineProperty("FFmpegRepositoryURL", "https://www.ffmpeg.org/releases/")
 349 
 350 loadProperties("$projectDir/build.properties")
 351 
 352 def supplementalPreBuildFile = file("$closedDir/closed-pre-build.gradle");
 353 def supplementalBuildFile = file("$closedDir/closed-build.gradle");
 354 
 355 if (BUILD_CLOSED) {
 356     apply from: supplementalPreBuildFile
 357 }
 358 
 359 // GRADLE_VERSION_CHECK specifies whether to fail the build if the
 360 // gradle version check fails
 361 defineProperty("GRADLE_VERSION_CHECK", "true")
 362 ext.IS_GRADLE_VERSION_CHECK = Boolean.parseBoolean(GRADLE_VERSION_CHECK)
 363 
 364 // JFX_DEPS_URL specifies the optional location of an alternate local repository
 365 defineProperty("JFX_DEPS_URL", "")
 366 
 367 // JDK_DOCS_LINK specifies the optional URL for offline javadoc linking
 368 defineProperty("JDK_DOCS_LINK", "")
 369 
 370 // COMPILE_WEBKIT specifies whether to build all of webkit.
 371 defineProperty("COMPILE_WEBKIT", "false")
 372 ext.IS_COMPILE_WEBKIT = Boolean.parseBoolean(COMPILE_WEBKIT)
 373 
 374 // COMPILE_MEDIA specifies whether to build all of media.
 375 defineProperty("COMPILE_MEDIA", "false")
 376 ext.IS_COMPILE_MEDIA = Boolean.parseBoolean(COMPILE_MEDIA)
 377 
 378 // BUILD_LIBAV_STUBS specifies whether to download and build libav/ffmpeg libraries
 379 defineProperty("BUILD_LIBAV_STUBS", "false")
 380 ext.IS_BUILD_LIBAV_STUBS = IS_LINUX ? Boolean.parseBoolean(BUILD_LIBAV_STUBS) : false
 381 
 382 // BUILD_WORKING_LIBAV specifies whether to build libav/ffmpeg libraries with
 383 // decoder, demuxer, etc. required to run media. Valid only if BUILD_LIBAV_STUBS is true.
 384 defineProperty("BUILD_WORKING_LIBAV", "false")
 385 ext.IS_BUILD_WORKING_LIBAV = IS_LINUX ? Boolean.parseBoolean(BUILD_WORKING_LIBAV) : false
 386 
 387 // COMPILE_PANGO specifies whether to build javafx_font_pango.
 388 defineProperty("COMPILE_PANGO", "${IS_LINUX}")
 389 ext.IS_COMPILE_PANGO = Boolean.parseBoolean(COMPILE_PANGO)
 390 
 391 // COMPILE_HARFBUZZ specifies whether to use Harfbuzz.
 392 defineProperty("COMPILE_HARFBUZZ", "false")
 393 ext.IS_COMPILE_HARFBUZZ = Boolean.parseBoolean(COMPILE_HARFBUZZ)
 394 
 395 // COMPILE_PARFAIT specifies whether to build parfait
 396 defineProperty("COMPILE_PARFAIT", "false")
 397 ext.IS_COMPILE_PARFAIT = Boolean.parseBoolean(COMPILE_PARFAIT)
 398 
 399 // Define the SWT.jar that we are going to have to download during the build process based
 400 // on what platform we are compiling from (not based on our target).
 401 ext.SWT_FILE_NAME = IS_MAC ? "org.eclipse.swt.cocoa.macosx.x86_64_3.105.3.v20170228-0512" :
 402     IS_WINDOWS && IS_64 ? "org.eclipse.swt.win32.win32.x86_64_3.105.3.v20170228-0512" :
 403     IS_WINDOWS && !IS_64 ? "org.eclipse.swt.win32.win32.x86_3.105.3.v20170228-0512" :
 404     IS_LINUX && IS_64 ? "org.eclipse.swt.gtk.linux.x86_64_3.105.3.v20170228-0512" :
 405     IS_LINUX && !IS_64 ? "org.eclipse.swt.gtk.linux.x86_3.105.3.v20170228-0512" : ""
 406 
 407 // Specifies whether to run full tests (true) or smoke tests (false)
 408 defineProperty("FULL_TEST", "false")
 409 ext.IS_FULL_TEST = Boolean.parseBoolean(FULL_TEST);
 410 
 411 defineProperty("FORCE_TESTS", "false")
 412 ext.IS_FORCE_TESTS = Boolean.parseBoolean(FORCE_TESTS);
 413 
 414 // Specifies whether to run robot-based visual tests (only used when FULL_TEST is also enabled)
 415 defineProperty("USE_ROBOT", "false")
 416 ext.IS_USE_ROBOT = Boolean.parseBoolean(USE_ROBOT);
 417 
 418 // Specified whether to run tests in headless mode
 419 defineProperty("HEADLESS_TEST", "false")
 420 ext.IS_HEADLESS_TEST = Boolean.parseBoolean(HEADLESS_TEST);
 421 
 422 // Specifies whether to run system tests that depend on AWT (only used when FULL_TEST is also enabled)
 423 defineProperty("AWT_TEST", "true")
 424 ext.IS_AWT_TEST = Boolean.parseBoolean(AWT_TEST);
 425 
 426 // Specifies whether to run system tests that depend on SWT (only used when FULL_TEST is also enabled)
 427 defineProperty("SWT_TEST", "true")
 428 ext.IS_SWT_TEST = Boolean.parseBoolean(SWT_TEST);
 429 
 430 // Specifies whether to run unstable tests (true) - tests that don't run well with Hudson builds
 431 // These tests should be protected with :
 432 //    assumeTrue(Boolean.getBoolean("unstable.test"));
 433 defineProperty("UNSTABLE_TEST", "false")
 434 ext.IS_UNSTABLE_TEST = Boolean.parseBoolean(UNSTABLE_TEST);
 435 
 436 // Toggle diagnostic output from the Gradle workaround and the Sandbox test apps.
 437 defineProperty("WORKER_DEBUG", "false")
 438 ext.IS_WORKER_DEBUG = Boolean.parseBoolean(WORKER_DEBUG);
 439 
 440 // Specify the build configuration (Release, Debug, or DebugNative)
 441 defineProperty("CONF", "Debug")
 442 ext.IS_DEBUG_JAVA = CONF == "Debug" || CONF == "DebugNative"
 443 ext.IS_DEBUG_NATIVE = CONF == "DebugNative"
 444 
 445 // Defines the compiler warning levels to use. If empty, then no warnings are generated. If
 446 // not empty, then the expected syntax is as a space or comma separated list of names, such
 447 // as defined in the javac documentation.
 448 defineProperty("LINT", "none")
 449 ext.IS_LINT = LINT != "none"
 450 
 451 defineProperty("DOC_LINT", "all")
 452 ext.IS_DOC_LINT = DOC_LINT != ""
 453 
 454 // Specifies whether to use the "useDepend" option when compiling Java sources
 455 defineProperty("USE_DEPEND", "true")
 456 ext.IS_USE_DEPEND = Boolean.parseBoolean(USE_DEPEND)
 457 
 458 // Specifies whether to use the "incremental" option when compiling Java sources
 459 defineProperty("INCREMENTAL", "false")
 460 ext.IS_INCREMENTAL = Boolean.parseBoolean(INCREMENTAL)
 461 
 462 // Specifies whether to include the Null3D pipeline (for perf debugging)
 463 defineProperty("INCLUDE_NULL3D", "false")
 464 ext.IS_INCLUDE_NULL3D = Boolean.parseBoolean(INCLUDE_NULL3D)
 465 
 466 // Specifies whether to include the ES2 pipeline if available
 467 defineProperty("INCLUDE_ES2", IS_WINDOWS ? "false" : "true")
 468 ext.IS_INCLUDE_ES2 = Boolean.parseBoolean(INCLUDE_ES2)
 469 
 470 // Specifies whether to generate code coverage statistics when running tests
 471 defineProperty("JCOV", "false")
 472 ext.DO_JCOV = Boolean.parseBoolean(JCOV)
 473 
 474 // Define the number of threads to use when compiling (specifically for native compilation)
 475 // On Mac we limit it to 1 by default due to problems running gcc in parallel
 476 if (IS_MAC) {
 477     defineProperty("NUM_COMPILE_THREADS", "1")
 478 } else {
 479     defineProperty("NUM_COMPILE_THREADS", "${Runtime.runtime.availableProcessors()}")
 480 }
 481 
 482 //
 483 // The next three sections of properties are used to generate the
 484 // VersionInfo class, and the Windows DLL manifest.
 485 //
 486 
 487 // The following properties should be left alone by developers and set only from Hudson.
 488 defineProperty("HUDSON_JOB_NAME", "not_hudson")
 489 defineProperty("HUDSON_BUILD_NUMBER","0000")
 490 defineProperty("PROMOTED_BUILD_NUMBER", "0")
 491 defineProperty("MILESTONE_FCS", "false")
 492 ext.IS_MILESTONE_FCS = Boolean.parseBoolean(MILESTONE_FCS)
 493 
 494 // The following properties define the product name for Oracle JDK and OpenJDK
 495 // for VersionInfo and the DLL manifest.
 496 if (BUILD_CLOSED) {
 497     defineProperty("PRODUCT_NAME", "Java(TM)")
 498     defineProperty("COMPANY_NAME", "Oracle Corporation")
 499     defineProperty("PLATFORM_NAME", "Platform SE")
 500 } else {
 501     defineProperty("PRODUCT_NAME", "OpenJFX")
 502     defineProperty("COMPANY_NAME", "N/A")
 503     defineProperty("PLATFORM_NAME", "Platform")
 504 }
 505 
 506 // The following properties are set based on properties defined in
 507 // build.properties. The release version and suffix should be updated
 508 // in that file.
 509 def relVer = 0
 510 if (jfxReleasePatchVersion == "0") {
 511     if (jfxReleaseSecurityVersion == "0") {
 512         if (jfxReleaseMinorVersion == "0") {
 513             relVer = "${jfxReleaseMajorVersion}"
 514         } else {
 515             relVer = "${jfxReleaseMajorVersion}.${jfxReleaseMinorVersion}"
 516         }
 517     } else {
 518         relVer = "${jfxReleaseMajorVersion}.${jfxReleaseMinorVersion}.${jfxReleaseSecurityVersion}"
 519     }
 520 } else {
 521     relVer = "${jfxReleaseMajorVersion}.${jfxReleaseMinorVersion}.${jfxReleaseSecurityVersion}.${jfxReleasePatchVersion}"
 522 }
 523 defineProperty("RELEASE_VERSION", relVer)
 524 defineProperty("RELEASE_VERSION_PADDED", "${jfxReleaseMajorVersion}.${jfxReleaseMinorVersion}.${jfxReleaseSecurityVersion}.${jfxReleasePatchVersion}")
 525 
 526 def buildDate = new java.util.Date()
 527 def buildTimestamp = new java.text.SimpleDateFormat("yyyy-MM-dd-HHmmss").format(buildDate)
 528 defineProperty("BUILD_TIMESTAMP", buildTimestamp)
 529 def relSuffix = ""
 530 def relOpt = ""
 531 if (HUDSON_JOB_NAME == "not_hudson") {
 532     relSuffix = "-internal"
 533     relOpt = "-${buildTimestamp}"
 534 } else {
 535     relSuffix = IS_MILESTONE_FCS ? "" : jfxReleaseSuffix
 536 }
 537 defineProperty("RELEASE_SUFFIX", relSuffix)
 538 defineProperty("RELEASE_VERSION_SHORT", "${RELEASE_VERSION}${RELEASE_SUFFIX}")
 539 defineProperty("RELEASE_VERSION_LONG", "${RELEASE_VERSION_SHORT}+${PROMOTED_BUILD_NUMBER}${relOpt}")
 540 defineProperty("MAVEN_VERSION", "$RELEASE_VERSION_LONG")
 541 
 542 // Check whether the COMPILE_TARGETS property has been specified (if so, it was done by
 543 // the user and not by this script). If it has not been defined then default
 544 // to building the normal desktop build for this machine
 545 project.ext.set("defaultHostTarget", IS_MAC ? "mac" : IS_WINDOWS ? "win" : IS_LINUX ? "linux" : "");
 546 defineProperty("COMPILE_TARGETS", "$defaultHostTarget")
 547 
 548 // Flag indicating whether to import cross compile tools
 549 def importCrossTools = false
 550 if (hasProperty("IMPORT_CROSS_TOOLS")) {
 551     importCrossTools = Boolean.parseBoolean(IMPORT_CROSS_TOOLS);
 552 }
 553 ext.IS_IMPORT_CROSS_TOOLS = importCrossTools
 554 
 555 // Location of the cross compile tools
 556 def crossToolsDir = "../crosslibs"
 557 if (hasProperty("CROSS_TOOLS_DIR")) {
 558     crossToolsDir = CROSS_TOOLS_DIR
 559 }
 560 ext.CROSS_TOOLS_DIR = file(crossToolsDir)
 561 
 562 // Specifies whether to run tests with the existing javafx.* modules instead of compiling a new one
 563 defineProperty("BUILD_SDK_FOR_TEST", "true")
 564 ext.DO_BUILD_SDK_FOR_TEST = Boolean.parseBoolean(BUILD_SDK_FOR_TEST)
 565 
 566 // All "classes" and "jar" tasks and their dependencies would be disabled
 567 // when running with DO_BUILD_SDK_FOR_TEST=false as they're unneeded for running tests
 568 if (!DO_BUILD_SDK_FOR_TEST) {
 569     gradle.taskGraph.useFilter({ task -> !task.name.equals("classes") && !task.name.equals("jar") })
 570 }
 571 
 572 // Make sure JDK_HOME/bin/java exists
 573 if (!file(JAVA).exists()) throw new Exception("Missing or incorrect path to 'java': '$JAVA'. Perhaps bad JDK_HOME? $JDK_HOME")
 574 if (!file(JAVAC).exists()) throw new Exception("Missing or incorrect path to 'javac': '$JAVAC'. Perhaps bad JDK_HOME? $JDK_HOME")
 575 if (!file(JAVADOC).exists()) throw new Exception("Missing or incorrect path to 'javadoc': '$JAVADOC'. Perhaps bad JDK_HOME? $JDK_HOME")
 576 
 577 // Determine the verion of Java in JDK_HOME. It looks like this:
 578 //
 579 // $ java -version
 580 // java version "1.7.0_45"
 581 // Java(TM) SE Runtime Environment (build 1.7.0_45-b18)
 582 // Java HotSpot(TM) 64-Bit Server VM (build 24.45-b08, mixed mode)
 583 //
 584 // We need to parse the second line
 585 def inStream = new java.io.BufferedReader(new java.io.InputStreamReader(new java.lang.ProcessBuilder(JAVA, "-fullversion").start().getErrorStream()));
 586 try {
 587     String v = inStream.readLine().trim();
 588     if (v != null) {
 589         int ib = v.indexOf("full version \"");
 590         if (ib != -1) {
 591             String str = v.substring(ib);
 592             String ver = str.substring(str.indexOf("\"") + 1, str.size() - 1);
 593 
 594             defineProperty("jdkRuntimeVersion", ver)
 595             def jdkVersionInfo = parseJavaVersion(ver)
 596             defineProperty("jdkVersion", jdkVersionInfo[0])
 597             defineProperty("jdkBuildNumber", jdkVersionInfo[1])
 598         }
 599     }
 600 } finally {
 601     inStream.close();
 602 }
 603 if (!project.hasProperty("jdkRuntimeVersion")) throw new Exception("Unable to determine the version of Java in JDK_HOME at $JDK_HOME");
 604 
 605 
 606 // Determine whether the javafx.* modules are present in the JDK. To do this,
 607 // we will execute "java --list-modules" and search for javafx.base.
 608 // Also, check if jdk.unsupported.desktop module is present in JDK to ensure 
 609 // javafx.swing do not use internal JDK classes directly.
 610 ext.HAS_JAVAFX_MODULES = false;
 611 ext.HAS_UNSUPPORTED_DESKTOP = false;
 612 def inStream2 = new java.io.BufferedReader(new java.io.InputStreamReader(new java.lang.ProcessBuilder(JAVA, "--list-modules").start().getInputStream()));
 613 try {
 614     String v;
 615     while ((v = inStream2.readLine()) != null) {
 616         v = v.trim();
 617         if (v.startsWith("javafx.base")) ext.HAS_JAVAFX_MODULES = true;
 618         if (v.startsWith("jdk.unsupported.desktop")) ext.HAS_UNSUPPORTED_DESKTOP = true;
 619     }
 620 } finally {
 621     inStream2.close();
 622 }
 623 
 624 // The HAS_JAVAFX_MODULES flag will be used to determine the mode for building
 625 // and running the applications and tests.
 626 // If HAS_JAVAFX_MODULES is true, then we will build / test javafx modules
 627 // for exporting to a JDK build. If HAS_JAVAFX_MODULES is false, then we will
 628 // build / test a standalone sdk for running with a JDK that does not include
 629 // the javafx modules.
 630 
 631 
 632 /**
 633  * Fetch/Check that external tools are present for the build. This method
 634  * will conditionally download the packages from project defined ivy repositories
 635  * and unpack them into the specified destdir
 636  *
 637  * @param configName A unique name to distinguish the configuration (ie "ARMSFV6")
 638  * @param packages A list of required packages (with extensions .tgz, .zip)
 639  * @param destdir where the packages should be unpacked
 640  * @param doFetch if true, the named packages will be download
 641  */
 642 void fetchExternalTools(String configName, List packages, File destdir, boolean doFetch) {
 643     if (doFetch) {
 644         // create a unique configuration for this fetch
 645         def String fetchToolsConfig = "fetchTools$configName"
 646         rootProject.configurations.create(fetchToolsConfig)
 647 
 648         def List<String> fetchedPackages = []
 649         def int fetchCount = 0
 650 
 651         packages.each { pkgname->
 652             def int dotdex = pkgname.lastIndexOf('.')
 653             def int dashdex = pkgname.lastIndexOf('-')
 654             def String basename = pkgname.substring(0,dashdex)
 655             def String ver = pkgname.substring(dashdex+1,dotdex)
 656             def String ext = pkgname.substring(dotdex+1)
 657             def File pkgdir = file("$destdir/$basename-$ver")
 658 
 659             if (!pkgdir.isDirectory()) {
 660                 rootProject.dependencies.add(fetchToolsConfig, "javafx:$basename:$ver", {
 661                     artifact {
 662                         name = basename
 663                         type = ext
 664                     }
 665                 })
 666                 println "adding $pkgname as a downloadable item did not find $pkgdir"
 667                 fetchedPackages.add(pkgname)
 668                 fetchCount++
 669             }
 670         }
 671 
 672         //fetch all the missing packages
 673         if (fetchedPackages.size > 0) {
 674             destdir.mkdirs()
 675 
 676             logger.quiet "fetching missing packages $fetchedPackages"
 677             copy {
 678                 from rootProject.configurations[fetchToolsConfig]
 679                 into destdir
 680             }
 681 
 682             // unpack the fetched packages
 683             fetchedPackages.each { pkgname->
 684                 logger.quiet "expanding the package $pkgname"
 685                 def srcball = file("${destdir}/${pkgname}")
 686 
 687                 if (!srcball.exists()) {
 688                     throw new GradleException("Failed to fetch $pkgname");
 689                 }
 690 
 691                 def String basename = pkgname.substring(0,pkgname.lastIndexOf("."))
 692                 def File pkgdir = file("$destdir/$basename")
 693 
 694                 if (pkgname.endsWith(".tgz")) {
 695                     if (IS_LINUX || IS_MAC) {
 696                         // use native tar to support symlinks
 697                         pkgdir.mkdirs()
 698                         exec {
 699                             workingDir pkgdir
 700                             commandLine "tar", "zxf", "${srcball}"
 701                          }
 702                     } else {
 703                         copy {
 704                             from tarTree(resources.gzip("${srcball}"))
 705                             into pkgdir
 706                         }
 707                     }
 708                 } else if (pkgname.endsWith(".zip")) {
 709                      copy {
 710                          from zipTree("${srcball}")
 711                          into pkgdir
 712                      }
 713                 } else {
 714                     throw new GradleException("Unhandled package type for compile package ${pkgname}")
 715                 }
 716                 srcball.deleteOnExit();
 717             }
 718         } else {
 719             logger.quiet "all tool packages are present $packages"
 720         }
 721     } else { // !doFetch - so just check they are present
 722         // check that all the dirs are really there
 723         def List<String> errors = []
 724         packages.each { pkgname->
 725             def String basename = pkgname.substring(0,pkgname.lastIndexOf("."))
 726             def File pkgdir = file("$destdir/$basename")
 727 
 728             if (!pkgdir.isDirectory()) {
 729                 errors.add(pkgname)
 730             }
 731         }
 732         if (errors.size > 0) {
 733             throw new GradleException("Error: missing tool packages: $errors")
 734         } else {
 735             logger.quiet "all tool packages are present $packages"
 736         }
 737     }
 738 }
 739 
 740 // Make a forked ANT call.
 741 // This needs to be forked so that ant can be used with the right JDK and updated modules
 742 // for testing obscure things like packaging of apps
 743 void ant(String conf,   // platform configuration
 744          String dir,    // directory to run from
 745          String target, // ant target
 746          List<String>  params // parameters (usually -Dxxx=yyy)
 747          ) {
 748     // Try to use ANT_HOME
 749     String antHomeEnv = System.getenv("ANT_HOME")
 750     String antHome = antHomeEnv != null ? cygpath(antHomeEnv) : null;
 751     String ant = (antHome != null && !antHome.equals("")) ? "$antHome/bin/ant" : "ant";
 752 
 753     exec {
 754         workingDir = dir
 755         environment("JDK_HOME", JDK_HOME)
 756         environment("JAVA_HOME", JDK_HOME)
 757         if (IS_WINDOWS) {
 758             environment([
 759                     "VCINSTALLDIR"         : WINDOWS_VS_VCINSTALLDIR,
 760                     "VSINSTALLDIR"         : WINDOWS_VS_VSINSTALLDIR,
 761                     "DEVENVDIR"            : WINDOWS_VS_DEVENVDIR,
 762                     "MSVCDIR"              : WINDOWS_VS_MSVCDIR,
 763                     "INCLUDE"              : WINDOWS_VS_INCLUDE,
 764                     "LIB"                  : WINDOWS_VS_LIB,
 765                     "LIBPATH"              : WINDOWS_VS_LIBPATH,
 766                     "DXSDK_DIR"            : WINDOWS_DXSDK_DIR
 767             ]);
 768             commandLine "cmd", "/c", ant, "-Dbuild.compiler=javac1.7"
 769         } else {
 770             commandLine ant, "-Dbuild.compiler=javac1.7"
 771         }
 772         if ((conf != null) && !rootProject.defaultHostTarget.equals(conf)) {
 773             def targetProperties = rootProject.ext[conf.trim().toUpperCase()]
 774             args("-Dcross.platform=$conf")
 775             if (targetProperties.containsKey('arch')) {
 776                 args("-Dcross.platform.arch=${targetProperties.arch}")
 777             }
 778         }
 779         if (params != null) {
 780             params.each() { s->
 781                 args(s)
 782             }
 783         }
 784         if (IS_MILESTONE_FCS) {
 785             args('-Djfx.release.suffix=""')
 786         }
 787         args(target);
 788     }
 789 }
 790 
 791 List<String> computeLibraryPath(boolean working) {
 792     List<String> lp = []
 793 
 794     if (HAS_JAVAFX_MODULES) {
 795         List<String> modsWithNative = [ 'graphics', 'media', 'web' ]
 796 
 797         // the build/modular-sdk area
 798         def platformPrefix = ""
 799         def bundledSdkDirName = "${platformPrefix}modular-sdk"
 800         def bundledSdkDir = "${rootProject.buildDir}/${bundledSdkDirName}"
 801         def modulesLibsDir = "${bundledSdkDir}/modules_libs"
 802 
 803         modsWithNative.each() { m ->
 804             lp << cygpath("${modulesLibsDir}/javafx.${m}")
 805         }
 806     } else {
 807         def platformPrefix = ""
 808         def standaloneSdkDirName = "${platformPrefix}sdk"
 809         def standaloneSdkDir = "${rootProject.buildDir}/${standaloneSdkDirName}"
 810         def modulesLibName = IS_WINDOWS ? "bin" : "lib"
 811         def modulesLibsDir = "${standaloneSdkDir}/${modulesLibName}"
 812         lp << cygpath("${modulesLibsDir}")
 813     }
 814 
 815     return lp
 816 }
 817 
 818 // Return list with the arguments needed for --patch-module or --module-path
 819 // for the provided projects. Used with Java executables ie. tests
 820 List<String> computePatchModuleArgs(List<String> deps, boolean test, boolean includeJLP) {
 821     List<String> pma = []
 822 
 823     if (HAS_JAVAFX_MODULES) {
 824         deps.each { String projname ->
 825             def proj = project(projname)
 826             if (proj.hasProperty("moduleName")) {
 827                 File dir;
 828                 if (test && proj.sourceSets.hasProperty('shims')) {
 829                     dir = file("${rootProject.buildDir}/shims")
 830                 } else {
 831                     dir = file("${rootProject.buildDir}/modular-sdk/modules")
 832                 }
 833                 String moduleName = proj.ext.moduleName
 834                 String dirpath = cygpath("${dir}/${moduleName}")
 835                 pma += "--patch-module=${moduleName}=${dirpath}"
 836             }
 837         }
 838     } else {
 839         String mp = null
 840         deps.each { String projname ->
 841             def proj = project(projname)
 842             if (proj.hasProperty("moduleName")) {
 843                 String moduleName = proj.ext.moduleName
 844                 File dir;
 845                 if (test && proj.sourceSets.hasProperty('shims')) {
 846                     dir = file("${rootProject.buildDir}/shims/${moduleName}")
 847                 } else {
 848                     dir = file("${rootProject.buildDir}/sdk/lib/${moduleName}.jar")
 849                 }
 850                 if (mp == null) {
 851                     mp = dir.path
 852                 } else {
 853                     mp = mp + File.pathSeparator + dir.path
 854                 }
 855             }
 856         }
 857 
 858         // in some cases like base we could end up with an empty
 859         // path... make sure we don't pass one back
 860         if (mp == null) {
 861             return null
 862         }
 863 
 864         pma += '--module-path'
 865         pma += mp
 866 
 867         String addm = null
 868         deps.each {String projname ->
 869             def proj = project(projname)
 870             if (proj.hasProperty("moduleName") && proj.buildModule) {
 871                 if (addm == null) {
 872                     addm = proj.moduleName
 873                 } else {
 874                     addm = addm + "," + proj.moduleName
 875                 }
 876             }
 877         }
 878         if (addm != null) {
 879             pma += "--add-modules=${addm}"
 880         }
 881     }
 882 
 883     if (includeJLP) {
 884         pma += "-Djava.library.path=" + computeLibraryPath(true).join(File.pathSeparator)
 885     }
 886 
 887     return pma
 888 }
 889 
 890 // Return a list containing the --upgrade-module-path or --module-path
 891 // used with Javac
 892 List<String> computeModulePathArgs(String  pname, List<String> deps, boolean test) {
 893     List<String> mpa = HAS_JAVAFX_MODULES ? [ '--upgrade-module-path' ] : [ '--module-path' ]
 894     String mp = null
 895     deps.each { String projname ->
 896         def proj = project(projname)
 897         // for a non test set of args, we don't want the current module in the list
 898         // for a test test, we do need it to update what we built
 899 
 900         if (proj.hasProperty("moduleName") &&
 901                 proj.buildModule &&
 902                 !(!test && proj.name.equals(pname))) {
 903 
 904             File dir;
 905             if (test && proj.sourceSets.hasProperty('shims')) {
 906                 dir = new File(proj.sourceSets.shims.java.outputDir, proj.ext.moduleName);
 907             } else {
 908                 dir = new File(proj.sourceSets.main.java.outputDir, proj.ext.moduleName);
 909             }
 910             if (mp == null) {
 911                 mp = dir.path
 912             } else {
 913                 mp = mp + File.pathSeparator + dir.path
 914             }
 915         }
 916     }
 917 
 918     // in some cases like base we could end up with an empty
 919     // path... make sure we don't pass one back
 920     if (mp == null) {
 921         return null
 922     }
 923 
 924     mpa += mp
 925 
 926     if (!HAS_JAVAFX_MODULES) {
 927         String addm = null
 928         deps.each {String projname ->
 929             def proj = project(projname)
 930             // for a non test set of args, we don't want the current module in the list
 931             // for a test test, we do need it to update what we built
 932 
 933             if (proj.hasProperty("moduleName") &&
 934                     proj.buildModule &&
 935                     !(!test && proj.name.equals(pname))) {
 936 
 937                 if (addm == null) {
 938                     addm = proj.moduleName
 939                 } else {
 940                     addm = addm + "," + proj.moduleName
 941                 }
 942             }
 943         }
 944         if (addm != null) {
 945             mpa += "--add-modules=${addm}"
 946         }
 947     }
 948 
 949     return mpa
 950 }
 951 
 952 
 953 void writeRunArgsFile(File dest, List<String> libpath, List<String> modpath, List<String> modules) {
 954 
 955     dest.delete()
 956 
 957     logger.info("Creating file ${dest.path}")
 958 
 959     if (libpath != null) {
 960         dest <<  "-Djava.library.path=\"\\\n"
 961         libpath.each() { e->
 962             dest << "  "
 963             dest << e
 964             dest << File.pathSeparator
 965             dest << "\\\n"
 966         }
 967         dest <<  "  \"\n"
 968     }
 969 
 970     if (HAS_JAVAFX_MODULES) {
 971         modpath.each { e ->
 972             dest <<  "--patch-module=\""
 973             dest << e
 974             dest << "\"\n"
 975         }
 976     } else {
 977         if (modpath.size() == 1) {
 978             dest <<  "--module-path=\""
 979             dest << modpath[0]
 980             dest << "\"\n"
 981         } else {
 982             dest <<  "--module-path=\"\\\n"
 983             modpath.each() { e->
 984                 dest << "  "
 985                 dest << e
 986                 dest << File.pathSeparator
 987                 dest << "\\\n"
 988             }
 989             dest <<  "  \"\n"
 990         }
 991     }
 992 
 993     if (modules != null) {
 994         dest <<  "--add-modules="
 995         dest << modules.join(",")
 996         dest << "\n"
 997     }
 998 }
 999 
1000 void appendQualExports(File dest, List<String> qualExports) {
1001     qualExports.each { exp ->
1002         dest << exp
1003         dest << "\n"
1004     }
1005 }
1006 
1007 // perform common project manipulation for modules
1008 void commonModuleSetup(Project p, List<String> moduleChain) {
1009 
1010     p.ext.moduleChain = moduleChain
1011 
1012     if (p.hasProperty("moduleName")) {
1013         p.ext.moduleDir = new File (p.sourceSets.main.java.outputDir, "${p.moduleName}")
1014         if (p.sourceSets.hasProperty('shims')) {
1015             p.ext.moduleShimsDir = new File (p.sourceSets.shims.java.outputDir, "${p.moduleName}")
1016         }
1017     }
1018 
1019     def mpa = computeModulePathArgs(p.name, moduleChain, false)
1020     if (mpa != null) {
1021         p.ext.modulePathArgs = mpa
1022     }
1023 
1024     p.ext.testModulePathArgs = computePatchModuleArgs(moduleChain, true, false)
1025     p.ext.patchModuleArgs = computePatchModuleArgs(moduleChain ,false, true)
1026     p.ext.testPatchModuleArgs = computePatchModuleArgs(moduleChain, true, true)
1027 
1028     moduleChain.each() {e ->
1029         if (!e.equals(p.name)) {
1030             p.compileJava.dependsOn(project(e).classes)
1031             p.compileTestJava.dependsOn(project(e).testClasses)
1032         }
1033     }
1034 
1035     // read in any addExports file
1036     File addExportsFile = new File(p.projectDir,"src/test/addExports")
1037     if (addExportsFile.exists()) {
1038         List<String> ae = []
1039         addExportsFile.eachLine { line ->
1040             line = line.trim()
1041             if (!(line.startsWith("#") || line.equals(""))) {
1042                 ae += line.split(' ')
1043             }
1044         }
1045         p.ext.testAddExports  = ae.flatten()
1046     }
1047 
1048     // read in the temporary addExports file EXTRAADDEXPORTS)
1049     //
1050     // These extra --add-exports will be used in two places and so we
1051     // create/modify two items:
1052     // p.testAddExports - add the extra items so they are included in test builds
1053     //
1054     // p.extraAddExports - for use in any other place where we don't automatically update
1055     //    for example any non modular, non 'test' compile, any compile that does not
1056     //    use a module-source-path that includes the dependent modules
1057     //
1058     // Note that we don't modify the modular build (main, shims) because they use
1059     // module-info directly, and we don't want to cover up any missing items there.
1060     //
1061     if (!rootProject.hasProperty("EXTRA_ADDEXPORTS_ARGS")) {
1062         List<String> extraAddExportsList = []
1063         String fullae = ""
1064         File tmpaddExportsFile = new File(rootProject.projectDir, EXTRAADDEXPORTS)
1065         if (tmpaddExportsFile.exists()) {
1066             String nl = System.getProperty("line.separator")
1067             tmpaddExportsFile.eachLine { line ->
1068                 line = line.trim()
1069                 fullae += line + nl
1070                 if (!(line.startsWith("#") || line.equals(""))) {
1071                     extraAddExportsList += line.split(' ')
1072                 }
1073             }
1074         }
1075         // This string is used in the creation of the build/*.args files
1076         // so we preserve comments
1077         if (!extraAddExportsList.isEmpty()) {
1078             rootProject.ext.EXTRA_ADDEXPORTS_STRING = fullae
1079         }
1080         rootProject.ext.EXTRA_ADDEXPORTS_ARGS = extraAddExportsList
1081     }
1082 
1083     if (HAS_JAVAFX_MODULES) {
1084         // use this variable, because it shows we have a non empty addition
1085         if (rootProject.hasProperty("EXTRA_ADDEXPORTS_STRING")) {
1086             p.ext.extraAddExports = EXTRA_ADDEXPORTS_ARGS.flatten()
1087             if (p.hasProperty("testAddExports")) {
1088                 p.testAddExports += EXTRA_ADDEXPORTS_ARGS.flatten()
1089             }
1090         }
1091     }
1092 }
1093 
1094 // Now we need to define the native compilation tasks. The set of parameters to
1095 // native compilation depends on the target platform (and also to some extent what platform
1096 // you are compiling on). These settings are contained in various gradle files
1097 // such as mac.gradle and linux.gradle and armhf.gradle. Additionally, the developer
1098 // can specify COMPILE_FLAGS_FILE to be a URL or path to a different gradle file
1099 // that will contain the appropriate flags.
1100 defineProperty("COMPILE_FLAGS_FILES", COMPILE_TARGETS.split(",").collect {"buildSrc/${it.trim()}.gradle"}.join(","))
1101 if (COMPILE_TARGETS == "all") {
1102     def tmp = []
1103     File buildSrcDir = file("buildSrc")
1104     buildSrcDir.listFiles().each { File f ->
1105         if (f.isFile() && f.name.endsWith(".gradle") && !f.name.equals("build.gradle")) {
1106             def target = f.name.substring(0, f.name.lastIndexOf('.gradle')).toUpperCase(Locale.ROOT)
1107             apply from: f
1108             if (project.ext["${target}"].canBuild) {
1109                 tmp.add(target)
1110             }
1111         }
1112     }
1113     COMPILE_FLAGS_FILES = tmp.collect { "buildSrc/${it}.gradle"}.join(",")
1114     COMPILE_TARGETS = tmp.collect { "${it.toLowerCase()}"}.join(",")
1115 } else {
1116     COMPILE_FLAGS_FILES.split(",").each {
1117         logger.info("Applying COMPILE_FLAGS_FILE '$it'")
1118         apply from: it
1119     }
1120 }
1121 
1122 if (COMPILE_TARGETS != "") {
1123     def tmp = []
1124     COMPILE_TARGETS.split(",").each {target ->
1125         if (project.ext["${target.toUpperCase(Locale.ROOT)}"].canBuild) {
1126             tmp.add(target)
1127         }
1128     }
1129     COMPILE_TARGETS = tmp.collect { "${it.toLowerCase()}"}.join(",")
1130 }
1131 
1132 // Sanity check the expected properties all exist
1133 compileTargets { t ->
1134     // Every platform must define these variables
1135     if (!project.hasProperty(t.upper)) throw new Exception("ERROR: Incorrectly configured compile flags file, missing ${t.name} property")
1136     def props = project.ext[t.upper];
1137     // TODO: we could remove libDest in favor of modLibDest
1138     ["compileSwing", "compileSWT", "libDest"].each { prop ->
1139         if (!props.containsKey(prop)) throw new Exception("ERROR: Incorrectly configured compile flags file, missing ${prop} property on ${t.name}")
1140     }
1141 }
1142 
1143 // Various build flags may be set by the different target files, such as
1144 // whether to build Swing, SWT, etc. We iterate over all
1145 // compile targets and look for these settings in our properties. Note that
1146 // these properties cannot be set from the command line, but are set by
1147 // the target build files such as armv6hf.gradle or mac.gradle.
1148 ext.COMPILE_SWING = false;
1149 ext.COMPILE_SWT = false;
1150 compileTargets { t ->
1151     def targetProperties = project.rootProject.ext[t.upper]
1152 
1153     if (targetProperties.compileSwing) COMPILE_SWING = true
1154     if (targetProperties.compileSWT) COMPILE_SWT = true
1155 
1156     if (!targetProperties.containsKey('compileWebnodeNative')) {
1157         // unless specified otherwise, we will compile native Webnode if IS_COMPILE_WEBKIT
1158         targetProperties.compileWebnodeNative = true
1159     }
1160 
1161     if (!targetProperties.containsKey('compileMediaNative')) {
1162         // unless specified otherwise, we will compile native Media if IS_COMPILE_MEDIA
1163         targetProperties.compileMediaNative = true
1164     }
1165 
1166     if (!targetProperties.containsKey('includeSWT')) targetProperties.includeSWT = true
1167     if (!targetProperties.containsKey('includeSwing')) targetProperties.includeSwing = true
1168     if (!targetProperties.containsKey('includeNull3d')) targetProperties.includeNull3d = true
1169     if (!targetProperties.containsKey('includeMonocle')) targetProperties.includeMonocle = false
1170     if (!targetProperties.containsKey('includeEGL')) targetProperties.includeEGL = false
1171 
1172     if (!targetProperties.containsKey('includeGTK')) targetProperties.includeGTK = IS_LINUX
1173 
1174     if (!targetProperties.containsKey('modLibDest')) targetProperties.modLibDest = targetProperties.libDest
1175 
1176     // This value is used as a prefix for various directories under ./build,
1177     // such as sdk, to allow for a common name for the hosted build
1178     // (for use when building apps) and a unique name for cross builds.
1179     if (rootProject.defaultHostTarget.equals(t.name)) {
1180         // use a simple common default for the "host" build
1181         targetProperties.platformPrefix=""
1182     } else {
1183         // and a more complex one for cross builds
1184         targetProperties.platformPrefix="${t.name}-"
1185     }
1186 }
1187 
1188 /******************************************************************************
1189  *                                                                            *
1190  *                         Build Setup Sanity Checks                          *
1191  *                                                                            *
1192  *  Here we do a variety of checks so that if the version of Java you are     *
1193  *  building with is misconfigured, or you are using the wrong version of     *
1194  *  gradle, etc you will get some kind of helpful error / warning message     *
1195  *                                                                            *
1196  *****************************************************************************/
1197 
1198 // Sanity check that we actually have a list of compile targets to execute
1199 if (COMPILE_TARGETS == null || COMPILE_TARGETS == "") {
1200     throw new Exception("Unable to determine compilation platform, must specify valid COMPILE_TARGETS!")
1201 }
1202 
1203 // Verify that CONF is something useful
1204 if (CONF != "Release" && CONF != "Debug" && CONF != "DebugNative") {
1205     logger.warn("Unknown configuration CONF='$CONF'. Treating as 'Release'")
1206 }
1207 
1208 // If the number of compile threads is less than 1 then we have a problem!
1209 if (Integer.parseInt(NUM_COMPILE_THREADS.toString()) < 1) {
1210     logger.warn("NUM_COMPILE_THREADS was specified as '$NUM_COMPILE_THREADS' which is less than the minimum value of 1. " +
1211             "Building with a value of 1 instead.")
1212     NUM_COMPILE_THREADS = 1
1213 }
1214 
1215 // Check for Gradle 4.8, error if < 4.3.
1216 if (gradle.gradleVersion != "4.8") {
1217     def ver = gradle.gradleVersion.split("[\\.]");
1218     def gradleMajor = Integer.parseInt(ver[0]);
1219     def gradleMinor = Integer.parseInt(ver[1].split("[^0-9]")[0]);
1220     def err = "";
1221     if (gradleMajor < 4 || (gradleMajor == 4 && gradleMinor < 3)) {
1222         err = "Gradle version too old: ${gradle.gradleVersion}; must be at least 4.3"
1223     }
1224 
1225     if (IS_GRADLE_VERSION_CHECK && err != "") {
1226         fail(err);
1227     }
1228 
1229     logger.warn("*****************************************************************");
1230     logger.warn("Unsupported gradle version $gradle.gradleVersion in use.");
1231     logger.warn("Only version 4.8 is supported. Use this version at your own risk");
1232     if ( err != "") logger.warn(err);
1233     logger.warn("*****************************************************************");
1234 }
1235 
1236 // Look for stub runtime in bundled sdk, standalone sdk, or boot JDK
1237 
1238 def String cachedBundledRuntime = cygpath("$projectDir") + "/../caches/modular-sdk"
1239 def String cachedStandaloneRuntime = cygpath("$projectDir") + "/../caches/sdk"
1240 def String jdkStubRuntime = cygpath("$JDK_HOME")
1241 
1242 def defaultStubRuntime = ""
1243 if (file(cachedBundledRuntime).exists()) {
1244     defaultStubRuntime = cachedBundledRuntime
1245 } else if (file(cachedStandaloneRuntime).exists()) {
1246     defaultStubRuntime = cachedStandaloneRuntime
1247 } else if (BUILD_CLOSED) {
1248     defaultStubRuntime = cachedBundledRuntime
1249 } else {
1250     defaultStubRuntime = jdkStubRuntime
1251 }
1252 
1253 defineProperty("STUB_RUNTIME", defaultStubRuntime)
1254 
1255 if (STUB_RUNTIME.endsWith("/modular-sdk")) {
1256     def stubModulesLib = "$STUB_RUNTIME/modules_libs"
1257     defineProperty("MEDIA_STUB", "$stubModulesLib/javafx.media")
1258     defineProperty("WEB_STUB", "$stubModulesLib/javafx.web")
1259 } else {
1260     def libraryStub = IS_WINDOWS ? "$STUB_RUNTIME/bin" : "$STUB_RUNTIME/lib"
1261 
1262     defineProperty("MEDIA_STUB", libraryStub)
1263     defineProperty("WEB_STUB", libraryStub)
1264 }
1265 
1266 ext.UPDATE_STUB_CACHE = (BUILD_CLOSED && STUB_RUNTIME != "" && !file(STUB_RUNTIME).isDirectory())
1267 
1268 
1269 /******************************************************************************
1270  *                                                                            *
1271  *                      Logging of Properties and Settings                    *
1272  *                                                                            *
1273  *  Log some of the settings we've determined. We could log more here, it     *
1274  *  doesn't really hurt.                                                      *
1275  *                                                                            *
1276  *****************************************************************************/
1277 
1278 logger.quiet("gradle.gradleVersion: $gradle.gradleVersion")
1279 logger.quiet("OS_NAME: $OS_NAME")
1280 logger.quiet("OS_ARCH: $OS_ARCH")
1281 logger.quiet("JAVA_HOME: $JAVA_HOME")
1282 logger.quiet("JDK_HOME: $JDK_HOME")
1283 logger.quiet("java.runtime.version: ${javaRuntimeVersion}")
1284 logger.quiet("java version: ${javaVersion}")
1285 logger.quiet("java build number: ${javaBuildNumber}")
1286 logger.quiet("jdk.runtime.version: ${jdkRuntimeVersion}")
1287 logger.quiet("jdk version: ${jdkVersion}")
1288 logger.quiet("jdk build number: ${jdkBuildNumber}")
1289 logger.quiet("minimum jdk version: ${jfxBuildJdkVersionMin}")
1290 logger.quiet("minimum jdk build number: ${jfxBuildJdkBuildnumMin}")
1291 logger.quiet("HAS_JAVAFX_MODULES: $HAS_JAVAFX_MODULES")
1292 logger.quiet("HAS_UNSUPPORTED_DESKTOP: $HAS_UNSUPPORTED_DESKTOP")
1293 logger.quiet("STUB_RUNTIME: $STUB_RUNTIME")
1294 logger.quiet("CONF: $CONF")
1295 logger.quiet("NUM_COMPILE_THREADS: $NUM_COMPILE_THREADS")
1296 logger.quiet("COMPILE_TARGETS: $COMPILE_TARGETS")
1297 logger.quiet("COMPILE_FLAGS_FILES: $COMPILE_FLAGS_FILES")
1298 logger.quiet("HUDSON_JOB_NAME: $HUDSON_JOB_NAME")
1299 logger.quiet("HUDSON_BUILD_NUMBER: $HUDSON_BUILD_NUMBER")
1300 logger.quiet("PROMOTED_BUILD_NUMBER: $PROMOTED_BUILD_NUMBER")
1301 logger.quiet("PRODUCT_NAME: $PRODUCT_NAME")
1302 logger.quiet("RELEASE_VERSION: $RELEASE_VERSION")
1303 logger.quiet("RELEASE_SUFFIX: $RELEASE_SUFFIX")
1304 logger.quiet("RELEASE_VERSION_SHORT: $RELEASE_VERSION_SHORT")
1305 logger.quiet("RELEASE_VERSION_LONG: $RELEASE_VERSION_LONG")
1306 logger.quiet("RELEASE_VERSION_PADDED: $RELEASE_VERSION_PADDED")
1307 logger.quiet("MAVEN_VERSION: $MAVEN_VERSION")
1308 logger.quiet("UPDATE_STUB_CACHE: $UPDATE_STUB_CACHE")
1309 
1310 /******************************************************************************
1311  *                                                                            *
1312  *                Definition of Native Code Compilation Tasks                 *
1313  *                                                                            *
1314  *    - CCTask compiles native code. Specifically it will compile .m, .c,     *
1315  *      .cpp, or .cc files. It uses the headers provided by running           *
1316  *      'javac -h' plus additional platform specific headers. It will         *
1317  *      compile into .obj files.                                              *
1318  *    - LinkTask will perform native linking and create the .dll / .so /      *
1319  *      .dylib as necessary.                                                  *
1320  *                                                                            *
1321  *****************************************************************************/
1322 
1323 // Save a reference to the buildSrc.jar file because we need it for actually
1324 // compiling things, not just for the sake of this build script
1325 // (such as generating the JSL files, etc)
1326 ext.BUILD_SRC = rootProject.files("buildSrc/build/libs/buildSrc.jar")
1327 
1328 /**
1329  * Convenience method for creating cc, link, and "native" tasks in the given project. These
1330  * tasks are parameterized by name, so that we can produce, for example, ccGlass, etc
1331  * named tasks.
1332  *
1333  * @param project The project to add tasks to
1334  * @param name The name of the project, such as "prism-common". This name is used
1335  *        in the name of the generated task, such as ccPrismCommon, and also
1336  *        in the name of the final library, such as libprism-common.dylib.
1337  */
1338 void addNative(Project project, String name) {
1339     // TODO if we want to handle 32/64 bit windows in the same build,
1340     // Then we will need to modify the win compile target to be win32 or win64
1341     def capitalName = name.split("-").collect{it.capitalize()}.join()
1342     def nativeTask = project.task("native$capitalName", group: "Build") {
1343         description = "Generates JNI headers, compiles, and builds native dynamic library for $name for all compile targets"
1344     }
1345     def cleanTask = project.task("cleanNative$capitalName", type: Delete, group: "Build") {
1346         description = "Clean native objects for $name"
1347     }
1348     if (project.hasProperty("nativeAllTask")) project.nativeAllTask.dependsOn nativeTask
1349     project.assemble.dependsOn(nativeTask)
1350     if (project.hasProperty("cleanNativeAllTask")) project.cleanNativeAllTask.dependsOn cleanTask
1351 
1352     // Each of the different compile targets will be placed in a sub directory
1353     // of these root dirs, with the name of the dir being the name of the target
1354     def nativeRootDir = project.file("$project.buildDir/native/$name")
1355     def libRootDir = project.file("$project.buildDir/libs/$name")
1356     // For each compile target, create a cc / link pair
1357     compileTargets { t ->
1358         def targetProperties = project.rootProject.ext[t.upper]
1359         def library = targetProperties.library
1360         def properties = targetProperties.get(name)
1361         def nativeDir = file("$nativeRootDir/${t.name}")
1362         def headerDir = file("${project.buildDir}/gensrc/headers/${project.moduleName}")
1363 
1364         // If there is not a library clause in the properties, assume it is not wanted
1365         if (!targetProperties.containsKey(name)) {
1366             println("Ignoring native library ${name}. Not defined in ${t.name} project properties");
1367             return
1368         }
1369 
1370         // check for the property disable${name} = true
1371         def String disableKey = "disable${name}"
1372         def boolean disabled = targetProperties.containsKey(disableKey) ? targetProperties.get(disableKey) : false
1373         if (disabled) {
1374             println("Native library ${name} disabled in ${t.name} project properties");
1375             return
1376         }
1377 
1378         def variants = properties.containsKey("variants") ? properties.variants : [""];
1379         variants.each { variant ->
1380             def variantProperties = variant == "" ? properties : properties.get(variant)
1381             def capitalVariant = variant.capitalize()
1382             def ccOutput = variant == "" ? nativeDir : file("$nativeDir/$variant")
1383             def ccTask = project.task("cc${t.capital}$capitalName$capitalVariant", type: CCTask, group: "Build") {
1384                 description = "Compiles native sources for ${name} for ${t.name}${capitalVariant != '' ? ' for variant ' + capitalVariant : ''}"
1385                 matches = ".*\\.c|.*\\.cpp|.*\\.m|.*\\.cc"
1386                 headers = headerDir
1387                 output(ccOutput)
1388                 params.addAll(variantProperties.ccFlags)
1389                 compiler = variantProperties.compiler
1390                 source(variantProperties.nativeSource)
1391                 cleanTask.delete ccOutput
1392             }
1393             def linkTask = project.task("link${t.capital}$capitalName$capitalVariant", type: LinkTask, dependsOn: ccTask, group: "Build") {
1394                 description = "Creates native dynamic library for $name for ${t.name}${capitalVariant != '' ? ' for variant ' + capitalVariant : ''}"
1395                 objectDir = ccOutput
1396                 linkParams.addAll(variantProperties.linkFlags)
1397                 lib = file("$libRootDir/${t.name}/${variant == '' ? library(properties.lib) : library(variantProperties.lib)}")
1398                 linker = variantProperties.linker
1399                 cleanTask.delete "$libRootDir/${t.name}"
1400             }
1401             nativeTask.dependsOn(linkTask)
1402             if (IS_WINDOWS && t.name == "win") {
1403                 def rcTask = project.task("rc$capitalName$capitalVariant", type: CompileResourceTask, group: "Build") {
1404                     description = "Compiles native sources for $name"
1405                     matches = ".*\\.rc"
1406                     compiler = variantProperties.rcCompiler
1407                     source(variantProperties.rcSource)
1408                     if (variantProperties.rcFlags) {
1409                         rcParams.addAll(variantProperties.rcFlags)
1410                     }
1411                     output(ccOutput)
1412                 }
1413                 linkTask.dependsOn rcTask;
1414             }
1415         }
1416 
1417         def useLipo = targetProperties.containsKey('useLipo') ? targetProperties.useLipo : false
1418         if (useLipo) {
1419             def lipoTask = project.task("lipo${t.capital}$capitalName", type: LipoTask, group: "Build") {
1420                 description = "Creates native fat library for $name for ${t.name}"
1421                 libDir = file("$libRootDir/${t.name}")
1422                 lib = file("$libRootDir/${t.name}/${library(properties.lib)}")
1423             }
1424             nativeTask.dependsOn(lipoTask)
1425         }
1426     }
1427 }
1428 
1429 void addJSL(Project project, String name, String pkg, List<String> addExports, Closure compile) {
1430     def lowerName = name.toLowerCase()
1431 
1432     def modulePath = "${project.sourceSets.main.java.outputDir}"
1433     modulePath += File.pathSeparator + "${rootProject.projectDir}/modules/javafx.base/build/classes/java/main"
1434     def compileCompilers = project.task("compile${name}Compilers",
1435             type: JavaCompile,
1436             dependsOn: project.compileJava) {
1437         description = "Compile the $name JSL Compilers"
1438 
1439         classpath =
1440                project.files(project.sourceSets.jslc.java.outputDir) +
1441                project.configurations.antlr
1442         source = [project.file("src/main/jsl-$lowerName")]
1443         destinationDir = project.file("$project.buildDir/classes/jsl-compilers/$lowerName")
1444 
1445         options.compilerArgs.addAll([
1446             "-implicit:none",
1447             "--module-path", modulePath,
1448             "--add-modules=javafx.graphics"
1449             ])
1450         if (addExports != null) {
1451             options.compilerArgs.addAll(addExports)
1452         }
1453     }
1454 
1455     def generateShaders = project.task("generate${name}Shaders",
1456             dependsOn: compileCompilers) {
1457         description = "Generate $name shaders from JSL"
1458         def sourceDir = project.file("src/main/jsl-$lowerName")
1459         def destinationDir = project.file("$project.buildDir/gensrc/jsl-$lowerName")
1460         inputs.dir sourceDir
1461         outputs.dir destinationDir
1462         doLast {
1463             compile(sourceDir, destinationDir)
1464         }
1465     }
1466 
1467     def compileHLSLShaders = project.task("compile${name}HLSLShaders",
1468             dependsOn: generateShaders,
1469             type: CompileHLSLTask) {
1470         enabled = IS_WINDOWS
1471         description = "Compile $name HLSL files into .obj files"
1472         matches = ".*\\.hlsl"
1473         output project.file("$project.buildDir/hlsl/$name/$pkg")
1474         source project.file("$project.buildDir/gensrc/jsl-$lowerName/$pkg")
1475     }
1476 
1477     def processShaders = project.task("process${name}Shaders",
1478             dependsOn: [generateShaders, compileHLSLShaders],
1479             type: Copy,
1480             description: "Copy hlsl / frag shaders to build/resources/jsl-$lowerName") {
1481         from("$project.buildDir/hlsl/$name") {
1482             include "**/*.obj"
1483         }
1484         from("$project.buildDir/gensrc/jsl-$lowerName") {
1485             include("**/*.frag")
1486         }
1487         into project.moduleDir
1488     }
1489 
1490     project.processShaders.dependsOn(processShaders)
1491     project.sourceSets.shaders.output.dir("$project.buildDir/gensrc/jsl-$lowerName", builtBy: processShaders )
1492 
1493     def processShimsShaders = project.task("process${name}ShimsShaders",
1494             dependsOn: [generateShaders, compileHLSLShaders],
1495             type: Copy,
1496             description: "Copy hlsl / frag shaders to shims") {
1497         from("$project.buildDir/hlsl/$name") {
1498             include "**/*.obj"
1499         }
1500         from("$project.buildDir/gensrc/jsl-$lowerName") {
1501             include("**/*.frag")
1502         }
1503         into project.moduleShimsDir
1504     }
1505 
1506     project.processShimsShaders.dependsOn(processShimsShaders)
1507 
1508 }
1509 
1510 void addMavenPublication(Project project, List<String> projectDependencies) {
1511     project.apply plugin: 'maven-publish'
1512 
1513     project.group = MAVEN_GROUP_ID
1514     project.version = MAVEN_VERSION
1515 
1516     if (project.name == 'base') {
1517         project.publishing {
1518             publications {
1519                 javafx(MavenPublication) {
1520                     artifactId = 'javafx'
1521                     artifacts = []
1522                 }
1523             }
1524         }
1525     }
1526 
1527     gradle.taskGraph.whenReady { g ->
1528         project.tasks.findAll { it.name == 'generatePomFileForJavafxPublication'}.each { it ->
1529             it.doLast {
1530                 copy {
1531                     into project.file("${project.buildDir}/publications/javafx")
1532                     from file("${rootProject.projectDir}/javafx.pom")
1533                     rename "javafx.pom", "pom-default.xml"
1534                     filter { line ->
1535                         line.replaceAll("@VERSION@", MAVEN_VERSION)
1536                     }
1537                 }
1538             }
1539         }
1540     }
1541 
1542     project.publishing {
1543         repositories {
1544             maven {
1545                 def repositoryUrl = project.hasProperty('repositoryUrl') ? project.getProperty('repositoryUrl') : ""
1546                 def repositoryUsername = project.hasProperty('repositoryUsername') ? project.getProperty('repositoryUsername') : ""
1547                 def repositoryPassword = project.hasProperty('repositoryPassword') ? project.getProperty('repositoryPassword') : ""
1548                 url repositoryUrl
1549                 credentials {
1550                    username repositoryUsername
1551                    password repositoryPassword
1552                 }
1553             }
1554         }
1555     }
1556 
1557     compileTargets { t ->
1558         project.publishing {
1559             publications {
1560                 maven(MavenPublication) {
1561                     artifactId = "javafx-${project.name}"
1562 
1563                     artifact project.tasks."moduleEmptyPublicationJar$t.capital"
1564                     artifact project.tasks."modularPublicationJar$t.capital" {
1565                         classifier "$t.name"
1566                     }
1567 
1568                     pom.withXml {
1569                         Node parent = asNode().appendNode("parent")
1570                         parent.appendNode("groupId", MAVEN_GROUP_ID)
1571                         parent.appendNode("artifactId", "javafx")
1572                         parent.appendNode("version", MAVEN_VERSION)
1573 
1574                         Node dependencies = asNode().appendNode("dependencies")
1575 
1576                         Node projectDependencyPlatform = dependencies.appendNode("dependency")
1577                         projectDependencyPlatform.appendNode("groupId", MAVEN_GROUP_ID)
1578                         projectDependencyPlatform.appendNode("artifactId", "javafx-${project.name}")
1579                         projectDependencyPlatform.appendNode("version", MAVEN_VERSION)
1580                         projectDependencyPlatform.appendNode("classifier", "\${javafx.platform}")
1581 
1582                         if (!projectDependencies.empty) {
1583                             projectDependencies.each { dep ->
1584                                 Node projectDependency = dependencies.appendNode("dependency")
1585                                 projectDependency.appendNode("groupId", MAVEN_GROUP_ID)
1586                                 projectDependency.appendNode("artifactId", "javafx-$dep")
1587                                 projectDependency.appendNode("version", MAVEN_VERSION)
1588                            }
1589                         }
1590                     }
1591                 }
1592             }
1593 
1594         }
1595     }
1596 }
1597 
1598 /**
1599  * Parses a JDK version string. The string must be in one of the following
1600  * two formats:
1601  *
1602  *     major.minor.subminor
1603  * or
1604  *     major.minor.subminor_update
1605  *
1606  * In both cases a list of 4 integers is returned, with element 3 set to
1607  * 0 in the former case.
1608  */
1609 List parseJdkVersion(String version) {
1610     def arr = version.split("[_\\.]");
1611     def intArr = [];
1612     arr.each { s -> intArr += Integer.parseInt(s); }
1613     while (intArr.size() < 4) intArr += 0;
1614     return intArr;
1615 }
1616 
1617 /**
1618  * Returns -1, 0, or 1 depending on whether JDK version "a" is less than,
1619  * equal to, or grater than version "b".
1620  */
1621 int compareJdkVersion(String a, String b) {
1622     def aIntArr = parseJdkVersion(a);
1623     def bIntArr = parseJdkVersion(b);
1624 
1625     for (int i = 0; i < 4; i++) {
1626         if (aIntArr[i] < bIntArr[i]) return -1;
1627         if (aIntArr[i] > bIntArr[i]) return  1;
1628     }
1629     return 0;
1630 }
1631 
1632 // Task to verify the minimum level of Java needed to build JavaFX
1633 task verifyJava() {
1634     doLast {
1635         def status = compareJdkVersion(jdkVersion, jfxBuildJdkVersionMin);
1636         if (status < 0) {
1637             fail("java version mismatch: JDK version (${jdkVersion}) < minimum version (${jfxBuildJdkVersionMin})")
1638         } else if (status == 0) {
1639             def buildNum = Integer.parseInt(jdkBuildNumber)
1640             def minBuildNum = Integer.parseInt(jfxBuildJdkBuildnumMin)
1641             if (buildNum != 0 && buildNum < minBuildNum) {
1642                 fail("JDK build number ($buildNum) < minimum build number ($minBuildNum)")
1643             }
1644         }
1645     }
1646 }
1647 
1648 task updateCacheIfNeeded() {
1649     // an empty task we can add to as needed for UPDATE_STUB_CACHE
1650 }
1651 
1652 task createTestArgfiles {
1653     // an empty task we can add to as needed
1654 }
1655 
1656 
1657 /*****************************************************************************
1658 *        Project definitions (dependencies, etc)                             *
1659 *****************************************************************************/
1660 
1661 void addJCov(p, test) {
1662     test.doFirst {
1663         def jcovJVMArgument =
1664                 "include=javafx," +
1665                 "include=com.sun.javafx," +
1666                 "include=com.sun.glass," +
1667                 "include=com.sun.openpisces," +
1668                 "include=com.sun.pisces," +
1669                 "include=com.sun.prism," +
1670                 "include=com.sun.scenario," +
1671                 "include=com.sun.webkit," +
1672                 "exclude=com," +
1673                 "exclude=java," +
1674                 "exclude=javax," +
1675                 "exclude=\"**.test\"," +
1676                 "exclude=\"**.*Test\"," +
1677                 "file=build/reports/jcov/report.xml," +
1678                 "merge=merge";
1679         test.jvmArgs("-javaagent:${p.configurations.testCompile.files.find { it.name.startsWith('jcov') }}=$jcovJVMArgument");
1680         p.mkdir p.file("build/reports/jcov")
1681     }
1682     test.doLast {
1683         def reportFile = p.file("build/reports/jcov/report.xml")
1684         if (reportFile.exists()) {
1685             p.javaexec {
1686                 workingDir = p.file("build/reports/jcov")
1687                 classpath = p.files(p.configurations.testCompile.files.find { it.name.startsWith('jcov') })
1688                 main = "com.sun.tdk.jcov.Helper"
1689                 args = [
1690                         "RepGen",
1691                         "-exclude", "\"**.test\"",
1692                         "-exclude", "\"**.*Test\"",
1693                         "-output", ".",
1694                         "-source", p.sourceSets.main.java.srcDirs.collect{p.file(it)}.join(":"),
1695                         "report.xml"
1696                 ]
1697             }
1698         }
1699     }
1700 }
1701 
1702 allprojects {
1703 
1704     // Setup the repositories that we'll download libraries from.
1705     // By default we use Maven Central for most things. The custom "ivy"
1706     // repo is for downloading SWT. The way it works is to setup the
1707     // download URL such that it will resolve to the actual jar file to
1708     // download. See SWT_FILE_NAME for the name of the jar that will be
1709     // used as the "artifact" in the pattern below.
1710     // If JFX_DEPS_URL is set, then that overrides the default
1711     // repositories. This allows the dependencies to be cached locally.
1712 
1713     if (JFX_DEPS_URL != "") {
1714         repositories {
1715             ivy {
1716                 url JFX_DEPS_URL
1717                 layout "pattern", {
1718                     artifact "[artifact]-[revision](-[classifier]).[ext]"
1719                     artifact "[artifact].[ext]"
1720                 }
1721             }
1722         }
1723     }
1724 
1725     if (JFX_DEPS_URL == "") {
1726         repositories {
1727             mavenCentral()
1728             ivy {
1729                 url "http://download.eclipse.org/eclipse/updates/4.6/R-4.6.3-201703010400/plugins/"
1730                 layout "pattern", {
1731                     artifact "[artifact].[ext]"
1732                 }
1733             }
1734         }
1735     }
1736 
1737     if (JFX_DEPS_URL == "" && IS_BUILD_LIBAV_STUBS) {
1738         repositories {
1739             ivy {
1740                 url libAVRepositoryURL
1741                 layout "pattern", {
1742                     artifact "[artifact].[ext]"
1743                 }
1744             }
1745             ivy {
1746                 url FFmpegRepositoryURL
1747                 layout "pattern", {
1748                     artifact "[artifact].[ext]"
1749                 }
1750             }
1751         }
1752     }
1753 
1754     // We want to configure all projects as java projects and use the same compile settings
1755     // etc, except for the root project which we just want to ignore (and for now media)
1756     if (project == rootProject) {
1757        return
1758     }
1759     if (project.path.startsWith(":apps")) {
1760         // Lets handle the apps tree differently, as it is a collection of ant builds,
1761         // and the ant importer collides with the 'apply plugin:java'
1762         return
1763     }
1764 
1765     // All of our projects are java projects
1766 
1767     apply plugin: "java"
1768     sourceCompatibility = 10
1769 
1770     // By default all of our projects require junit for testing so we can just
1771     // setup this dependency here.
1772     dependencies {
1773         testCompile group: "junit", name: "junit", version: "4.8.2"
1774         if (BUILD_CLOSED && DO_JCOV)  {
1775             testCompile name: "jcov"
1776         }
1777     }
1778 
1779     compileJava.dependsOn verifyJava
1780 
1781     // At the moment the ASM library shipped with Gradle that is used to
1782     // discover the different test classes fails on Java 8, so in order
1783     // to have sourceCompatibility set to 1.8 I have to also turn scanForClasses off
1784     // and manually specify the includes / excludes. At the moment we use
1785     // Java 7 but when we switch to 8 this will be needed, and probably again when
1786     // we start building with Java 9.
1787     test {
1788         executable = JAVA;
1789         enableAssertions = true;
1790         testLogging.exceptionFormat = "full";
1791         scanForTestClasses = false;
1792         include("**/*Test.*");
1793         if (BUILD_CLOSED && DO_JCOV) {
1794             addJCov(project, test)
1795         }
1796 
1797         if (IS_HEADLESS_TEST) {
1798             systemProperty 'glass.platform', 'Monocle'
1799             systemProperty 'monocle.platform', 'Headless'
1800             systemProperty 'prism.order', 'sw'
1801             systemProperty 'com.sun.javafx.gestures.zoom', 'true'
1802             systemProperty 'com.sun.javafx.gestures.rotate', 'true'
1803             systemProperty 'com.sun.javafx.gestures.scroll', 'true'
1804         }
1805 
1806         systemProperty 'unstable.test', IS_UNSTABLE_TEST
1807     }
1808 
1809     compileTestJava {
1810     }
1811 }
1812 
1813 // Qualified exports needed by javafx.swing
1814 def qualExportsSwing = [
1815         "--add-exports=java.desktop/java.awt.dnd.peer=javafx.swing",
1816         "--add-exports=java.desktop/sun.awt=javafx.swing",
1817         "--add-exports=java.desktop/sun.awt.dnd=javafx.swing",
1818         "--add-exports=java.desktop/sun.awt.image=javafx.swing",
1819         "--add-exports=java.desktop/sun.java2d=javafx.swing",
1820         "--add-exports=java.desktop/sun.swing=javafx.swing",
1821 ]
1822 
1823 // These strings define the module-source-path to be used in compilation.
1824 // They need to contain the full paths to the sources and the * will be
1825 // used to infer the module name that is used.
1826 project.ext.defaultModuleSourcePath =
1827     cygpath(rootProject.projectDir.path + '/modules/*/src/main/java') +
1828         File.pathSeparator  +
1829     cygpath(rootProject.projectDir.path + '/modules/*/build/gensrc/{java,jsl-decora,jsl-prism}')
1830 
1831 // graphics pass one
1832 project.ext.defaultModuleSourcePath_GraphicsOne =
1833     cygpath(rootProject.projectDir.path + '/modules/*/src/main/java') +
1834         File.pathSeparator  +
1835     cygpath(rootProject.projectDir.path + '/modules/*/build/gensrc/{java,jsl-decora,jsl-prism}')
1836 
1837 // web pass one
1838 project.ext.defaultModuleSourcePath_WebOne =
1839     cygpath(rootProject.projectDir.path + '/modules/*/src/main/java')
1840 
1841 // Compiling the test shim files too.
1842 project.ext.defaultModuleSourcePathShim =
1843     cygpath(rootProject.projectDir.path + '/modules/*/src/{main,shims}/java') +
1844         File.pathSeparator  +
1845     cygpath(rootProject.projectDir.path + '/modules/*/build/gensrc/{java,jsl-decora,jsl-prism}')
1846 
1847 // The "base" project is our first module and the most basic one required for
1848 // all other modules. It is useful even for non-GUI applications.
1849 project(":base") {
1850     project.ext.buildModule = true
1851     project.ext.includeSources = true
1852     project.ext.moduleRuntime = true
1853     project.ext.moduleName = "javafx.base"
1854 
1855     sourceSets {
1856         main
1857         shims
1858         test
1859     }
1860 
1861     dependencies {
1862         testCompile group: "junit", name: "junit", version: "4.8.2"
1863     }
1864 
1865     commonModuleSetup(project, [ 'base' ])
1866 
1867     project.ext.moduleSourcePath = defaultModuleSourcePath
1868     project.ext.moduleSourcePathShim = defaultModuleSourcePathShim
1869 
1870     // We need to take the VersionInfo.java file and replace the various
1871     // properties within it
1872     def replacements = [
1873         "BUILD_TIMESTAMP": BUILD_TIMESTAMP,
1874         "HUDSON_JOB_NAME": HUDSON_JOB_NAME,
1875         "HUDSON_BUILD_NUMBER": HUDSON_BUILD_NUMBER,
1876         "PROMOTED_BUILD_NUMBER": PROMOTED_BUILD_NUMBER,
1877         "PRODUCT_NAME": PRODUCT_NAME,
1878         "RELEASE_VERSION": RELEASE_VERSION,
1879         "RELEASE_SUFFIX": RELEASE_SUFFIX];
1880     task processVersionInfo(type: Copy, description: "Replace params in VersionInfo and copy file to destination") {
1881         doFirst { mkdir "$buildDir/gensrc/java" }
1882         from "src/main/version-info"
1883         into "$buildDir/gensrc/java/com/sun/javafx/runtime"
1884         filter {line->
1885             replacements.each() {k, v ->
1886                 line = line.replace("@$k@", v.toString());
1887             }
1888             line
1889         }
1890     }
1891 
1892     // Make sure to include $buildDir/gensrc/java that we previously created.
1893     // We DO NOT want to include src/main/version-info
1894 
1895     sourceSets.main.java.srcDirs += "$buildDir/gensrc/java"
1896 
1897     compileJava.dependsOn processVersionInfo
1898     addMavenPublication(project, [])
1899 
1900 }
1901 
1902 // The graphics module is needed for any graphical JavaFX application. It requires
1903 // the base module and includes the scene graph, layout, css, prism, windowing, etc.
1904 // This is a fairly complicated module. There are many different types of native components
1905 // that all need to be compiled.
1906 project(":graphics") {
1907 
1908     project.ext.buildModule = true
1909     project.ext.includeSources = true
1910     project.ext.moduleRuntime = true
1911     project.ext.moduleName = "javafx.graphics"
1912     project.ext.mavenPublish = true
1913 
1914     getConfigurations().create("antlr");
1915 
1916     sourceSets {
1917         jslc   // JSLC gramar subset
1918         main
1919         shims
1920         shaders // generated shaders (prism & decora)
1921         test
1922         stub
1923     }
1924 
1925     dependencies {
1926         stubCompile group: "junit", name: "junit", version: "4.8.2"
1927 
1928         antlr group: "org.antlr", name: "antlr-complete", version: "3.5.2"
1929     }
1930 
1931     project.ext.moduleSourcePath = defaultModuleSourcePath_GraphicsOne
1932     project.ext.moduleSourcePathShim = defaultModuleSourcePathShim
1933 
1934     commonModuleSetup(project, [ 'base', 'graphics' ])
1935 
1936     List<String> decoraAddExports = [
1937             '--add-exports=javafx.graphics/com.sun.scenario.effect=ALL-UNNAMED',
1938             '--add-exports=javafx.graphics/com.sun.scenario.effect.light=ALL-UNNAMED',
1939             '--add-exports=javafx.graphics/com.sun.scenario.effect.impl.state=ALL-UNNAMED'
1940             ]
1941     /*
1942     Graphics compilation is "complicated" by the generated shaders.
1943 
1944     We have two shader groups - Decora and Prism.
1945 
1946     The shader groups each will generate a custom compiler that
1947     then genarates the shader code. These compilers rely on the JSLC
1948     gramar parser which is antlr generated and compile separately.
1949 
1950     The decora compiler relies on compileJava - which is sourceSet.main.java
1951     It also accesses module private packages, so will need add-exports
1952 
1953     Once the shader java code is generated, we can compileFullJava
1954 
1955     After that, we can generate the required native header and then build the native code
1956     */
1957 
1958     project.task("processShaders") {
1959         // an empty task to hang the prism and decora shaders on
1960     }
1961 
1962     project.task("processShimsShaders") {
1963         // an empty task to hang the prism and decora shaders on
1964     }
1965 
1966     compileShimsJava.dependsOn("processShimsShaders")
1967 
1968     // Generate the JSLC support grammar
1969     project.task("generateGrammarSource", type: JavaExec) {
1970         // use antlr to generate our grammar.
1971         // note: the antlr plugin creates some issues with the other compiles
1972         // so we will do this by hand
1973 
1974         File wd = file(project.projectDir.path + "/src/jslc/antlr")
1975 
1976         executable = JAVA
1977         classpath = project.configurations.antlr
1978         workingDir = wd
1979         main = "org.antlr.Tool"
1980 
1981         args = [
1982             "-Xconversiontimeout",
1983             "30000",
1984             "-o",
1985             "$buildDir/gensrc/antlr",
1986             "com/sun/scenario/effect/compiler/JSL.g" ]
1987 
1988         inputs.dir wd
1989         outputs.dir file("$buildDir/gensrc/antlr")
1990     }
1991     sourceSets.jslc.java.srcDirs += "$buildDir/gensrc/antlr"
1992 
1993     // and compile the JSLC support classes
1994     compileJslcJava.dependsOn(generateGrammarSource)
1995     compileJslcJava.classpath = project.configurations.antlr
1996 
1997     compileJava.dependsOn(compileJslcJava)
1998 
1999     // this task is the "second pass" compile of all of the module classes
2000     project.task("compileFullJava", type: JavaCompile, dependsOn: processShaders) {
2001         description = "Compile all of the graphics java classes - main and shaders"
2002 
2003         classpath = configurations.compile
2004 
2005         source = project.sourceSets.main.java.srcDirs
2006         source += "$buildDir/gensrc/java"
2007         source += project.sourceSets.shaders.output
2008 
2009         destinationDir = project.sourceSets.main.java.outputDir
2010         options.compilerArgs.addAll([
2011             '-h', "$buildDir/gensrc/headers/",  // Note: this creates the native headers
2012             '-implicit:none',
2013             '--module-source-path', defaultModuleSourcePath
2014             ] )
2015     }
2016     classes.dependsOn(compileFullJava)
2017 
2018     project.sourceSets.shims.java.srcDirs += project.sourceSets.shaders.output
2019     project.sourceSets.shims.java.srcDirs += "$buildDir/gensrc/jsl-prism"
2020     project.sourceSets.shims.java.srcDirs += "$buildDir/gensrc/jsl-decora"
2021 
2022     compileShimsJava.dependsOn(compileFullJava)
2023 
2024     // Create a single "native" task which will depend on all the individual native tasks for graphics
2025     project.ext.nativeAllTask = task("native", group: "Build", description: "Compiles and Builds all native libraries for Graphics");
2026     project.ext.cleanNativeAllTask = task("cleanNative", group: "Build", description: "Clean all native libraries and objects for Graphics");
2027 
2028     // Add tasks for native compilation
2029     addNative(project, "glass");
2030     addNative(project, "prism")
2031     addNative(project, "prismSW")
2032     addNative(project, "font")
2033     addNative(project, "iio")
2034     addNative(project, "prismES2")
2035 
2036     if (IS_COMPILE_PANGO) {
2037         addNative(project, "fontFreetype")
2038         addNative(project, "fontPango")
2039     }
2040 
2041     if (IS_WINDOWS) {
2042         addNative(project, "prismD3D")
2043         // TODO need to hook this up to be executed only if PassThroughVS.h is missing or PassThroughVS.hlsl is changed
2044         task generateD3DHeaders(group: "Build") {
2045             enabled = IS_WINDOWS
2046             inputs.file "src/main/native-prism-d3d/hlsl/Mtl1PS.hlsl"
2047             inputs.file "src/main/native-prism-d3d/hlsl/Mtl1VS.hlsl"
2048             inputs.file "src/main/native-prism-d3d/PassThroughVS.hlsl"
2049             outputs.dir "$buildDir/headers/PrismD3D/"
2050             outputs.dir "$buildDir/headers/PrismD3D/hlsl/"
2051             description = "Generate headers by compiling hlsl files"
2052             doLast {
2053                 mkdir file("$buildDir/headers/PrismD3D/hlsl")
2054                 def PS_3D_SRC = file("src/main/native-prism-d3d/hlsl/Mtl1PS.hlsl")
2055                 def VS_3D_SRC = file("src/main/native-prism-d3d/hlsl/Mtl1VS.hlsl")
2056                 def PASSTHROUGH_VS_SRC = file("src/main/native-prism-d3d/PassThroughVS.hlsl")
2057                 def jobs = [
2058                         ["$FXC", "/nologo", "/T", "vs_3_0", "/Fh", "$buildDir/headers/PrismD3D/PassThroughVS.h", "/E", "passThrough", "$PASSTHROUGH_VS_SRC"],
2059                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS.h", "/DSpec=0", "/DSType=0", "$PS_3D_SRC"],
2060                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_i.h", "/DSpec=0", "/DSType=0", "/DIllumMap=1", "$PS_3D_SRC"],
2061                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s1n.h", "/DSpec=1", "/DSType=0", "$PS_3D_SRC"],
2062                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s2n.h", "/DSpec=2", "/DSType=0", "$PS_3D_SRC"],
2063                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s3n.h", "/DSpec=3", "/DSType=0", "$PS_3D_SRC"],
2064                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s1t.h", "/DSpec=1", "/DSType=1", "$PS_3D_SRC"],
2065                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s2t.h", "/DSpec=2", "/DSType=1", "$PS_3D_SRC"],
2066                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s3t.h", "/DSpec=3", "/DSType=1", "$PS_3D_SRC"],
2067                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s1c.h", "/DSpec=1", "/DSType=2", "$PS_3D_SRC"],
2068                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s2c.h", "/DSpec=2", "/DSType=2", "$PS_3D_SRC"],
2069                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s3c.h", "/DSpec=3", "/DSType=2", "$PS_3D_SRC"],
2070                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s1m.h", "/DSpec=1", "/DSType=3", "$PS_3D_SRC"],
2071                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s2m.h", "/DSpec=2", "/DSType=3", "$PS_3D_SRC"],
2072                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s3m.h", "/DSpec=3", "/DSType=3", "$PS_3D_SRC"],
2073                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b1n.h", "/DSpec=1", "/DSType=0", "/DBump=1", "$PS_3D_SRC"],
2074                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b2n.h", "/DSpec=2", "/DSType=0", "/DBump=1", "$PS_3D_SRC"],
2075                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b3n.h", "/DSpec=3", "/DSType=0", "/DBump=1", "$PS_3D_SRC"],
2076                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b1t.h", "/DSpec=1", "/DSType=1", "/DBump=1", "$PS_3D_SRC"],
2077                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b2t.h", "/DSpec=2", "/DSType=1", "/DBump=1", "$PS_3D_SRC"],
2078                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b3t.h", "/DSpec=3", "/DSType=1", "/DBump=1", "$PS_3D_SRC"],
2079                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b1c.h", "/DSpec=1", "/DSType=2", "/DBump=1", "$PS_3D_SRC"],
2080                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b2c.h", "/DSpec=2", "/DSType=2", "/DBump=1", "$PS_3D_SRC"],
2081                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b3c.h", "/DSpec=3", "/DSType=2", "/DBump=1", "$PS_3D_SRC"],
2082                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b1m.h", "/DSpec=1", "/DSType=3", "/DBump=1", "$PS_3D_SRC"],
2083                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b2m.h", "/DSpec=2", "/DSType=3", "/DBump=1", "$PS_3D_SRC"],
2084                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b3m.h", "/DSpec=3", "/DSType=3", "/DBump=1", "$PS_3D_SRC"],
2085                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s1ni.h", "/DSpec=1", "/DSType=0", "/DIllumMap=1", "$PS_3D_SRC"],
2086                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s2ni.h", "/DSpec=2", "/DSType=0", "/DIllumMap=1", "$PS_3D_SRC"],
2087                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s3ni.h", "/DSpec=3", "/DSType=0", "/DIllumMap=1", "$PS_3D_SRC"],
2088                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s1ti.h", "/DSpec=1", "/DSType=1", "/DIllumMap=1", "$PS_3D_SRC"],
2089                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s2ti.h", "/DSpec=2", "/DSType=1", "/DIllumMap=1", "$PS_3D_SRC"],
2090                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s3ti.h", "/DSpec=3", "/DSType=1", "/DIllumMap=1", "$PS_3D_SRC"],
2091                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s1ci.h", "/DSpec=1", "/DSType=2", "/DIllumMap=1", "$PS_3D_SRC"],
2092                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s2ci.h", "/DSpec=2", "/DSType=2", "/DIllumMap=1", "$PS_3D_SRC"],
2093                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s3ci.h", "/DSpec=3", "/DSType=2", "/DIllumMap=1", "$PS_3D_SRC"],
2094                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s1mi.h", "/DSpec=1", "/DSType=3", "/DIllumMap=1", "$PS_3D_SRC"],
2095                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s2mi.h", "/DSpec=2", "/DSType=3", "/DIllumMap=1", "$PS_3D_SRC"],
2096                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s3mi.h", "/DSpec=3", "/DSType=3", "/DIllumMap=1", "$PS_3D_SRC"],
2097                         ["$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"],
2098                         ["$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"],
2099                         ["$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"],
2100                         ["$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"],
2101                         ["$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"],
2102                         ["$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"],
2103                         ["$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"],
2104                         ["$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"],
2105                         ["$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"],
2106                         ["$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"],
2107                         ["$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"],
2108                         ["$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"],
2109                         ["$FXC", "/nologo", "/T", "vs_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1VS_Obj.h", "/DVertexType=ObjVertex", "$VS_3D_SRC"]
2110                 ]
2111                 final ExecutorService executor = Executors.newFixedThreadPool(Integer.parseInt(project.NUM_COMPILE_THREADS.toString()));
2112                 final CountDownLatch latch = new CountDownLatch(jobs.size());
2113                 List futures = new ArrayList<Future>();
2114                 jobs.each { cmd ->
2115                     futures.add(executor.submit(new Runnable() {
2116                         @Override public void run() {
2117                             try {
2118                                 exec {
2119                                     commandLine cmd
2120                                 }
2121                             } finally {
2122                                 latch.countDown();
2123                             }
2124                         }
2125                     }));
2126                 }
2127                 latch.await();
2128                 // Looking for whether an exception occurred while executing any of the futures.
2129                 // By calling "get()" on each future an exception will be thrown if one had occurred
2130                 // on the background thread.
2131                 futures.each {it.get();}
2132             }
2133         }
2134 
2135         ccWinPrismD3D.dependsOn generateD3DHeaders
2136     }
2137 
2138     // The Decora and Prism JSL files have to be generated in a very specific set of steps.
2139     //      1) Compile the *Compile.java classes. These live in src/main/jsl-* and will be
2140     //         output to $buildDir/classes/jsl-compilers/* (where * == decora or prism).
2141     //      2) Generate source files from the JSL files contained in src/main/jsl-*. These
2142     //         will be output to $buildDir/gensrc/jsl-*
2143     //      3) Compile the JSL Java sources in $buildDir/gensrc/jsl-* and put the output
2144     //         into classes/jsl-*
2145     //      4) Compile the native JSL sources in $buildDir/gensrc/jsl-* and put the obj
2146     //         files into native/jsl-* and the resulting library into libs/jsl-*.dll|so|dylib
2147     //      5) Modify the jar step to include classes/jsl-*
2148     // The native library must be copied over during SDK creation time in the "sdk" task. In
2149     // addition to these steps, the clean task is created. Note that I didn't bother to create
2150     // a new task for each of the decora files, preferring instead just to create a rule?? Also
2151     // need "clean" tasks for each compile task.
2152 
2153     def modulePath = "${project.sourceSets.main.java.outputDir}"
2154     modulePath += File.pathSeparator + "${rootProject.projectDir}/modules/javafx.base/build/classes/java/main"
2155     addJSL(project, "Decora", "com/sun/scenario/effect/impl/hw/d3d/hlsl", decoraAddExports) { sourceDir, destinationDir ->
2156         [[fileName: "ColorAdjust", generator: "CompileJSL", outputs: "-all"],
2157          [fileName: "Brightpass", generator: "CompileJSL", outputs: "-all"],
2158          [fileName: "SepiaTone", generator: "CompileJSL", outputs: "-all"],
2159          [fileName: "PerspectiveTransform", generator: "CompileJSL", outputs: "-all"],
2160          [fileName: "DisplacementMap", generator: "CompileJSL", outputs: "-all"],
2161          [fileName: "InvertMask", generator: "CompileJSL", outputs: "-all"],
2162          [fileName: "Blend", generator: "CompileBlend", outputs: "-all"],
2163          [fileName: "PhongLighting", generator: "CompilePhong", outputs: "-all"],
2164          [fileName: "LinearConvolve", generator: "CompileLinearConvolve", outputs: "-hw"],
2165          [fileName: "LinearConvolveShadow", generator: "CompileLinearConvolve", outputs: "-hw"]].each { settings ->
2166             javaexec {
2167                 executable = JAVA
2168                 workingDir = project.projectDir
2169                 main = settings.generator
2170                 classpath = configurations.compile + configurations.antlr
2171                 classpath += files(project.sourceSets.jslc.java.outputDir)
2172 
2173                 classpath += files("${project.projectDir}/src/jslc/resources")
2174 
2175                 classpath += files("$buildDir/classes/jsl-compilers/decora")
2176                 jvmArgs += "--module-path=$modulePath"
2177                 jvmArgs += "--add-modules=javafx.graphics"
2178                 jvmArgs += decoraAddExports
2179                 args += ["-i", sourceDir, "-o", destinationDir, "-t", "-pkg", "com/sun/scenario/effect", "$settings.outputs", "$settings.fileName"]
2180             }
2181         }
2182     }
2183 
2184 
2185     task nativeDecora(dependsOn: compileDecoraHLSLShaders, group: "Build") {
2186         description = "Generates JNI headers, compiles, and builds native dynamic library for Decora"
2187     }
2188     task cleanNativeDecora(type: Delete, group: "Build") {
2189         description = "Clean native objects for Decora"
2190     }
2191 
2192     def headerDir = file("$buildDir/gensrc/headers/javafx.graphics")
2193     def nativeRootDir = project.file("$project.buildDir/native/jsl-decora")
2194     def libRootDir = project.file("$project.buildDir/libs/jsl-decora")
2195     // For each compile target, create cc and link tasks
2196     compileTargets { t ->
2197         def target = t.name
2198         def upperTarget = t.upper
2199         def capitalTarget = t.capital
2200         def targetProperties = rootProject.ext[upperTarget];
2201         def library = targetProperties.library
2202         def properties = targetProperties.get('decora')
2203         def nativeDir = file("$nativeRootDir/$target");
2204 
2205         def variants = properties.containsKey("variants") ? properties.variants : [""];
2206         variants.each { variant ->
2207             def variantProperties = variant == "" ? properties : properties.get(variant)
2208             def capitalVariant = variant.capitalize()
2209             def ccOutput = variant == "" ? nativeDir : file("$nativeDir/$variant")
2210 
2211             def ccTask = task("compileDecoraNativeShaders$capitalTarget$capitalVariant", type: CCTask ) {
2212                 description = "Compiles Decora SSE natives for ${t.name}${capitalVariant != '' ? ' for variant ' + capitalVariant : ''}"
2213                 matches = ".*\\.cc"
2214                 source file("$buildDir/gensrc/jsl-decora")
2215                 source file(project.projectDir.path + "/src/main/native-decora")
2216                 headers = headerDir
2217                 params.addAll(variantProperties.ccFlags)
2218                 output(ccOutput)
2219                 compiler = variantProperties.compiler
2220                 cleanNativeDecora.delete ccOutput
2221             }
2222 
2223             def linkTask = task("linkDecoraNativeShaders$capitalTarget$capitalVariant", type: LinkTask, dependsOn: ccTask) {
2224                 description = "Creates native dynamic library for Decora SSE ${t.name}${capitalVariant != '' ? ' for variant ' + capitalVariant : ''}"
2225                 objectDir = ccOutput
2226                 linkParams.addAll(variantProperties.linkFlags)
2227                 lib = file("$libRootDir/$t.name/${library(variantProperties.lib)}")
2228                 linker = variantProperties.linker
2229                 cleanNativeDecora.delete "$libRootDir/$t.name/"
2230             }
2231 
2232             if (IS_WINDOWS && target == "win") {
2233                 def rcTask = project.task("rcDecoraNativeShaders$capitalTarget$capitalVariant", type: CompileResourceTask) {
2234                     description = "Compiles native sources for Decora SSE"
2235                     matches = ".*\\.rc"
2236                     compiler = variantProperties.rcCompiler
2237                     source(variantProperties.rcSource)
2238                     if (variantProperties.rcFlags) {
2239                         rcParams.addAll(variantProperties.rcFlags)
2240                     }
2241                     output(ccOutput)
2242                 }
2243                 linkTask.dependsOn rcTask;
2244             }
2245 
2246             nativeDecora.dependsOn(linkTask)
2247         }
2248     }
2249 
2250     // Prism JSL
2251     addJSL(project, "Prism", "com/sun/prism/d3d/hlsl", null) { sourceDir, destinationDir ->
2252         def inputFiles = fileTree(dir: sourceDir)
2253         inputFiles.include "**/*.jsl"
2254         inputFiles.each { file ->
2255             javaexec {
2256                 executable = JAVA
2257                 workingDir = project.projectDir
2258                 main = "CompileJSL"
2259                 classpath = configurations.compile + configurations.antlr
2260                 classpath += files(project.sourceSets.jslc.java.outputDir)
2261                 classpath += files(project.sourceSets.jslc.resources)
2262                 classpath += files("$buildDir/classes/jsl-compilers/prism",
2263                     project.projectDir.path + "/src/main/jsl-prism") // for the .stg
2264                 args = ["-i", sourceDir, "-o", destinationDir, "-t", "-pkg", "com/sun/prism", "-d3d", "-es2", "-name", "$file"]
2265             }
2266         }
2267     }
2268 
2269     nativePrism.dependsOn compilePrismHLSLShaders;
2270 
2271     project.nativeAllTask.dependsOn nativeDecora
2272     project.cleanNativeAllTask.dependsOn cleanNativeDecora
2273     assemble.dependsOn nativeDecora
2274     processResources.dependsOn processDecoraShaders, processPrismShaders
2275 
2276     test {
2277         def cssDir = file("$buildDir/classes/java/main/${moduleName}/javafx")
2278         jvmArgs "-Djavafx.toolkit=test.com.sun.javafx.pgstub.StubToolkit",
2279             "-DCSS_META_DATA_TEST_DIR=$cssDir"
2280         enableAssertions = true
2281         testLogging.exceptionFormat = "full"
2282         scanForTestClasses = false
2283         include "**/*Test.*"
2284         if (BUILD_CLOSED && DO_JCOV) {
2285             addJCov(project, test)
2286         }
2287     }
2288 
2289     // To enable the IDEs to all be happy (no red squiggles) we need to have the libraries
2290     // available in some known location. Maybe in the future the Gradle plugins to each
2291     // of the IDEs will be good enough that we won't need this hack anymore.
2292     classes {
2293         doLast {
2294             // Copy all of the download libraries to the libs directory for the sake of the IDEs
2295             File libsDir = rootProject.file("build/libs");
2296 
2297             // In some IDEs (Eclipse for example), touching these libraries
2298             // cauese a full build within the IDE. When gradle is used
2299             // outside of the IDE, for example to build the native code,
2300             // a full rebuild is caused within the IDE. The fix is to check
2301             // for the presence of the target files in the lib directory
2302             // and not copy the files if all are present.
2303 
2304             libsDir.mkdirs();
2305 
2306             def allLibsPresent = true
2307             def libNames = [ "antlr-complete-3.5.2.jar" ]
2308             libNames.each { name ->
2309                 File f = new File(libsDir, name)
2310                 if (!f.exists()) allLibsPresent = false
2311             }
2312             if (allLibsPresent) return;
2313 
2314             for (File f : [configurations.compile.files, configurations.antlr.files].flatten()) {
2315                 copy {
2316                     into libsDir
2317                     from f.getParentFile()
2318                     include "**/antlr-complete-3.5.2.jar"
2319                     includeEmptyDirs = false
2320                 }
2321             }
2322         }
2323     }
2324 
2325     addMavenPublication(project, [ 'base' ])
2326 
2327 }
2328 
2329 project(":controls") {
2330     project.ext.buildModule = true
2331     project.ext.includeSources = true
2332     project.ext.moduleRuntime = true
2333     project.ext.moduleName = "javafx.controls"
2334 
2335     sourceSets {
2336         main
2337         shims
2338         test
2339     }
2340 
2341     project.ext.moduleSourcePath = defaultModuleSourcePath
2342     project.ext.moduleSourcePathShim = defaultModuleSourcePathShim
2343 
2344     commonModuleSetup(project, [ 'base', 'graphics', 'controls' ])
2345 
2346     dependencies {
2347         testCompile project(":graphics").sourceSets.test.output
2348         testCompile project(":base").sourceSets.test.output
2349     }
2350 
2351     test {
2352         def cssDir = file("$buildDir/classes/java/main/${moduleName}/javafx")
2353         jvmArgs "-Djavafx.toolkit=test.com.sun.javafx.pgstub.StubToolkit",
2354             "-DCSS_META_DATA_TEST_DIR=$cssDir"
2355     }
2356 
2357     def modulePath = "${project.sourceSets.main.java.outputDir}"
2358     modulePath += File.pathSeparator + "${rootProject.projectDir}/modules/javafx.graphics/build/classes/java/main"
2359     modulePath += File.pathSeparator + "${rootProject.projectDir}/modules/javafx.base/build/classes/java/main"
2360     processResources {
2361       doLast {
2362         def cssFiles = fileTree(dir: "$moduleDir/com/sun/javafx/scene/control/skin")
2363         cssFiles.include "**/*.css"
2364         cssFiles.each { css ->
2365             logger.info("converting CSS to BSS ${css}");
2366 
2367             javaexec {
2368                 executable = JAVA
2369                 workingDir = project.projectDir
2370                 jvmArgs += patchModuleArgs
2371                 jvmArgs += "--module-path=$modulePath"
2372                 jvmArgs += "--add-modules=javafx.graphics"
2373                 main = "com.sun.javafx.css.parser.Css2Bin"
2374                 args css
2375             }
2376         }
2377       }
2378     }
2379 
2380     processShimsResources.dependsOn(project.task("copyShimBss", type: Copy) {
2381         from project.moduleDir
2382         into project.moduleShimsDir
2383         include "**/*.bss"
2384     })
2385 
2386     addMavenPublication(project, [ 'graphics' ])
2387 
2388 }
2389 
2390 project(":swing") {
2391 
2392     tasks.all {
2393         if (!COMPILE_SWING) it.enabled = false
2394     }
2395 
2396     project.ext.buildModule = COMPILE_SWING
2397     project.ext.includeSources = true
2398     project.ext.moduleRuntime = true
2399     project.ext.moduleName = "javafx.swing"
2400 
2401     sourceSets {
2402         main
2403         //shims // no test shims needed
2404         test
2405     }
2406 
2407     project.ext.moduleSourcePath = defaultModuleSourcePath
2408     project.ext.moduleSourcePathShim = defaultModuleSourcePathShim
2409 
2410     commonModuleSetup(project, [ 'base', 'graphics', 'swing' ])
2411 
2412     dependencies {
2413     }
2414 
2415     test {
2416         enabled = IS_FULL_TEST && IS_AWT_TEST
2417 
2418         if (!HAS_JAVAFX_MODULES) {
2419             jvmArgs += qualExportsSwing
2420         }
2421     }
2422 
2423     sourceSets.main.java.srcDirs += "$buildDir/gensrc/java"
2424     sourceSets.main.java {
2425         if (!HAS_UNSUPPORTED_DESKTOP) {
2426             exclude("com/sun/javafx/embed/swing/newimpl/**")
2427         }
2428     }
2429     task copyModuleInfo(type: Copy, description: "copy module-info file to gensrc") {
2430         from "src/main/module-info/module-info.java"
2431         into "$buildDir/gensrc/java/"
2432         filter { line->
2433             !HAS_UNSUPPORTED_DESKTOP && line.contains('jdk.unsupported.desktop') ? null : line
2434         }
2435     }
2436     compileJava.dependsOn copyModuleInfo
2437 
2438     compileJava.options.compilerArgs.addAll(qualExportsSwing)
2439 
2440     addMavenPublication(project, [ 'graphics' ])
2441 }
2442 
2443 project(":swt") {
2444     tasks.all {
2445         if (!COMPILE_SWT) it.enabled = false
2446     }
2447 
2448     // javafx.swt is an automatic module
2449     project.ext.buildModule = false
2450 
2451     commonModuleSetup(project, [ 'base', 'graphics' ])
2452 
2453     dependencies {
2454         compile name: SWT_FILE_NAME
2455     }
2456 
2457     classes {
2458         doLast {
2459             // Copy all of the download libraries to libs directory for the sake of the IDEs
2460             File libsDir = rootProject.file("build/libs");
2461             File swtLib = new File(libsDir, "swt-debug.jar")
2462             libsDir.mkdirs();
2463 
2464             // Skip copy if file is present.
2465             if (swtLib.exists()) return;
2466 
2467             for (File f : configurations.compile.files) {
2468                 // Have to rename the swt jar because it is some platform specific name but
2469                 // for the sake of the IDEs we need to have a single stable name that works
2470                 // on every platform
2471                 copy {
2472                     into libsDir
2473                     from f.getParentFile()
2474                     include "**/*swt*.jar"
2475                     includeEmptyDirs = false
2476                     rename ".*swt.*jar", "swt-debug\\.jar"
2477                 }
2478             }
2479         }
2480     }
2481 
2482     compileJava.options.compilerArgs.addAll([
2483             "--add-exports=javafx.graphics/com.sun.glass.ui=ALL-UNNAMED",
2484             "--add-exports=javafx.graphics/com.sun.javafx.cursor=ALL-UNNAMED",
2485             "--add-exports=javafx.graphics/com.sun.javafx.embed=ALL-UNNAMED",
2486             "--add-exports=javafx.graphics/com.sun.javafx.stage=ALL-UNNAMED",
2487             "--add-exports=javafx.graphics/com.sun.javafx.tk=ALL-UNNAMED",
2488             ])
2489 
2490     test {
2491         //enabled = IS_FULL_TEST && IS_SWT_TEST
2492         enabled = false // FIXME: JIGSAW -- support this with modules
2493         logger.info("JIGSAW Testing disabled for swt")
2494 
2495         if (IS_MAC) {
2496             enabled = false
2497             logger.info("SWT tests are disabled on MAC, because Gradle test runner does not handle -XstartOnFirstThread properly (https://issues.gradle.org/browse/GRADLE-3290).")
2498         }
2499     }
2500 }
2501 
2502 project(":fxml") {
2503     project.ext.buildModule = true
2504     project.ext.includeSources = true
2505     project.ext.moduleRuntime = true
2506     project.ext.moduleName = "javafx.fxml"
2507 
2508     sourceSets {
2509         main
2510         shims
2511         test
2512     }
2513 
2514     project.ext.moduleSourcePath = defaultModuleSourcePath
2515     project.ext.moduleSourcePathShim = defaultModuleSourcePathShim
2516 
2517     commonModuleSetup(project, [ 'base', 'graphics', 'controls', 'fxml' ])
2518 
2519 
2520     dependencies {
2521         testCompile project(":graphics").sourceSets.test.output
2522         testCompile project(":base").sourceSets.test.output
2523     }
2524 
2525     test {
2526         // StubToolkit is not *really* needed here, but because some code inadvertently invokes performance
2527         // tracker and this attempts to fire up the toolkit and this looks for native libraries and fails,
2528         // we have to use the stub toolkit for now.
2529         jvmArgs "-Djavafx.toolkit=test.com.sun.javafx.pgstub.StubToolkit"
2530         // FIXME: change this to also allow JDK 9 boot jdk
2531         classpath += files("$JDK_HOME/jre/lib/ext/nashorn.jar")
2532     }
2533 
2534     addMavenPublication(project, [ 'controls' ])
2535 
2536 }
2537 
2538 project(":media") {
2539     configurations {
2540         media
2541     }
2542 
2543     project.ext.buildModule = true
2544     project.ext.includeSources = true
2545     project.ext.moduleRuntime = true
2546     project.ext.moduleName = "javafx.media"
2547 
2548     sourceSets {
2549         main
2550         //shims // no test shims needed
2551         test
2552         tools {
2553             java.srcDir "src/tools/java"
2554         }
2555     }
2556 
2557     project.ext.moduleSourcePath = defaultModuleSourcePath
2558     project.ext.moduleSourcePathShim = defaultModuleSourcePathShim
2559 
2560     commonModuleSetup(project, [ 'base', 'graphics', 'media' ])
2561 
2562     dependencies {
2563         if (IS_BUILD_LIBAV_STUBS) {
2564             media name: "libav-9.14", ext: "tar.gz"
2565             media name: "libav-11.4", ext: "tar.gz"
2566             media name: "libav-12.1", ext: "tar.gz"
2567             media name: "ffmpeg-3.3.3", ext: "tar.gz"
2568         }
2569     }
2570 
2571     compileJava.dependsOn updateCacheIfNeeded
2572 
2573     compileJava {
2574         // generate the native headers during compile
2575         options.compilerArgs.addAll([
2576             '-h', "${project.buildDir}/gensrc/headers"
2577             ])
2578     }
2579 
2580     compileToolsJava {
2581         enabled = IS_COMPILE_MEDIA
2582         def modulePath = "${project.sourceSets.main.java.outputDir}"
2583         options.compilerArgs.addAll([
2584             "--module-path=$modulePath",
2585             "--add-modules=javafx.media",
2586             '--add-exports', 'javafx.media/com.sun.media.jfxmedia=ALL-UNNAMED',
2587             ])
2588     }
2589 
2590     project.ext.makeJobsFlag = IS_WINDOWS && IS_DEBUG_NATIVE ? "-j1" : "-j5";
2591     project.ext.buildType = IS_DEBUG_NATIVE ? "Debug" : "Release";
2592 
2593     def nativeSrcDir = file("${projectDir}/src/main/native")
2594     def generatedHeadersDir = file("${buildDir}/gensrc/headers/${project.moduleName}")
2595 
2596     task generateMediaErrorHeader(dependsOn: [compileJava, compileToolsJava]) {
2597         enabled = IS_COMPILE_MEDIA
2598         def headerpath = file("$generatedHeadersDir/jfxmedia_errors.h");
2599         doLast {
2600             def classpath = files(sourceSets.tools.output);
2601             def sourcepath = sourceSets.main.java.srcDirs;
2602             def srcRoot = (sourcepath.toArray())[0];
2603 
2604             mkdir generatedHeadersDir;
2605 
2606             def modulePath = "${project.sourceSets.main.java.outputDir}"
2607             modulePath += File.pathSeparator + "${rootProject.projectDir}/modules/javafx.graphics/build/classes/java/main"
2608             modulePath += File.pathSeparator + "${rootProject.projectDir}/modules/javafx.base/build/classes/java/main"
2609 
2610             exec {
2611                 commandLine("$JAVA");
2612                 args += patchModuleArgs
2613                 args += [ "--module-path=$modulePath" ]
2614                 args += [ "--add-modules=javafx.media" ]
2615                 args +=  [ '--add-exports=javafx.media/com.sun.media.jfxmedia=ALL-UNNAMED' ]
2616                 args +=  [ '-classpath', "${classpath.asPath}" ]
2617                 args += [ "headergen.HeaderGen", "$headerpath", "$srcRoot" ]
2618             }
2619         }
2620         outputs.file(project.file("$headerpath"))
2621     }
2622 
2623     task buildNativeTargets {
2624         enabled = IS_COMPILE_MEDIA
2625     }
2626 
2627     compileTargets { t->
2628         def targetProperties = project.rootProject.ext[t.upper]
2629         def nativeOutputDir = file("${buildDir}/native/${t.name}")
2630         def projectDir = t.name.startsWith("arm") ? "linux" : t.name
2631         def mediaProperties = targetProperties.media
2632         // Makefile for OSX needs to know if we're building for parfait
2633         def compileParfait = IS_COMPILE_PARFAIT ? "true" : "false"
2634 
2635         def buildNative = task("build${t.capital}Native", dependsOn: [generateMediaErrorHeader]) {
2636             enabled = targetProperties.compileMediaNative
2637             if (!targetProperties.compileMediaNative) {
2638                 println("Not compiling native Media for ${t.name} per configuration request");
2639             }
2640 
2641             doLast {
2642                 exec {
2643                     commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/jfxmedia/projects/${projectDir}")
2644                     args("JAVA_HOME=${JDK_HOME}", "GENERATED_HEADERS_DIR=${generatedHeadersDir}",
2645                          "OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}", "BASE_NAME=jfxmedia",
2646                          "COMPILE_PARFAIT=${compileParfait}",
2647                          IS_64 ? "ARCH=x64" : "ARCH=x32",
2648                         "CC=${mediaProperties.compiler}", "LINKER=${mediaProperties.linker}")
2649 
2650                     if (t.name == "win") {
2651                         environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
2652                         args( "RESOURCE=${nativeOutputDir}/${buildType}/${WIN.media.jfxmediaRcFile}")
2653                     } else {
2654                         if (t.name.startsWith("arm")) {
2655                             args("EXTRA_CFLAGS=${mediaProperties.extra_cflags}", "EXTRA_LDFLAGS=${mediaProperties.extra_ldflags}")
2656                         } else {
2657                             args("HOST_COMPILE=1")
2658                         }
2659                     }
2660                 }
2661             }
2662         }
2663 
2664         // check for the property disable${name} = true
2665         def boolean disabled = targetProperties.containsKey('disableMedia') ? targetProperties.get('disableMedia') : false
2666         if (!disabled) {
2667             // Building GStreamer
2668             def buildGStreamer = task("build${t.capital}GStreamer") {
2669                 enabled = IS_COMPILE_MEDIA
2670                 doLast {
2671                     exec {
2672                         commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/gstreamer/projects/${projectDir}/gstreamer-lite")
2673                         args("OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}", "BASE_NAME=gstreamer-lite",
2674                              IS_64 ? "ARCH=x64" : "ARCH=x32", "CC=${mediaProperties.compiler}",
2675                              "AR=${mediaProperties.ar}", "LINKER=${mediaProperties.linker}")
2676 
2677                         if (t.name == "win") {
2678                             environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
2679                             args("RESOURCE=${nativeOutputDir}/${buildType}/${WIN.media.gstreamerRcFile}")
2680                         }
2681                     }
2682                 }
2683             }
2684 
2685             def buildPlugins = task("build${t.capital}Plugins", dependsOn: buildGStreamer) {
2686                 enabled = IS_COMPILE_MEDIA
2687 
2688                 doLast {
2689                     exec {
2690                         commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/gstreamer/projects/${projectDir}/fxplugins")
2691                         args("OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}", "BASE_NAME=fxplugins",
2692                              IS_64 ? "ARCH=x64" : "ARCH=x32",
2693                              "CC=${mediaProperties.compiler}", "AR=${mediaProperties.ar}", "LINKER=${mediaProperties.linker}")
2694 
2695                         if (t.name == "win") {
2696                             Map winEnv = new HashMap(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
2697 
2698                             String sdkDir = System.getenv("BASECLASSES_SDK_DIR");
2699                             if (sdkDir == null) {
2700                                 sdkDir = "C:/Program Files/Microsoft SDKs/Windows/v7.1" // Default value
2701                                 winEnv["BASECLASSES_SDK_DIR"] = sdkDir
2702                             }
2703                             environment(winEnv)
2704 
2705                             args("RESOURCE=${nativeOutputDir}/${buildType}/${WIN.media.fxpluginsRcFile}")
2706                         }
2707                     }
2708                 }
2709             }
2710 
2711             buildNative.dependsOn buildPlugins
2712 
2713             if (t.name == "linux") {
2714                 // Pre-defined command line arguments
2715                 def cfgCMDArgs = ["sh", "configure"]
2716                 def commonCfgArgs = ["--enable-shared", "--disable-debug", "--disable-static", "--disable-yasm", "--disable-doc", "--disable-programs", "--disable-everything"]
2717                 def codecsCfgArgs = ["--enable-decoder=aac,mp3,mp3float,h264", "--enable-parser=aac,h264", "--enable-demuxer=aac,h264,mpegts,mpegtsraw"]
2718 
2719                 def copyLibAVStubs = {String fromDir, String toDir ->
2720                     FileCollection config = files("config.h")
2721                     FileCollection libavcodec = files("avcodec.h", "avfft.h", "dxva2.h", "vaapi.h", "vda.h",
2722                                                       "vdpau.h", "version.h", "xvmc.h", "old_codec_ids.h")
2723                     FileCollection libavdevice = files("avdevice.h", "version.h")
2724                     FileCollection libavfilter = files("avfiltergraph.h", "avfilter.h", "buffersink.h", "buffersrc.h", "version.h");
2725                     FileCollection libavformat = files("avformat.h", "avio.h", "version.h")
2726                     FileCollection libavresample = files("avresample.h", "version.h")
2727                     FileCollection libavutil = files("adler32.h", "blowfish.h", "error.h", "log.h", "pixfmt.h",
2728                                                      "aes.h", "bswap.h", "eval.h", "lzo.h", "random_seed.h",
2729                                                      "attributes.h", "buffer.h", "fifo.h", "macros.h", "rational.h",
2730                                                      "audio_fifo.h", "channel_layout.h", "file.h", "mathematics.h", "samplefmt.h",
2731                                                      "avassert.h", "common.h", "frame.h", "md5.h", "sha.h",
2732                                                      "avconfig.h", "imgutils.h", "mem.h", "time.h", "avstring.h",
2733                                                      "cpu_internal.h", "intfloat.h", "opt.h", "version.h", "avutil.h",
2734                                                      "crc.h", "intreadwrite.h", "parseutils.h", "xtea.h", "base64.h",
2735                                                      "dict.h", "lfg.h", "pixdesc.h", "intfloat_readwrite.h", "old_pix_fmts.h", "audioconvert.h",
2736                                                      "cpu.h")
2737                     FileCollection libavutil_x86 = files("cpu.h") // Use cpu.h from x86 instead of libavutil root if exist
2738                     FileCollection libswscale = files("swscale.h", "version.h")
2739 
2740                     def copyLibAVFiles = {FileCollection files, String fDir, String tDir ->
2741                         File dir = file(tDir)
2742                         dir.mkdirs()
2743 
2744                         files.each { File file ->
2745                             copy {
2746                                 from fDir
2747                                 into tDir
2748                                 include file.name
2749                             }
2750                         }
2751                     }
2752 
2753                     copyLibAVFiles(config, fromDir, "${toDir}/include")
2754                     copyLibAVFiles(libavcodec, "${fromDir}/libavcodec", "${toDir}/include/libavcodec")
2755                     copyLibAVFiles(libavdevice, "${fromDir}/libavdevice", "${toDir}/include/libavdevice")
2756                     copyLibAVFiles(libavfilter, "${fromDir}/libavfilter", "${toDir}/include/libavfilter")
2757                     copyLibAVFiles(libavformat, "${fromDir}/libavformat", "${toDir}/include/libavformat")
2758                     copyLibAVFiles(libavresample, "${fromDir}/libavresample", "${toDir}/include/libavresample")
2759                     copyLibAVFiles(libavutil, "${fromDir}/libavutil", "${toDir}/include/libavutil")
2760                     copyLibAVFiles(libavutil_x86, "${fromDir}/libavutil/x86", "${toDir}/include/libavutil")
2761                     copyLibAVFiles(libswscale, "${fromDir}/libswscale", "${toDir}/include/libswscale")
2762 
2763                     // Copy libs
2764                     FileTree libs = fileTree(dir: "${fromDir}", include: "**/*.so*")
2765                     libs.each {File file ->
2766                         copy {
2767                             from file
2768                             into "${toDir}/lib"
2769                         }
2770                     }
2771                 }
2772 
2773                 def buildLibAVStubs = task("buildLibAVStubs", dependsOn: []) {
2774                     enabled = IS_BUILD_LIBAV_STUBS
2775 
2776                     doLast {
2777                         project.ext.libav = [:]
2778                         project.ext.libav.basedir = "${buildDir}/native/linux/libav"
2779                         project.ext.libav.versions = [ "9.14", "11.4", "12.1" ]
2780                         project.ext.libav.versionmap = [ "9.14" : "54", "11.4" : "56", "12.1" : "57" ]
2781 
2782                         libav.versions.each { version ->
2783                             def libavDir = "${libav.basedir}/libav-${version}"
2784                             for (File f : configurations.media.files) {
2785                                 if (f.name.startsWith("libav-${version}")) {
2786                                     File dir = file(libavDir)
2787                                     dir.mkdirs()
2788                                     def libavTar = "${libav.basedir}/libav-${version}.tar"
2789                                     ant.gunzip(src: f, dest: libavTar)
2790                                     ant.untar(src: libavTar, dest: libav.basedir)
2791                                 }
2792                             }
2793                         }
2794 
2795                         libav.versions.each { version ->
2796                             def libavDir = "${libav.basedir}/libav-${version}"
2797                             File dir = file(libavDir)
2798                             if (dir.exists()) {
2799                                 def configFile = "${libav.basedir}/libav-${version}/config.h"
2800                                 File cfgFile = file(configFile)
2801                                 if (!cfgFile.exists()) {
2802                                     // Add execute permissions to version.sh, otherwise build fails
2803                                     exec {
2804                                         workingDir("$libavDir")
2805                                         commandLine("chmod", "+x", "version.sh")
2806                                     }
2807                                     exec {
2808                                         workingDir("$libavDir")
2809                                         if (IS_BUILD_WORKING_LIBAV) {
2810                                             commandLine(cfgCMDArgs + commonCfgArgs + codecsCfgArgs)
2811                                         } else {
2812                                             commandLine(cfgCMDArgs + commonCfgArgs)
2813                                         }
2814                                     }
2815                                 }
2816                                 exec {
2817                                     workingDir("$libavDir")
2818                                     commandLine("make")
2819                                 }
2820                             }
2821                         }
2822 
2823                         libav.versions.each { version ->
2824                             def fromDir = "${libav.basedir}/libav-${version}"
2825                             def majorVersion = libav.versionmap[version]
2826                             def toDir = "${libav.basedir}/libav-${majorVersion}"
2827                             copyLibAVStubs(fromDir, toDir)
2828                         }
2829                     }
2830                 }
2831 
2832                 def buildLibAVFFmpegStubs = task("buildLibAVFFmpegStubs", dependsOn: []) {
2833                     enabled = IS_BUILD_LIBAV_STUBS
2834 
2835                     def extraCfgArgs = ["--build-suffix=-ffmpeg"]
2836 
2837                     doLast {
2838                         project.ext.libav = [:]
2839                         project.ext.libav.basedir = "${buildDir}/native/linux/libavffmpeg"
2840                         project.ext.libav.versions = [ "11.4" ]
2841                         project.ext.libav.versionmap = [ "11.4" : "56" ]
2842 
2843                         libav.versions.each { version ->
2844                             def libavDir = "${libav.basedir}/libav-${version}"
2845                             for (File f : configurations.media.files) {
2846                                 if (f.name.startsWith("libav-${version}")) {
2847                                     File dir = file(libavDir)
2848                                     dir.mkdirs()
2849                                     def libavTar = "${libav.basedir}/libav-${version}.tar"
2850                                     ant.gunzip(src: f, dest: libavTar)
2851                                     ant.untar(src: libavTar, dest: libav.basedir)
2852                                 }
2853                             }
2854                         }
2855 
2856                         libav.versions.each { version ->
2857                             def libavDir = "${libav.basedir}/libav-${version}"
2858                             File dir = file(libavDir)
2859                             if (dir.exists()) {
2860                                 def configFile = "${libav.basedir}/libav-${version}/config.h"
2861                                 File cfgFile = file(configFile)
2862                                 if (!cfgFile.exists()) {
2863                                     // Patch *.v files, so we have *_FFMPEG_$MAJOR instead of *_$MAJOR, otherwise library will not be loaded
2864                                     FileTree vfiles = fileTree(dir: "${libavDir}", include: "**/*.v")
2865                                     vfiles.each {File file ->
2866                                         String data = file.getText("UTF-8")
2867                                         data = data.replace("_\$MAJOR", "_FFMPEG_\$MAJOR")
2868                                         file.write(data, "UTF-8")
2869                                     }
2870                                     // Add execute permissions to version.sh, otherwise build fails
2871                                     exec {
2872                                         workingDir("$libavDir")
2873                                         commandLine("chmod", "+x", "version.sh")
2874                                     }
2875                                     exec {
2876                                         workingDir("$libavDir")
2877                                         if (IS_BUILD_WORKING_LIBAV) {
2878                                             commandLine(cfgCMDArgs + commonCfgArgs + codecsCfgArgs + extraCfgArgs)
2879                                         } else {
2880                                             commandLine(cfgCMDArgs + commonCfgArgs + extraCfgArgs)
2881                                         }
2882                                     }
2883                                 }
2884                                 exec {
2885                                     workingDir("$libavDir")
2886                                     commandLine("make")
2887                                 }
2888                             }
2889                         }
2890 
2891                         libav.versions.each { version ->
2892                             def fromDir = "${libav.basedir}/libav-${version}"
2893                             def majorVersion = libav.versionmap[version]
2894                             def toDir = "${libav.basedir}/libav-${majorVersion}"
2895                             copyLibAVStubs(fromDir, toDir)
2896 
2897                             // Special case to copy *-ffmpeg.so to *.so
2898                             FileTree libs = fileTree(dir: "${fromDir}", include: "**/*-ffmpeg.so")
2899                             libs.each {File file ->
2900                                 copy {
2901                                     from file
2902                                     into "${toDir}/lib"
2903                                     rename { String fileName ->
2904                                         fileName.replace("-ffmpeg", "")
2905                                     }
2906                                 }
2907                             }
2908                         }
2909                     }
2910                 }
2911 
2912                 def buildFFmpegStubs = task("buildFFmpegStubs", dependsOn: []) {
2913                     enabled = IS_BUILD_LIBAV_STUBS
2914 
2915                     doLast {
2916                         project.ext.libav = [:]
2917                         project.ext.libav.basedir = "${buildDir}/native/linux/ffmpeg"
2918                         project.ext.libav.versions = [ "3.3.3" ]
2919                         project.ext.libav.versionmap = [ "3.3.3" : "57" ]
2920 
2921                         libav.versions.each { version ->
2922                             def libavDir = "${libav.basedir}/ffmpeg-${version}"
2923                             for (File f : configurations.media.files) {
2924                                 if (f.name.startsWith("ffmpeg-${version}")) {
2925                                     File dir = file(libavDir)
2926                                     dir.mkdirs()
2927                                     def libavTar = "${libav.basedir}/ffmpeg-${version}.tar"
2928                                     ant.gunzip(src: f, dest: libavTar)
2929                                     ant.untar(src: libavTar, dest: libav.basedir)
2930                                 }
2931                             }
2932                         }
2933 
2934                         libav.versions.each { version ->
2935                             def libavDir = "${libav.basedir}/ffmpeg-${version}"
2936                             File dir = file(libavDir)
2937                             if (dir.exists()) {
2938                                 def configFile = "${libav.basedir}/ffmpeg-${version}/config.h"
2939                                 File cfgFile = file(configFile)
2940                                 if (!cfgFile.exists()) {
2941                                     // Add execute permissions to version.sh, otherwise build fails
2942                                     exec {
2943                                         workingDir("$libavDir")
2944                                         commandLine("chmod", "+x", "version.sh")
2945                                     }
2946                                     exec {
2947                                         workingDir("$libavDir")
2948                                         if (IS_BUILD_WORKING_LIBAV) {
2949                                             commandLine(cfgCMDArgs + commonCfgArgs + codecsCfgArgs)
2950                                         } else {
2951                                             commandLine(cfgCMDArgs + commonCfgArgs)
2952                                         }
2953                                     }
2954                                 }
2955                                 exec {
2956                                     workingDir("$libavDir")
2957                                     commandLine("make")
2958                                 }
2959                             }
2960                         }
2961 
2962                         libav.versions.each { version ->
2963                             def fromDir = "${libav.basedir}/ffmpeg-${version}"
2964                             def majorVersion = libav.versionmap[version]
2965                             def toDir = "${libav.basedir}/ffmpeg-${majorVersion}"
2966                             copyLibAVStubs(fromDir, toDir)
2967                         }
2968                     }
2969                 }
2970 
2971                 def buildAVPlugin = task( "buildAVPlugin", dependsOn: [buildPlugins, buildLibAVStubs, buildLibAVFFmpegStubs, buildFFmpegStubs]) {
2972                     enabled = IS_COMPILE_MEDIA
2973 
2974                     doLast {
2975                         if (IS_BUILD_LIBAV_STUBS) {
2976                             project.ext.libav = [:]
2977                             project.ext.libav.basedir = "${buildDir}/native/linux/libav/libav"
2978                             project.ext.libav.versions = [ "53", "54", "55", "56", "57" ]
2979                             project.ext.libav.libavffmpeg = [:]
2980                             project.ext.libav.libavffmpeg.basedir = "${buildDir}/native/linux/libavffmpeg/libav"
2981                             project.ext.libav.libavffmpeg.versions = [ "56" ]
2982                             project.ext.libav.ffmpeg = [:]
2983                             project.ext.libav.ffmpeg.basedir = "${buildDir}/native/linux/ffmpeg/ffmpeg"
2984                             project.ext.libav.ffmpeg.versions = [ "57" ]
2985 
2986                             project.ext.libav.versions.each { version ->
2987                                 def libavDir = "${project.ext.libav.basedir}-${version}"
2988                                 File dir = file(libavDir)
2989                                 if (dir.exists()) {
2990                                     exec {
2991                                         commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/gstreamer/projects/linux/avplugin")
2992                                         args("CC=${mediaProperties.compiler}", "LINKER=${mediaProperties.linker}",
2993                                              "OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}",
2994                                              "BASE_NAME=avplugin", "VERSION=${version}", "LIBAV_DIR=${libavDir}",
2995                                              "SUFFIX=", IS_64 ? "ARCH=x64" : "ARCH=x32")
2996                                     }
2997                                 }
2998                             }
2999 
3000                             project.ext.libav.libavffmpeg.versions.each { version ->
3001                                 def libavDir = "${project.ext.libav.libavffmpeg.basedir}-${version}"
3002                                 File dir = file(libavDir)
3003                                 if (dir.exists()) {
3004                                     exec {
3005                                         commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/gstreamer/projects/linux/avplugin")
3006                                         args("CC=${mediaProperties.compiler}", "LINKER=${mediaProperties.linker}",
3007                                              "OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}",
3008                                              "BASE_NAME=avplugin", "VERSION=${version}", "LIBAV_DIR=${libavDir}",
3009                                              "SUFFIX=-ffmpeg", IS_64 ? "ARCH=x64" : "ARCH=x32")
3010                                     }
3011                                 }
3012                             }
3013 
3014                             project.ext.libav.ffmpeg.versions.each { version ->
3015                                 def libavDir = "${project.ext.libav.ffmpeg.basedir}-${version}"
3016                                 File dir = file(libavDir)
3017                                 if (dir.exists()) {
3018                                     exec {
3019                                         commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/gstreamer/projects/linux/avplugin")
3020                                         args("CC=${mediaProperties.compiler}", "LINKER=${mediaProperties.linker}",
3021                                              "OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}",
3022                                              "BASE_NAME=avplugin", "VERSION=${version}", "LIBAV_DIR=${libavDir}",
3023                                              "SUFFIX=-ffmpeg", IS_64 ? "ARCH=x64" : "ARCH=x32")
3024                                     }
3025                                 }
3026                             }
3027                         } else {
3028                             // Building fxavcodec plugin (libav plugin)
3029                             exec {
3030                                 commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/gstreamer/projects/linux/avplugin")
3031                                 args("CC=${mediaProperties.compiler}", "LINKER=${mediaProperties.linker}",
3032                                      "OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}",
3033                                      "BASE_NAME=avplugin", IS_64 ? "ARCH=x64" : "ARCH=x32")
3034                             }
3035                         }
3036                     }
3037                 }
3038                 buildNative.dependsOn buildAVPlugin
3039             }
3040 
3041             if (t.name == "win") {
3042                 def buildResources = task("buildResources") {
3043                     doLast {
3044                         def rcOutputDir = "${nativeOutputDir}/${buildType}"
3045                         mkdir rcOutputDir
3046                         exec {
3047                             environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
3048                             commandLine (WIN.media.rcCompiler)
3049                             args(WIN.media.glibRcFlags)
3050                             args("/Fo${rcOutputDir}/${WIN.media.glibRcFile}", WIN.media.rcSource)
3051                         }
3052 
3053                         exec {
3054                             environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
3055                             commandLine (WIN.media.rcCompiler)
3056                             args(WIN.media.gstreamerRcFlags)
3057                             args("/Fo${rcOutputDir}/${WIN.media.gstreamerRcFile}", WIN.media.rcSource)
3058                         }
3059 
3060                         exec {
3061                             environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
3062                             commandLine (WIN.media.rcCompiler)
3063                             args(WIN.media.fxpluginsRcFlags)
3064                             args("/Fo${rcOutputDir}/${WIN.media.fxpluginsRcFile}", WIN.media.rcSource)
3065                         }
3066 
3067                         exec {
3068                             environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
3069                             commandLine (WIN.media.rcCompiler)
3070                             args(WIN.media.jfxmediaRcFlags)
3071                             args("/Fo${rcOutputDir}/${WIN.media.jfxmediaRcFile}", WIN.media.rcSource)
3072                         }
3073                     }
3074                 }
3075 
3076                 def buildGlib = task("build${t.capital}Glib", dependsOn: [buildResources]) {
3077                     enabled = IS_COMPILE_MEDIA
3078                     doLast {
3079                         exec {
3080                             environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
3081                             commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/gstreamer/projects/${projectDir}/glib-lite")
3082                             args("OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}", "BASE_NAME=glib-lite",
3083                                  IS_64 ? "ARCH=x64" : "ARCH=x32", "RESOURCE=${nativeOutputDir}/${buildType}/${WIN.media.glibRcFile}",
3084                                  "CC=${mediaProperties.compiler}", "AR=${mediaProperties.ar}", "LINKER=${mediaProperties.linker}")
3085                         }
3086                     }
3087                 }
3088                 buildGStreamer.dependsOn buildGlib
3089 
3090             } else if (t.name == "mac") {
3091                 def buildGlib = task("build${t.capital}Glib") {
3092                     enabled = IS_COMPILE_MEDIA
3093                     doLast {
3094                         exec {
3095                             commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/gstreamer/projects/${projectDir}/libffi")
3096                             args("OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}", "BASE_NAME=ffi")
3097                             args ("CC=${mediaProperties.compiler}", "LINKER=${mediaProperties.linker}", "AR=${mediaProperties.ar}")
3098                         }
3099 
3100                         exec {
3101                             commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/gstreamer/projects/${projectDir}/glib-lite")
3102                             args("OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}", "BASE_NAME=glib-lite")
3103                             args ("CC=${mediaProperties.compiler}", "LINKER=${mediaProperties.linker}")
3104                         }
3105                     }
3106                 }
3107                 buildGStreamer.dependsOn buildGlib
3108             }
3109         }
3110 
3111         buildNativeTargets.dependsOn buildNative
3112     }
3113 
3114     jar {
3115         exclude("headergen/**")
3116 
3117         dependsOn compileJava
3118         if (IS_COMPILE_MEDIA) {
3119             dependsOn buildNativeTargets
3120         }
3121     }
3122 
3123     addMavenPublication(project, [ 'graphics' ])
3124 
3125 }
3126 
3127 project(":web") {
3128     configurations {
3129         webkit
3130     }
3131     project.ext.buildModule = true
3132     project.ext.includeSources = true
3133     project.ext.moduleRuntime = true
3134     project.ext.moduleName = "javafx.web"
3135 
3136     sourceSets {
3137         main
3138         shims
3139         test
3140     }
3141 
3142     project.ext.moduleSourcePath = defaultModuleSourcePath
3143     project.ext.moduleSourcePathShim = defaultModuleSourcePathShim
3144 
3145     commonModuleSetup(project, [ 'base', 'graphics', 'controls', 'media', 'web' ])
3146 
3147     dependencies {
3148     }
3149 
3150     compileJava.dependsOn updateCacheIfNeeded
3151 
3152     task webArchiveJar(type: Jar) {
3153         from (project.file("$projectDir/src/test/resources/test/html")) {
3154             include "**/archive-*.*"
3155         }
3156         archiveName = "webArchiveJar.jar"
3157         destinationDir = file("$buildDir/testing/resources")
3158     }
3159 
3160     def gensrcDir = "${buildDir}/gensrc/java"
3161 
3162     // add in the wrappers to the compile
3163     sourceSets.main.java.srcDirs += "${gensrcDir}"
3164 
3165     if (IS_COMPILE_WEBKIT) {
3166         compileJava {
3167             // generate the native headers during compile
3168             // only needed if we are doing the native compile
3169             options.compilerArgs.addAll([
3170                 '-h', "${project.buildDir}/gensrc/headers"
3171                 ])
3172         }
3173     }
3174 
3175     // Copy these to a common location in the moduleSourcePath
3176     def copyWrappers = project.task("copyPreGeneratedWrappers", type: Copy) {
3177         from "src/main/native/Source/WebCore/bindings/java/dom3/java"
3178         into "${gensrcDir}"
3179     }
3180 
3181     compileJava.dependsOn(copyWrappers);
3182 
3183     test {
3184         doFirst {
3185             if (!IS_COMPILE_WEBKIT) {
3186                 println "*****************************************************"
3187                 println "WARNING: running web tests without building webkit."
3188                 println "The webkit native library will be copied from the JDK,"
3189                 println "which might lead to failures in some web tests."
3190                 println "To avoid these failures, you should either build"
3191                 println "webkit locally, copy the native webkit library from a"
3192                 println "recent build, or skip execution of web test cases with"
3193                 println "'-x :web:test'"
3194                 println "*****************************************************"
3195             }
3196         }
3197         // Run web tests in headless mode
3198         systemProperty 'glass.platform', 'Monocle'
3199         systemProperty 'monocle.platform', 'Headless'
3200         systemProperty 'prism.order', 'sw'
3201         dependsOn webArchiveJar
3202         def testResourceDir = file("$buildDir/testing/resources")
3203         jvmArgs "-DWEB_ARCHIVE_JAR_TEST_DIR=$testResourceDir"
3204     }
3205 
3206     task compileJavaDOMBinding()
3207 
3208     compileTargets { t ->
3209         def targetProperties = project.rootProject.ext[t.upper]
3210         def webkitProperties = targetProperties.webkit
3211         def classifier = (t.name != "linux" && t.name != "win") ? t.name :
3212                           IS_64 ? "${t.name}-amd64" : "${t.name}-i586"
3213 
3214         def webkitOutputDir = cygpath("$buildDir/${t.name}")
3215         def webkitConfig = IS_DEBUG_NATIVE ? "Debug" : "Release"
3216 
3217         File nativeBuildDir = new File("${webkitOutputDir}")
3218         nativeBuildDir.mkdirs()
3219 
3220         def compileNativeTask = task("compileNative${t.capital}", dependsOn: [compileJava]) {
3221             println "Building Webkit configuration /$webkitConfig/ into $webkitOutputDir"
3222             enabled =  (IS_COMPILE_WEBKIT)
3223 
3224             doLast {
3225                 exec {
3226                     workingDir("$webkitOutputDir")
3227                     commandLine("perl", "$projectDir/src/main/native/Tools/Scripts/set-webkit-configuration", "--$webkitConfig")
3228                     environment(["WEBKIT_OUTPUTDIR" : webkitOutputDir])
3229                 }
3230 
3231                 exec {
3232                     workingDir("$webkitOutputDir")
3233                     def cmakeArgs = "-DENABLE_TOOLS=1"
3234                     if (t.name == "win") {
3235                         String parfaitPath = IS_COMPILE_PARFAIT ? System.getenv().get("PARFAIT_PATH") + ";" : "";
3236                         Map environmentSettings = new HashMap(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
3237                         environmentSettings["PATH"] = parfaitPath + "$WINDOWS_VS_PATH"
3238                         /* To build with ICU:
3239                         1. Download http://javaweb.us.oracle.com/jcg/fx-webrevs/RT-17164/WebKitLibrariesICU.zip
3240                         and unzip it to WebKitLibraries folder.
3241                         2. Copy DLLs from
3242                         WebKitLibrariesICU.zip\WebKitLibraries\import\runtime
3243                         to %windir%\system32
3244                         3. Uncomment the line below
3245                          */
3246                         // args("--icu-unicode")
3247 
3248                         // To enable ninja build on Windows
3249                         environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT + ['CC' : 'cl', 'CXX' : 'cl'])
3250                     } else if (t.name == "mac") {
3251                         cmakeArgs = "-DCMAKE_OSX_DEPLOYMENT_TARGET=$MACOSX_MIN_VERSION -DCMAKE_OSX_SYSROOT=$MACOSX_SDK_PATH"
3252                     } else if (t.name == "linux") {
3253                         cmakeArgs = "-DCMAKE_SYSTEM_NAME=Linux -DCMAKE_C_COMPILER=${webkitProperties.compiler}"
3254                         if (IS_64) {
3255                             cmakeArgs = "$cmakeArgs -DCMAKE_SYSTEM_PROCESSOR=x86_64"
3256                         } else {
3257                             cmakeArgs = "$cmakeArgs -DCMAKE_SYSTEM_PROCESSOR=i586"
3258                         }
3259                         // TODO: Use cflags and ldflags from all platforms
3260                         def cFlags = webkitProperties.ccFlags?.join(' ') ?: ''
3261                         def lFlags = webkitProperties.linkFlags?.join(' ') ?: ''
3262                         // -shared flag should be omitted while creating executable.
3263                         def exeFlags = webkitProperties.linkFlags?.join(' ')?.replace('-shared', '') ?: ''
3264                         cmakeArgs = "$cmakeArgs -DCMAKE_C_FLAGS='${cFlags}' -DCMAKE_CXX_FLAGS='${cFlags}'"
3265                         cmakeArgs = "$cmakeArgs -DCMAKE_SHARED_LINKER_FLAGS='${lFlags}' -DCMAKE_EXE_LINKER_FLAGS='${exeFlags}'"
3266                     } else if (t.name.startsWith("arm")) {
3267                         fail("ARM target is not supported as of now.")
3268                     }
3269 
3270                     if (IS_COMPILE_PARFAIT) {
3271                         environment([
3272                             "COMPILE_PARFAIT" : "true"
3273                         ])
3274                         cmakeArgs = "-DCMAKE_C_COMPILER=parfait-gcc -DCMAKE_CXX_COMPILER=parfait-g++"
3275                     }
3276 
3277                     environment([
3278                         "JAVA_HOME"       : JDK_HOME,
3279                         "WEBKIT_OUTPUTDIR" : webkitOutputDir,
3280                         "PYTHONDONTWRITEBYTECODE" : "1",
3281                     ])
3282 
3283                     def targetCpuBitDepthSwitch = ""
3284                     if (IS_64) {
3285                         targetCpuBitDepthSwitch = "--64-bit"
3286                     } else {
3287                         targetCpuBitDepthSwitch = "--32-bit"
3288                     }
3289                     cmakeArgs += " -DJAVAFX_RELEASE_VERSION=${jfxReleaseMajorVersion}"
3290                     commandLine("perl", "$projectDir/src/main/native/Tools/Scripts/build-webkit",
3291                         "--java", "--icu-unicode", targetCpuBitDepthSwitch,
3292                         "--cmakeargs=${cmakeArgs}")
3293                 }
3294             }
3295         }
3296 
3297         // Cmake places Windows DLL in bin directory
3298         def dllDir = IS_WINDOWS ? "bin" : "lib"
3299         def copyDumpTreeNativeTask = task("copyDumpTreeNative${t.capital}", type: Copy,
3300                 dependsOn: [ compileNativeTask]) {
3301             def library = rootProject.ext[t.upper].library
3302             from "$webkitOutputDir/$webkitConfig/$dllDir/${library('DumpRenderTreeJava')}"
3303             into "$buildDir/test/${t.name}"
3304         }
3305 
3306         def copyNativeTask = task("copyNative${t.capital}", type: Copy,
3307                 dependsOn: [compileNativeTask, , copyDumpTreeNativeTask]) {
3308             enabled =  (IS_COMPILE_WEBKIT)
3309             def library = rootProject.ext[t.upper].library
3310             from "$webkitOutputDir/$webkitConfig/$dllDir/${library('jfxwebkit')}"
3311             into "$buildDir/libs/${t.name}"
3312         }
3313 
3314         if (IS_WINDOWS && t.name == "win") {
3315             def rcTask = project.task("rc${t.capital}", type: CompileResourceTask) {
3316                 compiler = webkitProperties.rcCompiler
3317                 source(webkitProperties.rcSource)
3318                 if (webkitProperties.rcFlags) {
3319                     rcParams.addAll(webkitProperties.rcFlags)
3320                 }
3321                 output(file("$webkitOutputDir/$webkitConfig/WebCore/obj"))
3322             }
3323             compileNativeTask.dependsOn rcTask
3324         }
3325 
3326         def compileJavaDOMBindingTask = task("compileJavaDOMBinding${t.capital}", type: JavaCompile,
3327                 dependsOn: [compileJava, compileNativeTask, copyNativeTask]) {
3328             destinationDir = file("$buildDir/classes/java/main")
3329             classpath = configurations.compile
3330             source = project.sourceSets.main.java.srcDirs
3331             options.compilerArgs.addAll([
3332                 '-implicit:none',
3333                 '--module-source-path', defaultModuleSourcePath
3334                 ])
3335         }
3336 
3337         compileJavaDOMBinding.dependsOn compileJavaDOMBindingTask
3338 
3339         if (!targetProperties.compileWebnodeNative) {
3340             println("Not compiling native Webkit for ${t.name} per configuration request");
3341             compileNativeTask.enabled = false
3342         }
3343     }
3344 
3345     def drtClasses = "**/com/sun/javafx/webkit/drt/**"
3346     task drtJar(type: Jar, dependsOn: compileJava) {
3347         archiveName = "drt.jar"
3348         destinationDir = file("$buildDir/test")
3349         from "$buildDir/classes/java/main/javafx.web/"
3350         include drtClasses
3351         includeEmptyDirs = false
3352     }
3353 
3354     if (IS_COMPILE_WEBKIT) {
3355         assemble.dependsOn compileJavaDOMBinding, drtJar
3356     }
3357 
3358     addMavenPublication(project, [ 'controls', 'media' ])
3359 
3360 }
3361 
3362 // This project is for system tests that need to run with a full SDK.
3363 // Most of them display a stage or do other things that preclude running
3364 // them in a shared JVM or as part of the "smoke test" run (which must
3365 // not pop up any windows or use audio). As such, they are only enabled
3366 // when FULL_TEST is specified, and each test runs in its own JVM
3367 project(":systemTests") {
3368 
3369     sourceSets {
3370         test
3371 
3372         // Source sets for standalone test apps (used for launcher tests)
3373         testapp1
3374 
3375         // Modular applications
3376         testapp2
3377         testapp3
3378         testapp4
3379         testapp5
3380         testapp6
3381     }
3382 
3383     project.ext.buildModule = false
3384     project.ext.moduleRuntime = false
3385     project.ext.moduleName = "systemTests"
3386 
3387     dependencies {
3388         testCompile project(":graphics").sourceSets.test.output
3389         testCompile project(":base").sourceSets.test.output
3390         testCompile project(":controls").sourceSets.test.output
3391         testCompile project(":swing").sourceSets.test.output
3392     }
3393 
3394     def dependentProjects = [ 'base', 'graphics', 'controls', 'media', 'web', 'swing', 'fxml' ]
3395     commonModuleSetup(project, dependentProjects)
3396 
3397     File testJavaPolicyFile = new File(rootProject.buildDir, TESTJAVAPOLICYFILE);
3398     File testRunArgsFile = new File(rootProject.buildDir,TESTRUNARGSFILE);
3399 
3400     File stRunArgsFile = new File(project.buildDir,"st.run.args");
3401 
3402     def sts = task("systemTestSetup") {
3403         outputs.file(stRunArgsFile)
3404 
3405         doLast() {
3406             stRunArgsFile.delete()
3407 
3408             logger.info("Creating patchmodule.args file ${stRunArgsFile}")
3409 
3410             // Create an argfile with the information needed to launch
3411             // the stand alone system unit tests.
3412 
3413             //First add in all of the patch-module args we use for the
3414             //normal unit tests, copied from test.run.args
3415             testRunArgsFile.eachLine { str ->
3416                 stRunArgsFile <<  "${str}\n"
3417             }
3418 
3419             // Now add in the working classpath elements (junit, test classes...)
3420             stRunArgsFile <<  "-cp \"\\\n"
3421             test.classpath.each() { elem ->
3422                 def e = cygpath("${elem}")
3423                 stRunArgsFile <<  "  ${e}${File.pathSeparator}\\\n"
3424             }
3425             stRunArgsFile <<  "\"\n"
3426         }
3427     }
3428 
3429     test.dependsOn(sts)
3430     test.dependsOn(createTestArgfiles);
3431 
3432     // Tasks to create standalone test applications for the launcher tests
3433 
3434     if (project.hasProperty('testModulePathArgs')) {
3435         compileTestapp1Java.options.compilerArgs.addAll(testModulePathArgs)
3436     }
3437     dependentProjects.each { e ->
3438         compileTestapp1Java.dependsOn(rootProject.project(e).testClasses)
3439     }
3440 
3441     def testapp1JarName = "testapp1.jar"
3442     task createTestapp1Jar1(type: Jar) {
3443         dependsOn compileTestapp1Java
3444         enabled = IS_FULL_TEST
3445 
3446         destinationDir = file("$buildDir/testapp1")
3447         archiveName = testapp1JarName
3448         includeEmptyDirs = false
3449         from project.sourceSets.testapp1.java.outputDir
3450         include("testapp/**")
3451         include("com/javafx/main/**")
3452 
3453         manifest {
3454             attributes(
3455                 "Main-Class" : "com.javafx.main.Main",
3456                 "JavaFX-Version" : "2.2",
3457                 "JavaFX-Application-Class" : "testapp.HelloWorld",
3458                 "JavaFX-Class-Path" : "jar2.jar"
3459             )
3460         }
3461     }
3462 
3463     task createTestapp1Jar2(type: Jar) {
3464         dependsOn compileTestapp1Java
3465         enabled = IS_FULL_TEST
3466 
3467         destinationDir = file("$buildDir/testapp1")
3468         archiveName = "jar2.jar";
3469         includeEmptyDirs = false
3470         from project.sourceSets.testapp1.java.outputDir
3471         include("pkg2/**")
3472     }
3473 
3474     task createTestApps() {
3475         dependsOn(createTestapp1Jar1)
3476         dependsOn(createTestapp1Jar2)
3477     }
3478     test.dependsOn(createTestApps);
3479 
3480     def modtestapps = [ "testapp2", "testapp3", "testapp4", "testapp5", "testapp6"  ]
3481     modtestapps.each { testapp ->
3482         def testappCapital = testapp.capitalize()
3483         def copyTestAppTask = task("copy${testappCapital}", type: Copy) {
3484             from project.sourceSets."${testapp}".java.outputDir
3485             from project.sourceSets."${testapp}".output.resourcesDir
3486             into "${project.buildDir}/modules/${testapp}"
3487         }
3488 
3489         def List<String> testAppSourceDirs = []
3490         project.sourceSets."${testapp}".java.srcDirs.each { dir ->
3491             testAppSourceDirs += dir
3492         }
3493         def testappCompileTasks = project.getTasksByName("compile${testappCapital}Java", true);
3494         def testappResourceTasks = project.getTasksByName("process${testappCapital}Resources", true);
3495         testappCompileTasks.each { appCompileTask ->
3496             appCompileTask.options.compilerArgs.addAll([
3497                 '-implicit:none',
3498                 '--module-source-path', testAppSourceDirs.join(File.pathSeparator),
3499                 ] )
3500             if (project.hasProperty('testModulePathArgs')) {
3501                 appCompileTask.options.compilerArgs.addAll(testModulePathArgs)
3502             }
3503 
3504             dependentProjects.each { e ->
3505                 appCompileTask.dependsOn(rootProject.project(e).testClasses)
3506             }
3507 
3508             copyTestAppTask.dependsOn(appCompileTask)
3509         }
3510         testappResourceTasks.each { appResourceTask ->
3511             copyTestAppTask.dependsOn(appResourceTask)
3512         }
3513 
3514         createTestApps.dependsOn(copyTestAppTask)
3515     }
3516 
3517     test {
3518         enabled = IS_FULL_TEST
3519 
3520         // Parse testPatchModuleArgs looking for "--module-path".
3521         // Save path if found so we can pass it to the module launcher tests
3522         def pendingModulePath = false
3523         testPatchModuleArgs.each { str ->
3524             if (pendingModulePath) {
3525                 project.ext.launcherModulePath = str;
3526                 pendingModulePath = false
3527             } else if (str == "--module-path") {
3528                 pendingModulePath = true
3529             }
3530         }
3531 
3532         // Properties passed to launcher tests
3533         systemProperty "launchertest.testapp1.jar", "build/testapp1/$testapp1JarName"
3534         modtestapps.each { testapp ->
3535             systemProperty "launchertest.${testapp}.module.path",
3536                     "${project.buildDir}/modules/${testapp}"
3537         }
3538 
3539         // Properties passed to test.util.Util
3540         systemProperties 'worker.debug': IS_WORKER_DEBUG
3541         systemProperties 'worker.patchmodule.file': cygpath(stRunArgsFile.path)
3542         if (project.hasProperty("launcherModulePath")) {
3543             systemProperties 'worker.module.path': launcherModulePath
3544         }
3545         systemProperties 'worker.patch.policy': cygpath(testJavaPolicyFile.path)
3546         systemProperties 'worker.java.cmd': JAVA
3547 
3548         if (rootProject.hasProperty("ClipShapeTest.numTests")) {
3549             systemProperty "ClipShapeTest.numTests", rootProject.getProperty("ClipShapeTest.numTests")
3550         }
3551 
3552         if (!IS_USE_ROBOT) {
3553             // Disable all robot-based visual tests
3554             exclude("test/robot/**");
3555         }
3556         if (!IS_UNSTABLE_TEST) {
3557             // JDK-8196607 Don't run monocle test cases 
3558             exclude("test/robot/com/sun/glass/ui/monocle/**");
3559         }
3560         if (!IS_AWT_TEST) {
3561             // Disable all AWT-based tests
3562             exclude("**/javafx/embed/swing/*.*");
3563             exclude("**/com/sun/javafx/application/Swing*.*");
3564         }
3565 
3566         if (!HAS_JAVAFX_MODULES) {
3567             jvmArgs += qualExportsSwing
3568         }
3569 
3570         forkEvery = 1
3571     }
3572 }
3573 
3574 allprojects {
3575     // The following block is a workaround for the fact that presently Gradle
3576     // can't set the -XDignore.symbol.file flag, because it appears that the
3577     // javac API is lacking support for it. So what we'll do is find any Compile
3578     // task and manually provide the options necessary to fire up the
3579     // compiler with the right settings.
3580     tasks.withType(JavaCompile) { compile ->
3581         if (compile.options.hasProperty("useAnt")) {
3582             compile.options.useAnt = true
3583             compile.options.useDepend = IS_USE_DEPEND
3584         } else if (compile.options.hasProperty("incremental")) {
3585             compile.options.incremental = IS_INCREMENTAL
3586         }
3587         compile.options.debug = true // we always generate debugging info in the class files
3588         compile.options.debugOptions.debugLevel = IS_DEBUG_JAVA ? "source,lines,vars" : "source,lines"
3589         compile.options.fork = true
3590 
3591         compile.options.forkOptions.executable = JAVAC
3592 
3593         compile.options.warnings = IS_LINT
3594 
3595         compile.options.compilerArgs += ["-XDignore.symbol.file", "-encoding", "UTF-8"]
3596 
3597         // we use a custom javadoc command
3598         project.javadoc.enabled = false
3599 
3600         // Add in the -Xlint options
3601         if (IS_LINT) {
3602             LINT.split("[, ]").each { s ->
3603                 compile.options.compilerArgs += "-Xlint:$s"
3604             }
3605         }
3606     } // tasks with javaCompile
3607 
3608     // If I am a module....
3609     if (project.hasProperty('moduleSourcePath') &&
3610             (project.hasProperty('buildModule') && project.buildModule)) {
3611         project.compileJava {
3612             options.compilerArgs.addAll([
3613                 '-implicit:none',
3614                 '--module-source-path', project.moduleSourcePath
3615                 ])
3616         }
3617         // no jars needed for modules
3618         project.jar.enabled = false
3619 
3620         // and redirect the resources into the module
3621         project.processResources.destinationDir = project.moduleDir
3622     }
3623 
3624     if (project.hasProperty('moduleSourcePathShim') &&
3625             project.sourceSets.hasProperty('shims')) {
3626 
3627         // sync up the obvious source directories with the shims
3628         // others (like the shaders in graphics) should be added in there
3629         project.sourceSets.shims.java.srcDirs += project.sourceSets.main.java.srcDirs
3630         project.sourceSets.shims.java.srcDirs += "$buildDir/gensrc/java"
3631 
3632         project.compileShimsJava {
3633             options.compilerArgs.addAll([
3634                 '-implicit:none',
3635                 '--module-source-path', project.moduleSourcePathShim
3636                 ])
3637         }
3638         project.compileShimsJava.dependsOn(project.compileJava)
3639 
3640         def copyGeneratedShimsTask = task("copyGeneratedShims", type: Copy, dependsOn: [compileShimsJava, processShimsResources]) {
3641             from project.sourceSets.shims.java.outputDir
3642             into "${rootProject.buildDir}/shims"
3643             if (HAS_JAVAFX_MODULES) {
3644                 exclude("*/module-info.class")
3645             }
3646         }
3647 
3648         project.processShimsResources.dependsOn(project.processResources)
3649 
3650         // shims resources should have the main resouces as a base
3651         project.sourceSets.shims.resources.srcDirs += project.sourceSets.main.resources.srcDirs
3652 
3653         // and redirect the resources into the module
3654         project.processShimsResources.destinationDir = project.moduleShimsDir
3655 
3656        compileTestJava.dependsOn(copyGeneratedShimsTask)
3657     }
3658 
3659     if (project.hasProperty('modulePathArgs')) {
3660         project.compileJava.options.compilerArgs.addAll(modulePathArgs)
3661     }
3662 
3663     if (project.hasProperty('testModulePathArgs')) {
3664         project.compileTestJava.options.compilerArgs.addAll(testModulePathArgs)
3665     }
3666 
3667     if (project.hasProperty('testPatchModuleArgs')) {
3668         project.test.jvmArgs += testPatchModuleArgs
3669     }
3670 
3671     /* Note: we should not have to add extraAddExports to the normal
3672      * modular compile, as it contains all of the module-info files.
3673      * In fact doing so might cover up a module-info issue.
3674      * so we don't do it, and I will leave this commented out
3675      * block as a reminder of this fact.
3676     if (project.hasProperty('extraAddExports')) {
3677         project.compileJava.options.compilerArgs.addAll(extraAddExports);
3678     }
3679     */
3680 
3681     if (project.hasProperty('testAddExports')) {
3682         project.compileTestJava.options.compilerArgs.addAll(testAddExports);
3683         project.test.jvmArgs += testAddExports
3684     }
3685 
3686     if (rootProject.hasProperty("EXTRA_TEST_ARGS") && project.hasProperty('test')) {
3687         EXTRA_TEST_ARGS.split(' ').each() { e ->
3688             project.test.jvmArgs += e
3689         }
3690     }
3691 
3692     if (rootProject.hasProperty("EXTRA_COMPILE_ARGS") && project.hasProperty('compileJava')) {
3693         project.compileJava.options.compilerArgs.addAll(EXTRA_COMPILE_ARGS.split(' '))
3694     }
3695 
3696     if (rootProject.hasProperty("EXTRA_COMPILE_ARGS") && project.hasProperty('compileTestJava')) {
3697         project.compileTestJava.options.compilerArgs.addAll(EXTRA_COMPILE_ARGS.split(' '))
3698     }
3699 }
3700 
3701 /******************************************************************************
3702  *                                                                            *
3703  *                             Top Level Tasks                                *
3704  *                                                                            *
3705  *  These are the tasks which are defined only for the top level project and  *
3706  *  not for any sub projects. These are generally the entry point that is     *
3707  *  used by Hudson and by the continuous build system.                        *
3708  *                                                                            *
3709  *****************************************************************************/
3710 
3711 task clean() {
3712     group = "Basic"
3713     description = "Deletes the build directory and the build directory of all sub projects"
3714     getSubprojects().each { subProject ->
3715         dependsOn(subProject.getTasksByName("clean", true));
3716     }
3717     doLast {
3718         delete(buildDir);
3719     }
3720 }
3721 
3722 task cleanAll() {
3723     group = "Basic"
3724     description = "Scrubs the repo of build artifacts"
3725     dependsOn(clean)
3726     doLast {
3727         //delete(".gradle"); This causes problems on windows.
3728         delete("buildSrc/build");
3729     }
3730 }
3731 
3732 task createMSPfile() {
3733     group = "Build"
3734     File mspFile = new File(rootProject.buildDir,MODULESOURCEPATH)
3735     outputs.file(mspFile)
3736 
3737     doLast {
3738         mspFile.delete()
3739         mspFile << "--module-source-path\n"
3740         mspFile << defaultModuleSourcePath
3741         mspFile << "\n"
3742 
3743         if (!HAS_JAVAFX_MODULES) {
3744             appendQualExports(mspFile, qualExportsSwing)
3745         }
3746     }
3747 }
3748 
3749 task javadoc(type: Javadoc, dependsOn: createMSPfile) {
3750     group = "Basic"
3751     description = "Generates the JavaDoc for all the public API"
3752     executable = JAVADOC
3753     def projectsToDocument = [
3754             project(":base"), project(":graphics"), project(":controls"), project(":media"),
3755             project(":swing"), /*project(":swt"),*/ project(":fxml"), project(":web")]
3756     source(projectsToDocument.collect({
3757         [it.sourceSets.main.java]
3758     }));
3759     setDestinationDir(new File(buildDir, 'javadoc'));
3760 
3761     exclude("com/**/*", "Compile*", "javafx/builder/**/*", "javafx/scene/accessibility/**/*");
3762 
3763     options.tags("apiNote:a:API Note:")
3764     options.tags("implSpec:a:Implementation Requirements:")
3765     options.tags("implNote:a:Implementation Note:")
3766     options.tags("param")
3767     options.tags("return")
3768     options.tags("throws")
3769     options.tags("moduleGraph:X")
3770     options.tags("since")
3771     options.tags("version")
3772     options.tags("serialData")
3773     options.tags("factory")
3774     options.tags("see")
3775 
3776     options.windowTitle("${javadocTitle}")
3777     options.header("${javadocHeader}")
3778     options.bottom("${javadocBottom}")
3779     options.locale("en");
3780     if (JDK_DOCS_LINK != "") {
3781         options.linksOffline(JDK_DOCS, JDK_DOCS_LINK);
3782     } else {
3783         options.links(JDK_DOCS);
3784     }
3785     options.addBooleanOption("XDignore.symbol.file").setValue(true);
3786     options.addBooleanOption("Xdoclint:${DOC_LINT}").setValue(IS_DOC_LINT);
3787     options.addBooleanOption("html5").setValue(true);
3788     options.addBooleanOption("javafx").setValue(true);
3789     options.addBooleanOption("use").setValue(true);
3790 
3791     options.setOptionFiles([
3792         new File(rootProject.buildDir,MODULESOURCEPATH)
3793         ]);
3794 
3795     doLast {
3796         // FIXME: remove JDK 10 logic once minimum JDK is bumped to 11
3797         def isBootJdk10 = jdkVersion.startsWith("10")
3798         projectsToDocument.each { p ->
3799             def destDir = isBootJdk10 ? "$buildDir/javadoc" : "$buildDir/javadoc/${p.ext.moduleName}"
3800             copy {
3801                 from("$p.projectDir/src/main/docs") {
3802                     include "**/*.html"
3803                     filter { line->
3804                         line = line.replace("@FXVERSION@", RELEASE_VERSION)
3805                     }
3806                 }
3807                 from("$p.projectDir/src/main/docs") {
3808                     exclude "**/*.html"
3809                 }
3810 
3811                 into destDir
3812             }
3813         }
3814     }
3815 
3816     dependsOn(projectsToDocument.collect { project -> project.getTasksByName("classes", true)});
3817 }
3818 
3819 task sdk() {
3820     if (DO_BUILD_SDK_FOR_TEST) {
3821         rootProject.getTasksByName("test", true).each { t ->
3822             if (t.enabled) t.dependsOn(sdk)
3823         }
3824     }
3825 }
3826 
3827 task jmods() {
3828     dependsOn(sdk)
3829     // real work items added later.
3830 }
3831 
3832 task appsjar() {
3833     dependsOn(sdk)
3834     // Note: the jar dependencies get added elsewhere see project(":apps")
3835 }
3836 
3837 // these are empty tasks, allowing us to depend on the task, which may have other
3838 // real work items added later.
3839 task copyAppsArtifacts() {
3840     dependsOn(appsjar)
3841 }
3842 
3843 task apps() {
3844     dependsOn(sdk)
3845     dependsOn(appsjar)
3846     dependsOn(copyAppsArtifacts)
3847 }
3848 
3849 task findbugs() {
3850     dependsOn(sdk)
3851 
3852     doLast {
3853         if (!BUILD_CLOSED) {
3854             println "findbugs task is only run for a closed build"
3855         }
3856     }
3857 }
3858 
3859 // create the zip file of modules for a JDK build
3860 task jdkZip {
3861     dependsOn(sdk)
3862 }
3863 
3864 // The following tasks are for the closed build only. They are a no-op for the open build
3865 
3866 task checkCache() {
3867     dependsOn(updateCacheIfNeeded)
3868 }
3869 
3870 task publicExports() {
3871     dependsOn(sdk, jmods, apps, javadoc, jdkZip)
3872     // note the real work is below in the compileTargets
3873 }
3874 
3875 task perf() {
3876     dependsOn(sdk, apps)
3877     doLast {
3878         if (!BUILD_CLOSED) {
3879             println "perf task is only run for a closed build"
3880         }
3881     }
3882 }
3883 
3884 task zips() {
3885     dependsOn(sdk, jmods, javadoc, apps, jdkZip, publicExports, perf)
3886     // note the real work is below in the compileTargets
3887 }
3888 
3889 task all() {
3890     dependsOn(sdk,publicExports,apps,perf,zips)
3891 }
3892 
3893 
3894 // Construct list of subprojects that are modules
3895 ext.moduleProjList = []
3896 subprojects {
3897     if (project.hasProperty("buildModule") && project.ext.buildModule) {
3898         rootProject.ext.moduleProjList += project
3899         println "module: $project (buildModule=YES)"
3900     } else {
3901         println "module: $project (buildModule=NO)"
3902     }
3903 }
3904 
3905 
3906 // Define the sdk task, which also produces the javafx.swt modular jar
3907 
3908 compileTargets { t ->
3909 
3910     def javafxSwtTask = task("javafxSwt$t.capital", type: Jar) {
3911         enabled = COMPILE_SWT
3912         group = "Basic"
3913         description = "Creates the javafx-swt.jar for the $t.name target"
3914         archiveName = "${project(":swt").buildDir}/libs/javafx-swt.jar";
3915         includeEmptyDirs = false
3916         from("${project(":swt").buildDir}/classes/java/main");
3917         include("**/javafx/embed/swt/**")
3918 
3919         dependsOn(
3920             project(":swt").compileJava,
3921             project(":swt").processResources,
3922             // note: assemble and classes are not enough for DidWork
3923             project(":swt").classes,
3924             // classes is needed for a jar copy
3925             )
3926     }
3927 
3928     // FIXME: do we really need the index task for this modular jar?
3929     def javafxSwtIndexTask = task("javafxSwtIndex$t.capital") {
3930         //the following is a workaround for the lack of indexing in gradle 1.4 through 1.7
3931         dependsOn(javafxSwtTask)
3932 
3933         doLast() {
3934             ant.jar (update: true, index: true, destfile: javafxSwtTask.archiveName)
3935         }
3936     }
3937 
3938     def sdkTask = task("sdk$t.capital") {
3939         group = "Basic"
3940         dependsOn(javafxSwtIndexTask)
3941     }
3942 
3943     sdk.dependsOn(sdkTask)
3944 }
3945 
3946 project(":apps") {
3947     // The apps build is Ant based, we will exec ant from gradle.
3948 
3949     // Download the Lucene libraries needed for the Ensemble8 app
3950     def luceneVersion = "7.4.0"
3951     getConfigurations().create("lucene");
3952     dependencies {
3953         lucene group: "org.apache.lucene", name: "lucene-core", version: luceneVersion
3954         lucene group: "org.apache.lucene", name: "lucene-grouping", version: luceneVersion
3955         lucene group: "org.apache.lucene", name: "lucene-queryparser", version: luceneVersion
3956     }
3957 
3958     // Copy Lucene libraries into the Ensemble8/lib directory
3959     File ensembleLibDir = rootProject.file("apps/samples/Ensemble8/lib");
3960     def libNames = [ "lucene-core-${luceneVersion}.jar",
3961                      "lucene-grouping-${luceneVersion}.jar",
3962                      "lucene-queryparser-${luceneVersion}.jar" ]
3963 
3964 
3965     task getLucene(type: Copy) {
3966         doFirst {
3967             ensembleLibDir.mkdirs();
3968         }
3969         into ensembleLibDir
3970         includeEmptyDirs = false
3971         configurations.lucene.files.each { f ->
3972             libNames.each { name ->
3973                 if (name == f.getName()) {
3974                     from f.getPath()
3975                 }
3976             }
3977         }
3978     }
3979 
3980     compileTargets { t ->
3981         List<String> params = []
3982 
3983         params << "-DtargetBld=$t.name"
3984 
3985         if (!rootProject.ext[t.upper].compileSwing) {
3986             params << "-DJFX_CORE_ONLY=true"
3987         }
3988         params << "-Dplatforms.JDK_1.9.home=${rootProject.ext.JDK_HOME}"
3989         params << "-Dcompile.patch=@${rootProject.buildDir}/${COMPILEARGSFILE}"
3990         params << "-Drun.patch=@${rootProject.buildDir}/${RUNARGSFILE}"
3991 
3992         def appsJar = project.task("appsJar${t.capital}") {
3993             dependsOn(sdk, getLucene)
3994             doLast() {
3995                 ant(t.name,
3996                       projectDir.path,
3997                       "appsJar",
3998                       params);
3999             }
4000         }
4001         rootProject.appsjar.dependsOn(appsJar)
4002 
4003         def appsClean = project.task("clean${t.capital}") {
4004             doLast() {
4005                 ant(t.name,
4006                       project.projectDir.path,
4007                       "clean",
4008                       params);
4009                 delete(ensembleLibDir);
4010             }
4011         }
4012         rootProject.clean.dependsOn(appsClean)
4013     }
4014 }
4015 
4016 // Tasks to create the disk layout for the sdk, jmods, and docs
4017 // in the artifacts directory (publicExports), and zip them up in
4018 // artifacts/bundles (zips)
4019 // These tasks are only used for the standalone SDK.
4020 compileTargets { t ->
4021     if (!HAS_JAVAFX_MODULES) {
4022         def targetProperties = rootProject.ext[t.upper]
4023         def platformPrefix = targetProperties.platformPrefix
4024 
4025         def artifactsDir = "${rootProject.buildDir}/artifacts"
4026         def bundlesDir = "${artifactsDir}/bundles"
4027 
4028         def sdkDirName = "${platformPrefix}sdk"
4029         def sdkDir = "${rootProject.buildDir}/${sdkDirName}"
4030         def sdkBundleName = "javafx-sdk-${RELEASE_VERSION}"
4031         def sdkArtifactsDir = "${artifactsDir}/${sdkBundleName}"
4032 
4033         def docsDirName = "javadoc"
4034         def docsDir = "${rootProject.buildDir}/${docsDirName}"
4035         def docsBundleName = "javafx-docs-${RELEASE_VERSION}"
4036         def docsArtifactsDir = "${artifactsDir}/${docsBundleName}"
4037 
4038         def jmodsDirName = "jmods"
4039         def jmodsDir = "${rootProject.buildDir}/${jmodsDirName}"
4040         def jmodsBundleName = "javafx-jmods-${RELEASE_VERSION}"
4041         def jmodsArtifactsDir = "${artifactsDir}/${jmodsBundleName}"
4042 
4043         def publicExportsTask = task ("publicExportsStandalone${t.capital}") {
4044             group = "Basic"
4045             description = "Creates the disk layout for sdk, jmods, and docs"
4046         }
4047         publicExports.dependsOn(publicExportsTask)
4048 
4049         def copyArtifactsSdkTask = task("copyArtifactsSdk$t.capital", type: Copy, dependsOn: [sdk,jmods,apps,javadoc]) {
4050             from sdkDir
4051             into sdkArtifactsDir
4052         }
4053         publicExportsTask.dependsOn(copyArtifactsSdkTask)
4054 
4055         // Need to modify file permissions Windows to make sure that the
4056         // execute bit is set, and that the files are world readable
4057         def chmodArtifactsSdkTask = task("chmodArtifactsSdk$t.capital", dependsOn: copyArtifactsSdkTask) {
4058             if (IS_WINDOWS) {
4059                 doLast {
4060                     exec {
4061                         workingDir(sdkArtifactsDir)
4062                         commandLine("chmod", "-R", "755", ".")
4063                     }
4064                 }
4065             }
4066         }
4067         publicExportsTask.dependsOn(chmodArtifactsSdkTask)
4068 
4069         def copyArtifactsDocsTask = task("copyArtifactsDocs$t.capital", type: Copy, dependsOn: chmodArtifactsSdkTask) {
4070             from docsDir
4071             into "${docsArtifactsDir}/api"
4072         }
4073         publicExportsTask.dependsOn(copyArtifactsDocsTask)
4074 
4075         def copyArtifactsJmodsTask = task("copyArtifactsJmods$t.capital", type: Copy, dependsOn: copyArtifactsDocsTask) {
4076             from jmodsDir
4077             into "${jmodsArtifactsDir}"
4078         }
4079         publicExportsTask.dependsOn(copyArtifactsJmodsTask)
4080 
4081         def zipsTask = task ("zipsStandalone${t.capital}") {
4082             group = "Basic"
4083             description = "Creates the public zip bundles"
4084         }
4085         zips.dependsOn(zipsTask)
4086 
4087         // Use native zip tool so that file permissions are preserved on Windows
4088         def zipSdkTask = task("zipSdk$t.capital", dependsOn: publicExportsTask) {
4089             doLast {
4090                 def outZipFile = "${bundlesDir}/${sdkBundleName}.zip"
4091                 mkdir bundlesDir
4092                 exec {
4093                     workingDir(artifactsDir)
4094                     commandLine("zip", "-q", "-r", outZipFile, sdkBundleName)
4095                 }
4096             }
4097         }
4098         zipsTask.dependsOn(zipSdkTask)
4099 
4100         def zipDocsTask = task("zipDocs$t.capital", type: Zip, dependsOn: zipSdkTask) {
4101             destinationDir = file("${bundlesDir}")
4102             archiveName = "${docsBundleName}.zip"
4103             includeEmptyDirs = false
4104             from docsArtifactsDir
4105             into "${docsBundleName}"
4106         }
4107         zipsTask.dependsOn(zipDocsTask)
4108 
4109         def zipJmodsTask = task("zipJmods$t.capital", type: Zip, dependsOn: zipDocsTask) {
4110             destinationDir = file("${bundlesDir}")
4111             archiveName = "${jmodsBundleName}.zip"
4112             includeEmptyDirs = false
4113             from jmodsArtifactsDir
4114             into "${jmodsBundleName}"
4115         }
4116         zipsTask.dependsOn(zipJmodsTask)
4117     }
4118 }
4119 
4120 
4121 /******************************************************************************
4122  *                                                                            *
4123  *                               Modules                                      *
4124  *                                                                            *
4125  *****************************************************************************/
4126 
4127 ext.moduleDependencies = [file("dependencies")]
4128 
4129 task buildModules {
4130 }
4131 
4132 // Combine the classes, lib, and bin for each module
4133 compileTargets { t ->
4134     def targetProperties = project.ext[t.upper]
4135 
4136     def platformPrefix = targetProperties.platformPrefix
4137     def bundledSdkDirName = "${platformPrefix}modular-sdk"
4138     def bundledSdkDir = "${rootProject.buildDir}/${bundledSdkDirName}"
4139     def modulesDir = "${bundledSdkDir}/modules"
4140     def modulesCmdsDir = "${bundledSdkDir}/modules_cmds"
4141     def modulesLibsDir = "${bundledSdkDir}/modules_libs"
4142     def modulesSrcDir = "${bundledSdkDir}/modules_src"
4143     def modulesConfDir = "${bundledSdkDir}/modules_conf"
4144     def modulesLegalDir = "${bundledSdkDir}/modules_legal"
4145     def modulesMakeDir = "${bundledSdkDir}/make"
4146 
4147     final File runArgsFile = file("${rootProject.buildDir}/${RUNARGSFILE}")
4148     final File compileArgsFile = file("${rootProject.buildDir}/${COMPILEARGSFILE}")
4149 
4150     project.files(runArgsFile);
4151 
4152     def buildModulesTask = task("buildModules$t.capital", group: "Build") {
4153         // BUNDLED SDK
4154 
4155         // Copy dependencies/*/module-info.java.extra
4156         // merging as needed, removing duplicates
4157         // only lines with 'exports' will be copied
4158         def dependencyRoots = moduleDependencies
4159         if (rootProject.hasProperty("closedModuleDepedencies")) {
4160             dependencyRoots = [dependencyRoots, closedModuleDepedencies].flatten()
4161         }
4162 
4163         // Create the inputs/outputs list first to support UP-TO-DATE
4164         ArrayList outputNames = new ArrayList()
4165         dependencyRoots.each { root ->
4166             FileTree ft = fileTree(root).include('**/*.extra')
4167             ft.each() { e->
4168                 inputs.file(e)
4169 
4170                 String usename = e.path
4171                 String filePath = e.getAbsolutePath()
4172                 String folderPath = root.getAbsolutePath()
4173                 if (filePath.startsWith(folderPath)) {
4174                     usename = filePath.substring(folderPath.length() + 1);
4175                 }
4176                 if (! outputNames.contains(usename) ) {
4177                     outputNames.add(usename)
4178                 }
4179             }
4180         }
4181 
4182         outputNames.each() { e->
4183                 File f = new File(modulesSrcDir, e)
4184                 outputs.file(f)
4185         }
4186 
4187         def outputPolicyDir = "${modulesConfDir}/java.base/security"
4188         def outputPolicyFile = file("${outputPolicyDir}/java.policy.extra")
4189 
4190         outputs.file(outputPolicyFile)
4191         moduleProjList.each { project ->
4192             def policyDir = "${project.projectDir}/src/main/conf/security"
4193             def policyFile = file("${policyDir}/java.policy")
4194             if (policyFile.exists()) {
4195                 inputs.file(policyFile)
4196             }
4197         }
4198 
4199         doLast {
4200             Map extras = [:]
4201 
4202             dependencyRoots.each { root ->
4203                 FileTree ft = fileTree(root).include('**/*.extra')
4204                 ft.each() { e->
4205                     String usename = e.path
4206                     String filePath = e.getAbsolutePath()
4207                     String folderPath = root.getAbsolutePath()
4208                     if (filePath.startsWith(folderPath)) {
4209                         usename = filePath.substring(folderPath.length() + 1);
4210                     }
4211                     if (extras.containsKey(usename)) {
4212                         List<String> lines = extras.get(usename)
4213                         e.eachLine { line ->
4214                             line = line.trim()
4215                             if (line.length() > 1 && Character.isLetter(line.charAt(0))) {
4216                                 lines << line
4217                             }
4218                         }
4219 
4220                     } else {
4221                         List<String> lines = []
4222                         e.eachLine { line ->
4223                             line = line.trim()
4224                             if (line.length() > 1 && Character.isLetter(line.charAt(0))) {
4225                                 lines << line
4226                             }
4227                         }
4228                         extras.put(usename,lines)
4229                     }
4230                 }
4231             }
4232             extras.keySet().each() { e->
4233                 File f = new File(modulesSrcDir, e)
4234                 f.getParentFile().mkdirs()
4235                 f.delete()
4236 
4237                 extras.get(e).unique().each() { l->
4238                     f << l
4239                     f << "\n"
4240                 }
4241             }
4242 
4243             // concatecate java.policy files into a single file
4244             //
4245             mkdir outputPolicyDir
4246             outputPolicyFile.delete()
4247             moduleProjList.each { project ->
4248                 def policyDir = "${project.projectDir}/src/main/conf/security"
4249                 def policyFile = file("${policyDir}/java.policy")
4250                 if (policyFile.exists()) outputPolicyFile << policyFile.text
4251             }
4252         }
4253     }
4254     buildModules.dependsOn(buildModulesTask)
4255 
4256     // BUNDLED SDK
4257     moduleProjList.each { project ->
4258         // Copy classes, bin, and lib directories
4259 
4260         def moduleName = project.ext.moduleName
4261         def buildDir = project.buildDir
4262 
4263         def srcClassesDir = "${buildDir}/${platformPrefix}module-classes"
4264         def dstClassesDir = "${modulesDir}/${moduleName}"
4265         def copyClassFilesTask = project.task("copyClassFiles$t.capital", type: Copy, dependsOn: project.assemble) {
4266             from srcClassesDir
4267             into dstClassesDir
4268             exclude("module-info.class")
4269         }
4270 
4271         def srcCmdsDir = "${buildDir}/${platformPrefix}module-bin"
4272         def dstCmdsDir = "${modulesCmdsDir}/${moduleName}"
4273         def copyBinFilesTask = project.task("copyBinFiles$t.capital", type: Copy, dependsOn: copyClassFilesTask) {
4274             from srcCmdsDir
4275             into dstCmdsDir
4276         }
4277 
4278         def srcLibsDir = "${buildDir}/${platformPrefix}module-lib"
4279         def dstLibsDir = "${modulesLibsDir}/${moduleName}"
4280         def copyLibFilesTask = project.task("copyLibFiles$t.capital", type: Copy, dependsOn: copyBinFilesTask) {
4281             from srcLibsDir
4282             into dstLibsDir
4283         }
4284 
4285         // Copy module sources
4286         // FIXME: javafx.swt sources?
4287         def copySources = project.hasProperty("includeSources") && project.includeSources
4288         def copySourceFilesTask = project.task("copySourceFiles$t.capital", type: Copy, dependsOn: copyLibFilesTask) {
4289             if (copySources) {
4290                 from "${project.projectDir}/src/main/java"
4291                 if (project.name.equals("base") || project.name.equals("swing")) {
4292                     from "${project.projectDir}/build/gensrc/java"
4293                 }
4294                 if (project.name.equals("web")) {
4295                     from "${project.projectDir}/src/main/native/Source/WebCore/bindings/java/dom3/java"
4296                 }
4297             } else {
4298                 from "${project.projectDir}/src/main/java/module-info.java"
4299             }
4300             into "${modulesSrcDir}/${moduleName}"
4301             include "**/*.java"
4302             if (!HAS_UNSUPPORTED_DESKTOP) {
4303                 exclude("com/sun/javafx/embed/swing/newimpl/**")
4304             }  
4305 
4306             if (project.hasProperty("sourceFilter")) {
4307                 filter(project.sourceFilter)
4308             }
4309         }
4310 
4311         // Copy .html and other files needed for doc bundles
4312         def copyDocFiles = project.task("copyDocFiles$t.capital", type: Copy, dependsOn: copySourceFilesTask) {
4313             if (copySources) {
4314                 from("${project.projectDir}/src/main/docs") {
4315                     include "**/*.html"
4316                     filter { line->
4317                         line = line.replace("@FXVERSION@", RELEASE_VERSION)
4318                     }
4319                 }
4320                 from("${project.projectDir}/src/main/docs") {
4321                     exclude "**/*.html"
4322                 }
4323                 from("${project.projectDir}/src/main/java") {
4324                     exclude "**/*.java"
4325                 }
4326 
4327                 into "${modulesSrcDir}/${moduleName}"
4328             }
4329         }
4330 
4331         // Copy make/build.properties
4332         def srcMakeDir = "${project.projectDir}/make"
4333         def dstMakeDir = "${modulesMakeDir}/${moduleName}"
4334         def copyBuildPropertiesTask = project.task("copyBuildProperties$t.capital", type: Copy, dependsOn: copyDocFiles) {
4335             from srcMakeDir
4336             into dstMakeDir
4337         }
4338 
4339         // Copy legal files
4340         def srcLegalDir = "${project.projectDir}/src/main/legal"
4341         def dstLegalDir = "${modulesLegalDir}/${moduleName}"
4342         def copyLegalTask = project.task("copyLegal$t.capital", type: Copy, dependsOn: copyBuildPropertiesTask) {
4343             from srcLegalDir
4344             into dstLegalDir
4345 
4346             // Exclude ANGLE since we (currently) do not use it
4347             exclude("angle.md")
4348         }
4349 
4350         buildModulesTask.dependsOn(
4351             copyClassFilesTask,
4352             copyLibFilesTask,
4353             copySourceFilesTask,
4354             copyDocFiles,
4355             copyBuildPropertiesTask,
4356             copyLegalTask)
4357     }
4358 
4359     // ============================================================
4360 
4361     def standaloneSdkDirName = "${platformPrefix}sdk"
4362     def standaloneSdkDir = "${rootProject.buildDir}/${standaloneSdkDirName}"
4363     def standaloneLibDir = "${standaloneSdkDir}/lib"
4364     def libDest=targetProperties.libDest
4365     def standaloneNativeDir = "${standaloneSdkDir}/${libDest}"
4366     def standaloneLegalDir = "${standaloneSdkDir}/legal"
4367     def standaloneSrcZipName = "src.zip"
4368 
4369     // STANDALONE SDK
4370     moduleProjList.each { project ->
4371         // Copy classes, bin, and lib directories
4372 
4373         def moduleName = project.ext.moduleName
4374         def buildDir = project.buildDir
4375 
4376         // Create modular jars
4377         def srcClassesDir = "${buildDir}/${platformPrefix}module-classes"
4378         def srcLibsDir = "${buildDir}/${platformPrefix}module-lib"
4379         def dstModularJarDir = "${standaloneLibDir}"
4380         def modularJarName = "${moduleName}.jar"
4381         def modularJarTask = project.task("modularJarStandalone$t.capital", type: Jar, dependsOn: project.assemble) {
4382             destinationDir = file("${dstModularJarDir}")
4383             archiveName = modularJarName
4384             includeEmptyDirs = false
4385             from srcClassesDir
4386         }
4387 
4388         // Copy native libraries
4389         def srcNativeDir = "${buildDir}/${platformPrefix}module-lib"
4390         def dstNativeDir = "${standaloneNativeDir}"
4391         def copyNativeFilesTask = project.task("copyNativeFilesStandalone$t.capital", type: Copy, dependsOn: modularJarTask) {
4392             from srcNativeDir
4393             into dstNativeDir
4394             include("*.dll")
4395         }
4396 
4397         // Copy other lib files
4398         def dstLibsDir = "${standaloneLibDir}"
4399         def copyLibFilesTask = project.task("copyLibFilesStandalone$t.capital", type: Copy, dependsOn: copyNativeFilesTask) {
4400             from srcLibsDir
4401             into dstLibsDir
4402             exclude("*.dll")
4403         }
4404 
4405         // Copy legal files
4406         def licenseFiles = [ "ADDITIONAL_LICENSE_INFO", "ASSEMBLY_EXCEPTION", "LICENSE" ]
4407         def srcLegalDir = "${project.projectDir}/src/main/legal"
4408         def dstLegalDir = "${standaloneLegalDir}/${moduleName}"
4409         def copyLegalTask = project.task("copyLegalStandalone$t.capital", type: Copy, dependsOn: copyLibFilesTask) {
4410 
4411             def rtDir = rootProject.file('.')
4412             licenseFiles.each { lFile ->
4413                 from "${rtDir}/${lFile}"
4414             }
4415 
4416             from srcLegalDir
4417 
4418             into dstLegalDir
4419 
4420             // Exclude ANGLE since we (currently) do not use it
4421             exclude("angle.md")
4422         }
4423 
4424         buildModulesTask.dependsOn(
4425             modularJarTask,
4426             copyNativeFilesTask,
4427             copyLibFilesTask,
4428             copyLegalTask)
4429     }
4430 
4431     // Zip module sources for standalone SDK
4432     //
4433     // NOTE: the input is taken from the modular-sdk/modules_src dir
4434     // so that we don't have to duplicate the logic and create another
4435     // temporary directory. This is somewhat inelegant, since the bundled sdk
4436     // and the standalone sdk should be independent of one another, but seems
4437     // better than the alternatives.
4438     def zipSourceFilesTask = project.task("zipSourceFilesStandalone$t.capital", type: Zip, dependsOn: buildModulesTask) {
4439         destinationDir = file("${standaloneLibDir}")
4440         archiveName = standaloneSrcZipName
4441         includeEmptyDirs = false
4442         from modulesSrcDir
4443         include "**/*.java"
4444     }
4445     buildModules.dependsOn(zipSourceFilesTask)
4446 
4447     // ============================================================
4448 
4449     // Maven Publications
4450     def publicationDirName = "${platformPrefix}publications"
4451     def publicationDir = "${rootProject.buildDir}/${publicationDirName}"
4452 
4453     moduleProjList.each { project -> 
4454         // Create publications to be uploaded 
4455 
4456         def moduleName = project.ext.moduleName
4457         def buildDir = project.buildDir
4458 
4459         def dstModularJarDir="${publicationDir}"
4460         def srcClassesDir = "${buildDir}/${platformPrefix}module-classes"
4461         def srcLibsDir = "${buildDir}/${platformPrefix}module-lib"
4462 
4463         def modularEmptyPublicationJarName = "${moduleName}.jar"
4464         def modularEmptyPublicationJarTask = project.task("moduleEmptyPublicationJar${t.capital}", type: Jar) {
4465             destinationDir = file("${dstModularJarDir}")
4466             archiveName = modularEmptyPublicationJarName
4467             manifest {
4468                 attributes(
4469                     'Automatic-Module-Name':"${moduleName}Empty"
4470                 )
4471             }
4472         }
4473 
4474         def modularPublicationJarName = "${moduleName}-${t.name}.jar"
4475         def modularPublicationJarTask = project.task("modularPublicationJar${t.capital}", type: Jar, dependsOn: modularEmptyPublicationJarTask) {
4476             destinationDir = file("${dstModularJarDir}")
4477             archiveName = modularPublicationJarName
4478             from srcLibsDir
4479             from srcClassesDir
4480         }
4481 
4482         buildModulesTask.dependsOn(modularPublicationJarTask)
4483 
4484     }
4485     // ============================================================
4486 
4487     def buildRunArgsTask = task("buildRunArgs$t.capital",
4488             group: "Build", dependsOn: buildModulesTask) {
4489         outputs.file(runArgsFile);
4490         inputs.file(EXTRAADDEXPORTS);
4491         doLast() {
4492             List<String>modpath = []
4493             List<String>modnames = []
4494 
4495             moduleProjList.each { project ->
4496                 def moduleName = project.ext.moduleName
4497                 def dstModuleDir = cygpath("${modulesDir}/${moduleName}")
4498                 if (HAS_JAVAFX_MODULES) {
4499                     modpath <<  "${moduleName}=${dstModuleDir}"
4500                 } else {
4501                     modnames << moduleName
4502                 }
4503             }
4504 
4505             if (HAS_JAVAFX_MODULES) {
4506                 writeRunArgsFile(runArgsFile, computeLibraryPath(true), modpath, null)
4507                 writeRunArgsFile(compileArgsFile, null, modpath, null)
4508 
4509                 if (rootProject.hasProperty("EXTRA_ADDEXPORTS_STRING")) {
4510                     runArgsFile << EXTRA_ADDEXPORTS_STRING
4511                     compileArgsFile << EXTRA_ADDEXPORTS_STRING
4512                 }
4513             } else {
4514                 modpath = [ cygpath("${standaloneLibDir}") ]
4515                 writeRunArgsFile(runArgsFile, null, modpath, modnames)
4516                 writeRunArgsFile(compileArgsFile, null, modpath, modnames)
4517             }
4518         }
4519     }
4520     buildModules.dependsOn(buildRunArgsTask)
4521 
4522     def isWindows = IS_WINDOWS && t.name == "win";
4523     def isMac = IS_MAC && t.name == "mac";
4524 
4525     // Create layout for modular classes
4526     moduleProjList.each { project ->
4527         def buildModuleClassesTask = project.task("buildModule$t.capital", group: "Build", type: Copy) {
4528             dependsOn(project.assemble)
4529             def buildDir = project.buildDir
4530             def sourceBuildDirs = [
4531                 "${buildDir}/classes/java/main/${project.moduleName}",
4532             ]
4533 
4534             def moduleClassesDir = "$buildDir/${platformPrefix}module-classes"
4535                 includeEmptyDirs = false
4536                 sourceBuildDirs.each { d ->
4537                     from d
4538                 }
4539                 into moduleClassesDir
4540 
4541                 // Exclude obsolete, experimental, or non-shipping code
4542                 exclude("version.rc")
4543                 exclude("com/sun/glass/ui/swt")
4544                 exclude("com/sun/javafx/tools/ant")
4545                 exclude("com/javafx/main")
4546                 exclude("com/sun/javafx/webkit/drt")
4547                 if (!IS_INCLUDE_NULL3D) {
4548                     exclude ("com/sun/prism/null3d")
4549                 }
4550                 if (!IS_INCLUDE_ES2) {
4551                        exclude("com/sun/prism/es2",
4552                                "com/sun/scenario/effect/impl/es2")
4553                 }
4554 
4555                 // Exclude platform-specific classes for other platforms
4556 
4557                 if (!isMac) {
4558                     exclude ("com/sun/media/jfxmediaimpl/platform/osx",
4559                              "com/sun/prism/es2/MacGL*",
4560                              "com/sun/glass/events/mac",
4561                              "com/sun/glass/ui/mac",
4562                              )
4563                 }
4564 
4565                 if (!isWindows) {
4566                     exclude ("**/*.hlsl",
4567                              "com/sun/glass/ui/win",
4568                              "com/sun/prism/d3d",
4569                              "com/sun/prism/es2/WinGL*",
4570                              "com/sun/scenario/effect/impl/hw/d3d"
4571                              )
4572                 }
4573 
4574                 if (!targetProperties.includeGTK) { //usually IS_LINUX
4575                     exclude (
4576                              "com/sun/glass/ui/gtk",
4577                              "com/sun/prism/es2/EGL*",
4578                              "com/sun/prism/es2/X11GL*"
4579                              )
4580                 }
4581 
4582                 if (!targetProperties.includeEGL) {
4583                     exclude ("com/sun/prism/es2/EGL*")
4584                 }
4585 
4586                 if (!targetProperties.includeMonocle) {
4587                     exclude ("com/sun/glass/ui/monocle")
4588                     exclude("com/sun/prism/es2/Monocle*")
4589                 }
4590 
4591                 if (t.name != 'ios') {
4592                     exclude ("com/sun/media/jfxmediaimpl/platform/ios",
4593                              "com/sun/glass/ui/ios",
4594                              "com/sun/prism/es2/IOS*"
4595                              )
4596                 }
4597 
4598                 if (t.name != 'android' && t.name != 'dalvik') {
4599                     exclude ("com/sun/glass/ui/android")
4600                 }
4601 
4602                 // Filter out other platform-specific classes
4603                 if (targetProperties.containsKey('jfxrtJarExcludes')) {
4604                     exclude(targetProperties.jfxrtJarExcludes)
4605                 }
4606 
4607                 /* FIXME: JIGSAW -- handle this in the module itself
4608                 String webbld = project(":web").buildDir.path
4609                 String ctrlbld = project(":controls").buildDir.path
4610                 if (t.name == 'android') {
4611                     from ("${webbld}/classes/android",
4612                           "${webbld}/resources/android",
4613                           "${ctrlbld}/classes/android",
4614                           "${ctrlbld}/resources/android")
4615                 } else if (t.name == 'ios') {
4616                     from ("${webbld}/classes/ios",
4617                           "${webbld}/resources/ios")
4618                 } else {
4619                     from ("${webbld}/classes/java/main")
4620                 }
4621                 */
4622         }
4623         buildModulesTask.dependsOn(buildModuleClassesTask)
4624     }
4625 
4626     def buildModuleLibsTask = task("buildModuleLibs$t.capital") {
4627         group = "Basic"
4628 
4629         def baseProject = project(":base");
4630 
4631         def graphicsProject = project(":graphics");
4632 
4633         def mediaProject = project(":media");
4634 
4635         def webProject = project(":web");
4636         dependsOn(webProject.assemble)
4637 
4638         def swtProject = project(":swt");
4639 
4640         def library = targetProperties.library
4641 
4642         def useLipo = targetProperties.containsKey('useLipo') ? targetProperties.useLipo : false
4643         def modLibDest = targetProperties.modLibDest
4644         def moduleNativeDirName = "${platformPrefix}module-$modLibDest"
4645 
4646         def buildModuleBaseTask = task("buildModuleBase$t.capital", dependsOn: baseProject.assemble) {
4647             group = "Basic"
4648             description = "creates javafx.base property files"
4649 
4650             def moduleLibDir = "${baseProject.buildDir}/${platformPrefix}module-lib"
4651             final File javafxProperties = file("${moduleLibDir}/javafx.properties")
4652             outputs.file(javafxProperties)
4653 
4654             if (targetProperties.containsKey("javafxPlatformProperties")) {
4655                 final File javafxPlatformProperties = file("${moduleLibDir}/javafx.platform.properties")
4656                 outputs.file(javafxPlatformProperties)
4657             }
4658 
4659             doLast {
4660                 mkdir moduleLibDir
4661 
4662                 javafxProperties.delete()
4663                 javafxProperties << "javafx.version=$RELEASE_VERSION_SHORT";
4664                 javafxProperties << "\n"
4665                 javafxProperties << "javafx.runtime.version=$RELEASE_VERSION_LONG";
4666                 javafxProperties << "\n"
4667                 javafxProperties << "javafx.runtime.build=$PROMOTED_BUILD_NUMBER";
4668                 javafxProperties << "\n"
4669                 // Include any properties that have been defined (most likely in
4670                 // one of the various platform gradle files)
4671                 if (targetProperties.containsKey("javafxProperties")) {
4672                     javafxProperties << targetProperties.javafxProperties
4673                     javafxProperties << "\n"
4674                 }
4675 
4676                 // Embedded builds define this file as well
4677                 if (targetProperties.containsKey("javafxPlatformProperties")) {
4678                     final File javafxPlatformProperties = file("${moduleLibDir}/javafx.platform.properties")
4679                     javafxPlatformProperties.delete()
4680                     javafxPlatformProperties << targetProperties.javafxPlatformProperties
4681                     javafxPlatformProperties << "\n"
4682                 }
4683             }
4684         }
4685 
4686         def buildModuleGraphicsTask = task("buildModuleGraphics$t.capital", type: Copy, dependsOn: graphicsProject.assemble) {
4687             group = "Basic"
4688             description = "copies javafx.graphics native libraries"
4689 
4690             into "${graphicsProject.buildDir}/${moduleNativeDirName}"
4691 
4692             from("${graphicsProject.buildDir}/libs/jsl-decora/${t.name}/${library(targetProperties.decora.lib)}")
4693             def libs = ['font', 'prism', 'prismSW', 'glass', 'iio']
4694             if (IS_INCLUDE_ES2) {
4695                 libs += ['prismES2'];
4696             }
4697             if (IS_COMPILE_PANGO) {
4698                 libs += ['fontFreetype', 'fontPango'];
4699             }
4700             libs.each { lib ->
4701                 def variants = targetProperties[lib].containsKey('variants') && !useLipo ? targetProperties[lib].variants : [null]
4702                 variants.each { variant ->
4703                     def variantProperties = variant ? targetProperties[lib][variant] : targetProperties[lib]
4704                     from ("${graphicsProject.buildDir}/libs/$lib/$t.name/${library(variantProperties.lib)}")
4705                 }
4706             }
4707             if (IS_WINDOWS) {
4708                 from ("${graphicsProject.buildDir}/libs/prismD3D/${t.name}/${library(targetProperties.prismD3D.lib)}");
4709                 targetProperties.VS2017DLLs.each { vslib ->
4710                     from ("$vslib");
4711                 }
4712                 targetProperties.WinSDKDLLs.each { winsdklib ->
4713                     from ("$winsdklib");
4714                 }
4715             }
4716         }
4717 
4718         def buildModuleMediaTask = task("buildModuleMedia$t.capital", type: Copy, dependsOn: mediaProject.assemble) {
4719             group = "Basic"
4720             description = "copies javafx.media native libraries"
4721 
4722             into "${mediaProject.buildDir}/${moduleNativeDirName}"
4723 
4724             def mediaBuildType = project(":media").ext.buildType
4725             if (IS_COMPILE_MEDIA) {
4726                 [ "fxplugins", "gstreamer-lite", "jfxmedia" ].each { name ->
4727                     from ("${mediaProject.buildDir}/native/${t.name}/${mediaBuildType}/${library(name)}") }
4728 
4729                 if (t.name == "mac") {
4730                     // OSX media natives
4731                     [ "jfxmedia_qtkit", "jfxmedia_avf", "glib-lite" ].each { name ->
4732                         from ("${mediaProject.buildDir}/native/${t.name}/${mediaBuildType}/${library(name)}") }
4733                 } else if (t.name == "linux") {
4734                     from("${mediaProject.buildDir}/native/${t.name}/${mediaBuildType}") { include "libavplugin*.so" }
4735                 } else from ("${mediaProject.buildDir}/native/${t.name}/${mediaBuildType}/${library("glib-lite")}")
4736             } else {
4737                 if (t.name != "android"  && t.name != "dalvik" ) {
4738                     [ "fxplugins", "gstreamer-lite", "jfxmedia" ].each { name ->
4739                         from ("$MEDIA_STUB/${library(name)}") }
4740                 }
4741 
4742                 if (t.name == "mac") {
4743                     // copy libjfxmedia_{avf,qtkit}.dylib if they exist
4744                     [ "jfxmedia_qtkit", "jfxmedia_avf", "glib-lite" ].each { name ->
4745                         from ("$MEDIA_STUB/${library(name)}") }
4746                 } else if (t.name == "linux") {
4747                     from(MEDIA_STUB) { include "libavplugin*.so" }
4748                 }
4749                 else if (t.name != "android"  && t.name != "dalvik" ) {
4750                     from ("$MEDIA_STUB/${library("glib-lite")}")
4751                 }
4752             }
4753         }
4754 
4755         def buildModuleWeb = task("buildModuleWeb$t.capital", type: Copy, dependsOn: webProject.assemble) {
4756             group = "Basic"
4757             description = "copies javafx.web native libraries"
4758 
4759             into "${webProject.buildDir}/${moduleNativeDirName}"
4760 
4761             if (IS_COMPILE_WEBKIT) {
4762                 from ("${webProject.buildDir}/libs/${t.name}/${library('jfxwebkit')}")
4763             } else {
4764                 if (t.name != "android" && t.name != "ios" && t.name != "dalvik") {
4765                     from ("$WEB_STUB/${library('jfxwebkit')}")
4766                 }
4767             }
4768         }
4769 
4770         def buildModuleSWT = task("buildModuleSWT$t.capital", type: Copy) {
4771             group = "Basic"
4772             description = "copies SWT JAR"
4773 
4774             // FIXME: the following is a hack to workaround the fact that there
4775             // is no way to deliver javafx-swt.jar other than in one of the
4776             // existing runtime modules.
4777 
4778             dependsOn(buildModuleGraphicsTask) // we copy to the graphics module
4779 
4780             if (COMPILE_SWT) {
4781                 def javafxSwtIndexTask = tasks.getByName("javafxSwtIndex${t.capital}");
4782                 dependsOn(javafxSwtIndexTask)
4783                 //enabled = COMPILE_SWT
4784             }
4785 
4786             // Copy javafx-swt.jar to the javafx-graphics module lib dir
4787             from "${swtProject.buildDir}/libs/javafx-swt.jar"
4788             into "${graphicsProject.buildDir}/${platformPrefix}module-lib"
4789         }
4790 
4791         dependsOn(
4792             buildModuleBaseTask,
4793             buildModuleGraphicsTask,
4794             buildModuleMediaTask,
4795             buildModuleWeb,
4796             buildModuleSWT,
4797             )
4798     }
4799     buildModulesTask.dependsOn(buildModuleLibsTask)
4800 
4801     def zipTask = project.task("buildModuleZip$t.capital", type: Zip, group: "Build",
4802             dependsOn: buildModulesTask ) {
4803 
4804         // FIXME: JIGSAW -- this should be moved to a sub-directory so we can keep the same name
4805         def jfxBundle = "${platformPrefix}javafx-exports.zip"
4806 
4807         doFirst() {
4808             file("${rootProject.buildDir}/${jfxBundle}").delete()
4809         }
4810 
4811         archiveName = jfxBundle
4812         destinationDir = file("${rootProject.buildDir}")
4813         includeEmptyDirs = false
4814         from "${bundledSdkDir}"
4815     }
4816     jdkZip.dependsOn(zipTask)
4817 
4818     Task testArgFiles = task("createTestArgfiles${t.capital}") {
4819 
4820         File testRunArgsFile = new File(rootProject.buildDir, TESTRUNARGSFILE)
4821         //test (shimed) version
4822         File testCompileArgsFile = new File(rootProject.buildDir, TESTCOMPILEARGSFILE)
4823         // And a test java.policy file
4824         File testJavaPolicyFile = new File(rootProject.buildDir, TESTJAVAPOLICYFILE)
4825         // and the non-test version to go with run.args
4826         File runJavaPolicyFile = new File(rootProject.buildDir, RUNJAVAPOLICYFILE);
4827 
4828         outputs.file(testRunArgsFile)
4829         outputs.file(testCompileArgsFile)
4830         outputs.file(testJavaPolicyFile)
4831         outputs.file(runJavaPolicyFile)
4832         inputs.file(EXTRAADDEXPORTS);
4833 
4834         doLast() {
4835             rootProject.buildDir.mkdir()
4836 
4837             List<String> projNames = []
4838             moduleProjList.each { project ->
4839                 projNames << project.name
4840             }
4841 
4842             // And the test (shimed) variation...
4843 
4844             testRunArgsFile.delete()
4845             testCompileArgsFile.delete()
4846 
4847             testJavaPolicyFile.delete()
4848             runJavaPolicyFile.delete()
4849 
4850             List<String> modpath = []
4851 
4852             if (HAS_JAVAFX_MODULES) {
4853                 moduleProjList.each { project ->
4854                     if (project.hasProperty("moduleName") && project.buildModule) {
4855                         File dir;
4856                         if (project.sourceSets.hasProperty('shims')) {
4857                            dir = new File(rootProject.buildDir, "shims/${project.ext.moduleName}")
4858                         } else {
4859                            dir = new File(rootProject.buildDir, "modular-sdk/modules/${project.ext.moduleName}")
4860                         }
4861 
4862                         def dstModuleDir = cygpath(dir.path)
4863                         modpath << "${project.ext.moduleName}=${dstModuleDir}"
4864 
4865                         String themod = dir.toURI()
4866                         testJavaPolicyFile <<  "grant codeBase \"${themod}\" {\n" +
4867                         "    permission java.security.AllPermission;\n" +
4868                         "};\n"
4869 
4870                         dir = new File(rootProject.buildDir, "modular-sdk/modules/${project.ext.moduleName}")
4871                         themod = dir.toURI()
4872                         runJavaPolicyFile <<  "grant codeBase \"${themod}\" {\n" +
4873                         "    permission java.security.AllPermission;\n" +
4874                         "};\n"
4875                     }
4876                 }
4877 
4878                 writeRunArgsFile(testCompileArgsFile, null, modpath, null)
4879                 writeRunArgsFile(testRunArgsFile, computeLibraryPath(true), modpath, null)
4880 
4881                 if (rootProject.hasProperty("EXTRA_ADDEXPORTS_STRING")) {
4882                     testCompileArgsFile << EXTRA_ADDEXPORTS_STRING
4883                     testRunArgsFile << EXTRA_ADDEXPORTS_STRING
4884                 }
4885             } else  {
4886                 def modnames = []
4887                 moduleProjList.each { project ->
4888                     if (project.hasProperty("moduleName") && project.buildModule) {
4889                         modnames << project.ext.moduleName
4890                         File dir;
4891                         if (project.sourceSets.hasProperty('shims')) {
4892                            dir = new File(rootProject.buildDir, "shims/${project.ext.moduleName}")
4893                         } else {
4894                            dir = new File(rootProject.buildDir, "sdk/lib/${project.ext.moduleName}.jar")
4895                         }
4896 
4897                         def dstModuleDir = cygpath(dir.path)
4898                         modpath << "${dstModuleDir}"
4899 
4900                         String themod = dir.toURI()
4901                         testJavaPolicyFile <<  "grant codeBase \"${themod}\" {\n" +
4902                         "    permission java.security.AllPermission;\n" +
4903                         "};\n"
4904 
4905                         dir = new File(rootProject.buildDir, "sdk/lib/${project.ext.moduleName}.jar")
4906                         themod = dir.toURI()
4907                         runJavaPolicyFile <<  "grant codeBase \"${themod}\" {\n" +
4908                         "    permission java.security.AllPermission;\n" +
4909                         "};\n"
4910                     }
4911                 }
4912 
4913                 writeRunArgsFile(testCompileArgsFile, null, modpath, modnames)
4914                 writeRunArgsFile(testRunArgsFile, computeLibraryPath(true), modpath, modnames)
4915 
4916                 appendQualExports(testCompileArgsFile, qualExportsSwing)
4917                 appendQualExports(testRunArgsFile, qualExportsSwing)
4918             }
4919         }
4920     }
4921     sdk.dependsOn(testArgFiles)
4922     createTestArgfiles.dependsOn(testArgFiles)
4923 
4924     def sdkTask = tasks.getByName("sdk${t.capital}");
4925     sdkTask.dependsOn(buildModulesTask)
4926 }
4927 sdk.dependsOn(buildModules)
4928 
4929 // Build the jmod for each module for the standalone SDK only.
4930 compileTargets { t ->
4931     if (!HAS_JAVAFX_MODULES) {
4932         def targetProperties = project.ext[t.upper]
4933 
4934         def platformPrefix = targetProperties.platformPrefix
4935         def jmodsDirName = "${platformPrefix}jmods"
4936         def jmodsDir = "${rootProject.buildDir}/${jmodsDirName}"
4937         def standaloneSdkDirName = "${platformPrefix}sdk"
4938         def standaloneSdkDir = "${rootProject.buildDir}/${standaloneSdkDirName}"
4939         def standaloneLegalDir = "${standaloneSdkDir}/legal"
4940 
4941         def excludeNativeLibs = []
4942         if (IS_WINDOWS) {
4943             // List of duplicate Microsoft DLLs to exclude
4944             excludeNativeLibs += targetProperties.VS2017DLLNames
4945             excludeNativeLibs += targetProperties.WinSDKDLLNames
4946         }
4947 
4948         moduleProjList.each { project ->
4949             def moduleName = project.ext.moduleName
4950             def buildDir = project.buildDir
4951 
4952             def srcClassesDir = "${buildDir}/${platformPrefix}module-classes"
4953             def srcLibDir = "${buildDir}/${platformPrefix}module-lib"
4954             def srcLegalDir = "${standaloneLegalDir}/${moduleName}"
4955 
4956             def jmodName = "${moduleName}.jmod"
4957             def jmodFile = "${jmodsDir}/${jmodName}"
4958             def jmodTask = project.task("jmod$t.capital", group: "Build", dependsOn: sdk) {
4959                 doLast {
4960                     mkdir jmodsDir
4961                     delete(jmodFile);
4962                     exec {
4963                         commandLine(JMOD)
4964                         args("create")
4965                         args("--class-path")
4966                         args(srcClassesDir)
4967                         // Not all modules have a "lib" dir
4968                         if (file(srcLibDir).isDirectory()) {
4969                             args("--libs")
4970                             args(srcLibDir)
4971                         }
4972                         // Exclude duplicate native libs from javafx.graphics.jmod
4973                         if (moduleName == "javafx.graphics") {
4974                             excludeNativeLibs.each { name ->
4975                                 args("--exclude")
4976                                 args(name)
4977                             }
4978                         }
4979                         args("--legal-notices")
4980                         args(srcLegalDir)
4981                         args(jmodFile)
4982                     }
4983                 }
4984             }
4985 
4986             jmods.dependsOn(jmodTask)
4987         }
4988     }
4989 }
4990 
4991 task checkrepo() {
4992     doLast {
4993         logger.info("checking for whitespace (open)");
4994         exec {
4995             if (IS_WINDOWS) {
4996                 commandLine  'bash', 'tools/scripts/checkWhiteSpace'
4997             } else {
4998                 commandLine  'bash', 'tools/scripts/checkWhiteSpace', '-x'
4999             }
5000         }
5001     }
5002 }
5003 
5004 task checkrepoall() {
5005     doLast {
5006         logger.info("checking for all whitespace (open)");
5007         exec {
5008             if (IS_WINDOWS) {
5009                 commandLine  'bash', 'tools/scripts/checkWhiteSpace', '-a'
5010             } else {
5011                 commandLine  'bash', 'tools/scripts/checkWhiteSpace', '-x', '-a'
5012             }
5013         }
5014     }
5015 }
5016 
5017 /******************************************************************************
5018  *                                                                            *
5019  *                              BUILD_CLOSED                                  *
5020  *                                                                            *
5021  * This next section should remain at the end of the build script. It allows  *
5022  * for a "supplemental" gradle file to be used to extend the normal build     *
5023  * structure. For example, this is used for passing a supplemental gradle     *
5024  * file for producing official JavaFX builds.                                 *
5025  *                                                                            *
5026  *****************************************************************************/
5027 
5028 if (BUILD_CLOSED) {
5029     apply from: supplementalBuildFile
5030 }
5031 
5032 task showFlags {
5033 }
5034 
5035 compileTargets { t ->
5036     // Every platform must define these variables
5037     def props = project.ext[t.upper];
5038     showFlags.dependsOn(
5039         project.task("showFlags$t.upper") {
5040             doLast() {
5041                 println "Properties set for $t.upper"
5042                 props.each { println it }
5043             }
5044         }
5045     )
5046 
5047 }