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         testscriptapp2
3576     }
3577 
3578     def nonModSrcSets = [
3579         sourceSets.test,
3580         sourceSets.testapp1
3581     ]
3582 
3583     def modSrcSets = [
3584         sourceSets.testapp2,
3585         sourceSets.testapp3,
3586         sourceSets.testapp4,
3587         sourceSets.testapp5,
3588         sourceSets.testapp6,
3589         sourceSets.testscriptapp1,
3590         sourceSets.testscriptapp2
3591     ]
3592 
3593     project.ext.buildModule = false
3594     project.ext.moduleRuntime = false
3595     project.ext.moduleName = "systemTests"
3596 
3597     dependencies {
3598         testCompile project(":graphics").sourceSets.test.output
3599         testCompile project(":base").sourceSets.test.output
3600         testCompile project(":controls").sourceSets.test.output
3601         testCompile project(":swing").sourceSets.test.output
3602     }
3603 
3604     def dependentProjects = [ 'base', 'graphics', 'controls', 'media', 'web', 'swing', 'fxml' ]
3605     commonModuleSetup(project, dependentProjects)
3606 
3607     File testJavaPolicyFile = new File(rootProject.buildDir, TESTJAVAPOLICYFILE);
3608     File testRunArgsFile = new File(rootProject.buildDir,TESTRUNARGSFILE);
3609 
3610     File stRunArgsFile = new File(project.buildDir,"st.run.args");
3611 
3612     def sts = task("systemTestSetup") {
3613         outputs.file(stRunArgsFile)
3614 
3615         doLast() {
3616             stRunArgsFile.delete()
3617 
3618             logger.info("Creating patchmodule.args file ${stRunArgsFile}")
3619 
3620             // Create an argfile with the information needed to launch
3621             // the stand alone system unit tests.
3622 
3623             //First add in all of the patch-module args we use for the
3624             //normal unit tests, copied from test.run.args
3625             testRunArgsFile.eachLine { str ->
3626                 stRunArgsFile <<  "${str}\n"
3627             }
3628 
3629             // Now add in the working classpath elements (junit, test classes...)
3630             stRunArgsFile <<  "-cp \"\\\n"
3631             test.classpath.each() { elem ->
3632                 def e = cygpath("${elem}")
3633                 stRunArgsFile <<  "  ${e}${File.pathSeparator}\\\n"
3634             }
3635             stRunArgsFile <<  "\"\n"
3636         }
3637     }
3638 
3639     test.dependsOn(sts)
3640     test.dependsOn(createTestArgfiles);
3641 
3642     // Tasks to create standalone test applications for the launcher tests
3643 
3644     if (project.hasProperty('testModulePathArgs')) {
3645         compileTestapp1Java.options.compilerArgs.addAll(testModulePathArgs)
3646     }
3647     dependentProjects.each { e ->
3648         compileTestapp1Java.dependsOn(rootProject.project(e).testClasses)
3649     }
3650 
3651     def testapp1JarName = "testapp1.jar"
3652     task createTestapp1Jar1(type: Jar) {
3653         dependsOn compileTestapp1Java
3654         enabled = IS_FULL_TEST
3655 
3656         destinationDir = file("$buildDir/testapp1")
3657         archiveName = testapp1JarName
3658         includeEmptyDirs = false
3659         from project.sourceSets.testapp1.java.outputDir
3660         include("testapp/**")
3661         include("com/javafx/main/**")
3662 
3663         manifest {
3664             attributes(
3665                 "Main-Class" : "com.javafx.main.Main",
3666                 "JavaFX-Version" : "2.2",
3667                 "JavaFX-Application-Class" : "testapp.HelloWorld",
3668                 "JavaFX-Class-Path" : "jar2.jar"
3669             )
3670         }
3671     }
3672 
3673     task createTestapp1Jar2(type: Jar) {
3674         dependsOn compileTestapp1Java
3675         enabled = IS_FULL_TEST
3676 
3677         destinationDir = file("$buildDir/testapp1")
3678         archiveName = "jar2.jar";
3679         includeEmptyDirs = false
3680         from project.sourceSets.testapp1.java.outputDir
3681         include("pkg2/**")
3682     }
3683 
3684     task createTestApps() {
3685         dependsOn(createTestapp1Jar1)
3686         dependsOn(createTestapp1Jar2)
3687     }
3688     test.dependsOn(createTestApps);
3689 
3690     def modtestapps = [ "testapp2", "testapp3", "testapp4", "testapp5", "testapp6", "testscriptapp1", "testscriptapp2" ]
3691     modtestapps.each { testapp ->
3692         def testappCapital = testapp.capitalize()
3693         def copyTestAppTask = task("copy${testappCapital}", type: Copy) {
3694             from project.sourceSets."${testapp}".java.outputDir
3695             from project.sourceSets."${testapp}".output.resourcesDir
3696             into "${project.buildDir}/modules/${testapp}"
3697         }
3698 
3699         def List<String> testAppSourceDirs = []
3700         project.sourceSets."${testapp}".java.srcDirs.each { dir ->
3701             testAppSourceDirs += dir
3702         }
3703         def testappCompileTasks = project.getTasksByName("compile${testappCapital}Java", true);
3704         def testappResourceTasks = project.getTasksByName("process${testappCapital}Resources", true);
3705         testappCompileTasks.each { appCompileTask ->
3706             appCompileTask.options.compilerArgs.addAll([
3707                 '-implicit:none',
3708                 '--module-source-path', testAppSourceDirs.join(File.pathSeparator),
3709                 ] )
3710             if (project.hasProperty('testModulePathArgs')) {
3711                 appCompileTask.options.compilerArgs.addAll(testModulePathArgs)
3712             }
3713 
3714             dependentProjects.each { e ->
3715                 appCompileTask.dependsOn(rootProject.project(e).testClasses)
3716             }
3717 
3718             copyTestAppTask.dependsOn(appCompileTask)
3719         }
3720         testappResourceTasks.each { appResourceTask ->
3721             copyTestAppTask.dependsOn(appResourceTask)
3722         }
3723 
3724         createTestApps.dependsOn(copyTestAppTask)
3725     }
3726 
3727     test {
3728         enabled = IS_FULL_TEST
3729 
3730         // Parse testPatchModuleArgs looking for "--module-path".
3731         // Save path if found so we can pass it to the module launcher tests
3732         def pendingModulePath = false
3733         testPatchModuleArgs.each { str ->
3734             if (pendingModulePath) {
3735                 project.ext.launcherModulePath = str;
3736                 pendingModulePath = false
3737             } else if (str == "--module-path") {
3738                 pendingModulePath = true
3739             }
3740         }
3741 
3742         // Properties passed to launcher tests
3743         systemProperty "launchertest.testapp1.jar", "build/testapp1/$testapp1JarName"
3744         modtestapps.each { testapp ->
3745             systemProperty "launchertest.${testapp}.module.path",
3746                     "${project.buildDir}/modules/${testapp}"
3747         }
3748 
3749         // Properties passed to test.util.Util
3750         systemProperties 'worker.debug': IS_WORKER_DEBUG
3751         systemProperties 'worker.patchmodule.file': cygpath(stRunArgsFile.path)
3752         if (project.hasProperty("launcherModulePath")) {
3753             systemProperties 'worker.module.path': launcherModulePath
3754         }
3755         systemProperties 'worker.patch.policy': cygpath(testJavaPolicyFile.path)
3756         systemProperties 'worker.java.cmd': JAVA
3757 
3758         if (rootProject.hasProperty("ClipShapeTest.numTests")) {
3759             systemProperty "ClipShapeTest.numTests", rootProject.getProperty("ClipShapeTest.numTests")
3760         }
3761 
3762         if (!IS_USE_ROBOT) {
3763             // Disable all robot-based visual tests
3764             exclude("test/robot/**");
3765         }
3766         if (!IS_UNSTABLE_TEST) {
3767             // JDK-8196607 Don't run monocle test cases 
3768             exclude("test/robot/com/sun/glass/ui/monocle/**");
3769         }
3770         if (!IS_AWT_TEST) {
3771             // Disable all AWT-based tests
3772             exclude("**/javafx/embed/swing/*.*");
3773             exclude("**/com/sun/javafx/application/Swing*.*");
3774         }
3775 
3776         forkEvery = 1
3777     }
3778 
3779     addValidateSourceSets(project, nonModSrcSets, modSrcSets)
3780 }
3781 
3782 allprojects {
3783     // The following block is a workaround for the fact that presently Gradle
3784     // can't set the -XDignore.symbol.file flag, because it appears that the
3785     // javac API is lacking support for it. So what we'll do is find any Compile
3786     // task and manually provide the options necessary to fire up the
3787     // compiler with the right settings.
3788     tasks.withType(JavaCompile) { compile ->
3789         if (compile.options.hasProperty("useAnt")) {
3790             compile.options.useAnt = true
3791             compile.options.useDepend = IS_USE_DEPEND
3792         } else if (compile.options.hasProperty("incremental")) {
3793             compile.options.incremental = IS_INCREMENTAL
3794         }
3795         compile.options.debug = true // we always generate debugging info in the class files
3796         compile.options.debugOptions.debugLevel = IS_DEBUG_JAVA ? "source,lines,vars" : "source,lines"
3797         compile.options.fork = true
3798 
3799         compile.options.forkOptions.executable = JAVAC
3800 
3801         compile.options.warnings = IS_LINT
3802 
3803         compile.options.compilerArgs += ["-XDignore.symbol.file", "-encoding", "UTF-8"]
3804 
3805         // we use a custom javadoc command
3806         project.javadoc.enabled = false
3807 
3808         // Add in the -Xlint options
3809         if (IS_LINT) {
3810             LINT.split("[, ]").each { s ->
3811                 compile.options.compilerArgs += "-Xlint:$s"
3812             }
3813         }
3814     } // tasks with javaCompile
3815 
3816     // If I am a module....
3817     if (project.hasProperty('moduleSourcePath') &&
3818             (project.hasProperty('buildModule') && project.buildModule)) {
3819         project.compileJava {
3820             options.compilerArgs.addAll([
3821                 '-implicit:none',
3822                 '--module-source-path', project.moduleSourcePath
3823                 ])
3824         }
3825         // no jars needed for modules
3826         project.jar.enabled = false
3827 
3828         // and redirect the resources into the module
3829         project.sourceSets.main.output.resourcesDir = project.moduleDir
3830         project.processResources.destinationDir = project.moduleDir
3831     }
3832 
3833     if (project.hasProperty('moduleSourcePathShim') &&
3834             project.sourceSets.hasProperty('shims')) {
3835 
3836         // sync up the obvious source directories with the shims
3837         // others (like the shaders in graphics) should be added in there
3838         project.sourceSets.shims.java.srcDirs += project.sourceSets.main.java.srcDirs
3839         project.sourceSets.shims.java.srcDirs += "$buildDir/gensrc/java"
3840 
3841         project.compileShimsJava {
3842             options.compilerArgs.addAll([
3843                 '-implicit:none',
3844                 '--module-source-path', project.moduleSourcePathShim
3845                 ])
3846         }
3847         project.compileShimsJava.dependsOn(project.compileJava)
3848 
3849         def copyGeneratedShimsTask = task("copyGeneratedShims", type: Copy, dependsOn: [compileShimsJava, processShimsResources]) {
3850             from project.sourceSets.shims.java.outputDir
3851             into "${rootProject.buildDir}/shims"
3852             if (HAS_JAVAFX_MODULES) {
3853                 exclude("*/module-info.class")
3854             }
3855         }
3856 
3857         project.processShimsResources.dependsOn(project.processResources)
3858 
3859         // shims resources should have the main resouces as a base
3860         project.sourceSets.shims.resources.srcDirs += project.sourceSets.main.resources.srcDirs
3861 
3862         // and redirect the resources into the module
3863         project.sourceSets.shims.output.resourcesDir = project.moduleShimsDir
3864         project.processShimsResources.destinationDir = project.moduleShimsDir
3865 
3866        compileTestJava.dependsOn(copyGeneratedShimsTask)
3867     }
3868 
3869     if (project.hasProperty('modulePathArgs')) {
3870         project.compileJava.options.compilerArgs.addAll(modulePathArgs)
3871     }
3872 
3873     if (project.hasProperty('testModulePathArgs')) {
3874         project.compileTestJava.options.compilerArgs.addAll(testModulePathArgs)
3875     }
3876 
3877     if (project.hasProperty('testPatchModuleArgs')) {
3878         project.test.jvmArgs += testPatchModuleArgs
3879     }
3880 
3881     /* Note: we should not have to add extraAddExports to the normal
3882      * modular compile, as it contains all of the module-info files.
3883      * In fact doing so might cover up a module-info issue.
3884      * so we don't do it, and I will leave this commented out
3885      * block as a reminder of this fact.
3886     if (project.hasProperty('extraAddExports')) {
3887         project.compileJava.options.compilerArgs.addAll(extraAddExports);
3888     }
3889     */
3890 
3891     if (project.hasProperty('testAddExports')) {
3892         project.compileTestJava.options.compilerArgs.addAll(testAddExports);
3893         project.test.jvmArgs += testAddExports
3894     }
3895 
3896     if (rootProject.hasProperty("EXTRA_TEST_ARGS") && project.hasProperty('test')) {
3897         EXTRA_TEST_ARGS.split(' ').each() { e ->
3898             project.test.jvmArgs += e
3899         }
3900     }
3901 
3902     if (rootProject.hasProperty("EXTRA_COMPILE_ARGS") && project.hasProperty('compileJava')) {
3903         project.compileJava.options.compilerArgs.addAll(EXTRA_COMPILE_ARGS.split(' '))
3904     }
3905 
3906     if (rootProject.hasProperty("EXTRA_COMPILE_ARGS") && project.hasProperty('compileTestJava')) {
3907         project.compileTestJava.options.compilerArgs.addAll(EXTRA_COMPILE_ARGS.split(' '))
3908     }
3909 }
3910 
3911 /******************************************************************************
3912  *                                                                            *
3913  *                             Top Level Tasks                                *
3914  *                                                                            *
3915  *  These are the tasks which are defined only for the top level project and  *
3916  *  not for any sub projects. These are generally the entry point that is     *
3917  *  used by Hudson and by the continuous build system.                        *
3918  *                                                                            *
3919  *****************************************************************************/
3920 
3921 task clean() {
3922     group = "Basic"
3923     description = "Deletes the build directory and the build directory of all sub projects"
3924     getSubprojects().each { subProject ->
3925         dependsOn(subProject.getTasksByName("clean", true));
3926     }
3927     doLast {
3928         delete(buildDir);
3929     }
3930 }
3931 
3932 task cleanAll() {
3933     group = "Basic"
3934     description = "Scrubs the repo of build artifacts"
3935     dependsOn(clean)
3936     doLast {
3937         //delete(".gradle"); This causes problems on windows.
3938         delete("buildSrc/build");
3939     }
3940 }
3941 
3942 task createMSPfile() {
3943     group = "Build"
3944     File mspFile = new File(rootProject.buildDir,MODULESOURCEPATH)
3945     outputs.file(mspFile)
3946 
3947     doLast {
3948         mspFile.delete()
3949         mspFile << "--module-source-path\n"
3950         mspFile << defaultModuleSourcePath
3951         mspFile << "\n"
3952     }
3953 }
3954 
3955 task javadoc(type: Javadoc, dependsOn: createMSPfile) {
3956     group = "Basic"
3957     description = "Generates the JavaDoc for all the public API"
3958     executable = JAVADOC
3959     def projectsToDocument = [
3960             project(":base"), project(":graphics"), project(":controls"), project(":media"),
3961             project(":swing"), /*project(":swt"),*/ project(":fxml"), project(":web")]
3962     source(projectsToDocument.collect({
3963         [it.sourceSets.main.java]
3964     }));
3965     setDestinationDir(new File(buildDir, 'javadoc'));
3966 
3967     exclude("com/**/*", "Compile*", "javafx/builder/**/*", "javafx/scene/accessibility/**/*");
3968 
3969     options.tags("apiNote:a:API Note:")
3970     options.tags("implSpec:a:Implementation Requirements:")
3971     options.tags("implNote:a:Implementation Note:")
3972     options.tags("param")
3973     options.tags("return")
3974     options.tags("throws")
3975     options.tags("moduleGraph:X")
3976     options.tags("since")
3977     options.tags("version")
3978     options.tags("serialData")
3979     options.tags("factory")
3980     options.tags("see")
3981 
3982     options.windowTitle("${javadocTitle}")
3983     options.header("${javadocHeader}")
3984     options.bottom("${javadocBottom}")
3985     options.locale("en");
3986     if (JDK_DOCS_LINK != "") {
3987         options.linksOffline(JDK_DOCS, JDK_DOCS_LINK);
3988     } else {
3989         options.links(JDK_DOCS);
3990     }
3991     options.addBooleanOption("XDignore.symbol.file").setValue(true);
3992     options.addBooleanOption("Xdoclint:${DOC_LINT}").setValue(IS_DOC_LINT);
3993     options.addBooleanOption("html5").setValue(true);
3994     options.addBooleanOption("javafx").setValue(true);
3995     options.addBooleanOption("use").setValue(true);
3996 
3997     options.setOptionFiles([
3998         new File(rootProject.buildDir,MODULESOURCEPATH)
3999         ]);
4000 
4001     doLast {
4002         projectsToDocument.each { p ->
4003             def destDir = "$buildDir/javadoc/${p.ext.moduleName}"
4004             copy {
4005                 from("$p.projectDir/src/main/docs") {
4006                     include "**/*.html"
4007                     filter { line->
4008                         line = line.replace("@FXVERSION@", RELEASE_VERSION)
4009                     }
4010                 }
4011                 from("$p.projectDir/src/main/docs") {
4012                     exclude "**/*.html"
4013                 }
4014 
4015                 into destDir
4016             }
4017         }
4018     }
4019 
4020     dependsOn(projectsToDocument.collect { project -> project.getTasksByName("classes", true)});
4021 }
4022 
4023 task sdk() {
4024     if (DO_BUILD_SDK_FOR_TEST) {
4025         rootProject.getTasksByName("test", true).each { t ->
4026             if (t.enabled) t.dependsOn(sdk)
4027         }
4028     }
4029 }
4030 
4031 task jmods() {
4032     dependsOn(sdk)
4033     // real work items added later.
4034 }
4035 
4036 task appsjar() {
4037     dependsOn(sdk)
4038     // Note: the jar dependencies get added elsewhere see project(":apps")
4039 }
4040 
4041 // these are empty tasks, allowing us to depend on the task, which may have other
4042 // real work items added later.
4043 task copyAppsArtifacts() {
4044     dependsOn(appsjar)
4045 }
4046 
4047 task apps() {
4048     dependsOn(sdk)
4049     dependsOn(appsjar)
4050     dependsOn(copyAppsArtifacts)
4051 }
4052 
4053 task findbugs() {
4054     dependsOn(sdk)
4055 
4056     doLast {
4057         if (!BUILD_CLOSED) {
4058             println "findbugs task is only run for a closed build"
4059         }
4060     }
4061 }
4062 
4063 // create the zip file of modules for a JDK build
4064 task jdkZip {
4065     dependsOn(sdk)
4066 }
4067 
4068 // The following tasks are for the closed build only. They are a no-op for the open build
4069 
4070 task checkCache() {
4071     dependsOn(updateCacheIfNeeded)
4072 }
4073 
4074 task publicExports() {
4075     dependsOn(sdk, jmods, apps, javadoc, jdkZip)
4076     // note the real work is below in the compileTargets
4077 }
4078 
4079 task perf() {
4080     dependsOn(sdk, apps)
4081     doLast {
4082         if (!BUILD_CLOSED) {
4083             println "perf task is only run for a closed build"
4084         }
4085     }
4086 }
4087 
4088 task zips() {
4089     dependsOn(sdk, jmods, javadoc, apps, jdkZip, publicExports, perf)
4090     // note the real work is below in the compileTargets
4091 }
4092 
4093 task all() {
4094     dependsOn(sdk,publicExports,apps,perf,zips)
4095 }
4096 
4097 
4098 // Construct list of subprojects that are modules
4099 ext.moduleProjList = []
4100 subprojects {
4101     if (project.hasProperty("buildModule") && project.ext.buildModule) {
4102         rootProject.ext.moduleProjList += project
4103         println "module: $project (buildModule=YES)"
4104     } else {
4105         println "module: $project (buildModule=NO)"
4106     }
4107 }
4108 
4109 
4110 // Define the sdk task, which also produces the javafx.swt modular jar
4111 
4112 compileTargets { t ->
4113 
4114     def javafxSwtTask = task("javafxSwt$t.capital", type: Jar) {
4115         enabled = COMPILE_SWT
4116         group = "Basic"
4117         description = "Creates the javafx-swt.jar for the $t.name target"
4118         destinationDir = file("${project(":swt").buildDir}/libs")
4119         archiveName = "javafx-swt.jar"
4120         includeEmptyDirs = false
4121         from("${project(":swt").buildDir}/classes/java/main");
4122         include("**/javafx/embed/swt/**")
4123 
4124         dependsOn(
4125             project(":swt").compileJava,
4126             project(":swt").processResources,
4127             // note: assemble and classes are not enough for DidWork
4128             project(":swt").classes,
4129             // classes is needed for a jar copy
4130             )
4131     }
4132 
4133     // FIXME: do we really need the index task for this modular jar?
4134     def javafxSwtIndexTask = task("javafxSwtIndex$t.capital") {
4135         //the following is a workaround for the lack of indexing in gradle 1.4 through 1.7
4136         dependsOn(javafxSwtTask)
4137 
4138         doLast() {
4139             ant.jar (update: true, index: true, destfile: "${javafxSwtTask.destinationDir}/${javafxSwtTask.archiveName}")
4140         }
4141     }
4142 
4143     def sdkTask = task("sdk$t.capital") {
4144         group = "Basic"
4145         dependsOn(javafxSwtIndexTask)
4146     }
4147 
4148     sdk.dependsOn(sdkTask)
4149 }
4150 
4151 project(":apps") {
4152     // The apps build is Ant based, we will exec ant from gradle.
4153 
4154     // Download the Lucene libraries needed for the Ensemble8 app
4155     def luceneVersion = "7.7.2"
4156     getConfigurations().create("lucene");
4157     dependencies {
4158         lucene group: "org.apache.lucene", name: "lucene-core", version: luceneVersion
4159         lucene group: "org.apache.lucene", name: "lucene-grouping", version: luceneVersion
4160         lucene group: "org.apache.lucene", name: "lucene-queryparser", version: luceneVersion
4161     }
4162 
4163     // Copy Lucene libraries into the Ensemble8/lib directory
4164     File ensembleLibDir = rootProject.file("apps/samples/Ensemble8/lib");
4165     def libNames = [ "lucene-core-${luceneVersion}.jar",
4166                      "lucene-grouping-${luceneVersion}.jar",
4167                      "lucene-queryparser-${luceneVersion}.jar" ]
4168 
4169 
4170     task getLucene(type: Copy) {
4171         doFirst {
4172             ensembleLibDir.mkdirs();
4173         }
4174         into ensembleLibDir
4175         includeEmptyDirs = false
4176         configurations.lucene.files.each { f ->
4177             libNames.each { name ->
4178                 if (name == f.getName()) {
4179                     from f.getPath()
4180                 }
4181             }
4182         }
4183     }
4184 
4185     compileTargets { t ->
4186         List<String> params = []
4187 
4188         params << "-DtargetBld=$t.name"
4189 
4190         if (!rootProject.ext[t.upper].compileSwing) {
4191             params << "-DJFX_CORE_ONLY=true"
4192         }
4193         params << "-Dplatforms.JDK_1.9.home=${rootProject.ext.JDK_HOME}"
4194         params << "-Dcompile.patch=@${rootProject.buildDir}/${COMPILEARGSFILE}"
4195         params << "-Drun.patch=@${rootProject.buildDir}/${RUNARGSFILE}"
4196 
4197         def appsJar = project.task("appsJar${t.capital}") {
4198             dependsOn(sdk, getLucene)
4199             doLast() {
4200                 ant(t.name,
4201                       projectDir.path,
4202                       "appsJar",
4203                       params);
4204             }
4205         }
4206         rootProject.appsjar.dependsOn(appsJar)
4207 
4208         def appsClean = project.task("clean${t.capital}") {
4209             doLast() {
4210                 ant(t.name,
4211                       project.projectDir.path,
4212                       "clean",
4213                       params);
4214                 delete(ensembleLibDir);
4215             }
4216         }
4217         rootProject.clean.dependsOn(appsClean)
4218     }
4219 }
4220 
4221 // Tasks to create the disk layout for the sdk, jmods, and docs
4222 // in the artifacts directory (publicExports), and zip them up in
4223 // artifacts/bundles (zips)
4224 // These tasks are only used for the standalone SDK.
4225 compileTargets { t ->
4226     if (!HAS_JAVAFX_MODULES) {
4227         def targetProperties = rootProject.ext[t.upper]
4228         def platformPrefix = targetProperties.platformPrefix
4229 
4230         def artifactsDir = "${rootProject.buildDir}/artifacts"
4231         def bundlesDir = "${artifactsDir}/bundles"
4232 
4233         def sdkDirName = "${platformPrefix}sdk"
4234         def sdkDir = "${rootProject.buildDir}/${sdkDirName}"
4235         def sdkBundleName = "javafx-sdk-${RELEASE_VERSION}"
4236         def sdkArtifactsDir = "${artifactsDir}/${sdkBundleName}"
4237 
4238         def docsDirName = "javadoc"
4239         def docsDir = "${rootProject.buildDir}/${docsDirName}"
4240         def docsBundleName = "javafx-docs-${RELEASE_VERSION}"
4241         def docsArtifactsDir = "${artifactsDir}/${docsBundleName}"
4242 
4243         def jmodsDirName = "jmods"
4244         def jmodsDir = "${rootProject.buildDir}/${jmodsDirName}"
4245         def jmodsBundleName = "javafx-jmods-${RELEASE_VERSION}"
4246         def jmodsArtifactsDir = "${artifactsDir}/${jmodsBundleName}"
4247 
4248         def publicExportsTask = task ("publicExportsStandalone${t.capital}") {
4249             group = "Basic"
4250             description = "Creates the disk layout for sdk, jmods, and docs"
4251         }
4252         publicExports.dependsOn(publicExportsTask)
4253 
4254         def copyArtifactsSdkTask = task("copyArtifactsSdk$t.capital", type: Copy, dependsOn: [sdk,jmods,apps,javadoc]) {
4255             from sdkDir
4256             into sdkArtifactsDir
4257         }
4258         publicExportsTask.dependsOn(copyArtifactsSdkTask)
4259 
4260         // Need to modify file permissions Windows to make sure that the
4261         // execute bit is set, and that the files are world readable
4262         def chmodArtifactsSdkTask = task("chmodArtifactsSdk$t.capital", dependsOn: copyArtifactsSdkTask) {
4263             if (IS_WINDOWS && IS_USE_CYGWIN) {
4264                 doLast {
4265                     exec {
4266                         workingDir(sdkArtifactsDir)
4267                         commandLine("chmod", "-R", "755", ".")
4268                     }
4269                 }
4270             }
4271         }
4272         publicExportsTask.dependsOn(chmodArtifactsSdkTask)
4273 
4274         def copyArtifactsDocsTask = task("copyArtifactsDocs$t.capital", type: Copy, dependsOn: chmodArtifactsSdkTask) {
4275             from docsDir
4276             into "${docsArtifactsDir}/api"
4277         }
4278         publicExportsTask.dependsOn(copyArtifactsDocsTask)
4279 
4280         def copyArtifactsJmodsTask = task("copyArtifactsJmods$t.capital", type: Copy, dependsOn: copyArtifactsDocsTask) {
4281             from jmodsDir
4282             into "${jmodsArtifactsDir}"
4283         }
4284         publicExportsTask.dependsOn(copyArtifactsJmodsTask)
4285 
4286         def zipsTask = task ("zipsStandalone${t.capital}") {
4287             group = "Basic"
4288             description = "Creates the public zip bundles"
4289         }
4290         zips.dependsOn(zipsTask)
4291 
4292         // Use native zip tool so that file permissions are preserved on Windows
4293         def zipSdkTask = task("zipSdk$t.capital", dependsOn: publicExportsTask) {
4294             doLast {
4295                 def outZipFile = "${bundlesDir}/${sdkBundleName}.zip"
4296                 mkdir bundlesDir
4297                 exec {
4298                     workingDir(artifactsDir)
4299                     commandLine("zip", "-q", "-r", outZipFile, sdkBundleName)
4300                 }
4301             }
4302         }
4303         zipsTask.dependsOn(zipSdkTask)
4304 
4305         def zipDocsTask = task("zipDocs$t.capital", type: Zip, dependsOn: zipSdkTask) {
4306             destinationDir = file("${bundlesDir}")
4307             archiveName = "${docsBundleName}.zip"
4308             includeEmptyDirs = false
4309             from docsArtifactsDir
4310             into "${docsBundleName}"
4311         }
4312         zipsTask.dependsOn(zipDocsTask)
4313 
4314         def zipJmodsTask = task("zipJmods$t.capital", type: Zip, dependsOn: zipDocsTask) {
4315             destinationDir = file("${bundlesDir}")
4316             archiveName = "${jmodsBundleName}.zip"
4317             includeEmptyDirs = false
4318             from jmodsArtifactsDir
4319             into "${jmodsBundleName}"
4320         }
4321         zipsTask.dependsOn(zipJmodsTask)
4322     }
4323 }
4324 
4325 
4326 /******************************************************************************
4327  *                                                                            *
4328  *                               Modules                                      *
4329  *                                                                            *
4330  *****************************************************************************/
4331 
4332 ext.moduleDependencies = [file("dependencies")]
4333 
4334 task buildModules {
4335 }
4336 
4337 // Combine the classes, lib, and bin for each module
4338 compileTargets { t ->
4339     def targetProperties = project.ext[t.upper]
4340 
4341     def platformPrefix = targetProperties.platformPrefix
4342     def bundledSdkDirName = "${platformPrefix}modular-sdk"
4343     def bundledSdkDir = "${rootProject.buildDir}/${bundledSdkDirName}"
4344     def modulesDir = "${bundledSdkDir}/modules"
4345     def modulesCmdsDir = "${bundledSdkDir}/modules_cmds"
4346     def modulesLibsDir = "${bundledSdkDir}/modules_libs"
4347     def modulesSrcDir = "${bundledSdkDir}/modules_src"
4348     def modulesConfDir = "${bundledSdkDir}/modules_conf"
4349     def modulesLegalDir = "${bundledSdkDir}/modules_legal"
4350     def modulesMakeDir = "${bundledSdkDir}/make"
4351 
4352     final File runArgsFile = file("${rootProject.buildDir}/${RUNARGSFILE}")
4353     final File compileArgsFile = file("${rootProject.buildDir}/${COMPILEARGSFILE}")
4354 
4355     project.files(runArgsFile);
4356 
4357     def buildModulesTask = task("buildModules$t.capital", group: "Build") {
4358         // BUNDLED SDK
4359 
4360         // Copy dependencies/*/module-info.java.extra
4361         // merging as needed, removing duplicates
4362         // only lines with 'exports' will be copied
4363         def dependencyRoots = moduleDependencies
4364         if (rootProject.hasProperty("closedModuleDepedencies")) {
4365             dependencyRoots = [dependencyRoots, closedModuleDepedencies].flatten()
4366         }
4367 
4368         // Create the inputs/outputs list first to support UP-TO-DATE
4369         ArrayList outputNames = new ArrayList()
4370         dependencyRoots.each { root ->
4371             FileTree ft = fileTree(root).include('**/*.extra')
4372             ft.each() { e->
4373                 inputs.file(e)
4374 
4375                 String usename = e.path
4376                 String filePath = e.getAbsolutePath()
4377                 String folderPath = root.getAbsolutePath()
4378                 if (filePath.startsWith(folderPath)) {
4379                     usename = filePath.substring(folderPath.length() + 1);
4380                 }
4381                 if (! outputNames.contains(usename) ) {
4382                     outputNames.add(usename)
4383                 }
4384             }
4385         }
4386 
4387         outputNames.each() { e->
4388                 File f = new File(modulesSrcDir, e)
4389                 outputs.file(f)
4390         }
4391 
4392         def outputPolicyDir = "${modulesConfDir}/java.base/security"
4393         def outputPolicyFile = file("${outputPolicyDir}/java.policy.extra")
4394 
4395         outputs.file(outputPolicyFile)
4396         moduleProjList.each { project ->
4397             def policyDir = "${project.projectDir}/src/main/conf/security"
4398             def policyFile = file("${policyDir}/java.policy")
4399             if (policyFile.exists()) {
4400                 inputs.file(policyFile)
4401             }
4402         }
4403 
4404         doLast {
4405             Map extras = [:]
4406 
4407             dependencyRoots.each { root ->
4408                 FileTree ft = fileTree(root).include('**/*.extra')
4409                 ft.each() { e->
4410                     String usename = e.path
4411                     String filePath = e.getAbsolutePath()
4412                     String folderPath = root.getAbsolutePath()
4413                     if (filePath.startsWith(folderPath)) {
4414                         usename = filePath.substring(folderPath.length() + 1);
4415                     }
4416                     if (extras.containsKey(usename)) {
4417                         List<String> lines = extras.get(usename)
4418                         e.eachLine { line ->
4419                             line = line.trim()
4420                             if (line.length() > 1 && Character.isLetter(line.charAt(0))) {
4421                                 lines << line
4422                             }
4423                         }
4424 
4425                     } else {
4426                         List<String> lines = []
4427                         e.eachLine { line ->
4428                             line = line.trim()
4429                             if (line.length() > 1 && Character.isLetter(line.charAt(0))) {
4430                                 lines << line
4431                             }
4432                         }
4433                         extras.put(usename,lines)
4434                     }
4435                 }
4436             }
4437             extras.keySet().each() { e->
4438                 File f = new File(modulesSrcDir, e)
4439                 f.getParentFile().mkdirs()
4440                 f.delete()
4441 
4442                 extras.get(e).unique().each() { l->
4443                     f << l
4444                     f << "\n"
4445                 }
4446             }
4447 
4448             // concatecate java.policy files into a single file
4449             //
4450             mkdir outputPolicyDir
4451             outputPolicyFile.delete()
4452             moduleProjList.each { project ->
4453                 def policyDir = "${project.projectDir}/src/main/conf/security"
4454                 def policyFile = file("${policyDir}/java.policy")
4455                 if (policyFile.exists()) outputPolicyFile << policyFile.text
4456             }
4457         }
4458     }
4459     buildModules.dependsOn(buildModulesTask)
4460 
4461     // BUNDLED SDK
4462     moduleProjList.each { project ->
4463         // Copy classes, bin, and lib directories
4464 
4465         def moduleName = project.ext.moduleName
4466         def buildDir = project.buildDir
4467 
4468         def srcClassesDir = "${buildDir}/${platformPrefix}module-classes"
4469         def dstClassesDir = "${modulesDir}/${moduleName}"
4470         def copyClassFilesTask = project.task("copyClassFiles$t.capital", type: Copy, dependsOn: project.assemble) {
4471             from srcClassesDir
4472             into dstClassesDir
4473             exclude("module-info.class")
4474         }
4475 
4476         def srcCmdsDir = "${buildDir}/${platformPrefix}module-bin"
4477         def dstCmdsDir = "${modulesCmdsDir}/${moduleName}"
4478         def copyBinFilesTask = project.task("copyBinFiles$t.capital", type: Copy, dependsOn: copyClassFilesTask) {
4479             from srcCmdsDir
4480             into dstCmdsDir
4481         }
4482 
4483         def srcLibsDir = "${buildDir}/${platformPrefix}module-lib"
4484         def dstLibsDir = "${modulesLibsDir}/${moduleName}"
4485         def copyLibFilesTask = project.task("copyLibFiles$t.capital", type: Copy, dependsOn: copyBinFilesTask) {
4486             from srcLibsDir
4487             into dstLibsDir
4488         }
4489 
4490         // Copy module sources
4491         // FIXME: javafx.swt sources?
4492         def copySources = project.hasProperty("includeSources") && project.includeSources
4493         def copySourceFilesTask = project.task("copySourceFiles$t.capital", type: Copy, dependsOn: copyLibFilesTask) {
4494             if (copySources) {
4495                 from "${project.projectDir}/src/main/java"
4496                 if (project.name.equals("base")) {
4497                     from "${project.projectDir}/build/gensrc/java"
4498                 }
4499                 if (project.name.equals("web")) {
4500                     from "${project.projectDir}/src/main/native/Source/WebCore/bindings/java/dom3/java"
4501                 }
4502             } else {
4503                 from "${project.projectDir}/src/main/java/module-info.java"
4504             }
4505             into "${modulesSrcDir}/${moduleName}"
4506             include "**/*.java"
4507 
4508             if (project.hasProperty("sourceFilter")) {
4509                 filter(project.sourceFilter)
4510             }
4511         }
4512 
4513         // Copy .html and other files needed for doc bundles
4514         def copyDocFiles = project.task("copyDocFiles$t.capital", type: Copy, dependsOn: copySourceFilesTask) {
4515             if (copySources) {
4516                 from("${project.projectDir}/src/main/docs") {
4517                     include "**/*.html"
4518                     filter { line->
4519                         line = line.replace("@FXVERSION@", RELEASE_VERSION)
4520                     }
4521                 }
4522                 from("${project.projectDir}/src/main/docs") {
4523                     exclude "**/*.html"
4524                 }
4525                 from("${project.projectDir}/src/main/java") {
4526                     exclude "**/*.java"
4527                 }
4528 
4529                 into "${modulesSrcDir}/${moduleName}"
4530             }
4531         }
4532 
4533         // Copy make/build.properties
4534         def srcMakeDir = "${project.projectDir}/make"
4535         def dstMakeDir = "${modulesMakeDir}/${moduleName}"
4536         def copyBuildPropertiesTask = project.task("copyBuildProperties$t.capital", type: Copy, dependsOn: copyDocFiles) {
4537             from srcMakeDir
4538             into dstMakeDir
4539         }
4540 
4541         // Copy legal files
4542         def srcLegalDir = "${project.projectDir}/src/main/legal"
4543         def dstLegalDir = "${modulesLegalDir}/${moduleName}"
4544         def copyLegalTask = project.task("copyLegal$t.capital", type: Copy, dependsOn: copyBuildPropertiesTask) {
4545             from srcLegalDir
4546             into dstLegalDir
4547 
4548             // Exclude ANGLE since we (currently) do not use it
4549             exclude("angle.md")
4550         }
4551 
4552         buildModulesTask.dependsOn(
4553             copyClassFilesTask,
4554             copyLibFilesTask,
4555             copySourceFilesTask,
4556             copyDocFiles,
4557             copyBuildPropertiesTask,
4558             copyLegalTask)
4559     }
4560 
4561     // ============================================================
4562 
4563     def standaloneSdkDirName = "${platformPrefix}sdk"
4564     def standaloneSdkDir = "${rootProject.buildDir}/${standaloneSdkDirName}"
4565     def standaloneLibDir = "${standaloneSdkDir}/lib"
4566     def libDest=targetProperties.libDest
4567     def standaloneNativeDir = "${standaloneSdkDir}/${libDest}"
4568     def standaloneLegalDir = "${standaloneSdkDir}/legal"
4569     def standaloneSrcZipName = "src.zip"
4570 
4571     // STANDALONE SDK
4572     moduleProjList.each { project ->
4573         // Copy classes, bin, and lib directories
4574 
4575         def moduleName = project.ext.moduleName
4576         def buildDir = project.buildDir
4577 
4578         // Create modular jars
4579         def srcClassesDir = "${buildDir}/${platformPrefix}module-classes"
4580         def srcLibsDir = "${buildDir}/${platformPrefix}module-lib"
4581         def dstModularJarDir = "${standaloneLibDir}"
4582         def modularJarName = "${moduleName}.jar"
4583         def modularJarTask = project.task("modularJarStandalone$t.capital", type: Jar, dependsOn: project.assemble) {
4584             destinationDir = file("${dstModularJarDir}")
4585             archiveName = modularJarName
4586             includeEmptyDirs = false
4587             from srcClassesDir
4588         }
4589 
4590         // Copy native libraries
4591         def srcNativeDir = "${buildDir}/${platformPrefix}module-lib"
4592         def dstNativeDir = "${standaloneNativeDir}"
4593         def copyNativeFilesTask = project.task("copyNativeFilesStandalone$t.capital", type: Copy, dependsOn: modularJarTask) {
4594             from srcNativeDir
4595             into dstNativeDir
4596             include("*.dll")
4597         }
4598 
4599         // Copy other lib files
4600         def dstLibsDir = "${standaloneLibDir}"
4601         def copyLibFilesTask = project.task("copyLibFilesStandalone$t.capital", type: Copy, dependsOn: copyNativeFilesTask) {
4602             from srcLibsDir
4603             into dstLibsDir
4604             exclude("*.dll")
4605         }
4606 
4607         // Copy legal files
4608         def licenseFiles = [ "ADDITIONAL_LICENSE_INFO", "ASSEMBLY_EXCEPTION", "LICENSE" ]
4609         def srcLegalDir = "${project.projectDir}/src/main/legal"
4610         def dstLegalDir = "${standaloneLegalDir}/${moduleName}"
4611         def copyLegalTask = project.task("copyLegalStandalone$t.capital", type: Copy, dependsOn: copyLibFilesTask) {
4612 
4613             def rtDir = rootProject.file('.')
4614             licenseFiles.each { lFile ->
4615                 from "${rtDir}/${lFile}"
4616             }
4617 
4618             from srcLegalDir
4619 
4620             into dstLegalDir
4621 
4622             // Exclude ANGLE since we (currently) do not use it
4623             exclude("angle.md")
4624         }
4625 
4626         buildModulesTask.dependsOn(
4627             modularJarTask,
4628             copyNativeFilesTask,
4629             copyLibFilesTask,
4630             copyLegalTask)
4631     }
4632 
4633     // Zip module sources for standalone SDK
4634     //
4635     // NOTE: the input is taken from the modular-sdk/modules_src dir
4636     // so that we don't have to duplicate the logic and create another
4637     // temporary directory. This is somewhat inelegant, since the bundled sdk
4638     // and the standalone sdk should be independent of one another, but seems
4639     // better than the alternatives.
4640     def zipSourceFilesTask = project.task("zipSourceFilesStandalone$t.capital", type: Zip, dependsOn: buildModulesTask) {
4641         destinationDir = file("${standaloneLibDir}")
4642         archiveName = standaloneSrcZipName
4643         includeEmptyDirs = false
4644         from modulesSrcDir
4645         include "**/*.java"
4646     }
4647     buildModules.dependsOn(zipSourceFilesTask)
4648 
4649     // ============================================================
4650 
4651     // Maven Publications
4652     def publicationDirName = "${platformPrefix}publications"
4653     def publicationDir = "${rootProject.buildDir}/${publicationDirName}"
4654 
4655     moduleProjList.each { project -> 
4656         // Create publications to be uploaded 
4657 
4658         def moduleName = project.ext.moduleName
4659         def buildDir = project.buildDir
4660 
4661         def dstModularJarDir="${publicationDir}"
4662         def srcClassesDir = "${buildDir}/${platformPrefix}module-classes"
4663         def srcLibsDir = "${buildDir}/${platformPrefix}module-lib"
4664 
4665         def modularEmptyPublicationJarName = "${moduleName}.jar"
4666         def modularEmptyPublicationJarTask = project.task("moduleEmptyPublicationJar${t.capital}", type: Jar) {
4667             destinationDir = file("${dstModularJarDir}")
4668             archiveName = modularEmptyPublicationJarName
4669             manifest {
4670                 attributes(
4671                     'Automatic-Module-Name':"${moduleName}Empty"
4672                 )
4673             }
4674         }
4675 
4676         def modularPublicationJarName = "${moduleName}-${t.name}.jar"
4677         def modularPublicationJarTask = project.task("modularPublicationJar${t.capital}", type: Jar, dependsOn: modularEmptyPublicationJarTask) {
4678             destinationDir = file("${dstModularJarDir}")
4679             archiveName = modularPublicationJarName
4680             from srcLibsDir
4681             from srcClassesDir
4682         }
4683 
4684         buildModulesTask.dependsOn(modularPublicationJarTask)
4685 
4686     }
4687     // ============================================================
4688 
4689     def buildRunArgsTask = task("buildRunArgs$t.capital",
4690             group: "Build", dependsOn: buildModulesTask) {
4691         outputs.file(runArgsFile);
4692         inputs.file(EXTRAADDEXPORTS);
4693         doLast() {
4694             List<String>modpath = []
4695             List<String>modnames = []
4696 
4697             moduleProjList.each { project ->
4698                 def moduleName = project.ext.moduleName
4699                 def dstModuleDir = cygpath("${modulesDir}/${moduleName}")
4700                 if (HAS_JAVAFX_MODULES) {
4701                     modpath <<  "${moduleName}=${dstModuleDir}"
4702                 } else {
4703                     modnames << moduleName
4704                 }
4705             }
4706 
4707             if (HAS_JAVAFX_MODULES) {
4708                 writeRunArgsFile(runArgsFile, computeLibraryPath(true), modpath, null)
4709                 writeRunArgsFile(compileArgsFile, null, modpath, null)
4710 
4711                 if (rootProject.hasProperty("EXTRA_ADDEXPORTS_STRING")) {
4712                     runArgsFile << EXTRA_ADDEXPORTS_STRING
4713                     compileArgsFile << EXTRA_ADDEXPORTS_STRING
4714                 }
4715             } else {
4716                 modpath = [ cygpath("${standaloneLibDir}") ]
4717                 writeRunArgsFile(runArgsFile, null, modpath, modnames)
4718                 writeRunArgsFile(compileArgsFile, null, modpath, modnames)
4719             }
4720         }
4721     }
4722     buildModules.dependsOn(buildRunArgsTask)
4723 
4724     def isWindows = IS_WINDOWS && t.name == "win";
4725     def isMac = IS_MAC && t.name == "mac";
4726 
4727     // Create layout for modular classes
4728     moduleProjList.each { project ->
4729         def buildModuleClassesTask = project.task("buildModule$t.capital", group: "Build", type: Copy) {
4730             dependsOn(project.assemble)
4731             def buildDir = project.buildDir
4732             def sourceBuildDirs = [
4733                 "${buildDir}/classes/java/main/${project.moduleName}",
4734             ]
4735 
4736             def moduleClassesDir = "$buildDir/${platformPrefix}module-classes"
4737                 includeEmptyDirs = false
4738                 sourceBuildDirs.each { d ->
4739                     from d
4740                 }
4741                 into moduleClassesDir
4742 
4743                 // Exclude obsolete, experimental, or non-shipping code
4744                 exclude("version.rc")
4745                 exclude("com/sun/glass/ui/swt")
4746                 exclude("com/sun/javafx/tools/ant")
4747                 exclude("com/javafx/main")
4748                 exclude("com/sun/javafx/webkit/drt")
4749                 if (!IS_INCLUDE_NULL3D) {
4750                     exclude ("com/sun/prism/null3d")
4751                 }
4752                 if (!IS_INCLUDE_ES2) {
4753                        exclude("com/sun/prism/es2",
4754                                "com/sun/scenario/effect/impl/es2")
4755                 }
4756 
4757                 // Exclude platform-specific classes for other platforms
4758 
4759                 if (!isMac) {
4760                     exclude ("com/sun/media/jfxmediaimpl/platform/osx",
4761                              "com/sun/prism/es2/MacGL*",
4762                              "com/sun/glass/events/mac",
4763                              "com/sun/glass/ui/mac",
4764                              )
4765                 }
4766 
4767                 if (!isWindows) {
4768                     exclude ("**/*.hlsl",
4769                              "com/sun/glass/ui/win",
4770                              "com/sun/prism/d3d",
4771                              "com/sun/prism/es2/WinGL*",
4772                              "com/sun/scenario/effect/impl/hw/d3d"
4773                              )
4774                 }
4775 
4776                 if (!targetProperties.includeGTK) { //usually IS_LINUX
4777                     exclude (
4778                              "com/sun/glass/ui/gtk",
4779                              "com/sun/prism/es2/EGL*",
4780                              "com/sun/prism/es2/X11GL*"
4781                              )
4782                 }
4783 
4784                 if (!targetProperties.includeEGL) {
4785                     exclude ("com/sun/prism/es2/EGL*")
4786                 }
4787 
4788                 if (!targetProperties.includeMonocle) {
4789                     exclude ("com/sun/glass/ui/monocle")
4790                     exclude("com/sun/prism/es2/Monocle*")
4791                 }
4792 
4793                 if (t.name != 'ios') {
4794                     exclude ("com/sun/media/jfxmediaimpl/platform/ios",
4795                              "com/sun/glass/ui/ios",
4796                              "com/sun/prism/es2/IOS*"
4797                              )
4798                 }
4799 
4800                 if (t.name != 'android' && t.name != 'dalvik') {
4801                     exclude ("com/sun/glass/ui/android")
4802                 }
4803 
4804                 // Filter out other platform-specific classes
4805                 if (targetProperties.containsKey('jfxrtJarExcludes')) {
4806                     exclude(targetProperties.jfxrtJarExcludes)
4807                 }
4808 
4809                 /* FIXME: JIGSAW -- handle this in the module itself
4810                 String webbld = project(":web").buildDir.path
4811                 String ctrlbld = project(":controls").buildDir.path
4812                 if (t.name == 'android') {
4813                     from ("${webbld}/classes/android",
4814                           "${webbld}/resources/android",
4815                           "${ctrlbld}/classes/android",
4816                           "${ctrlbld}/resources/android")
4817                 } else if (t.name == 'ios') {
4818                     from ("${webbld}/classes/ios",
4819                           "${webbld}/resources/ios")
4820                 } else {
4821                     from ("${webbld}/classes/java/main")
4822                 }
4823                 */
4824         }
4825         buildModulesTask.dependsOn(buildModuleClassesTask)
4826     }
4827 
4828     def buildModuleLibsTask = task("buildModuleLibs$t.capital") {
4829         group = "Basic"
4830 
4831         def baseProject = project(":base");
4832 
4833         def graphicsProject = project(":graphics");
4834 
4835         def mediaProject = project(":media");
4836 
4837         def webProject = project(":web");
4838         dependsOn(webProject.assemble)
4839 
4840         def swtProject = project(":swt");
4841 
4842         def library = targetProperties.library
4843 
4844         def useLipo = targetProperties.containsKey('useLipo') ? targetProperties.useLipo : false
4845         def modLibDest = targetProperties.modLibDest
4846         def moduleNativeDirName = "${platformPrefix}module-$modLibDest"
4847 
4848         def buildModuleBaseTask = task("buildModuleBase$t.capital", dependsOn: baseProject.assemble) {
4849             group = "Basic"
4850             description = "creates javafx.base property files"
4851 
4852             def moduleLibDir = "${baseProject.buildDir}/${platformPrefix}module-lib"
4853             final File javafxProperties = file("${moduleLibDir}/javafx.properties")
4854             outputs.file(javafxProperties)
4855 
4856             if (targetProperties.containsKey("javafxPlatformProperties")) {
4857                 final File javafxPlatformProperties = file("${moduleLibDir}/javafx.platform.properties")
4858                 outputs.file(javafxPlatformProperties)
4859             }
4860 
4861             doLast {
4862                 mkdir moduleLibDir
4863 
4864                 javafxProperties.delete()
4865                 javafxProperties << "javafx.version=$RELEASE_VERSION_SHORT";
4866                 javafxProperties << "\n"
4867                 javafxProperties << "javafx.runtime.version=$RELEASE_VERSION_LONG";
4868                 javafxProperties << "\n"
4869                 javafxProperties << "javafx.runtime.build=$PROMOTED_BUILD_NUMBER";
4870                 javafxProperties << "\n"
4871                 // Include any properties that have been defined (most likely in
4872                 // one of the various platform gradle files)
4873                 if (targetProperties.containsKey("javafxProperties")) {
4874                     javafxProperties << targetProperties.javafxProperties
4875                     javafxProperties << "\n"
4876                 }
4877 
4878                 // Embedded builds define this file as well
4879                 if (targetProperties.containsKey("javafxPlatformProperties")) {
4880                     final File javafxPlatformProperties = file("${moduleLibDir}/javafx.platform.properties")
4881                     javafxPlatformProperties.delete()
4882                     javafxPlatformProperties << targetProperties.javafxPlatformProperties
4883                     javafxPlatformProperties << "\n"
4884                 }
4885             }
4886         }
4887 
4888         def buildModuleGraphicsTask = task("buildModuleGraphics$t.capital", type: Copy, dependsOn: graphicsProject.assemble) {
4889             group = "Basic"
4890             description = "copies javafx.graphics native libraries"
4891 
4892             into "${graphicsProject.buildDir}/${moduleNativeDirName}"
4893 
4894             from("${graphicsProject.buildDir}/libs/jsl-decora/${t.name}/${library(targetProperties.decora.lib)}")
4895             def libs = ['font', 'prism', 'prismSW', 'glass', 'iio']
4896             if (IS_INCLUDE_ES2) {
4897                 libs += ['prismES2'];
4898             }
4899             if (IS_COMPILE_PANGO) {
4900                 libs += ['fontFreetype', 'fontPango'];
4901             }
4902             libs.each { lib ->
4903                 def variants = targetProperties[lib].containsKey('variants') && !useLipo ? targetProperties[lib].variants : [null]
4904                 variants.each { variant ->
4905                     def variantProperties = variant ? targetProperties[lib][variant] : targetProperties[lib]
4906                     from ("${graphicsProject.buildDir}/libs/$lib/$t.name/${library(variantProperties.lib)}")
4907                 }
4908             }
4909             if (IS_WINDOWS) {
4910                 from ("${graphicsProject.buildDir}/libs/prismD3D/${t.name}/${library(targetProperties.prismD3D.lib)}");
4911                 targetProperties.VS2017DLLs.each { vslib ->
4912                     from ("$vslib");
4913                 }
4914                 targetProperties.WinSDKDLLs.each { winsdklib ->
4915                     from ("$winsdklib");
4916                 }
4917             }
4918         }
4919 
4920         def buildModuleMediaTask = task("buildModuleMedia$t.capital", type: Copy, dependsOn: mediaProject.assemble) {
4921             group = "Basic"
4922             description = "copies javafx.media native libraries"
4923 
4924             into "${mediaProject.buildDir}/${moduleNativeDirName}"
4925 
4926             def mediaBuildType = project(":media").ext.buildType
4927             if (IS_COMPILE_MEDIA) {
4928                 [ "fxplugins", "gstreamer-lite", "jfxmedia" ].each { name ->
4929                     from ("${mediaProject.buildDir}/native/${t.name}/${mediaBuildType}/${library(name)}") }
4930 
4931                 if (t.name == "mac") {
4932                     // OSX media natives
4933                     [ "jfxmedia_qtkit", "jfxmedia_avf", "glib-lite" ].each { name ->
4934                         from ("${mediaProject.buildDir}/native/${t.name}/${mediaBuildType}/${library(name)}") }
4935                 } else if (t.name == "linux") {
4936                     from("${mediaProject.buildDir}/native/${t.name}/${mediaBuildType}") { include "libavplugin*.so" }
4937                 } else from ("${mediaProject.buildDir}/native/${t.name}/${mediaBuildType}/${library("glib-lite")}")
4938             } else {
4939                 if (t.name != "android"  && t.name != "dalvik" ) {
4940                     [ "fxplugins", "gstreamer-lite", "jfxmedia" ].each { name ->
4941                         from ("$MEDIA_STUB/${library(name)}") }
4942                 }
4943 
4944                 if (t.name == "mac") {
4945                     // copy libjfxmedia_{avf,qtkit}.dylib if they exist
4946                     [ "jfxmedia_qtkit", "jfxmedia_avf", "glib-lite" ].each { name ->
4947                         from ("$MEDIA_STUB/${library(name)}") }
4948                 } else if (t.name == "linux") {
4949                     from(MEDIA_STUB) { include "libavplugin*.so" }
4950                 }
4951                 else if (t.name != "android"  && t.name != "dalvik" ) {
4952                     from ("$MEDIA_STUB/${library("glib-lite")}")
4953                 }
4954             }
4955         }
4956 
4957         def buildModuleWeb = task("buildModuleWeb$t.capital", type: Copy, dependsOn: webProject.assemble) {
4958             group = "Basic"
4959             description = "copies javafx.web native libraries"
4960 
4961             into "${webProject.buildDir}/${moduleNativeDirName}"
4962 
4963             if (IS_COMPILE_WEBKIT) {
4964                 from ("${webProject.buildDir}/libs/${t.name}/${library('jfxwebkit')}")
4965             } else {
4966                 if (t.name != "android" && t.name != "ios" && t.name != "dalvik") {
4967                     from ("$WEB_STUB/${library('jfxwebkit')}")
4968                 }
4969             }
4970         }
4971 
4972         def buildModuleSWT = task("buildModuleSWT$t.capital", type: Copy) {
4973             group = "Basic"
4974             description = "copies SWT JAR"
4975 
4976             // FIXME: the following is a hack to workaround the fact that there
4977             // is no way to deliver javafx-swt.jar other than in one of the
4978             // existing runtime modules.
4979 
4980             dependsOn(buildModuleGraphicsTask) // we copy to the graphics module
4981 
4982             if (COMPILE_SWT) {
4983                 def javafxSwtIndexTask = tasks.getByName("javafxSwtIndex${t.capital}");
4984                 dependsOn(javafxSwtIndexTask)
4985                 //enabled = COMPILE_SWT
4986             }
4987 
4988             // Copy javafx-swt.jar to the javafx-graphics module lib dir
4989             from "${swtProject.buildDir}/libs/javafx-swt.jar"
4990             into "${graphicsProject.buildDir}/${platformPrefix}module-lib"
4991         }
4992 
4993         dependsOn(
4994             buildModuleBaseTask,
4995             buildModuleGraphicsTask,
4996             buildModuleMediaTask,
4997             buildModuleWeb,
4998             buildModuleSWT,
4999             )
5000     }
5001     buildModulesTask.dependsOn(buildModuleLibsTask)
5002 
5003     def zipTask = project.task("buildModuleZip$t.capital", type: Zip, group: "Build",
5004             dependsOn: buildModulesTask ) {
5005 
5006         // FIXME: JIGSAW -- this should be moved to a sub-directory so we can keep the same name
5007         def jfxBundle = "${platformPrefix}javafx-exports.zip"
5008 
5009         doFirst() {
5010             file("${rootProject.buildDir}/${jfxBundle}").delete()
5011         }
5012 
5013         archiveName = jfxBundle
5014         destinationDir = file("${rootProject.buildDir}")
5015         includeEmptyDirs = false
5016         from "${bundledSdkDir}"
5017     }
5018     jdkZip.dependsOn(zipTask)
5019 
5020     Task testArgFiles = task("createTestArgfiles${t.capital}") {
5021 
5022         File testRunArgsFile = new File(rootProject.buildDir, TESTRUNARGSFILE)
5023         //test (shimed) version
5024         File testCompileArgsFile = new File(rootProject.buildDir, TESTCOMPILEARGSFILE)
5025         // And a test java.policy file
5026         File testJavaPolicyFile = new File(rootProject.buildDir, TESTJAVAPOLICYFILE)
5027         // and the non-test version to go with run.args
5028         File runJavaPolicyFile = new File(rootProject.buildDir, RUNJAVAPOLICYFILE);
5029 
5030         outputs.file(testRunArgsFile)
5031         outputs.file(testCompileArgsFile)
5032         outputs.file(testJavaPolicyFile)
5033         outputs.file(runJavaPolicyFile)
5034         inputs.file(EXTRAADDEXPORTS);
5035 
5036         doLast() {
5037             rootProject.buildDir.mkdir()
5038 
5039             List<String> projNames = []
5040             moduleProjList.each { project ->
5041                 projNames << project.name
5042             }
5043 
5044             // And the test (shimed) variation...
5045 
5046             testRunArgsFile.delete()
5047             testCompileArgsFile.delete()
5048 
5049             testJavaPolicyFile.delete()
5050             runJavaPolicyFile.delete()
5051 
5052             List<String> modpath = []
5053 
5054             if (HAS_JAVAFX_MODULES) {
5055                 moduleProjList.each { project ->
5056                     if (project.hasProperty("moduleName") && project.buildModule) {
5057                         File dir;
5058                         if (project.sourceSets.hasProperty('shims')) {
5059                            dir = new File(rootProject.buildDir, "shims/${project.ext.moduleName}")
5060                         } else {
5061                            dir = new File(rootProject.buildDir, "modular-sdk/modules/${project.ext.moduleName}")
5062                         }
5063 
5064                         def dstModuleDir = cygpath(dir.path)
5065                         modpath << "${project.ext.moduleName}=${dstModuleDir}"
5066 
5067                         String themod = dir.toURI()
5068                         testJavaPolicyFile <<  "grant codeBase \"${themod}\" {\n" +
5069                         "    permission java.security.AllPermission;\n" +
5070                         "};\n"
5071 
5072                         dir = new File(rootProject.buildDir, "modular-sdk/modules/${project.ext.moduleName}")
5073                         themod = dir.toURI()
5074                         runJavaPolicyFile <<  "grant codeBase \"${themod}\" {\n" +
5075                         "    permission java.security.AllPermission;\n" +
5076                         "};\n"
5077                     }
5078                 }
5079 
5080                 writeRunArgsFile(testCompileArgsFile, null, modpath, null)
5081                 writeRunArgsFile(testRunArgsFile, computeLibraryPath(true), modpath, null)
5082 
5083                 if (rootProject.hasProperty("EXTRA_ADDEXPORTS_STRING")) {
5084                     testCompileArgsFile << EXTRA_ADDEXPORTS_STRING
5085                     testRunArgsFile << EXTRA_ADDEXPORTS_STRING
5086                 }
5087             } else  {
5088                 def modnames = []
5089                 moduleProjList.each { project ->
5090                     if (project.hasProperty("moduleName") && project.buildModule) {
5091                         modnames << project.ext.moduleName
5092                         File dir;
5093                         if (project.sourceSets.hasProperty('shims')) {
5094                            dir = new File(rootProject.buildDir, "shims/${project.ext.moduleName}")
5095                         } else {
5096                            dir = new File(rootProject.buildDir, "sdk/lib/${project.ext.moduleName}.jar")
5097                         }
5098 
5099                         def dstModuleDir = cygpath(dir.path)
5100                         modpath << "${dstModuleDir}"
5101 
5102                         String themod = dir.toURI()
5103                         testJavaPolicyFile <<  "grant codeBase \"${themod}\" {\n" +
5104                         "    permission java.security.AllPermission;\n" +
5105                         "};\n"
5106 
5107                         dir = new File(rootProject.buildDir, "sdk/lib/${project.ext.moduleName}.jar")
5108                         themod = dir.toURI()
5109                         runJavaPolicyFile <<  "grant codeBase \"${themod}\" {\n" +
5110                         "    permission java.security.AllPermission;\n" +
5111                         "};\n"
5112                     }
5113                 }
5114 
5115                 writeRunArgsFile(testCompileArgsFile, null, modpath, modnames)
5116                 writeRunArgsFile(testRunArgsFile, computeLibraryPath(true), modpath, modnames)
5117 
5118             }
5119         }
5120     }
5121     sdk.dependsOn(testArgFiles)
5122     createTestArgfiles.dependsOn(testArgFiles)
5123 
5124     def sdkTask = tasks.getByName("sdk${t.capital}");
5125     sdkTask.dependsOn(buildModulesTask)
5126 }
5127 sdk.dependsOn(buildModules)
5128 
5129 // Build the jmod for each module for the standalone SDK only.
5130 compileTargets { t ->
5131     if (!HAS_JAVAFX_MODULES) {
5132         def targetProperties = project.ext[t.upper]
5133 
5134         def platformPrefix = targetProperties.platformPrefix
5135         def jmodsDirName = "${platformPrefix}jmods"
5136         def jmodsDir = "${rootProject.buildDir}/${jmodsDirName}"
5137         def standaloneSdkDirName = "${platformPrefix}sdk"
5138         def standaloneSdkDir = "${rootProject.buildDir}/${standaloneSdkDirName}"
5139         def standaloneLegalDir = "${standaloneSdkDir}/legal"
5140 
5141         def excludeNativeLibs = []
5142         if (IS_WINDOWS) {
5143             // List of duplicate Microsoft DLLs to exclude
5144             excludeNativeLibs += targetProperties.VS2017DLLNames
5145             excludeNativeLibs += targetProperties.WinSDKDLLNames
5146         }
5147 
5148         moduleProjList.each { project ->
5149             def moduleName = project.ext.moduleName
5150             def buildDir = project.buildDir
5151 
5152             def srcClassesDir = "${buildDir}/${platformPrefix}module-classes"
5153             def srcLibDir = "${buildDir}/${platformPrefix}module-lib"
5154             def srcLegalDir = "${standaloneLegalDir}/${moduleName}"
5155 
5156             def jmodName = "${moduleName}.jmod"
5157             def jmodFile = "${jmodsDir}/${jmodName}"
5158             def jmodTask = project.task("jmod$t.capital", group: "Build", dependsOn: sdk) {
5159                 doLast {
5160                     mkdir jmodsDir
5161                     delete(jmodFile);
5162                     exec {
5163                         commandLine(JMOD)
5164                         args("create")
5165                         args("--class-path")
5166                         args(srcClassesDir)
5167                         // Not all modules have a "lib" dir
5168                         if (file(srcLibDir).isDirectory()) {
5169                             args("--libs")
5170                             args(srcLibDir)
5171                         }
5172                         // Exclude duplicate native libs from javafx.graphics.jmod
5173                         if (moduleName == "javafx.graphics") {
5174                             excludeNativeLibs.each { name ->
5175                                 args("--exclude")
5176                                 args(name)
5177                             }
5178                         }
5179                         args("--legal-notices")
5180                         args(srcLegalDir)
5181                         args(jmodFile)
5182                     }
5183                 }
5184             }
5185 
5186             jmods.dependsOn(jmodTask)
5187         }
5188     }
5189 }
5190 
5191 /******************************************************************************
5192  *                                                                            *
5193  *                              BUILD_CLOSED                                  *
5194  *                                                                            *
5195  * This next section should remain at the end of the build script. It allows  *
5196  * for a "supplemental" gradle file to be used to extend the normal build     *
5197  * structure. For example, this is used for passing a supplemental gradle     *
5198  * file for producing official JavaFX builds.                                 *
5199  *                                                                            *
5200  *****************************************************************************/
5201 
5202 if (BUILD_CLOSED) {
5203     apply from: supplementalBuildFile
5204 }
5205 
5206 task showFlags {
5207 }
5208 
5209 compileTargets { t ->
5210     // Every platform must define these variables
5211     def props = project.ext[t.upper];
5212     showFlags.dependsOn(
5213         project.task("showFlags$t.upper") {
5214             doLast() {
5215                 println "Properties set for $t.upper"
5216                 props.each { println it }
5217             }
5218         }
5219     )
5220 
5221 }