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