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