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", IS_MILESTONE_FCS ? "${RELEASE_VERSION_SHORT}" : "${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.8.
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 < 8)) {
1222         err = "Gradle version too old: ${gradle.gradleVersion}; must be at least 4.8"
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     if (COMPILE_SWING) {
2441         addMavenPublication(project, [ 'graphics' ])
2442     }
2443 }
2444 
2445 project(":swt") {
2446     tasks.all {
2447         if (!COMPILE_SWT) it.enabled = false
2448     }
2449 
2450     // javafx.swt is an automatic module
2451     project.ext.buildModule = false
2452 
2453     commonModuleSetup(project, [ 'base', 'graphics' ])
2454 
2455     dependencies {
2456         compile name: SWT_FILE_NAME
2457     }
2458 
2459     classes {
2460         doLast {
2461             // Copy all of the download libraries to libs directory for the sake of the IDEs
2462             File libsDir = rootProject.file("build/libs");
2463             File swtLib = new File(libsDir, "swt-debug.jar")
2464             libsDir.mkdirs();
2465 
2466             // Skip copy if file is present.
2467             if (swtLib.exists()) return;
2468 
2469             for (File f : configurations.compile.files) {
2470                 // Have to rename the swt jar because it is some platform specific name but
2471                 // for the sake of the IDEs we need to have a single stable name that works
2472                 // on every platform
2473                 copy {
2474                     into libsDir
2475                     from f.getParentFile()
2476                     include "**/*swt*.jar"
2477                     includeEmptyDirs = false
2478                     rename ".*swt.*jar", "swt-debug\\.jar"
2479                 }
2480             }
2481         }
2482     }
2483 
2484     compileJava.options.compilerArgs.addAll([
2485             "--add-exports=javafx.graphics/com.sun.glass.ui=ALL-UNNAMED",
2486             "--add-exports=javafx.graphics/com.sun.javafx.cursor=ALL-UNNAMED",
2487             "--add-exports=javafx.graphics/com.sun.javafx.embed=ALL-UNNAMED",
2488             "--add-exports=javafx.graphics/com.sun.javafx.stage=ALL-UNNAMED",
2489             "--add-exports=javafx.graphics/com.sun.javafx.tk=ALL-UNNAMED",
2490             ])
2491 
2492     test {
2493         //enabled = IS_FULL_TEST && IS_SWT_TEST
2494         enabled = false // FIXME: JIGSAW -- support this with modules
2495         logger.info("JIGSAW Testing disabled for swt")
2496 
2497         if (IS_MAC) {
2498             enabled = false
2499             logger.info("SWT tests are disabled on MAC, because Gradle test runner does not handle -XstartOnFirstThread properly (https://issues.gradle.org/browse/GRADLE-3290).")
2500         }
2501     }
2502 }
2503 
2504 project(":fxml") {
2505     project.ext.buildModule = true
2506     project.ext.includeSources = true
2507     project.ext.moduleRuntime = true
2508     project.ext.moduleName = "javafx.fxml"
2509 
2510     sourceSets {
2511         main
2512         shims
2513         test
2514     }
2515 
2516     project.ext.moduleSourcePath = defaultModuleSourcePath
2517     project.ext.moduleSourcePathShim = defaultModuleSourcePathShim
2518 
2519     commonModuleSetup(project, [ 'base', 'graphics', 'controls', 'fxml' ])
2520 
2521 
2522     dependencies {
2523         testCompile project(":graphics").sourceSets.test.output
2524         testCompile project(":base").sourceSets.test.output
2525     }
2526 
2527     test {
2528         // StubToolkit is not *really* needed here, but because some code inadvertently invokes performance
2529         // tracker and this attempts to fire up the toolkit and this looks for native libraries and fails,
2530         // we have to use the stub toolkit for now.
2531         jvmArgs "-Djavafx.toolkit=test.com.sun.javafx.pgstub.StubToolkit"
2532         // FIXME: change this to also allow JDK 9 boot jdk
2533         classpath += files("$JDK_HOME/jre/lib/ext/nashorn.jar")
2534     }
2535 
2536     addMavenPublication(project, [ 'controls' ])
2537 
2538 }
2539 
2540 project(":media") {
2541     configurations {
2542         media
2543     }
2544 
2545     project.ext.buildModule = true
2546     project.ext.includeSources = true
2547     project.ext.moduleRuntime = true
2548     project.ext.moduleName = "javafx.media"
2549 
2550     sourceSets {
2551         main
2552         //shims // no test shims needed
2553         test
2554         tools {
2555             java.srcDir "src/tools/java"
2556         }
2557     }
2558 
2559     project.ext.moduleSourcePath = defaultModuleSourcePath
2560     project.ext.moduleSourcePathShim = defaultModuleSourcePathShim
2561 
2562     commonModuleSetup(project, [ 'base', 'graphics', 'media' ])
2563 
2564     dependencies {
2565         if (IS_BUILD_LIBAV_STUBS) {
2566             media name: "libav-9.14", ext: "tar.gz"
2567             media name: "libav-11.4", ext: "tar.gz"
2568             media name: "libav-12.1", ext: "tar.gz"
2569             media name: "ffmpeg-3.3.3", ext: "tar.gz"
2570         }
2571     }
2572 
2573     compileJava.dependsOn updateCacheIfNeeded
2574 
2575     compileJava {
2576         // generate the native headers during compile
2577         options.compilerArgs.addAll([
2578             '-h', "${project.buildDir}/gensrc/headers"
2579             ])
2580     }
2581 
2582     compileToolsJava {
2583         enabled = IS_COMPILE_MEDIA
2584         def modulePath = "${project.sourceSets.main.java.outputDir}"
2585         options.compilerArgs.addAll([
2586             "--module-path=$modulePath",
2587             "--add-modules=javafx.media",
2588             '--add-exports', 'javafx.media/com.sun.media.jfxmedia=ALL-UNNAMED',
2589             ])
2590     }
2591 
2592     project.ext.makeJobsFlag = IS_WINDOWS && IS_DEBUG_NATIVE ? "-j1" : "-j5";
2593     project.ext.buildType = IS_DEBUG_NATIVE ? "Debug" : "Release";
2594 
2595     def nativeSrcDir = file("${projectDir}/src/main/native")
2596     def generatedHeadersDir = file("${buildDir}/gensrc/headers/${project.moduleName}")
2597 
2598     task generateMediaErrorHeader(dependsOn: [compileJava, compileToolsJava]) {
2599         enabled = IS_COMPILE_MEDIA
2600         def headerpath = file("$generatedHeadersDir/jfxmedia_errors.h");
2601         doLast {
2602             def classpath = files(sourceSets.tools.output);
2603             def sourcepath = sourceSets.main.java.srcDirs;
2604             def srcRoot = (sourcepath.toArray())[0];
2605 
2606             mkdir generatedHeadersDir;
2607 
2608             def modulePath = "${project.sourceSets.main.java.outputDir}"
2609             modulePath += File.pathSeparator + "${rootProject.projectDir}/modules/javafx.graphics/build/classes/java/main"
2610             modulePath += File.pathSeparator + "${rootProject.projectDir}/modules/javafx.base/build/classes/java/main"
2611 
2612             exec {
2613                 commandLine("$JAVA");
2614                 args += patchModuleArgs
2615                 args += [ "--module-path=$modulePath" ]
2616                 args += [ "--add-modules=javafx.media" ]
2617                 args +=  [ '--add-exports=javafx.media/com.sun.media.jfxmedia=ALL-UNNAMED' ]
2618                 args +=  [ '-classpath', "${classpath.asPath}" ]
2619                 args += [ "headergen.HeaderGen", "$headerpath", "$srcRoot" ]
2620             }
2621         }
2622         outputs.file(project.file("$headerpath"))
2623     }
2624 
2625     task buildNativeTargets {
2626         enabled = IS_COMPILE_MEDIA
2627     }
2628 
2629     compileTargets { t->
2630         def targetProperties = project.rootProject.ext[t.upper]
2631         def nativeOutputDir = file("${buildDir}/native/${t.name}")
2632         def projectDir = t.name.startsWith("arm") ? "linux" : t.name
2633         def mediaProperties = targetProperties.media
2634         // Makefile for OSX needs to know if we're building for parfait
2635         def compileParfait = IS_COMPILE_PARFAIT ? "true" : "false"
2636 
2637         def buildNative = task("build${t.capital}Native", dependsOn: [generateMediaErrorHeader]) {
2638             enabled = targetProperties.compileMediaNative
2639             if (!targetProperties.compileMediaNative) {
2640                 println("Not compiling native Media for ${t.name} per configuration request");
2641             }
2642 
2643             doLast {
2644                 exec {
2645                     commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/jfxmedia/projects/${projectDir}")
2646                     args("JAVA_HOME=${JDK_HOME}", "GENERATED_HEADERS_DIR=${generatedHeadersDir}",
2647                          "OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}", "BASE_NAME=jfxmedia",
2648                          "COMPILE_PARFAIT=${compileParfait}",
2649                          IS_64 ? "ARCH=x64" : "ARCH=x32",
2650                         "CC=${mediaProperties.compiler}", "LINKER=${mediaProperties.linker}")
2651 
2652                     if (t.name == "win") {
2653                         environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
2654                         args( "RESOURCE=${nativeOutputDir}/${buildType}/${WIN.media.jfxmediaRcFile}")
2655                     } else {
2656                         if (t.name.startsWith("arm")) {
2657                             args("EXTRA_CFLAGS=${mediaProperties.extra_cflags}", "EXTRA_LDFLAGS=${mediaProperties.extra_ldflags}")
2658                         } else {
2659                             args("HOST_COMPILE=1")
2660                         }
2661                     }
2662                 }
2663             }
2664         }
2665 
2666         // check for the property disable${name} = true
2667         def boolean disabled = targetProperties.containsKey('disableMedia') ? targetProperties.get('disableMedia') : false
2668         if (!disabled) {
2669             // Building GStreamer
2670             def buildGStreamer = task("build${t.capital}GStreamer") {
2671                 enabled = IS_COMPILE_MEDIA
2672                 doLast {
2673                     exec {
2674                         commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/gstreamer/projects/${projectDir}/gstreamer-lite")
2675                         args("OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}", "BASE_NAME=gstreamer-lite",
2676                              IS_64 ? "ARCH=x64" : "ARCH=x32", "CC=${mediaProperties.compiler}",
2677                              "AR=${mediaProperties.ar}", "LINKER=${mediaProperties.linker}")
2678 
2679                         if (t.name == "win") {
2680                             environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
2681                             args("RESOURCE=${nativeOutputDir}/${buildType}/${WIN.media.gstreamerRcFile}")
2682                         }
2683                     }
2684                 }
2685             }
2686 
2687             def buildPlugins = task("build${t.capital}Plugins", dependsOn: buildGStreamer) {
2688                 enabled = IS_COMPILE_MEDIA
2689 
2690                 doLast {
2691                     exec {
2692                         commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/gstreamer/projects/${projectDir}/fxplugins")
2693                         args("OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}", "BASE_NAME=fxplugins",
2694                              IS_64 ? "ARCH=x64" : "ARCH=x32",
2695                              "CC=${mediaProperties.compiler}", "AR=${mediaProperties.ar}", "LINKER=${mediaProperties.linker}")
2696 
2697                         if (t.name == "win") {
2698                             Map winEnv = new HashMap(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
2699 
2700                             String sdkDir = System.getenv("BASECLASSES_SDK_DIR");
2701                             if (sdkDir == null) {
2702                                 sdkDir = "C:/Program Files/Microsoft SDKs/Windows/v7.1" // Default value
2703                                 winEnv["BASECLASSES_SDK_DIR"] = sdkDir
2704                             }
2705                             environment(winEnv)
2706 
2707                             args("RESOURCE=${nativeOutputDir}/${buildType}/${WIN.media.fxpluginsRcFile}")
2708                         }
2709                     }
2710                 }
2711             }
2712 
2713             buildNative.dependsOn buildPlugins
2714 
2715             if (t.name == "linux") {
2716                 // Pre-defined command line arguments
2717                 def cfgCMDArgs = ["sh", "configure"]
2718                 def commonCfgArgs = ["--enable-shared", "--disable-debug", "--disable-static", "--disable-yasm", "--disable-doc", "--disable-programs", "--disable-everything"]
2719                 def codecsCfgArgs = ["--enable-decoder=aac,mp3,mp3float,h264", "--enable-parser=aac,h264", "--enable-demuxer=aac,h264,mpegts,mpegtsraw"]
2720 
2721                 def copyLibAVStubs = {String fromDir, String toDir ->
2722                     FileCollection config = files("config.h")
2723                     FileCollection libavcodec = files("avcodec.h", "avfft.h", "dxva2.h", "vaapi.h", "vda.h",
2724                                                       "vdpau.h", "version.h", "xvmc.h", "old_codec_ids.h")
2725                     FileCollection libavdevice = files("avdevice.h", "version.h")
2726                     FileCollection libavfilter = files("avfiltergraph.h", "avfilter.h", "buffersink.h", "buffersrc.h", "version.h");
2727                     FileCollection libavformat = files("avformat.h", "avio.h", "version.h")
2728                     FileCollection libavresample = files("avresample.h", "version.h")
2729                     FileCollection libavutil = files("adler32.h", "blowfish.h", "error.h", "log.h", "pixfmt.h",
2730                                                      "aes.h", "bswap.h", "eval.h", "lzo.h", "random_seed.h",
2731                                                      "attributes.h", "buffer.h", "fifo.h", "macros.h", "rational.h",
2732                                                      "audio_fifo.h", "channel_layout.h", "file.h", "mathematics.h", "samplefmt.h",
2733                                                      "avassert.h", "common.h", "frame.h", "md5.h", "sha.h",
2734                                                      "avconfig.h", "imgutils.h", "mem.h", "time.h", "avstring.h",
2735                                                      "cpu_internal.h", "intfloat.h", "opt.h", "version.h", "avutil.h",
2736                                                      "crc.h", "intreadwrite.h", "parseutils.h", "xtea.h", "base64.h",
2737                                                      "dict.h", "lfg.h", "pixdesc.h", "intfloat_readwrite.h", "old_pix_fmts.h", "audioconvert.h",
2738                                                      "cpu.h")
2739                     FileCollection libavutil_x86 = files("cpu.h") // Use cpu.h from x86 instead of libavutil root if exist
2740                     FileCollection libswscale = files("swscale.h", "version.h")
2741 
2742                     def copyLibAVFiles = {FileCollection files, String fDir, String tDir ->
2743                         File dir = file(tDir)
2744                         dir.mkdirs()
2745 
2746                         files.each { File file ->
2747                             copy {
2748                                 from fDir
2749                                 into tDir
2750                                 include file.name
2751                             }
2752                         }
2753                     }
2754 
2755                     copyLibAVFiles(config, fromDir, "${toDir}/include")
2756                     copyLibAVFiles(libavcodec, "${fromDir}/libavcodec", "${toDir}/include/libavcodec")
2757                     copyLibAVFiles(libavdevice, "${fromDir}/libavdevice", "${toDir}/include/libavdevice")
2758                     copyLibAVFiles(libavfilter, "${fromDir}/libavfilter", "${toDir}/include/libavfilter")
2759                     copyLibAVFiles(libavformat, "${fromDir}/libavformat", "${toDir}/include/libavformat")
2760                     copyLibAVFiles(libavresample, "${fromDir}/libavresample", "${toDir}/include/libavresample")
2761                     copyLibAVFiles(libavutil, "${fromDir}/libavutil", "${toDir}/include/libavutil")
2762                     copyLibAVFiles(libavutil_x86, "${fromDir}/libavutil/x86", "${toDir}/include/libavutil")
2763                     copyLibAVFiles(libswscale, "${fromDir}/libswscale", "${toDir}/include/libswscale")
2764 
2765                     // Copy libs
2766                     FileTree libs = fileTree(dir: "${fromDir}", include: "**/*.so*")
2767                     libs.each {File file ->
2768                         copy {
2769                             from file
2770                             into "${toDir}/lib"
2771                         }
2772                     }
2773                 }
2774 
2775                 def buildLibAVStubs = task("buildLibAVStubs", dependsOn: []) {
2776                     enabled = IS_BUILD_LIBAV_STUBS
2777 
2778                     doLast {
2779                         project.ext.libav = [:]
2780                         project.ext.libav.basedir = "${buildDir}/native/linux/libav"
2781                         project.ext.libav.versions = [ "9.14", "11.4", "12.1" ]
2782                         project.ext.libav.versionmap = [ "9.14" : "54", "11.4" : "56", "12.1" : "57" ]
2783 
2784                         libav.versions.each { version ->
2785                             def libavDir = "${libav.basedir}/libav-${version}"
2786                             for (File f : configurations.media.files) {
2787                                 if (f.name.startsWith("libav-${version}")) {
2788                                     File dir = file(libavDir)
2789                                     dir.mkdirs()
2790                                     def libavTar = "${libav.basedir}/libav-${version}.tar"
2791                                     ant.gunzip(src: f, dest: libavTar)
2792                                     ant.untar(src: libavTar, dest: libav.basedir)
2793                                 }
2794                             }
2795                         }
2796 
2797                         libav.versions.each { version ->
2798                             def libavDir = "${libav.basedir}/libav-${version}"
2799                             File dir = file(libavDir)
2800                             if (dir.exists()) {
2801                                 def configFile = "${libav.basedir}/libav-${version}/config.h"
2802                                 File cfgFile = file(configFile)
2803                                 if (!cfgFile.exists()) {
2804                                     // Add execute permissions to version.sh, otherwise build fails
2805                                     exec {
2806                                         workingDir("$libavDir")
2807                                         commandLine("chmod", "+x", "version.sh")
2808                                     }
2809                                     exec {
2810                                         workingDir("$libavDir")
2811                                         if (IS_BUILD_WORKING_LIBAV) {
2812                                             commandLine(cfgCMDArgs + commonCfgArgs + codecsCfgArgs)
2813                                         } else {
2814                                             commandLine(cfgCMDArgs + commonCfgArgs)
2815                                         }
2816                                     }
2817                                 }
2818                                 exec {
2819                                     workingDir("$libavDir")
2820                                     commandLine("make")
2821                                 }
2822                             }
2823                         }
2824 
2825                         libav.versions.each { version ->
2826                             def fromDir = "${libav.basedir}/libav-${version}"
2827                             def majorVersion = libav.versionmap[version]
2828                             def toDir = "${libav.basedir}/libav-${majorVersion}"
2829                             copyLibAVStubs(fromDir, toDir)
2830                         }
2831                     }
2832                 }
2833 
2834                 def buildLibAVFFmpegStubs = task("buildLibAVFFmpegStubs", dependsOn: []) {
2835                     enabled = IS_BUILD_LIBAV_STUBS
2836 
2837                     def extraCfgArgs = ["--build-suffix=-ffmpeg"]
2838 
2839                     doLast {
2840                         project.ext.libav = [:]
2841                         project.ext.libav.basedir = "${buildDir}/native/linux/libavffmpeg"
2842                         project.ext.libav.versions = [ "11.4" ]
2843                         project.ext.libav.versionmap = [ "11.4" : "56" ]
2844 
2845                         libav.versions.each { version ->
2846                             def libavDir = "${libav.basedir}/libav-${version}"
2847                             for (File f : configurations.media.files) {
2848                                 if (f.name.startsWith("libav-${version}")) {
2849                                     File dir = file(libavDir)
2850                                     dir.mkdirs()
2851                                     def libavTar = "${libav.basedir}/libav-${version}.tar"
2852                                     ant.gunzip(src: f, dest: libavTar)
2853                                     ant.untar(src: libavTar, dest: libav.basedir)
2854                                 }
2855                             }
2856                         }
2857 
2858                         libav.versions.each { version ->
2859                             def libavDir = "${libav.basedir}/libav-${version}"
2860                             File dir = file(libavDir)
2861                             if (dir.exists()) {
2862                                 def configFile = "${libav.basedir}/libav-${version}/config.h"
2863                                 File cfgFile = file(configFile)
2864                                 if (!cfgFile.exists()) {
2865                                     // Patch *.v files, so we have *_FFMPEG_$MAJOR instead of *_$MAJOR, otherwise library will not be loaded
2866                                     FileTree vfiles = fileTree(dir: "${libavDir}", include: "**/*.v")
2867                                     vfiles.each {File file ->
2868                                         String data = file.getText("UTF-8")
2869                                         data = data.replace("_\$MAJOR", "_FFMPEG_\$MAJOR")
2870                                         file.write(data, "UTF-8")
2871                                     }
2872                                     // Add execute permissions to version.sh, otherwise build fails
2873                                     exec {
2874                                         workingDir("$libavDir")
2875                                         commandLine("chmod", "+x", "version.sh")
2876                                     }
2877                                     exec {
2878                                         workingDir("$libavDir")
2879                                         if (IS_BUILD_WORKING_LIBAV) {
2880                                             commandLine(cfgCMDArgs + commonCfgArgs + codecsCfgArgs + extraCfgArgs)
2881                                         } else {
2882                                             commandLine(cfgCMDArgs + commonCfgArgs + extraCfgArgs)
2883                                         }
2884                                     }
2885                                 }
2886                                 exec {
2887                                     workingDir("$libavDir")
2888                                     commandLine("make")
2889                                 }
2890                             }
2891                         }
2892 
2893                         libav.versions.each { version ->
2894                             def fromDir = "${libav.basedir}/libav-${version}"
2895                             def majorVersion = libav.versionmap[version]
2896                             def toDir = "${libav.basedir}/libav-${majorVersion}"
2897                             copyLibAVStubs(fromDir, toDir)
2898 
2899                             // Special case to copy *-ffmpeg.so to *.so
2900                             FileTree libs = fileTree(dir: "${fromDir}", include: "**/*-ffmpeg.so")
2901                             libs.each {File file ->
2902                                 copy {
2903                                     from file
2904                                     into "${toDir}/lib"
2905                                     rename { String fileName ->
2906                                         fileName.replace("-ffmpeg", "")
2907                                     }
2908                                 }
2909                             }
2910                         }
2911                     }
2912                 }
2913 
2914                 def buildFFmpegStubs = task("buildFFmpegStubs", dependsOn: []) {
2915                     enabled = IS_BUILD_LIBAV_STUBS
2916 
2917                     doLast {
2918                         project.ext.libav = [:]
2919                         project.ext.libav.basedir = "${buildDir}/native/linux/ffmpeg"
2920                         project.ext.libav.versions = [ "3.3.3" ]
2921                         project.ext.libav.versionmap = [ "3.3.3" : "57" ]
2922 
2923                         libav.versions.each { version ->
2924                             def libavDir = "${libav.basedir}/ffmpeg-${version}"
2925                             for (File f : configurations.media.files) {
2926                                 if (f.name.startsWith("ffmpeg-${version}")) {
2927                                     File dir = file(libavDir)
2928                                     dir.mkdirs()
2929                                     def libavTar = "${libav.basedir}/ffmpeg-${version}.tar"
2930                                     ant.gunzip(src: f, dest: libavTar)
2931                                     ant.untar(src: libavTar, dest: libav.basedir)
2932                                 }
2933                             }
2934                         }
2935 
2936                         libav.versions.each { version ->
2937                             def libavDir = "${libav.basedir}/ffmpeg-${version}"
2938                             File dir = file(libavDir)
2939                             if (dir.exists()) {
2940                                 def configFile = "${libav.basedir}/ffmpeg-${version}/config.h"
2941                                 File cfgFile = file(configFile)
2942                                 if (!cfgFile.exists()) {
2943                                     // Add execute permissions to version.sh, otherwise build fails
2944                                     exec {
2945                                         workingDir("$libavDir")
2946                                         commandLine("chmod", "+x", "version.sh")
2947                                     }
2948                                     exec {
2949                                         workingDir("$libavDir")
2950                                         if (IS_BUILD_WORKING_LIBAV) {
2951                                             commandLine(cfgCMDArgs + commonCfgArgs + codecsCfgArgs)
2952                                         } else {
2953                                             commandLine(cfgCMDArgs + commonCfgArgs)
2954                                         }
2955                                     }
2956                                 }
2957                                 exec {
2958                                     workingDir("$libavDir")
2959                                     commandLine("make")
2960                                 }
2961                             }
2962                         }
2963 
2964                         libav.versions.each { version ->
2965                             def fromDir = "${libav.basedir}/ffmpeg-${version}"
2966                             def majorVersion = libav.versionmap[version]
2967                             def toDir = "${libav.basedir}/ffmpeg-${majorVersion}"
2968                             copyLibAVStubs(fromDir, toDir)
2969                         }
2970                     }
2971                 }
2972 
2973                 def buildAVPlugin = task( "buildAVPlugin", dependsOn: [buildPlugins, buildLibAVStubs, buildLibAVFFmpegStubs, buildFFmpegStubs]) {
2974                     enabled = IS_COMPILE_MEDIA
2975 
2976                     doLast {
2977                         if (IS_BUILD_LIBAV_STUBS) {
2978                             project.ext.libav = [:]
2979                             project.ext.libav.basedir = "${buildDir}/native/linux/libav/libav"
2980                             project.ext.libav.versions = [ "53", "54", "55", "56", "57" ]
2981                             project.ext.libav.libavffmpeg = [:]
2982                             project.ext.libav.libavffmpeg.basedir = "${buildDir}/native/linux/libavffmpeg/libav"
2983                             project.ext.libav.libavffmpeg.versions = [ "56" ]
2984                             project.ext.libav.ffmpeg = [:]
2985                             project.ext.libav.ffmpeg.basedir = "${buildDir}/native/linux/ffmpeg/ffmpeg"
2986                             project.ext.libav.ffmpeg.versions = [ "57" ]
2987 
2988                             project.ext.libav.versions.each { version ->
2989                                 def libavDir = "${project.ext.libav.basedir}-${version}"
2990                                 File dir = file(libavDir)
2991                                 if (dir.exists()) {
2992                                     exec {
2993                                         commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/gstreamer/projects/linux/avplugin")
2994                                         args("CC=${mediaProperties.compiler}", "LINKER=${mediaProperties.linker}",
2995                                              "OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}",
2996                                              "BASE_NAME=avplugin", "VERSION=${version}", "LIBAV_DIR=${libavDir}",
2997                                              "SUFFIX=", IS_64 ? "ARCH=x64" : "ARCH=x32")
2998                                     }
2999                                 }
3000                             }
3001 
3002                             project.ext.libav.libavffmpeg.versions.each { version ->
3003                                 def libavDir = "${project.ext.libav.libavffmpeg.basedir}-${version}"
3004                                 File dir = file(libavDir)
3005                                 if (dir.exists()) {
3006                                     exec {
3007                                         commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/gstreamer/projects/linux/avplugin")
3008                                         args("CC=${mediaProperties.compiler}", "LINKER=${mediaProperties.linker}",
3009                                              "OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}",
3010                                              "BASE_NAME=avplugin", "VERSION=${version}", "LIBAV_DIR=${libavDir}",
3011                                              "SUFFIX=-ffmpeg", IS_64 ? "ARCH=x64" : "ARCH=x32")
3012                                     }
3013                                 }
3014                             }
3015 
3016                             project.ext.libav.ffmpeg.versions.each { version ->
3017                                 def libavDir = "${project.ext.libav.ffmpeg.basedir}-${version}"
3018                                 File dir = file(libavDir)
3019                                 if (dir.exists()) {
3020                                     exec {
3021                                         commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/gstreamer/projects/linux/avplugin")
3022                                         args("CC=${mediaProperties.compiler}", "LINKER=${mediaProperties.linker}",
3023                                              "OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}",
3024                                              "BASE_NAME=avplugin", "VERSION=${version}", "LIBAV_DIR=${libavDir}",
3025                                              "SUFFIX=-ffmpeg", IS_64 ? "ARCH=x64" : "ARCH=x32")
3026                                     }
3027                                 }
3028                             }
3029                         } else {
3030                             // Building fxavcodec plugin (libav plugin)
3031                             exec {
3032                                 commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/gstreamer/projects/linux/avplugin")
3033                                 args("CC=${mediaProperties.compiler}", "LINKER=${mediaProperties.linker}",
3034                                      "OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}",
3035                                      "BASE_NAME=avplugin", IS_64 ? "ARCH=x64" : "ARCH=x32")
3036                             }
3037                         }
3038                     }
3039                 }
3040                 buildNative.dependsOn buildAVPlugin
3041             }
3042 
3043             if (t.name == "win") {
3044                 def buildResources = task("buildResources") {
3045                     doLast {
3046                         def rcOutputDir = "${nativeOutputDir}/${buildType}"
3047                         mkdir rcOutputDir
3048                         exec {
3049                             environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
3050                             commandLine (WIN.media.rcCompiler)
3051                             args(WIN.media.glibRcFlags)
3052                             args("/Fo${rcOutputDir}/${WIN.media.glibRcFile}", WIN.media.rcSource)
3053                         }
3054 
3055                         exec {
3056                             environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
3057                             commandLine (WIN.media.rcCompiler)
3058                             args(WIN.media.gstreamerRcFlags)
3059                             args("/Fo${rcOutputDir}/${WIN.media.gstreamerRcFile}", WIN.media.rcSource)
3060                         }
3061 
3062                         exec {
3063                             environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
3064                             commandLine (WIN.media.rcCompiler)
3065                             args(WIN.media.fxpluginsRcFlags)
3066                             args("/Fo${rcOutputDir}/${WIN.media.fxpluginsRcFile}", WIN.media.rcSource)
3067                         }
3068 
3069                         exec {
3070                             environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
3071                             commandLine (WIN.media.rcCompiler)
3072                             args(WIN.media.jfxmediaRcFlags)
3073                             args("/Fo${rcOutputDir}/${WIN.media.jfxmediaRcFile}", WIN.media.rcSource)
3074                         }
3075                     }
3076                 }
3077 
3078                 def buildGlib = task("build${t.capital}Glib", dependsOn: [buildResources]) {
3079                     enabled = IS_COMPILE_MEDIA
3080                     doLast {
3081                         exec {
3082                             environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
3083                             commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/gstreamer/projects/${projectDir}/glib-lite")
3084                             args("OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}", "BASE_NAME=glib-lite",
3085                                  IS_64 ? "ARCH=x64" : "ARCH=x32", "RESOURCE=${nativeOutputDir}/${buildType}/${WIN.media.glibRcFile}",
3086                                  "CC=${mediaProperties.compiler}", "AR=${mediaProperties.ar}", "LINKER=${mediaProperties.linker}")
3087                         }
3088                     }
3089                 }
3090                 buildGStreamer.dependsOn buildGlib
3091 
3092             } else if (t.name == "mac") {
3093                 def buildGlib = task("build${t.capital}Glib") {
3094                     enabled = IS_COMPILE_MEDIA
3095                     doLast {
3096                         exec {
3097                             commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/gstreamer/projects/${projectDir}/libffi")
3098                             args("OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}", "BASE_NAME=ffi")
3099                             args ("CC=${mediaProperties.compiler}", "LINKER=${mediaProperties.linker}", "AR=${mediaProperties.ar}")
3100                         }
3101 
3102                         exec {
3103                             commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/gstreamer/projects/${projectDir}/glib-lite")
3104                             args("OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}", "BASE_NAME=glib-lite")
3105                             args ("CC=${mediaProperties.compiler}", "LINKER=${mediaProperties.linker}")
3106                         }
3107                     }
3108                 }
3109                 buildGStreamer.dependsOn buildGlib
3110             }
3111         }
3112 
3113         buildNativeTargets.dependsOn buildNative
3114     }
3115 
3116     jar {
3117         exclude("headergen/**")
3118 
3119         dependsOn compileJava
3120         if (IS_COMPILE_MEDIA) {
3121             dependsOn buildNativeTargets
3122         }
3123     }
3124 
3125     addMavenPublication(project, [ 'graphics' ])
3126 
3127 }
3128 
3129 project(":web") {
3130     configurations {
3131         webkit
3132     }
3133     project.ext.buildModule = true
3134     project.ext.includeSources = true
3135     project.ext.moduleRuntime = true
3136     project.ext.moduleName = "javafx.web"
3137 
3138     sourceSets {
3139         main
3140         shims
3141         test
3142     }
3143 
3144     project.ext.moduleSourcePath = defaultModuleSourcePath
3145     project.ext.moduleSourcePathShim = defaultModuleSourcePathShim
3146 
3147     commonModuleSetup(project, [ 'base', 'graphics', 'controls', 'media', 'web' ])
3148 
3149     dependencies {
3150     }
3151 
3152     compileJava.dependsOn updateCacheIfNeeded
3153 
3154     task webArchiveJar(type: Jar) {
3155         from (project.file("$projectDir/src/test/resources/test/html")) {
3156             include "**/archive-*.*"
3157         }
3158         archiveName = "webArchiveJar.jar"
3159         destinationDir = file("$buildDir/testing/resources")
3160     }
3161 
3162     def gensrcDir = "${buildDir}/gensrc/java"
3163 
3164     // add in the wrappers to the compile
3165     sourceSets.main.java.srcDirs += "${gensrcDir}"
3166 
3167     if (IS_COMPILE_WEBKIT) {
3168         compileJava {
3169             // generate the native headers during compile
3170             // only needed if we are doing the native compile
3171             options.compilerArgs.addAll([
3172                 '-h', "${project.buildDir}/gensrc/headers"
3173                 ])
3174         }
3175     }
3176 
3177     // Copy these to a common location in the moduleSourcePath
3178     def copyWrappers = project.task("copyPreGeneratedWrappers", type: Copy) {
3179         from "src/main/native/Source/WebCore/bindings/java/dom3/java"
3180         into "${gensrcDir}"
3181     }
3182 
3183     compileJava.dependsOn(copyWrappers);
3184 
3185     test {
3186         doFirst {
3187             if (!IS_COMPILE_WEBKIT) {
3188                 println "*****************************************************"
3189                 println "WARNING: running web tests without building webkit."
3190                 println "The webkit native library will be copied from the JDK,"
3191                 println "which might lead to failures in some web tests."
3192                 println "To avoid these failures, you should either build"
3193                 println "webkit locally, copy the native webkit library from a"
3194                 println "recent build, or skip execution of web test cases with"
3195                 println "'-x :web:test'"
3196                 println "*****************************************************"
3197             }
3198         }
3199         // Run web tests in headless mode
3200         systemProperty 'glass.platform', 'Monocle'
3201         systemProperty 'monocle.platform', 'Headless'
3202         systemProperty 'prism.order', 'sw'
3203         dependsOn webArchiveJar
3204         def testResourceDir = file("$buildDir/testing/resources")
3205         jvmArgs "-DWEB_ARCHIVE_JAR_TEST_DIR=$testResourceDir"
3206     }
3207 
3208     task compileJavaDOMBinding()
3209 
3210     compileTargets { t ->
3211         def targetProperties = project.rootProject.ext[t.upper]
3212         def webkitProperties = targetProperties.webkit
3213         def classifier = (t.name != "linux" && t.name != "win") ? t.name :
3214                           IS_64 ? "${t.name}-amd64" : "${t.name}-i586"
3215 
3216         def webkitOutputDir = cygpath("$buildDir/${t.name}")
3217         def webkitConfig = IS_DEBUG_NATIVE ? "Debug" : "Release"
3218 
3219         File nativeBuildDir = new File("${webkitOutputDir}")
3220         nativeBuildDir.mkdirs()
3221 
3222         def compileNativeTask = task("compileNative${t.capital}", dependsOn: [compileJava]) {
3223             println "Building Webkit configuration /$webkitConfig/ into $webkitOutputDir"
3224             enabled =  (IS_COMPILE_WEBKIT)
3225 
3226             doLast {
3227                 exec {
3228                     workingDir("$webkitOutputDir")
3229                     commandLine("perl", "$projectDir/src/main/native/Tools/Scripts/set-webkit-configuration", "--$webkitConfig")
3230                     environment(["WEBKIT_OUTPUTDIR" : webkitOutputDir])
3231                 }
3232 
3233                 exec {
3234                     workingDir("$webkitOutputDir")
3235                     def cmakeArgs = "-DENABLE_TOOLS=1"
3236                     if (t.name == "win") {
3237                         String parfaitPath = IS_COMPILE_PARFAIT ? System.getenv().get("PARFAIT_PATH") + ";" : "";
3238                         Map environmentSettings = new HashMap(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
3239                         environmentSettings["PATH"] = parfaitPath + "$WINDOWS_VS_PATH"
3240                         /* To build with ICU:
3241                         1. Download http://javaweb.us.oracle.com/jcg/fx-webrevs/RT-17164/WebKitLibrariesICU.zip
3242                         and unzip it to WebKitLibraries folder.
3243                         2. Copy DLLs from
3244                         WebKitLibrariesICU.zip\WebKitLibraries\import\runtime
3245                         to %windir%\system32
3246                         3. Uncomment the line below
3247                          */
3248                         // args("--icu-unicode")
3249 
3250                         // To enable ninja build on Windows
3251                         environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT + ['CC' : 'cl', 'CXX' : 'cl'])
3252                     } else if (t.name == "mac") {
3253                         cmakeArgs = "-DCMAKE_OSX_DEPLOYMENT_TARGET=$MACOSX_MIN_VERSION -DCMAKE_OSX_SYSROOT=$MACOSX_SDK_PATH"
3254                     } else if (t.name == "linux") {
3255                         cmakeArgs = "-DCMAKE_SYSTEM_NAME=Linux -DCMAKE_C_COMPILER=${webkitProperties.compiler}"
3256                         if (IS_64) {
3257                             cmakeArgs = "$cmakeArgs -DCMAKE_SYSTEM_PROCESSOR=x86_64"
3258                         } else {
3259                             cmakeArgs = "$cmakeArgs -DCMAKE_SYSTEM_PROCESSOR=i586"
3260                         }
3261                         // TODO: Use cflags and ldflags from all platforms
3262                         def cFlags = webkitProperties.ccFlags?.join(' ') ?: ''
3263                         def lFlags = webkitProperties.linkFlags?.join(' ') ?: ''
3264                         // -shared flag should be omitted while creating executable.
3265                         def exeFlags = webkitProperties.linkFlags?.join(' ')?.replace('-shared', '') ?: ''
3266                         cmakeArgs = "$cmakeArgs -DCMAKE_C_FLAGS='${cFlags}' -DCMAKE_CXX_FLAGS='${cFlags}'"
3267                         cmakeArgs = "$cmakeArgs -DCMAKE_SHARED_LINKER_FLAGS='${lFlags}' -DCMAKE_EXE_LINKER_FLAGS='${exeFlags}'"
3268                     } else if (t.name.startsWith("arm")) {
3269                         fail("ARM target is not supported as of now.")
3270                     }
3271 
3272                     if (IS_COMPILE_PARFAIT) {
3273                         environment([
3274                             "COMPILE_PARFAIT" : "true"
3275                         ])
3276                         cmakeArgs = "-DCMAKE_C_COMPILER=parfait-gcc -DCMAKE_CXX_COMPILER=parfait-g++"
3277                     }
3278 
3279                     environment([
3280                         "JAVA_HOME"       : JDK_HOME,
3281                         "WEBKIT_OUTPUTDIR" : webkitOutputDir,
3282                         "PYTHONDONTWRITEBYTECODE" : "1",
3283                     ])
3284 
3285                     def targetCpuBitDepthSwitch = ""
3286                     if (IS_64) {
3287                         targetCpuBitDepthSwitch = "--64-bit"
3288                     } else {
3289                         targetCpuBitDepthSwitch = "--32-bit"
3290                     }
3291                     cmakeArgs += " -DJAVAFX_RELEASE_VERSION=${jfxReleaseMajorVersion}"
3292                     commandLine("perl", "$projectDir/src/main/native/Tools/Scripts/build-webkit",
3293                         "--java", "--icu-unicode", targetCpuBitDepthSwitch,
3294                         "--cmakeargs=${cmakeArgs}")
3295                 }
3296             }
3297         }
3298 
3299         // Cmake places Windows DLL in bin directory
3300         def dllDir = IS_WINDOWS ? "bin" : "lib"
3301         def copyDumpTreeNativeTask = task("copyDumpTreeNative${t.capital}", type: Copy,
3302                 dependsOn: [ compileNativeTask]) {
3303             def library = rootProject.ext[t.upper].library
3304             from "$webkitOutputDir/$webkitConfig/$dllDir/${library('DumpRenderTreeJava')}"
3305             into "$buildDir/test/${t.name}"
3306         }
3307 
3308         def copyNativeTask = task("copyNative${t.capital}", type: Copy,
3309                 dependsOn: [compileNativeTask, , copyDumpTreeNativeTask]) {
3310             enabled =  (IS_COMPILE_WEBKIT)
3311             def library = rootProject.ext[t.upper].library
3312             from "$webkitOutputDir/$webkitConfig/$dllDir/${library('jfxwebkit')}"
3313             into "$buildDir/libs/${t.name}"
3314         }
3315 
3316         if (IS_WINDOWS && t.name == "win") {
3317             def rcTask = project.task("rc${t.capital}", type: CompileResourceTask) {
3318                 compiler = webkitProperties.rcCompiler
3319                 source(webkitProperties.rcSource)
3320                 if (webkitProperties.rcFlags) {
3321                     rcParams.addAll(webkitProperties.rcFlags)
3322                 }
3323                 output(file("$webkitOutputDir/$webkitConfig/WebCore/obj"))
3324             }
3325             compileNativeTask.dependsOn rcTask
3326         }
3327 
3328         def compileJavaDOMBindingTask = task("compileJavaDOMBinding${t.capital}", type: JavaCompile,
3329                 dependsOn: [compileJava, compileNativeTask, copyNativeTask]) {
3330             destinationDir = file("$buildDir/classes/java/main")
3331             classpath = configurations.compile
3332             source = project.sourceSets.main.java.srcDirs
3333             options.compilerArgs.addAll([
3334                 '-implicit:none',
3335                 '--module-source-path', defaultModuleSourcePath
3336                 ])
3337         }
3338 
3339         compileJavaDOMBinding.dependsOn compileJavaDOMBindingTask
3340 
3341         if (!targetProperties.compileWebnodeNative) {
3342             println("Not compiling native Webkit for ${t.name} per configuration request");
3343             compileNativeTask.enabled = false
3344         }
3345     }
3346 
3347     def drtClasses = "**/com/sun/javafx/webkit/drt/**"
3348     task drtJar(type: Jar, dependsOn: compileJava) {
3349         archiveName = "drt.jar"
3350         destinationDir = file("$buildDir/test")
3351         from "$buildDir/classes/java/main/javafx.web/"
3352         include drtClasses
3353         includeEmptyDirs = false
3354     }
3355 
3356     if (IS_COMPILE_WEBKIT) {
3357         assemble.dependsOn compileJavaDOMBinding, drtJar
3358     }
3359 
3360     addMavenPublication(project, [ 'controls', 'media' ])
3361 
3362 }
3363 
3364 // This project is for system tests that need to run with a full SDK.
3365 // Most of them display a stage or do other things that preclude running
3366 // them in a shared JVM or as part of the "smoke test" run (which must
3367 // not pop up any windows or use audio). As such, they are only enabled
3368 // when FULL_TEST is specified, and each test runs in its own JVM
3369 project(":systemTests") {
3370 
3371     sourceSets {
3372         test
3373 
3374         // Source sets for standalone test apps (used for launcher tests)
3375         testapp1
3376 
3377         // Modular applications
3378         testapp2
3379         testapp3
3380         testapp4
3381         testapp5
3382         testapp6
3383     }
3384 
3385     project.ext.buildModule = false
3386     project.ext.moduleRuntime = false
3387     project.ext.moduleName = "systemTests"
3388 
3389     dependencies {
3390         testCompile project(":graphics").sourceSets.test.output
3391         testCompile project(":base").sourceSets.test.output
3392         testCompile project(":controls").sourceSets.test.output
3393         testCompile project(":swing").sourceSets.test.output
3394     }
3395 
3396     def dependentProjects = [ 'base', 'graphics', 'controls', 'media', 'web', 'swing', 'fxml' ]
3397     commonModuleSetup(project, dependentProjects)
3398 
3399     File testJavaPolicyFile = new File(rootProject.buildDir, TESTJAVAPOLICYFILE);
3400     File testRunArgsFile = new File(rootProject.buildDir,TESTRUNARGSFILE);
3401 
3402     File stRunArgsFile = new File(project.buildDir,"st.run.args");
3403 
3404     def sts = task("systemTestSetup") {
3405         outputs.file(stRunArgsFile)
3406 
3407         doLast() {
3408             stRunArgsFile.delete()
3409 
3410             logger.info("Creating patchmodule.args file ${stRunArgsFile}")
3411 
3412             // Create an argfile with the information needed to launch
3413             // the stand alone system unit tests.
3414 
3415             //First add in all of the patch-module args we use for the
3416             //normal unit tests, copied from test.run.args
3417             testRunArgsFile.eachLine { str ->
3418                 stRunArgsFile <<  "${str}\n"
3419             }
3420 
3421             // Now add in the working classpath elements (junit, test classes...)
3422             stRunArgsFile <<  "-cp \"\\\n"
3423             test.classpath.each() { elem ->
3424                 def e = cygpath("${elem}")
3425                 stRunArgsFile <<  "  ${e}${File.pathSeparator}\\\n"
3426             }
3427             stRunArgsFile <<  "\"\n"
3428         }
3429     }
3430 
3431     test.dependsOn(sts)
3432     test.dependsOn(createTestArgfiles);
3433 
3434     // Tasks to create standalone test applications for the launcher tests
3435 
3436     if (project.hasProperty('testModulePathArgs')) {
3437         compileTestapp1Java.options.compilerArgs.addAll(testModulePathArgs)
3438     }
3439     dependentProjects.each { e ->
3440         compileTestapp1Java.dependsOn(rootProject.project(e).testClasses)
3441     }
3442 
3443     def testapp1JarName = "testapp1.jar"
3444     task createTestapp1Jar1(type: Jar) {
3445         dependsOn compileTestapp1Java
3446         enabled = IS_FULL_TEST
3447 
3448         destinationDir = file("$buildDir/testapp1")
3449         archiveName = testapp1JarName
3450         includeEmptyDirs = false
3451         from project.sourceSets.testapp1.java.outputDir
3452         include("testapp/**")
3453         include("com/javafx/main/**")
3454 
3455         manifest {
3456             attributes(
3457                 "Main-Class" : "com.javafx.main.Main",
3458                 "JavaFX-Version" : "2.2",
3459                 "JavaFX-Application-Class" : "testapp.HelloWorld",
3460                 "JavaFX-Class-Path" : "jar2.jar"
3461             )
3462         }
3463     }
3464 
3465     task createTestapp1Jar2(type: Jar) {
3466         dependsOn compileTestapp1Java
3467         enabled = IS_FULL_TEST
3468 
3469         destinationDir = file("$buildDir/testapp1")
3470         archiveName = "jar2.jar";
3471         includeEmptyDirs = false
3472         from project.sourceSets.testapp1.java.outputDir
3473         include("pkg2/**")
3474     }
3475 
3476     task createTestApps() {
3477         dependsOn(createTestapp1Jar1)
3478         dependsOn(createTestapp1Jar2)
3479     }
3480     test.dependsOn(createTestApps);
3481 
3482     def modtestapps = [ "testapp2", "testapp3", "testapp4", "testapp5", "testapp6"  ]
3483     modtestapps.each { testapp ->
3484         def testappCapital = testapp.capitalize()
3485         def copyTestAppTask = task("copy${testappCapital}", type: Copy) {
3486             from project.sourceSets."${testapp}".java.outputDir
3487             from project.sourceSets."${testapp}".output.resourcesDir
3488             into "${project.buildDir}/modules/${testapp}"
3489         }
3490 
3491         def List<String> testAppSourceDirs = []
3492         project.sourceSets."${testapp}".java.srcDirs.each { dir ->
3493             testAppSourceDirs += dir
3494         }
3495         def testappCompileTasks = project.getTasksByName("compile${testappCapital}Java", true);
3496         def testappResourceTasks = project.getTasksByName("process${testappCapital}Resources", true);
3497         testappCompileTasks.each { appCompileTask ->
3498             appCompileTask.options.compilerArgs.addAll([
3499                 '-implicit:none',
3500                 '--module-source-path', testAppSourceDirs.join(File.pathSeparator),
3501                 ] )
3502             if (project.hasProperty('testModulePathArgs')) {
3503                 appCompileTask.options.compilerArgs.addAll(testModulePathArgs)
3504             }
3505 
3506             dependentProjects.each { e ->
3507                 appCompileTask.dependsOn(rootProject.project(e).testClasses)
3508             }
3509 
3510             copyTestAppTask.dependsOn(appCompileTask)
3511         }
3512         testappResourceTasks.each { appResourceTask ->
3513             copyTestAppTask.dependsOn(appResourceTask)
3514         }
3515 
3516         createTestApps.dependsOn(copyTestAppTask)
3517     }
3518 
3519     test {
3520         enabled = IS_FULL_TEST
3521 
3522         // Parse testPatchModuleArgs looking for "--module-path".
3523         // Save path if found so we can pass it to the module launcher tests
3524         def pendingModulePath = false
3525         testPatchModuleArgs.each { str ->
3526             if (pendingModulePath) {
3527                 project.ext.launcherModulePath = str;
3528                 pendingModulePath = false
3529             } else if (str == "--module-path") {
3530                 pendingModulePath = true
3531             }
3532         }
3533 
3534         // Properties passed to launcher tests
3535         systemProperty "launchertest.testapp1.jar", "build/testapp1/$testapp1JarName"
3536         modtestapps.each { testapp ->
3537             systemProperty "launchertest.${testapp}.module.path",
3538                     "${project.buildDir}/modules/${testapp}"
3539         }
3540 
3541         // Properties passed to test.util.Util
3542         systemProperties 'worker.debug': IS_WORKER_DEBUG
3543         systemProperties 'worker.patchmodule.file': cygpath(stRunArgsFile.path)
3544         if (project.hasProperty("launcherModulePath")) {
3545             systemProperties 'worker.module.path': launcherModulePath
3546         }
3547         systemProperties 'worker.patch.policy': cygpath(testJavaPolicyFile.path)
3548         systemProperties 'worker.java.cmd': JAVA
3549 
3550         if (rootProject.hasProperty("ClipShapeTest.numTests")) {
3551             systemProperty "ClipShapeTest.numTests", rootProject.getProperty("ClipShapeTest.numTests")
3552         }
3553 
3554         if (!IS_USE_ROBOT) {
3555             // Disable all robot-based visual tests
3556             exclude("test/robot/**");
3557         }
3558         if (!IS_UNSTABLE_TEST) {
3559             // JDK-8196607 Don't run monocle test cases 
3560             exclude("test/robot/com/sun/glass/ui/monocle/**");
3561         }
3562         if (!IS_AWT_TEST) {
3563             // Disable all AWT-based tests
3564             exclude("**/javafx/embed/swing/*.*");
3565             exclude("**/com/sun/javafx/application/Swing*.*");
3566         }
3567 
3568         if (!HAS_JAVAFX_MODULES) {
3569             jvmArgs += qualExportsSwing
3570         }
3571 
3572         forkEvery = 1
3573     }
3574 }
3575 
3576 allprojects {
3577     // The following block is a workaround for the fact that presently Gradle
3578     // can't set the -XDignore.symbol.file flag, because it appears that the
3579     // javac API is lacking support for it. So what we'll do is find any Compile
3580     // task and manually provide the options necessary to fire up the
3581     // compiler with the right settings.
3582     tasks.withType(JavaCompile) { compile ->
3583         if (compile.options.hasProperty("useAnt")) {
3584             compile.options.useAnt = true
3585             compile.options.useDepend = IS_USE_DEPEND
3586         } else if (compile.options.hasProperty("incremental")) {
3587             compile.options.incremental = IS_INCREMENTAL
3588         }
3589         compile.options.debug = true // we always generate debugging info in the class files
3590         compile.options.debugOptions.debugLevel = IS_DEBUG_JAVA ? "source,lines,vars" : "source,lines"
3591         compile.options.fork = true
3592 
3593         compile.options.forkOptions.executable = JAVAC
3594 
3595         compile.options.warnings = IS_LINT
3596 
3597         compile.options.compilerArgs += ["-XDignore.symbol.file", "-encoding", "UTF-8"]
3598 
3599         // we use a custom javadoc command
3600         project.javadoc.enabled = false
3601 
3602         // Add in the -Xlint options
3603         if (IS_LINT) {
3604             LINT.split("[, ]").each { s ->
3605                 compile.options.compilerArgs += "-Xlint:$s"
3606             }
3607         }
3608     } // tasks with javaCompile
3609 
3610     // If I am a module....
3611     if (project.hasProperty('moduleSourcePath') &&
3612             (project.hasProperty('buildModule') && project.buildModule)) {
3613         project.compileJava {
3614             options.compilerArgs.addAll([
3615                 '-implicit:none',
3616                 '--module-source-path', project.moduleSourcePath
3617                 ])
3618         }
3619         // no jars needed for modules
3620         project.jar.enabled = false
3621 
3622         // and redirect the resources into the module
3623         project.processResources.destinationDir = project.moduleDir
3624     }
3625 
3626     if (project.hasProperty('moduleSourcePathShim') &&
3627             project.sourceSets.hasProperty('shims')) {
3628 
3629         // sync up the obvious source directories with the shims
3630         // others (like the shaders in graphics) should be added in there
3631         project.sourceSets.shims.java.srcDirs += project.sourceSets.main.java.srcDirs
3632         project.sourceSets.shims.java.srcDirs += "$buildDir/gensrc/java"
3633 
3634         project.compileShimsJava {
3635             options.compilerArgs.addAll([
3636                 '-implicit:none',
3637                 '--module-source-path', project.moduleSourcePathShim
3638                 ])
3639         }
3640         project.compileShimsJava.dependsOn(project.compileJava)
3641 
3642         def copyGeneratedShimsTask = task("copyGeneratedShims", type: Copy, dependsOn: [compileShimsJava, processShimsResources]) {
3643             from project.sourceSets.shims.java.outputDir
3644             into "${rootProject.buildDir}/shims"
3645             if (HAS_JAVAFX_MODULES) {
3646                 exclude("*/module-info.class")
3647             }
3648         }
3649 
3650         project.processShimsResources.dependsOn(project.processResources)
3651 
3652         // shims resources should have the main resouces as a base
3653         project.sourceSets.shims.resources.srcDirs += project.sourceSets.main.resources.srcDirs
3654 
3655         // and redirect the resources into the module
3656         project.processShimsResources.destinationDir = project.moduleShimsDir
3657 
3658        compileTestJava.dependsOn(copyGeneratedShimsTask)
3659     }
3660 
3661     if (project.hasProperty('modulePathArgs')) {
3662         project.compileJava.options.compilerArgs.addAll(modulePathArgs)
3663     }
3664 
3665     if (project.hasProperty('testModulePathArgs')) {
3666         project.compileTestJava.options.compilerArgs.addAll(testModulePathArgs)
3667     }
3668 
3669     if (project.hasProperty('testPatchModuleArgs')) {
3670         project.test.jvmArgs += testPatchModuleArgs
3671     }
3672 
3673     /* Note: we should not have to add extraAddExports to the normal
3674      * modular compile, as it contains all of the module-info files.
3675      * In fact doing so might cover up a module-info issue.
3676      * so we don't do it, and I will leave this commented out
3677      * block as a reminder of this fact.
3678     if (project.hasProperty('extraAddExports')) {
3679         project.compileJava.options.compilerArgs.addAll(extraAddExports);
3680     }
3681     */
3682 
3683     if (project.hasProperty('testAddExports')) {
3684         project.compileTestJava.options.compilerArgs.addAll(testAddExports);
3685         project.test.jvmArgs += testAddExports
3686     }
3687 
3688     if (rootProject.hasProperty("EXTRA_TEST_ARGS") && project.hasProperty('test')) {
3689         EXTRA_TEST_ARGS.split(' ').each() { e ->
3690             project.test.jvmArgs += e
3691         }
3692     }
3693 
3694     if (rootProject.hasProperty("EXTRA_COMPILE_ARGS") && project.hasProperty('compileJava')) {
3695         project.compileJava.options.compilerArgs.addAll(EXTRA_COMPILE_ARGS.split(' '))
3696     }
3697 
3698     if (rootProject.hasProperty("EXTRA_COMPILE_ARGS") && project.hasProperty('compileTestJava')) {
3699         project.compileTestJava.options.compilerArgs.addAll(EXTRA_COMPILE_ARGS.split(' '))
3700     }
3701 }
3702 
3703 /******************************************************************************
3704  *                                                                            *
3705  *                             Top Level Tasks                                *
3706  *                                                                            *
3707  *  These are the tasks which are defined only for the top level project and  *
3708  *  not for any sub projects. These are generally the entry point that is     *
3709  *  used by Hudson and by the continuous build system.                        *
3710  *                                                                            *
3711  *****************************************************************************/
3712 
3713 task clean() {
3714     group = "Basic"
3715     description = "Deletes the build directory and the build directory of all sub projects"
3716     getSubprojects().each { subProject ->
3717         dependsOn(subProject.getTasksByName("clean", true));
3718     }
3719     doLast {
3720         delete(buildDir);
3721     }
3722 }
3723 
3724 task cleanAll() {
3725     group = "Basic"
3726     description = "Scrubs the repo of build artifacts"
3727     dependsOn(clean)
3728     doLast {
3729         //delete(".gradle"); This causes problems on windows.
3730         delete("buildSrc/build");
3731     }
3732 }
3733 
3734 task createMSPfile() {
3735     group = "Build"
3736     File mspFile = new File(rootProject.buildDir,MODULESOURCEPATH)
3737     outputs.file(mspFile)
3738 
3739     doLast {
3740         mspFile.delete()
3741         mspFile << "--module-source-path\n"
3742         mspFile << defaultModuleSourcePath
3743         mspFile << "\n"
3744 
3745         if (!HAS_JAVAFX_MODULES) {
3746             appendQualExports(mspFile, qualExportsSwing)
3747         }
3748     }
3749 }
3750 
3751 task javadoc(type: Javadoc, dependsOn: createMSPfile) {
3752     group = "Basic"
3753     description = "Generates the JavaDoc for all the public API"
3754     executable = JAVADOC
3755     def projectsToDocument = [
3756             project(":base"), project(":graphics"), project(":controls"), project(":media"),
3757             project(":swing"), /*project(":swt"),*/ project(":fxml"), project(":web")]
3758     source(projectsToDocument.collect({
3759         [it.sourceSets.main.java]
3760     }));
3761     setDestinationDir(new File(buildDir, 'javadoc'));
3762 
3763     exclude("com/**/*", "Compile*", "javafx/builder/**/*", "javafx/scene/accessibility/**/*");
3764 
3765     options.tags("apiNote:a:API Note:")
3766     options.tags("implSpec:a:Implementation Requirements:")
3767     options.tags("implNote:a:Implementation Note:")
3768     options.tags("param")
3769     options.tags("return")
3770     options.tags("throws")
3771     options.tags("moduleGraph:X")
3772     options.tags("since")
3773     options.tags("version")
3774     options.tags("serialData")
3775     options.tags("factory")
3776     options.tags("see")
3777 
3778     options.windowTitle("${javadocTitle}")
3779     options.header("${javadocHeader}")
3780     options.bottom("${javadocBottom}")
3781     options.locale("en");
3782     if (JDK_DOCS_LINK != "") {
3783         options.linksOffline(JDK_DOCS, JDK_DOCS_LINK);
3784     } else {
3785         options.links(JDK_DOCS);
3786     }
3787     options.addBooleanOption("XDignore.symbol.file").setValue(true);
3788     options.addBooleanOption("Xdoclint:${DOC_LINT}").setValue(IS_DOC_LINT);
3789     options.addBooleanOption("html5").setValue(true);
3790     options.addBooleanOption("javafx").setValue(true);
3791     options.addBooleanOption("use").setValue(true);
3792 
3793     options.setOptionFiles([
3794         new File(rootProject.buildDir,MODULESOURCEPATH)
3795         ]);
3796 
3797     doLast {
3798         // FIXME: remove JDK 10 logic once minimum JDK is bumped to 11
3799         def isBootJdk10 = jdkVersion.startsWith("10")
3800         projectsToDocument.each { p ->
3801             def destDir = isBootJdk10 ? "$buildDir/javadoc" : "$buildDir/javadoc/${p.ext.moduleName}"
3802             copy {
3803                 from("$p.projectDir/src/main/docs") {
3804                     include "**/*.html"
3805                     filter { line->
3806                         line = line.replace("@FXVERSION@", RELEASE_VERSION)
3807                     }
3808                 }
3809                 from("$p.projectDir/src/main/docs") {
3810                     exclude "**/*.html"
3811                 }
3812 
3813                 into destDir
3814             }
3815         }
3816     }
3817 
3818     dependsOn(projectsToDocument.collect { project -> project.getTasksByName("classes", true)});
3819 }
3820 
3821 task sdk() {
3822     if (DO_BUILD_SDK_FOR_TEST) {
3823         rootProject.getTasksByName("test", true).each { t ->
3824             if (t.enabled) t.dependsOn(sdk)
3825         }
3826     }
3827 }
3828 
3829 task jmods() {
3830     dependsOn(sdk)
3831     // real work items added later.
3832 }
3833 
3834 task appsjar() {
3835     dependsOn(sdk)
3836     // Note: the jar dependencies get added elsewhere see project(":apps")
3837 }
3838 
3839 // these are empty tasks, allowing us to depend on the task, which may have other
3840 // real work items added later.
3841 task copyAppsArtifacts() {
3842     dependsOn(appsjar)
3843 }
3844 
3845 task apps() {
3846     dependsOn(sdk)
3847     dependsOn(appsjar)
3848     dependsOn(copyAppsArtifacts)
3849 }
3850 
3851 task findbugs() {
3852     dependsOn(sdk)
3853 
3854     doLast {
3855         if (!BUILD_CLOSED) {
3856             println "findbugs task is only run for a closed build"
3857         }
3858     }
3859 }
3860 
3861 // create the zip file of modules for a JDK build
3862 task jdkZip {
3863     dependsOn(sdk)
3864 }
3865 
3866 // The following tasks are for the closed build only. They are a no-op for the open build
3867 
3868 task checkCache() {
3869     dependsOn(updateCacheIfNeeded)
3870 }
3871 
3872 task publicExports() {
3873     dependsOn(sdk, jmods, apps, javadoc, jdkZip)
3874     // note the real work is below in the compileTargets
3875 }
3876 
3877 task perf() {
3878     dependsOn(sdk, apps)
3879     doLast {
3880         if (!BUILD_CLOSED) {
3881             println "perf task is only run for a closed build"
3882         }
3883     }
3884 }
3885 
3886 task zips() {
3887     dependsOn(sdk, jmods, javadoc, apps, jdkZip, publicExports, perf)
3888     // note the real work is below in the compileTargets
3889 }
3890 
3891 task all() {
3892     dependsOn(sdk,publicExports,apps,perf,zips)
3893 }
3894 
3895 
3896 // Construct list of subprojects that are modules
3897 ext.moduleProjList = []
3898 subprojects {
3899     if (project.hasProperty("buildModule") && project.ext.buildModule) {
3900         rootProject.ext.moduleProjList += project
3901         println "module: $project (buildModule=YES)"
3902     } else {
3903         println "module: $project (buildModule=NO)"
3904     }
3905 }
3906 
3907 
3908 // Define the sdk task, which also produces the javafx.swt modular jar
3909 
3910 compileTargets { t ->
3911 
3912     def javafxSwtTask = task("javafxSwt$t.capital", type: Jar) {
3913         enabled = COMPILE_SWT
3914         group = "Basic"
3915         description = "Creates the javafx-swt.jar for the $t.name target"
3916         archiveName = "${project(":swt").buildDir}/libs/javafx-swt.jar";
3917         includeEmptyDirs = false
3918         from("${project(":swt").buildDir}/classes/java/main");
3919         include("**/javafx/embed/swt/**")
3920 
3921         dependsOn(
3922             project(":swt").compileJava,
3923             project(":swt").processResources,
3924             // note: assemble and classes are not enough for DidWork
3925             project(":swt").classes,
3926             // classes is needed for a jar copy
3927             )
3928     }
3929 
3930     // FIXME: do we really need the index task for this modular jar?
3931     def javafxSwtIndexTask = task("javafxSwtIndex$t.capital") {
3932         //the following is a workaround for the lack of indexing in gradle 1.4 through 1.7
3933         dependsOn(javafxSwtTask)
3934 
3935         doLast() {
3936             ant.jar (update: true, index: true, destfile: javafxSwtTask.archiveName)
3937         }
3938     }
3939 
3940     def sdkTask = task("sdk$t.capital") {
3941         group = "Basic"
3942         dependsOn(javafxSwtIndexTask)
3943     }
3944 
3945     sdk.dependsOn(sdkTask)
3946 }
3947 
3948 project(":apps") {
3949     // The apps build is Ant based, we will exec ant from gradle.
3950 
3951     // Download the Lucene libraries needed for the Ensemble8 app
3952     def luceneVersion = "7.4.0"
3953     getConfigurations().create("lucene");
3954     dependencies {
3955         lucene group: "org.apache.lucene", name: "lucene-core", version: luceneVersion
3956         lucene group: "org.apache.lucene", name: "lucene-grouping", version: luceneVersion
3957         lucene group: "org.apache.lucene", name: "lucene-queryparser", version: luceneVersion
3958     }
3959 
3960     // Copy Lucene libraries into the Ensemble8/lib directory
3961     File ensembleLibDir = rootProject.file("apps/samples/Ensemble8/lib");
3962     def libNames = [ "lucene-core-${luceneVersion}.jar",
3963                      "lucene-grouping-${luceneVersion}.jar",
3964                      "lucene-queryparser-${luceneVersion}.jar" ]
3965 
3966 
3967     task getLucene(type: Copy) {
3968         doFirst {
3969             ensembleLibDir.mkdirs();
3970         }
3971         into ensembleLibDir
3972         includeEmptyDirs = false
3973         configurations.lucene.files.each { f ->
3974             libNames.each { name ->
3975                 if (name == f.getName()) {
3976                     from f.getPath()
3977                 }
3978             }
3979         }
3980     }
3981 
3982     compileTargets { t ->
3983         List<String> params = []
3984 
3985         params << "-DtargetBld=$t.name"
3986 
3987         if (!rootProject.ext[t.upper].compileSwing) {
3988             params << "-DJFX_CORE_ONLY=true"
3989         }
3990         params << "-Dplatforms.JDK_1.9.home=${rootProject.ext.JDK_HOME}"
3991         params << "-Dcompile.patch=@${rootProject.buildDir}/${COMPILEARGSFILE}"
3992         params << "-Drun.patch=@${rootProject.buildDir}/${RUNARGSFILE}"
3993 
3994         def appsJar = project.task("appsJar${t.capital}") {
3995             dependsOn(sdk, getLucene)
3996             doLast() {
3997                 ant(t.name,
3998                       projectDir.path,
3999                       "appsJar",
4000                       params);
4001             }
4002         }
4003         rootProject.appsjar.dependsOn(appsJar)
4004 
4005         def appsClean = project.task("clean${t.capital}") {
4006             doLast() {
4007                 ant(t.name,
4008                       project.projectDir.path,
4009                       "clean",
4010                       params);
4011                 delete(ensembleLibDir);
4012             }
4013         }
4014         rootProject.clean.dependsOn(appsClean)
4015     }
4016 }
4017 
4018 // Tasks to create the disk layout for the sdk, jmods, and docs
4019 // in the artifacts directory (publicExports), and zip them up in
4020 // artifacts/bundles (zips)
4021 // These tasks are only used for the standalone SDK.
4022 compileTargets { t ->
4023     if (!HAS_JAVAFX_MODULES) {
4024         def targetProperties = rootProject.ext[t.upper]
4025         def platformPrefix = targetProperties.platformPrefix
4026 
4027         def artifactsDir = "${rootProject.buildDir}/artifacts"
4028         def bundlesDir = "${artifactsDir}/bundles"
4029 
4030         def sdkDirName = "${platformPrefix}sdk"
4031         def sdkDir = "${rootProject.buildDir}/${sdkDirName}"
4032         def sdkBundleName = "javafx-sdk-${RELEASE_VERSION}"
4033         def sdkArtifactsDir = "${artifactsDir}/${sdkBundleName}"
4034 
4035         def docsDirName = "javadoc"
4036         def docsDir = "${rootProject.buildDir}/${docsDirName}"
4037         def docsBundleName = "javafx-docs-${RELEASE_VERSION}"
4038         def docsArtifactsDir = "${artifactsDir}/${docsBundleName}"
4039 
4040         def jmodsDirName = "jmods"
4041         def jmodsDir = "${rootProject.buildDir}/${jmodsDirName}"
4042         def jmodsBundleName = "javafx-jmods-${RELEASE_VERSION}"
4043         def jmodsArtifactsDir = "${artifactsDir}/${jmodsBundleName}"
4044 
4045         def publicExportsTask = task ("publicExportsStandalone${t.capital}") {
4046             group = "Basic"
4047             description = "Creates the disk layout for sdk, jmods, and docs"
4048         }
4049         publicExports.dependsOn(publicExportsTask)
4050 
4051         def copyArtifactsSdkTask = task("copyArtifactsSdk$t.capital", type: Copy, dependsOn: [sdk,jmods,apps,javadoc]) {
4052             from sdkDir
4053             into sdkArtifactsDir
4054         }
4055         publicExportsTask.dependsOn(copyArtifactsSdkTask)
4056 
4057         // Need to modify file permissions Windows to make sure that the
4058         // execute bit is set, and that the files are world readable
4059         def chmodArtifactsSdkTask = task("chmodArtifactsSdk$t.capital", dependsOn: copyArtifactsSdkTask) {
4060             if (IS_WINDOWS) {
4061                 doLast {
4062                     exec {
4063                         workingDir(sdkArtifactsDir)
4064                         commandLine("chmod", "-R", "755", ".")
4065                     }
4066                 }
4067             }
4068         }
4069         publicExportsTask.dependsOn(chmodArtifactsSdkTask)
4070 
4071         def copyArtifactsDocsTask = task("copyArtifactsDocs$t.capital", type: Copy, dependsOn: chmodArtifactsSdkTask) {
4072             from docsDir
4073             into "${docsArtifactsDir}/api"
4074         }
4075         publicExportsTask.dependsOn(copyArtifactsDocsTask)
4076 
4077         def copyArtifactsJmodsTask = task("copyArtifactsJmods$t.capital", type: Copy, dependsOn: copyArtifactsDocsTask) {
4078             from jmodsDir
4079             into "${jmodsArtifactsDir}"
4080         }
4081         publicExportsTask.dependsOn(copyArtifactsJmodsTask)
4082 
4083         def zipsTask = task ("zipsStandalone${t.capital}") {
4084             group = "Basic"
4085             description = "Creates the public zip bundles"
4086         }
4087         zips.dependsOn(zipsTask)
4088 
4089         // Use native zip tool so that file permissions are preserved on Windows
4090         def zipSdkTask = task("zipSdk$t.capital", dependsOn: publicExportsTask) {
4091             doLast {
4092                 def outZipFile = "${bundlesDir}/${sdkBundleName}.zip"
4093                 mkdir bundlesDir
4094                 exec {
4095                     workingDir(artifactsDir)
4096                     commandLine("zip", "-q", "-r", outZipFile, sdkBundleName)
4097                 }
4098             }
4099         }
4100         zipsTask.dependsOn(zipSdkTask)
4101 
4102         def zipDocsTask = task("zipDocs$t.capital", type: Zip, dependsOn: zipSdkTask) {
4103             destinationDir = file("${bundlesDir}")
4104             archiveName = "${docsBundleName}.zip"
4105             includeEmptyDirs = false
4106             from docsArtifactsDir
4107             into "${docsBundleName}"
4108         }
4109         zipsTask.dependsOn(zipDocsTask)
4110 
4111         def zipJmodsTask = task("zipJmods$t.capital", type: Zip, dependsOn: zipDocsTask) {
4112             destinationDir = file("${bundlesDir}")
4113             archiveName = "${jmodsBundleName}.zip"
4114             includeEmptyDirs = false
4115             from jmodsArtifactsDir
4116             into "${jmodsBundleName}"
4117         }
4118         zipsTask.dependsOn(zipJmodsTask)
4119     }
4120 }
4121 
4122 
4123 /******************************************************************************
4124  *                                                                            *
4125  *                               Modules                                      *
4126  *                                                                            *
4127  *****************************************************************************/
4128 
4129 ext.moduleDependencies = [file("dependencies")]
4130 
4131 task buildModules {
4132 }
4133 
4134 // Combine the classes, lib, and bin for each module
4135 compileTargets { t ->
4136     def targetProperties = project.ext[t.upper]
4137 
4138     def platformPrefix = targetProperties.platformPrefix
4139     def bundledSdkDirName = "${platformPrefix}modular-sdk"
4140     def bundledSdkDir = "${rootProject.buildDir}/${bundledSdkDirName}"
4141     def modulesDir = "${bundledSdkDir}/modules"
4142     def modulesCmdsDir = "${bundledSdkDir}/modules_cmds"
4143     def modulesLibsDir = "${bundledSdkDir}/modules_libs"
4144     def modulesSrcDir = "${bundledSdkDir}/modules_src"
4145     def modulesConfDir = "${bundledSdkDir}/modules_conf"
4146     def modulesLegalDir = "${bundledSdkDir}/modules_legal"
4147     def modulesMakeDir = "${bundledSdkDir}/make"
4148 
4149     final File runArgsFile = file("${rootProject.buildDir}/${RUNARGSFILE}")
4150     final File compileArgsFile = file("${rootProject.buildDir}/${COMPILEARGSFILE}")
4151 
4152     project.files(runArgsFile);
4153 
4154     def buildModulesTask = task("buildModules$t.capital", group: "Build") {
4155         // BUNDLED SDK
4156 
4157         // Copy dependencies/*/module-info.java.extra
4158         // merging as needed, removing duplicates
4159         // only lines with 'exports' will be copied
4160         def dependencyRoots = moduleDependencies
4161         if (rootProject.hasProperty("closedModuleDepedencies")) {
4162             dependencyRoots = [dependencyRoots, closedModuleDepedencies].flatten()
4163         }
4164 
4165         // Create the inputs/outputs list first to support UP-TO-DATE
4166         ArrayList outputNames = new ArrayList()
4167         dependencyRoots.each { root ->
4168             FileTree ft = fileTree(root).include('**/*.extra')
4169             ft.each() { e->
4170                 inputs.file(e)
4171 
4172                 String usename = e.path
4173                 String filePath = e.getAbsolutePath()
4174                 String folderPath = root.getAbsolutePath()
4175                 if (filePath.startsWith(folderPath)) {
4176                     usename = filePath.substring(folderPath.length() + 1);
4177                 }
4178                 if (! outputNames.contains(usename) ) {
4179                     outputNames.add(usename)
4180                 }
4181             }
4182         }
4183 
4184         outputNames.each() { e->
4185                 File f = new File(modulesSrcDir, e)
4186                 outputs.file(f)
4187         }
4188 
4189         def outputPolicyDir = "${modulesConfDir}/java.base/security"
4190         def outputPolicyFile = file("${outputPolicyDir}/java.policy.extra")
4191 
4192         outputs.file(outputPolicyFile)
4193         moduleProjList.each { project ->
4194             def policyDir = "${project.projectDir}/src/main/conf/security"
4195             def policyFile = file("${policyDir}/java.policy")
4196             if (policyFile.exists()) {
4197                 inputs.file(policyFile)
4198             }
4199         }
4200 
4201         doLast {
4202             Map extras = [:]
4203 
4204             dependencyRoots.each { root ->
4205                 FileTree ft = fileTree(root).include('**/*.extra')
4206                 ft.each() { e->
4207                     String usename = e.path
4208                     String filePath = e.getAbsolutePath()
4209                     String folderPath = root.getAbsolutePath()
4210                     if (filePath.startsWith(folderPath)) {
4211                         usename = filePath.substring(folderPath.length() + 1);
4212                     }
4213                     if (extras.containsKey(usename)) {
4214                         List<String> lines = extras.get(usename)
4215                         e.eachLine { line ->
4216                             line = line.trim()
4217                             if (line.length() > 1 && Character.isLetter(line.charAt(0))) {
4218                                 lines << line
4219                             }
4220                         }
4221 
4222                     } else {
4223                         List<String> lines = []
4224                         e.eachLine { line ->
4225                             line = line.trim()
4226                             if (line.length() > 1 && Character.isLetter(line.charAt(0))) {
4227                                 lines << line
4228                             }
4229                         }
4230                         extras.put(usename,lines)
4231                     }
4232                 }
4233             }
4234             extras.keySet().each() { e->
4235                 File f = new File(modulesSrcDir, e)
4236                 f.getParentFile().mkdirs()
4237                 f.delete()
4238 
4239                 extras.get(e).unique().each() { l->
4240                     f << l
4241                     f << "\n"
4242                 }
4243             }
4244 
4245             // concatecate java.policy files into a single file
4246             //
4247             mkdir outputPolicyDir
4248             outputPolicyFile.delete()
4249             moduleProjList.each { project ->
4250                 def policyDir = "${project.projectDir}/src/main/conf/security"
4251                 def policyFile = file("${policyDir}/java.policy")
4252                 if (policyFile.exists()) outputPolicyFile << policyFile.text
4253             }
4254         }
4255     }
4256     buildModules.dependsOn(buildModulesTask)
4257 
4258     // BUNDLED SDK
4259     moduleProjList.each { project ->
4260         // Copy classes, bin, and lib directories
4261 
4262         def moduleName = project.ext.moduleName
4263         def buildDir = project.buildDir
4264 
4265         def srcClassesDir = "${buildDir}/${platformPrefix}module-classes"
4266         def dstClassesDir = "${modulesDir}/${moduleName}"
4267         def copyClassFilesTask = project.task("copyClassFiles$t.capital", type: Copy, dependsOn: project.assemble) {
4268             from srcClassesDir
4269             into dstClassesDir
4270             exclude("module-info.class")
4271         }
4272 
4273         def srcCmdsDir = "${buildDir}/${platformPrefix}module-bin"
4274         def dstCmdsDir = "${modulesCmdsDir}/${moduleName}"
4275         def copyBinFilesTask = project.task("copyBinFiles$t.capital", type: Copy, dependsOn: copyClassFilesTask) {
4276             from srcCmdsDir
4277             into dstCmdsDir
4278         }
4279 
4280         def srcLibsDir = "${buildDir}/${platformPrefix}module-lib"
4281         def dstLibsDir = "${modulesLibsDir}/${moduleName}"
4282         def copyLibFilesTask = project.task("copyLibFiles$t.capital", type: Copy, dependsOn: copyBinFilesTask) {
4283             from srcLibsDir
4284             into dstLibsDir
4285         }
4286 
4287         // Copy module sources
4288         // FIXME: javafx.swt sources?
4289         def copySources = project.hasProperty("includeSources") && project.includeSources
4290         def copySourceFilesTask = project.task("copySourceFiles$t.capital", type: Copy, dependsOn: copyLibFilesTask) {
4291             if (copySources) {
4292                 from "${project.projectDir}/src/main/java"
4293                 if (project.name.equals("base") || project.name.equals("swing")) {
4294                     from "${project.projectDir}/build/gensrc/java"
4295                 }
4296                 if (project.name.equals("web")) {
4297                     from "${project.projectDir}/src/main/native/Source/WebCore/bindings/java/dom3/java"
4298                 }
4299             } else {
4300                 from "${project.projectDir}/src/main/java/module-info.java"
4301             }
4302             into "${modulesSrcDir}/${moduleName}"
4303             include "**/*.java"
4304             if (!HAS_UNSUPPORTED_DESKTOP) {
4305                 exclude("com/sun/javafx/embed/swing/newimpl/**")
4306             }  
4307 
4308             if (project.hasProperty("sourceFilter")) {
4309                 filter(project.sourceFilter)
4310             }
4311         }
4312 
4313         // Copy .html and other files needed for doc bundles
4314         def copyDocFiles = project.task("copyDocFiles$t.capital", type: Copy, dependsOn: copySourceFilesTask) {
4315             if (copySources) {
4316                 from("${project.projectDir}/src/main/docs") {
4317                     include "**/*.html"
4318                     filter { line->
4319                         line = line.replace("@FXVERSION@", RELEASE_VERSION)
4320                     }
4321                 }
4322                 from("${project.projectDir}/src/main/docs") {
4323                     exclude "**/*.html"
4324                 }
4325                 from("${project.projectDir}/src/main/java") {
4326                     exclude "**/*.java"
4327                 }
4328 
4329                 into "${modulesSrcDir}/${moduleName}"
4330             }
4331         }
4332 
4333         // Copy make/build.properties
4334         def srcMakeDir = "${project.projectDir}/make"
4335         def dstMakeDir = "${modulesMakeDir}/${moduleName}"
4336         def copyBuildPropertiesTask = project.task("copyBuildProperties$t.capital", type: Copy, dependsOn: copyDocFiles) {
4337             from srcMakeDir
4338             into dstMakeDir
4339         }
4340 
4341         // Copy legal files
4342         def srcLegalDir = "${project.projectDir}/src/main/legal"
4343         def dstLegalDir = "${modulesLegalDir}/${moduleName}"
4344         def copyLegalTask = project.task("copyLegal$t.capital", type: Copy, dependsOn: copyBuildPropertiesTask) {
4345             from srcLegalDir
4346             into dstLegalDir
4347 
4348             // Exclude ANGLE since we (currently) do not use it
4349             exclude("angle.md")
4350         }
4351 
4352         buildModulesTask.dependsOn(
4353             copyClassFilesTask,
4354             copyLibFilesTask,
4355             copySourceFilesTask,
4356             copyDocFiles,
4357             copyBuildPropertiesTask,
4358             copyLegalTask)
4359     }
4360 
4361     // ============================================================
4362 
4363     def standaloneSdkDirName = "${platformPrefix}sdk"
4364     def standaloneSdkDir = "${rootProject.buildDir}/${standaloneSdkDirName}"
4365     def standaloneLibDir = "${standaloneSdkDir}/lib"
4366     def libDest=targetProperties.libDest
4367     def standaloneNativeDir = "${standaloneSdkDir}/${libDest}"
4368     def standaloneLegalDir = "${standaloneSdkDir}/legal"
4369     def standaloneSrcZipName = "src.zip"
4370 
4371     // STANDALONE SDK
4372     moduleProjList.each { project ->
4373         // Copy classes, bin, and lib directories
4374 
4375         def moduleName = project.ext.moduleName
4376         def buildDir = project.buildDir
4377 
4378         // Create modular jars
4379         def srcClassesDir = "${buildDir}/${platformPrefix}module-classes"
4380         def srcLibsDir = "${buildDir}/${platformPrefix}module-lib"
4381         def dstModularJarDir = "${standaloneLibDir}"
4382         def modularJarName = "${moduleName}.jar"
4383         def modularJarTask = project.task("modularJarStandalone$t.capital", type: Jar, dependsOn: project.assemble) {
4384             destinationDir = file("${dstModularJarDir}")
4385             archiveName = modularJarName
4386             includeEmptyDirs = false
4387             from srcClassesDir
4388         }
4389 
4390         // Copy native libraries
4391         def srcNativeDir = "${buildDir}/${platformPrefix}module-lib"
4392         def dstNativeDir = "${standaloneNativeDir}"
4393         def copyNativeFilesTask = project.task("copyNativeFilesStandalone$t.capital", type: Copy, dependsOn: modularJarTask) {
4394             from srcNativeDir
4395             into dstNativeDir
4396             include("*.dll")
4397         }
4398 
4399         // Copy other lib files
4400         def dstLibsDir = "${standaloneLibDir}"
4401         def copyLibFilesTask = project.task("copyLibFilesStandalone$t.capital", type: Copy, dependsOn: copyNativeFilesTask) {
4402             from srcLibsDir
4403             into dstLibsDir
4404             exclude("*.dll")
4405         }
4406 
4407         // Copy legal files
4408         def licenseFiles = [ "ADDITIONAL_LICENSE_INFO", "ASSEMBLY_EXCEPTION", "LICENSE" ]
4409         def srcLegalDir = "${project.projectDir}/src/main/legal"
4410         def dstLegalDir = "${standaloneLegalDir}/${moduleName}"
4411         def copyLegalTask = project.task("copyLegalStandalone$t.capital", type: Copy, dependsOn: copyLibFilesTask) {
4412 
4413             def rtDir = rootProject.file('.')
4414             licenseFiles.each { lFile ->
4415                 from "${rtDir}/${lFile}"
4416             }
4417 
4418             from srcLegalDir
4419 
4420             into dstLegalDir
4421 
4422             // Exclude ANGLE since we (currently) do not use it
4423             exclude("angle.md")
4424         }
4425 
4426         buildModulesTask.dependsOn(
4427             modularJarTask,
4428             copyNativeFilesTask,
4429             copyLibFilesTask,
4430             copyLegalTask)
4431     }
4432 
4433     // Zip module sources for standalone SDK
4434     //
4435     // NOTE: the input is taken from the modular-sdk/modules_src dir
4436     // so that we don't have to duplicate the logic and create another
4437     // temporary directory. This is somewhat inelegant, since the bundled sdk
4438     // and the standalone sdk should be independent of one another, but seems
4439     // better than the alternatives.
4440     def zipSourceFilesTask = project.task("zipSourceFilesStandalone$t.capital", type: Zip, dependsOn: buildModulesTask) {
4441         destinationDir = file("${standaloneLibDir}")
4442         archiveName = standaloneSrcZipName
4443         includeEmptyDirs = false
4444         from modulesSrcDir
4445         include "**/*.java"
4446     }
4447     buildModules.dependsOn(zipSourceFilesTask)
4448 
4449     // ============================================================
4450 
4451     // Maven Publications
4452     def publicationDirName = "${platformPrefix}publications"
4453     def publicationDir = "${rootProject.buildDir}/${publicationDirName}"
4454 
4455     moduleProjList.each { project -> 
4456         // Create publications to be uploaded 
4457 
4458         def moduleName = project.ext.moduleName
4459         def buildDir = project.buildDir
4460 
4461         def dstModularJarDir="${publicationDir}"
4462         def srcClassesDir = "${buildDir}/${platformPrefix}module-classes"
4463         def srcLibsDir = "${buildDir}/${platformPrefix}module-lib"
4464 
4465         def modularEmptyPublicationJarName = "${moduleName}.jar"
4466         def modularEmptyPublicationJarTask = project.task("moduleEmptyPublicationJar${t.capital}", type: Jar) {
4467             destinationDir = file("${dstModularJarDir}")
4468             archiveName = modularEmptyPublicationJarName
4469             manifest {
4470                 attributes(
4471                     'Automatic-Module-Name':"${moduleName}Empty"
4472                 )
4473             }
4474         }
4475 
4476         def modularPublicationJarName = "${moduleName}-${t.name}.jar"
4477         def modularPublicationJarTask = project.task("modularPublicationJar${t.capital}", type: Jar, dependsOn: modularEmptyPublicationJarTask) {
4478             destinationDir = file("${dstModularJarDir}")
4479             archiveName = modularPublicationJarName
4480             from srcLibsDir
4481             from srcClassesDir
4482         }
4483 
4484         buildModulesTask.dependsOn(modularPublicationJarTask)
4485 
4486     }
4487     // ============================================================
4488 
4489     def buildRunArgsTask = task("buildRunArgs$t.capital",
4490             group: "Build", dependsOn: buildModulesTask) {
4491         outputs.file(runArgsFile);
4492         inputs.file(EXTRAADDEXPORTS);
4493         doLast() {
4494             List<String>modpath = []
4495             List<String>modnames = []
4496 
4497             moduleProjList.each { project ->
4498                 def moduleName = project.ext.moduleName
4499                 def dstModuleDir = cygpath("${modulesDir}/${moduleName}")
4500                 if (HAS_JAVAFX_MODULES) {
4501                     modpath <<  "${moduleName}=${dstModuleDir}"
4502                 } else {
4503                     modnames << moduleName
4504                 }
4505             }
4506 
4507             if (HAS_JAVAFX_MODULES) {
4508                 writeRunArgsFile(runArgsFile, computeLibraryPath(true), modpath, null)
4509                 writeRunArgsFile(compileArgsFile, null, modpath, null)
4510 
4511                 if (rootProject.hasProperty("EXTRA_ADDEXPORTS_STRING")) {
4512                     runArgsFile << EXTRA_ADDEXPORTS_STRING
4513                     compileArgsFile << EXTRA_ADDEXPORTS_STRING
4514                 }
4515             } else {
4516                 modpath = [ cygpath("${standaloneLibDir}") ]
4517                 writeRunArgsFile(runArgsFile, null, modpath, modnames)
4518                 writeRunArgsFile(compileArgsFile, null, modpath, modnames)
4519             }
4520         }
4521     }
4522     buildModules.dependsOn(buildRunArgsTask)
4523 
4524     def isWindows = IS_WINDOWS && t.name == "win";
4525     def isMac = IS_MAC && t.name == "mac";
4526 
4527     // Create layout for modular classes
4528     moduleProjList.each { project ->
4529         def buildModuleClassesTask = project.task("buildModule$t.capital", group: "Build", type: Copy) {
4530             dependsOn(project.assemble)
4531             def buildDir = project.buildDir
4532             def sourceBuildDirs = [
4533                 "${buildDir}/classes/java/main/${project.moduleName}",
4534             ]
4535 
4536             def moduleClassesDir = "$buildDir/${platformPrefix}module-classes"
4537                 includeEmptyDirs = false
4538                 sourceBuildDirs.each { d ->
4539                     from d
4540                 }
4541                 into moduleClassesDir
4542 
4543                 // Exclude obsolete, experimental, or non-shipping code
4544                 exclude("version.rc")
4545                 exclude("com/sun/glass/ui/swt")
4546                 exclude("com/sun/javafx/tools/ant")
4547                 exclude("com/javafx/main")
4548                 exclude("com/sun/javafx/webkit/drt")
4549                 if (!IS_INCLUDE_NULL3D) {
4550                     exclude ("com/sun/prism/null3d")
4551                 }
4552                 if (!IS_INCLUDE_ES2) {
4553                        exclude("com/sun/prism/es2",
4554                                "com/sun/scenario/effect/impl/es2")
4555                 }
4556 
4557                 // Exclude platform-specific classes for other platforms
4558 
4559                 if (!isMac) {
4560                     exclude ("com/sun/media/jfxmediaimpl/platform/osx",
4561                              "com/sun/prism/es2/MacGL*",
4562                              "com/sun/glass/events/mac",
4563                              "com/sun/glass/ui/mac",
4564                              )
4565                 }
4566 
4567                 if (!isWindows) {
4568                     exclude ("**/*.hlsl",
4569                              "com/sun/glass/ui/win",
4570                              "com/sun/prism/d3d",
4571                              "com/sun/prism/es2/WinGL*",
4572                              "com/sun/scenario/effect/impl/hw/d3d"
4573                              )
4574                 }
4575 
4576                 if (!targetProperties.includeGTK) { //usually IS_LINUX
4577                     exclude (
4578                              "com/sun/glass/ui/gtk",
4579                              "com/sun/prism/es2/EGL*",
4580                              "com/sun/prism/es2/X11GL*"
4581                              )
4582                 }
4583 
4584                 if (!targetProperties.includeEGL) {
4585                     exclude ("com/sun/prism/es2/EGL*")
4586                 }
4587 
4588                 if (!targetProperties.includeMonocle) {
4589                     exclude ("com/sun/glass/ui/monocle")
4590                     exclude("com/sun/prism/es2/Monocle*")
4591                 }
4592 
4593                 if (t.name != 'ios') {
4594                     exclude ("com/sun/media/jfxmediaimpl/platform/ios",
4595                              "com/sun/glass/ui/ios",
4596                              "com/sun/prism/es2/IOS*"
4597                              )
4598                 }
4599 
4600                 if (t.name != 'android' && t.name != 'dalvik') {
4601                     exclude ("com/sun/glass/ui/android")
4602                 }
4603 
4604                 // Filter out other platform-specific classes
4605                 if (targetProperties.containsKey('jfxrtJarExcludes')) {
4606                     exclude(targetProperties.jfxrtJarExcludes)
4607                 }
4608 
4609                 /* FIXME: JIGSAW -- handle this in the module itself
4610                 String webbld = project(":web").buildDir.path
4611                 String ctrlbld = project(":controls").buildDir.path
4612                 if (t.name == 'android') {
4613                     from ("${webbld}/classes/android",
4614                           "${webbld}/resources/android",
4615                           "${ctrlbld}/classes/android",
4616                           "${ctrlbld}/resources/android")
4617                 } else if (t.name == 'ios') {
4618                     from ("${webbld}/classes/ios",
4619                           "${webbld}/resources/ios")
4620                 } else {
4621                     from ("${webbld}/classes/java/main")
4622                 }
4623                 */
4624         }
4625         buildModulesTask.dependsOn(buildModuleClassesTask)
4626     }
4627 
4628     def buildModuleLibsTask = task("buildModuleLibs$t.capital") {
4629         group = "Basic"
4630 
4631         def baseProject = project(":base");
4632 
4633         def graphicsProject = project(":graphics");
4634 
4635         def mediaProject = project(":media");
4636 
4637         def webProject = project(":web");
4638         dependsOn(webProject.assemble)
4639 
4640         def swtProject = project(":swt");
4641 
4642         def library = targetProperties.library
4643 
4644         def useLipo = targetProperties.containsKey('useLipo') ? targetProperties.useLipo : false
4645         def modLibDest = targetProperties.modLibDest
4646         def moduleNativeDirName = "${platformPrefix}module-$modLibDest"
4647 
4648         def buildModuleBaseTask = task("buildModuleBase$t.capital", dependsOn: baseProject.assemble) {
4649             group = "Basic"
4650             description = "creates javafx.base property files"
4651 
4652             def moduleLibDir = "${baseProject.buildDir}/${platformPrefix}module-lib"
4653             final File javafxProperties = file("${moduleLibDir}/javafx.properties")
4654             outputs.file(javafxProperties)
4655 
4656             if (targetProperties.containsKey("javafxPlatformProperties")) {
4657                 final File javafxPlatformProperties = file("${moduleLibDir}/javafx.platform.properties")
4658                 outputs.file(javafxPlatformProperties)
4659             }
4660 
4661             doLast {
4662                 mkdir moduleLibDir
4663 
4664                 javafxProperties.delete()
4665                 javafxProperties << "javafx.version=$RELEASE_VERSION_SHORT";
4666                 javafxProperties << "\n"
4667                 javafxProperties << "javafx.runtime.version=$RELEASE_VERSION_LONG";
4668                 javafxProperties << "\n"
4669                 javafxProperties << "javafx.runtime.build=$PROMOTED_BUILD_NUMBER";
4670                 javafxProperties << "\n"
4671                 // Include any properties that have been defined (most likely in
4672                 // one of the various platform gradle files)
4673                 if (targetProperties.containsKey("javafxProperties")) {
4674                     javafxProperties << targetProperties.javafxProperties
4675                     javafxProperties << "\n"
4676                 }
4677 
4678                 // Embedded builds define this file as well
4679                 if (targetProperties.containsKey("javafxPlatformProperties")) {
4680                     final File javafxPlatformProperties = file("${moduleLibDir}/javafx.platform.properties")
4681                     javafxPlatformProperties.delete()
4682                     javafxPlatformProperties << targetProperties.javafxPlatformProperties
4683                     javafxPlatformProperties << "\n"
4684                 }
4685             }
4686         }
4687 
4688         def buildModuleGraphicsTask = task("buildModuleGraphics$t.capital", type: Copy, dependsOn: graphicsProject.assemble) {
4689             group = "Basic"
4690             description = "copies javafx.graphics native libraries"
4691 
4692             into "${graphicsProject.buildDir}/${moduleNativeDirName}"
4693 
4694             from("${graphicsProject.buildDir}/libs/jsl-decora/${t.name}/${library(targetProperties.decora.lib)}")
4695             def libs = ['font', 'prism', 'prismSW', 'glass', 'iio']
4696             if (IS_INCLUDE_ES2) {
4697                 libs += ['prismES2'];
4698             }
4699             if (IS_COMPILE_PANGO) {
4700                 libs += ['fontFreetype', 'fontPango'];
4701             }
4702             libs.each { lib ->
4703                 def variants = targetProperties[lib].containsKey('variants') && !useLipo ? targetProperties[lib].variants : [null]
4704                 variants.each { variant ->
4705                     def variantProperties = variant ? targetProperties[lib][variant] : targetProperties[lib]
4706                     from ("${graphicsProject.buildDir}/libs/$lib/$t.name/${library(variantProperties.lib)}")
4707                 }
4708             }
4709             if (IS_WINDOWS) {
4710                 from ("${graphicsProject.buildDir}/libs/prismD3D/${t.name}/${library(targetProperties.prismD3D.lib)}");
4711                 targetProperties.VS2017DLLs.each { vslib ->
4712                     from ("$vslib");
4713                 }
4714                 targetProperties.WinSDKDLLs.each { winsdklib ->
4715                     from ("$winsdklib");
4716                 }
4717             }
4718         }
4719 
4720         def buildModuleMediaTask = task("buildModuleMedia$t.capital", type: Copy, dependsOn: mediaProject.assemble) {
4721             group = "Basic"
4722             description = "copies javafx.media native libraries"
4723 
4724             into "${mediaProject.buildDir}/${moduleNativeDirName}"
4725 
4726             def mediaBuildType = project(":media").ext.buildType
4727             if (IS_COMPILE_MEDIA) {
4728                 [ "fxplugins", "gstreamer-lite", "jfxmedia" ].each { name ->
4729                     from ("${mediaProject.buildDir}/native/${t.name}/${mediaBuildType}/${library(name)}") }
4730 
4731                 if (t.name == "mac") {
4732                     // OSX media natives
4733                     [ "jfxmedia_qtkit", "jfxmedia_avf", "glib-lite" ].each { name ->
4734                         from ("${mediaProject.buildDir}/native/${t.name}/${mediaBuildType}/${library(name)}") }
4735                 } else if (t.name == "linux") {
4736                     from("${mediaProject.buildDir}/native/${t.name}/${mediaBuildType}") { include "libavplugin*.so" }
4737                 } else from ("${mediaProject.buildDir}/native/${t.name}/${mediaBuildType}/${library("glib-lite")}")
4738             } else {
4739                 if (t.name != "android"  && t.name != "dalvik" ) {
4740                     [ "fxplugins", "gstreamer-lite", "jfxmedia" ].each { name ->
4741                         from ("$MEDIA_STUB/${library(name)}") }
4742                 }
4743 
4744                 if (t.name == "mac") {
4745                     // copy libjfxmedia_{avf,qtkit}.dylib if they exist
4746                     [ "jfxmedia_qtkit", "jfxmedia_avf", "glib-lite" ].each { name ->
4747                         from ("$MEDIA_STUB/${library(name)}") }
4748                 } else if (t.name == "linux") {
4749                     from(MEDIA_STUB) { include "libavplugin*.so" }
4750                 }
4751                 else if (t.name != "android"  && t.name != "dalvik" ) {
4752                     from ("$MEDIA_STUB/${library("glib-lite")}")
4753                 }
4754             }
4755         }
4756 
4757         def buildModuleWeb = task("buildModuleWeb$t.capital", type: Copy, dependsOn: webProject.assemble) {
4758             group = "Basic"
4759             description = "copies javafx.web native libraries"
4760 
4761             into "${webProject.buildDir}/${moduleNativeDirName}"
4762 
4763             if (IS_COMPILE_WEBKIT) {
4764                 from ("${webProject.buildDir}/libs/${t.name}/${library('jfxwebkit')}")
4765             } else {
4766                 if (t.name != "android" && t.name != "ios" && t.name != "dalvik") {
4767                     from ("$WEB_STUB/${library('jfxwebkit')}")
4768                 }
4769             }
4770         }
4771 
4772         def buildModuleSWT = task("buildModuleSWT$t.capital", type: Copy) {
4773             group = "Basic"
4774             description = "copies SWT JAR"
4775 
4776             // FIXME: the following is a hack to workaround the fact that there
4777             // is no way to deliver javafx-swt.jar other than in one of the
4778             // existing runtime modules.
4779 
4780             dependsOn(buildModuleGraphicsTask) // we copy to the graphics module
4781 
4782             if (COMPILE_SWT) {
4783                 def javafxSwtIndexTask = tasks.getByName("javafxSwtIndex${t.capital}");
4784                 dependsOn(javafxSwtIndexTask)
4785                 //enabled = COMPILE_SWT
4786             }
4787 
4788             // Copy javafx-swt.jar to the javafx-graphics module lib dir
4789             from "${swtProject.buildDir}/libs/javafx-swt.jar"
4790             into "${graphicsProject.buildDir}/${platformPrefix}module-lib"
4791         }
4792 
4793         dependsOn(
4794             buildModuleBaseTask,
4795             buildModuleGraphicsTask,
4796             buildModuleMediaTask,
4797             buildModuleWeb,
4798             buildModuleSWT,
4799             )
4800     }
4801     buildModulesTask.dependsOn(buildModuleLibsTask)
4802 
4803     def zipTask = project.task("buildModuleZip$t.capital", type: Zip, group: "Build",
4804             dependsOn: buildModulesTask ) {
4805 
4806         // FIXME: JIGSAW -- this should be moved to a sub-directory so we can keep the same name
4807         def jfxBundle = "${platformPrefix}javafx-exports.zip"
4808 
4809         doFirst() {
4810             file("${rootProject.buildDir}/${jfxBundle}").delete()
4811         }
4812 
4813         archiveName = jfxBundle
4814         destinationDir = file("${rootProject.buildDir}")
4815         includeEmptyDirs = false
4816         from "${bundledSdkDir}"
4817     }
4818     jdkZip.dependsOn(zipTask)
4819 
4820     Task testArgFiles = task("createTestArgfiles${t.capital}") {
4821 
4822         File testRunArgsFile = new File(rootProject.buildDir, TESTRUNARGSFILE)
4823         //test (shimed) version
4824         File testCompileArgsFile = new File(rootProject.buildDir, TESTCOMPILEARGSFILE)
4825         // And a test java.policy file
4826         File testJavaPolicyFile = new File(rootProject.buildDir, TESTJAVAPOLICYFILE)
4827         // and the non-test version to go with run.args
4828         File runJavaPolicyFile = new File(rootProject.buildDir, RUNJAVAPOLICYFILE);
4829 
4830         outputs.file(testRunArgsFile)
4831         outputs.file(testCompileArgsFile)
4832         outputs.file(testJavaPolicyFile)
4833         outputs.file(runJavaPolicyFile)
4834         inputs.file(EXTRAADDEXPORTS);
4835 
4836         doLast() {
4837             rootProject.buildDir.mkdir()
4838 
4839             List<String> projNames = []
4840             moduleProjList.each { project ->
4841                 projNames << project.name
4842             }
4843 
4844             // And the test (shimed) variation...
4845 
4846             testRunArgsFile.delete()
4847             testCompileArgsFile.delete()
4848 
4849             testJavaPolicyFile.delete()
4850             runJavaPolicyFile.delete()
4851 
4852             List<String> modpath = []
4853 
4854             if (HAS_JAVAFX_MODULES) {
4855                 moduleProjList.each { project ->
4856                     if (project.hasProperty("moduleName") && project.buildModule) {
4857                         File dir;
4858                         if (project.sourceSets.hasProperty('shims')) {
4859                            dir = new File(rootProject.buildDir, "shims/${project.ext.moduleName}")
4860                         } else {
4861                            dir = new File(rootProject.buildDir, "modular-sdk/modules/${project.ext.moduleName}")
4862                         }
4863 
4864                         def dstModuleDir = cygpath(dir.path)
4865                         modpath << "${project.ext.moduleName}=${dstModuleDir}"
4866 
4867                         String themod = dir.toURI()
4868                         testJavaPolicyFile <<  "grant codeBase \"${themod}\" {\n" +
4869                         "    permission java.security.AllPermission;\n" +
4870                         "};\n"
4871 
4872                         dir = new File(rootProject.buildDir, "modular-sdk/modules/${project.ext.moduleName}")
4873                         themod = dir.toURI()
4874                         runJavaPolicyFile <<  "grant codeBase \"${themod}\" {\n" +
4875                         "    permission java.security.AllPermission;\n" +
4876                         "};\n"
4877                     }
4878                 }
4879 
4880                 writeRunArgsFile(testCompileArgsFile, null, modpath, null)
4881                 writeRunArgsFile(testRunArgsFile, computeLibraryPath(true), modpath, null)
4882 
4883                 if (rootProject.hasProperty("EXTRA_ADDEXPORTS_STRING")) {
4884                     testCompileArgsFile << EXTRA_ADDEXPORTS_STRING
4885                     testRunArgsFile << EXTRA_ADDEXPORTS_STRING
4886                 }
4887             } else  {
4888                 def modnames = []
4889                 moduleProjList.each { project ->
4890                     if (project.hasProperty("moduleName") && project.buildModule) {
4891                         modnames << project.ext.moduleName
4892                         File dir;
4893                         if (project.sourceSets.hasProperty('shims')) {
4894                            dir = new File(rootProject.buildDir, "shims/${project.ext.moduleName}")
4895                         } else {
4896                            dir = new File(rootProject.buildDir, "sdk/lib/${project.ext.moduleName}.jar")
4897                         }
4898 
4899                         def dstModuleDir = cygpath(dir.path)
4900                         modpath << "${dstModuleDir}"
4901 
4902                         String themod = dir.toURI()
4903                         testJavaPolicyFile <<  "grant codeBase \"${themod}\" {\n" +
4904                         "    permission java.security.AllPermission;\n" +
4905                         "};\n"
4906 
4907                         dir = new File(rootProject.buildDir, "sdk/lib/${project.ext.moduleName}.jar")
4908                         themod = dir.toURI()
4909                         runJavaPolicyFile <<  "grant codeBase \"${themod}\" {\n" +
4910                         "    permission java.security.AllPermission;\n" +
4911                         "};\n"
4912                     }
4913                 }
4914 
4915                 writeRunArgsFile(testCompileArgsFile, null, modpath, modnames)
4916                 writeRunArgsFile(testRunArgsFile, computeLibraryPath(true), modpath, modnames)
4917 
4918                 appendQualExports(testCompileArgsFile, qualExportsSwing)
4919                 appendQualExports(testRunArgsFile, qualExportsSwing)
4920             }
4921         }
4922     }
4923     sdk.dependsOn(testArgFiles)
4924     createTestArgfiles.dependsOn(testArgFiles)
4925 
4926     def sdkTask = tasks.getByName("sdk${t.capital}");
4927     sdkTask.dependsOn(buildModulesTask)
4928 }
4929 sdk.dependsOn(buildModules)
4930 
4931 // Build the jmod for each module for the standalone SDK only.
4932 compileTargets { t ->
4933     if (!HAS_JAVAFX_MODULES) {
4934         def targetProperties = project.ext[t.upper]
4935 
4936         def platformPrefix = targetProperties.platformPrefix
4937         def jmodsDirName = "${platformPrefix}jmods"
4938         def jmodsDir = "${rootProject.buildDir}/${jmodsDirName}"
4939         def standaloneSdkDirName = "${platformPrefix}sdk"
4940         def standaloneSdkDir = "${rootProject.buildDir}/${standaloneSdkDirName}"
4941         def standaloneLegalDir = "${standaloneSdkDir}/legal"
4942 
4943         def excludeNativeLibs = []
4944         if (IS_WINDOWS) {
4945             // List of duplicate Microsoft DLLs to exclude
4946             excludeNativeLibs += targetProperties.VS2017DLLNames
4947             excludeNativeLibs += targetProperties.WinSDKDLLNames
4948         }
4949 
4950         moduleProjList.each { project ->
4951             def moduleName = project.ext.moduleName
4952             def buildDir = project.buildDir
4953 
4954             def srcClassesDir = "${buildDir}/${platformPrefix}module-classes"
4955             def srcLibDir = "${buildDir}/${platformPrefix}module-lib"
4956             def srcLegalDir = "${standaloneLegalDir}/${moduleName}"
4957 
4958             def jmodName = "${moduleName}.jmod"
4959             def jmodFile = "${jmodsDir}/${jmodName}"
4960             def jmodTask = project.task("jmod$t.capital", group: "Build", dependsOn: sdk) {
4961                 doLast {
4962                     mkdir jmodsDir
4963                     delete(jmodFile);
4964                     exec {
4965                         commandLine(JMOD)
4966                         args("create")
4967                         args("--class-path")
4968                         args(srcClassesDir)
4969                         // Not all modules have a "lib" dir
4970                         if (file(srcLibDir).isDirectory()) {
4971                             args("--libs")
4972                             args(srcLibDir)
4973                         }
4974                         // Exclude duplicate native libs from javafx.graphics.jmod
4975                         if (moduleName == "javafx.graphics") {
4976                             excludeNativeLibs.each { name ->
4977                                 args("--exclude")
4978                                 args(name)
4979                             }
4980                         }
4981                         args("--legal-notices")
4982                         args(srcLegalDir)
4983                         args(jmodFile)
4984                     }
4985                 }
4986             }
4987 
4988             jmods.dependsOn(jmodTask)
4989         }
4990     }
4991 }
4992 
4993 task checkrepo() {
4994     doLast {
4995         logger.info("checking for whitespace (open)");
4996         exec {
4997             if (IS_WINDOWS) {
4998                 commandLine  'bash', 'tools/scripts/checkWhiteSpace'
4999             } else {
5000                 commandLine  'bash', 'tools/scripts/checkWhiteSpace', '-x'
5001             }
5002         }
5003     }
5004 }
5005 
5006 task checkrepoall() {
5007     doLast {
5008         logger.info("checking for all whitespace (open)");
5009         exec {
5010             if (IS_WINDOWS) {
5011                 commandLine  'bash', 'tools/scripts/checkWhiteSpace', '-a'
5012             } else {
5013                 commandLine  'bash', 'tools/scripts/checkWhiteSpace', '-x', '-a'
5014             }
5015         }
5016     }
5017 }
5018 
5019 /******************************************************************************
5020  *                                                                            *
5021  *                              BUILD_CLOSED                                  *
5022  *                                                                            *
5023  * This next section should remain at the end of the build script. It allows  *
5024  * for a "supplemental" gradle file to be used to extend the normal build     *
5025  * structure. For example, this is used for passing a supplemental gradle     *
5026  * file for producing official JavaFX builds.                                 *
5027  *                                                                            *
5028  *****************************************************************************/
5029 
5030 if (BUILD_CLOSED) {
5031     apply from: supplementalBuildFile
5032 }
5033 
5034 task showFlags {
5035 }
5036 
5037 compileTargets { t ->
5038     // Every platform must define these variables
5039     def props = project.ext[t.upper];
5040     showFlags.dependsOn(
5041         project.task("showFlags$t.upper") {
5042             doLast() {
5043                 println "Properties set for $t.upper"
5044                 props.each { println it }
5045             }
5046         }
5047     )
5048 
5049 }