1 /*
   2  * Copyright (c) 2013, 2014, 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  *          - is jfxrt.jar there?
  35  *          - does jfxrt.jar contain stuff it shouldn't (doc-files, iml, etc)
  36  *          - does jfxrt.jar contain stuff it should (bss files, etc)
  37  *  - Perform sanity checking to make sure a JDK exists with javac, javah, etc
  38  *  - Support building with no known JDK location, as long as javac, javah, etc are on the path
  39  *  - Check all of the native flags. We're adding weight to some libs that don't need it, and so forth.
  40  *
  41  * Additional projects to work on as we go:
  42  *  - Add "developer debug". This is where the natives do not have debug symbols, but the Java code does
  43  *  - The genVSproperties.bat doesn't find the directory where RC.exe lives. So it is hard coded. Might be a problem.
  44  *  - special tasks for common needs, such as:
  45  *      - updating copyright headers
  46  *      - stripping trailing whitespace (?)
  47  *  - checkstyle
  48  *  - findbugs
  49  *  - re needs?
  50  *  - sqe testing
  51  *  - API change check
  52  *  - Pushing results to a repo?
  53  *  - ServiceWithSecurityManagerTest fails to complete when run from gradle.
  54  *  - Integrate Parfait reports for C code
  55  *  - FXML Project tests are not running
  56  */
  57 defaultTasks = ["sdk"]
  58 
  59 import java.util.concurrent.CountDownLatch
  60 import java.util.concurrent.ExecutorService
  61 import java.util.concurrent.Executors
  62 import java.util.concurrent.Future
  63 
  64 /******************************************************************************
  65  *                              Utility methods                               *
  66  *****************************************************************************/
  67 
  68 /**
  69  * If the given named property is not defined, then this method will define
  70  * it with the given defaultValue. Any properties defined by this method can
  71  * be substituted on the command line by using -P, or by specifying a
  72  * gradle.properties file in the user home dir
  73  *
  74  * @param name The name of the property to define
  75  * @param defaultValue The default value to assign the property
  76  */
  77 void defineProperty(String name, String defaultValue) {
  78     if (!project.hasProperty(name)) {
  79         project.ext.set(name, defaultValue);
  80     }
  81 }
  82 
  83 /**
  84  * If the given named property is not defined, then this method will attempt to
  85  * look up the property in the props map, and use the defaultValue if it cannot be found.
  86  *
  87  * @param name The name of the property to look up and/or define
  88  * @param props The properties to look for the named property in, if it has not already been defined
  89  * @param defaultValue The default value if the property has not been defined and the
  90  *                     props map does not contain the named property
  91  */
  92 void defineProperty(String name, Properties props, String defaultValue) {
  93     if (!project.hasProperty(name)) {
  94         project.ext.set(name, props.getProperty(name, defaultValue));
  95     }
  96 }
  97 
  98 /**
  99  * Converts cygwin style paths to windows style paths, but with a forward slash.
 100  * This method is safe to call from any platform, and will only do work if
 101  * called on Windows (in all other cases it simply returns the supplied path.
 102  * In the future I would like to modify this so that it only does work if
 103  * cygwin is installed, as I hope one day to remove the requirement to build
 104  * with cygwin, but at present (due to GStreamer / Webkit) cygwin is needed
 105  * anyway.
 106  * 
 107  * @param path the path to convert
 108  * @return the path converted to windows style, if on windows, otherwise it
 109  *         is the supplied path.
 110  */
 111 String cygpath(String path) {
 112     if (!IS_WINDOWS) return path;
 113     if (path == null || "".equals(path)) return path;
 114     ByteArrayOutputStream out = new ByteArrayOutputStream();
 115     logger.info("Converting path '$path' via cygpath")
 116     exec {
 117         standardOutput = out
 118         commandLine "cmd", "/c", "cygpath", "-m", path
 119     }
 120     return out.toString().trim();
 121 }
 122 
 123 void loadProperties(String sourceFileName) {
 124     def config = new Properties()
 125     def propFile = new File(sourceFileName)
 126     if (propFile.canRead()) {
 127         config.load(new FileInputStream(propFile))
 128         for (Map.Entry property in config) {
 129             def keySplit = property.key.split("\\.");
 130             def key = keySplit[0];
 131             for (int i = 1; i < keySplit.length; i++) {
 132                 key = key + keySplit[i].capitalize();
 133             }
 134             ext[key] = property.value;
 135         }
 136     }
 137 }
 138 
 139 /**
 140  * Struct used to contain some information passed to the closure
 141  * passed to compileTargets.
 142  */
 143 class CompileTarget {
 144     String name;
 145     String upper;
 146     String capital;
 147 }
 148 
 149 /**
 150  * Iterates over each of the compile targets, passing the given closure
 151  * a CompileTarget instance.
 152  * 
 153  * @param c The closure to call
 154  */
 155 void compileTargets(Closure c) {
 156     if (COMPILE_TARGETS == "") {
 157         return
 158     }
 159     COMPILE_TARGETS.split(",").each { target ->
 160         CompileTarget ct = new CompileTarget();
 161         ct.name = target;
 162         ct.upper = target.trim().toUpperCase(Locale.ROOT)
 163         ct.capital = target.trim().capitalize()
 164         c(ct)
 165     }
 166 }
 167 
 168 /**
 169  * Manages the execution of some closure which is responsible for producing
 170  * content for a properties file built at build time and stored in the
 171  * root project's $buildDir, and then loading that properties file and
 172  * passing it to the processor closure.
 173  * 
 174  * This is used on windows to produce a properties file containing all the
 175  * windows visual studio paths and environment variables, and on Linux
 176  * for storing the results of pkg-config calls.
 177  * 
 178  * @param name the name of the file to produce
 179  * @param loader a closure which is invoked, given the properties file. This
 180  *        closure is invoked only if the properties file needs to be created
 181  *        and is responsible for populating the properties file.
 182  * @param processor a closure which is invoked every time this method is
 183  *        called and which will be given a Properties object, fully populated.
 184  *        The processor is then responsible for doing whatever it is that it
 185  *        must do with those properties (such as setting up environment
 186  *        variables used in subsequent native builds, or whatnot).
 187  */
 188 void setupTools(String name, Closure loader, Closure processor) {
 189     // Check to see whether $buildDir/$name.properties file exists. If not,
 190     // then generate it. Once generated, we need to read the properties file to
 191     // help us define the defaults for this block of properties
 192     File propFile = file("$buildDir/${name}.properties");
 193     if (!propFile.exists()) {
 194         // Create the properties file
 195         propFile.getParentFile().mkdirs();
 196         propFile.createNewFile();
 197         loader(propFile);
 198     }
 199 
 200     // Try reading the properties in order to define the properties. If the property file cannot
 201     // be located, then we will throw an exception because we cannot guess these values
 202     InputStream propStream = null;
 203     try {
 204         Properties properties = new Properties();
 205         propStream = new FileInputStream(propFile);
 206         properties.load(propStream);
 207         processor(properties);
 208     } finally {
 209         try { propStream.close() } catch (Exception e) { }
 210     }
 211 }
 212 
 213 /**
 214  * Fails the build with the specified error message
 215  *
 216  * @param msg the reason for the failure
 217  */
 218 void fail(String msg) {
 219     throw new GradleException("FAIL: " + msg);
 220 }
 221 
 222 /******************************************************************************
 223  *                                                                            *
 224  *                   Definition of project properties                         *
 225  *                                                                            *
 226  *  All properties defined using ext. are immediately available throughout    *
 227  *  the script as variables that can be used. These variables are attached    *
 228  *  to the root project (whereas if they were defined as def variables then   *
 229  *  they would only be available within the root project scope).              *
 230  *                                                                            *
 231  *  All properties defined using the "defineProperty" method can be replaced  *
 232  *  on the command line by using the -P flag. For example, to override the    *
 233  *  location of the binary plug, you would specify -PBINARY_PLUG=some/where   *
 234  *                                                                            *
 235  *****************************************************************************/
 236 
 237 // If the ../rt-closed directory exists, then we are doing a closed build.
 238 // In this case, build and property files will be read from
 239 // ../rt-closed/closed-build.gradle and ../rt-closed/closed-properties.gradle
 240 // respectively
 241 
 242 def closedDir = file("../rt-closed")
 243 def buildClosed = closedDir.isDirectory()
 244 ext.BUILD_CLOSED = buildClosed
 245 
 246 // These variables indicate what platform is running the build. Is
 247 // this build running on a Mac, Windows, or Linux machine? 32 or 64 bit?
 248 ext.OS_NAME = System.getProperty("os.name").toLowerCase()
 249 ext.OS_ARCH = System.getProperty("os.arch")
 250 ext.IS_64 = OS_ARCH.toLowerCase().contains("64")
 251 ext.IS_MAC = OS_NAME.contains("mac") || OS_NAME.contains("darwin")
 252 ext.IS_WINDOWS = OS_NAME.contains("windows")
 253 ext.IS_LINUX = OS_NAME.contains("linux")
 254 
 255 // Get the JDK_HOME automatically based on the version of Java used to execute gradle. Or, if specified,
 256 // use a user supplied JDK_HOME, STUB_RUNTIME, JAVAC, and/or JAVAH, all of which may be specified
 257 // independently (or we'll try to get the right one based on other supplied info). Sometimes the
 258 // JRE might be the thing that is being used instead of the JRE embedded in the JDK, such as:
 259 //    c:\Program Files (x86)\Java\jdk1.8.0\jre
 260 //    c:\Program Files (x86)\Java\jre8\
 261 // Because of this, you may sometimes get the jdk's JRE (in which case the logic we used to have here
 262 // was correct and consistent with all other platforms), or it might be the standalone JRE (for the love!).
 263 def envJavaHome = cygpath(System.getenv("JDK_HOME"))
 264 if (envJavaHome == null || envJavaHome.equals("")) envJavaHome = cygpath(System.getenv("JAVA_HOME"))
 265 def javaHome = envJavaHome == null || envJavaHome.equals("") ? System.getProperty("java.home") : envJavaHome
 266 def javaHomeFile = file(javaHome)
 267 defineProperty("JDK_HOME",
 268         javaHomeFile.name == "jre" ?
 269         javaHomeFile.getParent().toString() :
 270         javaHomeFile.name.startsWith("jre") ?
 271         new File(javaHomeFile.getParent(), "jdk1.${javaHomeFile.name.substring(3)}.0").toString() :
 272         javaHome) // we have to bail and set it to something and this is as good as any!
 273 ext.JAVA_HOME = JDK_HOME
 274 defineProperty("JAVA", cygpath("$JDK_HOME/bin/java${IS_WINDOWS ? '.exe' : ''}"))
 275 defineProperty("JAVAC", cygpath("$JDK_HOME/bin/javac${IS_WINDOWS ? '.exe' : ''}"))
 276 defineProperty("JAVAH", cygpath("$JDK_HOME/bin/javah${IS_WINDOWS ? '.exe' : ''}"))
 277 defineProperty("JAVADOC", cygpath("$JDK_HOME/bin/javadoc${IS_WINDOWS ? '.exe' : ''}"))
 278 defineProperty("JDK_DOCS", "http://docs.oracle.com/javase/8/docs/api/")
 279 
 280 defineProperty("javaRuntimeVersion", System.getProperty("java.runtime.version"))
 281 defineProperty("javaVersion", javaRuntimeVersion.split("-")[0])
 282 defineProperty("javaBuildNumber", javaRuntimeVersion.substring(javaRuntimeVersion.lastIndexOf("-b") + 2))
 283 
 284 loadProperties("$projectDir/build.properties")
 285 
 286 def String closedCacheStubRuntime = cygpath("$projectDir") + "/../caches/sdk/rt"
 287 defineProperty("STUB_RUNTIME", BUILD_CLOSED ? closedCacheStubRuntime : cygpath("$JDK_HOME/jre"))
 288 defineProperty("LIBRARY_STUB", IS_MAC ? "$STUB_RUNTIME/lib" :
 289                                IS_WINDOWS ? "$STUB_RUNTIME/bin" :
 290                                "$STUB_RUNTIME/lib/$OS_ARCH")
 291 defineProperty("UPDATE_STUB_CACHE", (STUB_RUNTIME.equals(closedCacheStubRuntime) ? 'true' : 'false'))
 292 
 293 def supplementalPreBuildFile = file("$closedDir/closed-pre-build.gradle");
 294 def supplementalBuildFile = file("$closedDir/closed-build.gradle");
 295 
 296 if (BUILD_CLOSED) {
 297     apply from: supplementalPreBuildFile
 298 }
 299 
 300 // GRADLE_VERSION_CHECK specifies whether to fail the build if the
 301 // gradle version check fails
 302 defineProperty("GRADLE_VERSION_CHECK", "true")
 303 ext.IS_GRADLE_VERSION_CHECK = Boolean.parseBoolean(GRADLE_VERSION_CHECK)
 304 
 305 // COMPILE_WEBKIT specifies whether to build all of webkit.
 306 defineProperty("COMPILE_WEBKIT", "false")
 307 ext.IS_COMPILE_WEBKIT = Boolean.parseBoolean(COMPILE_WEBKIT)
 308 
 309 // COMPILE_MEDIA specifies whether to build all of media.
 310 defineProperty("COMPILE_MEDIA", "false")
 311 ext.IS_COMPILE_MEDIA = Boolean.parseBoolean(COMPILE_MEDIA)
 312 
 313 // COMPILE_PANGO specifies whether to build javafx_font_pango.
 314 defineProperty("COMPILE_PANGO", "${IS_LINUX}")
 315 ext.IS_COMPILE_PANGO = Boolean.parseBoolean(COMPILE_PANGO)
 316 
 317 // COMPILE_HARFBUZZ specifies whether to use Harfbuzz.
 318 defineProperty("COMPILE_HARFBUZZ", "false")
 319 ext.IS_COMPILE_HARFBUZZ = Boolean.parseBoolean(COMPILE_HARFBUZZ)
 320 
 321 // COMPILE_PARFAIT specifies whether to build parfait
 322 defineProperty("COMPILE_PARFAIT", "false")
 323 ext.IS_COMPILE_PARFAIT = Boolean.parseBoolean(COMPILE_PARFAIT)
 324 
 325 // COMPILE_JFR specifies whether to build code that logs to JRockit Flight Recorder
 326 defineProperty("COMPILE_JFR", Boolean.toString(file("$JDK_HOME/jre/lib/jfr.jar").exists()))
 327 ext.IS_COMPILE_JFR = Boolean.parseBoolean(COMPILE_JFR)
 328 
 329 // RETAIN_PACKAGER_TESTS specifies whether the tests in fxpackager should
 330 // keep generated files instead of attempting to automatically delete them
 331 defineProperty("RETAIN_PACKAGER_TESTS", "false")
 332 ext.IS_RETAIN_PACKAGER_TESTS = Boolean.parseBoolean(RETAIN_PACKAGER_TESTS)
 333 
 334 // Define the SWT.jar that we are going to have to download during the build process based
 335 // on what platform we are compiling from (not based on our target).
 336 ext.SWT_FILE_NAME = IS_MAC ? "org.eclipse.swt.cocoa.macosx.x86_64_3.7.2.v3740f" :
 337     IS_WINDOWS && IS_64 ? "org.eclipse.swt.win32.win32.x86_64_3.7.2.v3740f" :
 338     IS_WINDOWS && !IS_64 ? "org.eclipse.swt.win32.win32.x86_3.7.2.v3740f" :
 339     IS_LINUX && IS_64 ? "org.eclipse.swt.gtk.linux.x86_64_3.7.2.v3740f" :
 340     IS_LINUX && !IS_64 ? "org.eclipse.swt.gtk.linux.x86_3.7.2.v3740f" : ""
 341 
 342 // Build javadocs only if BUILD_JAVADOC=true
 343 defineProperty("BUILD_JAVADOC", "false")
 344 ext.IS_BUILD_JAVADOC = Boolean.parseBoolean(BUILD_JAVADOC)
 345 
 346 // Specifies whether to build the javafx-src bundle
 347 defineProperty("BUILD_SRC_ZIP", "false")
 348 ext.IS_BUILD_SRC_ZIP = Boolean.parseBoolean(BUILD_SRC_ZIP)
 349 
 350 // Specifies whether to run full tests (true) or smoke tests (false)
 351 defineProperty("FULL_TEST", "false")
 352 ext.IS_FULL_TEST = Boolean.parseBoolean(FULL_TEST);
 353 
 354 // Specifies whether to run robot-based visual tests (only used when FULL_TEST is also enabled)
 355 defineProperty("USE_ROBOT", "false")
 356 ext.IS_USE_ROBOT = Boolean.parseBoolean(USE_ROBOT);
 357 
 358 // Specified whether to run tests in headless mode
 359 defineProperty("HEADLESS_TEST", "false")
 360 ext.IS_HEADLESS_TEST = Boolean.parseBoolean(HEADLESS_TEST);
 361 
 362 // Specifies whether to run system tests that depend on AWT (only used when FULL_TEST is also enabled)
 363 defineProperty("AWT_TEST", "true")
 364 ext.IS_AWT_TEST = Boolean.parseBoolean(AWT_TEST);
 365 
 366 // Specify the build configuration (Release, Debug, or DebugNative)
 367 defineProperty("CONF", "Debug")
 368 ext.IS_DEBUG_JAVA = CONF == "Debug" || CONF == "DebugNative"
 369 ext.IS_DEBUG_NATIVE = CONF == "DebugNative"
 370 
 371 // Defines the compiler warning levels to use. If empty, then no warnings are generated. If
 372 // not empty, then the expected syntax is as a space or comma separated list of names, such
 373 // as defined in the javac documentation.
 374 defineProperty("LINT", "none")
 375 ext.IS_LINT = LINT != "none"
 376 
 377 defineProperty("DOC_LINT", "none")
 378 ext.IS_DOC_LINT = DOC_LINT != "none"
 379 
 380 // Specifies whether to use the "useDepend" option when compiling Java sources
 381 defineProperty("USE_DEPEND", "true")
 382 ext.IS_USE_DEPEND = Boolean.parseBoolean(USE_DEPEND)
 383 
 384 // Specifies whether to generate code coverage statistics when running tests
 385 defineProperty("JCOV", "false")
 386 ext.DO_JCOV = Boolean.parseBoolean(JCOV)
 387 
 388 // Define the number of threads to use when compiling (specifically for native compilation)
 389 // On Mac we limit it to 1 by default due to problems running gcc in parallel
 390 if (IS_MAC) {
 391     defineProperty("NUM_COMPILE_THREADS", "1")
 392 } else {
 393     defineProperty("NUM_COMPILE_THREADS", "${Runtime.runtime.availableProcessors()}")
 394 }
 395 
 396 //
 397 // The next three sections of properties are used to generate the
 398 // VersionInfo class, and the Windows DLL manifest.
 399 //
 400 
 401 // The following properties should be left alone by developers and set only from Hudson.
 402 defineProperty("HUDSON_JOB_NAME", "not_hudson")
 403 defineProperty("HUDSON_BUILD_NUMBER","0000")
 404 defineProperty("PROMOTED_BUILD_NUMBER", "00")
 405 
 406 // The following properties define the product name for Oracle JDK and OpenJDK
 407 // for VersionInfo and the DLL manifest.
 408 if (BUILD_CLOSED) {
 409     defineProperty("PRODUCT_NAME", "Java(TM)")
 410     defineProperty("COMPANY_NAME", "Oracle Corporation")
 411     defineProperty("PLATFORM_NAME", "Platform SE")
 412 } else {
 413     defineProperty("PRODUCT_NAME", "OpenJFX")
 414     defineProperty("COMPANY_NAME", "N/A")
 415     defineProperty("PLATFORM_NAME", "Platform")
 416 }
 417 
 418 // The following properties are set based on properties defined in
 419 // build.properties. The release number or milestone number should be updated
 420 // in that file.
 421 def jfxReleaseVersion = "${jfxReleaseMajorVersion}.${jfxReleaseMinorVersion}.${jfxReleaseMicroVersion}"
 422 defineProperty("RAW_VERSION", jfxReleaseVersion)
 423 defineProperty("RELEASE_NAME", jfxReleaseName)
 424 defineProperty("RELEASE_MILESTONE", jfxReleaseMilestone)
 425 
 426 // Check whether the COMPILE_TARGETS property has been specified (if so, it was done by
 427 // the user and not by this script). If it has not been defined then default
 428 // to building the normal desktop build for this machine
 429 project.ext.set("defaultHostTarget", IS_MAC ? "mac" : IS_WINDOWS ? "win" : IS_LINUX ? "linux" : "");
 430 defineProperty("COMPILE_TARGETS", "$defaultHostTarget")
 431 
 432 // Flag indicating whether to import cross compile tools
 433 def importCrossTools = BUILD_CLOSED ? true : false;
 434 if (!importCrossTools && hasProperty("IMPORT_CROSS_TOOLS")) {
 435     importCrossTools = Boolean.parseBoolean(IMPORT_CROSS_TOOLS);
 436 }
 437 ext.IS_IMPORT_CROSS_TOOLS = importCrossTools
 438 
 439 // Location of the cross compile tools
 440 def crossToolsDir = "../crosslibs" 
 441 if (hasProperty("CROSS_TOOLS_DIR")) {
 442     crossToolsDir = CROSS_TOOLS_DIR
 443 }
 444 ext.CROSS_TOOLS_DIR = file(crossToolsDir)
 445 
 446 /**
 447  * Fetch/Check that external tools are present for the build. This method
 448  * will conditionally download the packages from project defined ivy repositories
 449  * and unpack them into the specified destdir
 450  *
 451  * @param configName A unique name to distinguish the configuration (ie "ARMSFV6")
 452  * @param packages A list of required packages (with extensions .tgz, .zip)
 453  * @param destdir where the packages should be unpacked
 454  * @param doFetch if true, the named packages will be download
 455  */
 456 void fetchExternalTools(String configName, List packages, File destdir, boolean doFetch) {
 457     if (doFetch) {
 458         // create a unique configuration for this fetch
 459         def String fetchToolsConfig = "fetchTools$configName"
 460         rootProject.configurations.create(fetchToolsConfig)
 461 
 462         def List<String> fetchedPackages = []
 463         def int fetchCount = 0
 464 
 465         packages.each { pkgname->
 466             def int dotdex = pkgname.lastIndexOf('.')
 467             def int dashdex = pkgname.lastIndexOf('-')
 468             def String basename = pkgname.substring(0,dashdex)
 469             def String ver = pkgname.substring(dashdex+1,dotdex)
 470             def String ext = pkgname.substring(dotdex+1)
 471             def File pkgdir = file("$destdir/$basename-$ver")
 472 
 473             if (!pkgdir.isDirectory()) {
 474                 rootProject.dependencies.add(fetchToolsConfig, "javafx:$basename:$ver", {
 475                     artifact {
 476                         name = basename
 477                         version = ver
 478                         type = ext
 479                     }
 480                 })
 481                 println "adding $pkgname as a downloadable item did not find $pkgdir"
 482                 fetchedPackages.add(pkgname)
 483                 fetchCount++
 484             }
 485         }
 486 
 487         //fetch all the missing packages
 488         if (fetchedPackages.size > 0) {
 489             destdir.mkdirs()
 490 
 491             logger.quiet "fetching missing packages $fetchedPackages"
 492             copy {
 493                 from rootProject.configurations[fetchToolsConfig]
 494                 into destdir
 495             }
 496 
 497             // unpack the fetched packages
 498             fetchedPackages.each { pkgname->
 499                 logger.quiet "expanding the package $pkgname"
 500                 def srcball = file("${destdir}/${pkgname}")
 501 
 502                 if (!srcball.exists()) {
 503                     throw new GradleException("Failed to fetch $pkgname");
 504                 }
 505 
 506                 def String basename = pkgname.substring(0,pkgname.lastIndexOf("."))
 507                 def File pkgdir = file("$destdir/$basename")
 508 
 509                 if (pkgname.endsWith(".tgz")) {
 510                     if (IS_LINUX || IS_MAC) {
 511                         // use native tar to support symlinks
 512                         pkgdir.mkdirs()
 513                         exec {
 514                             workingDir pkgdir
 515                             commandLine "tar", "zxf", "${srcball}"
 516                          }
 517                     } else {
 518                         copy {
 519                             from tarTree(resources.gzip("${srcball}"))
 520                             into pkgdir
 521                         }
 522                     }
 523                 } else if (pkgname.endsWith(".zip")) {
 524                      copy {
 525                          from zipTree("${srcball}")
 526                          into pkgdir
 527                      }
 528                 } else {
 529                     throw new GradleException("Unhandled pacakge type for compile package ${pkgname}")
 530                 }
 531                 srcball.deleteOnExit();
 532             }
 533         } else {
 534             logger.quiet "all tool packages are present $packages"
 535         }
 536     } else { // !doFetch - so just check they are present
 537         // check that all the dirs are really there
 538         def List<String> errors = []
 539         packages.each { pkgname->
 540             def String basename = pkgname.substring(0,pkgname.lastIndexOf("."))
 541             def File pkgdir = file("$destdir/$basename")
 542 
 543             if (!pkgdir.isDirectory()) {
 544                 errors.add(pkgname)
 545             }
 546         }
 547         if (errors.size > 0) {
 548             throw new GradleException("Error: missing tool packages: $errors")
 549         } else {
 550             logger.quiet "all tool packages are present $packages"
 551         }
 552     }
 553 }
 554 
 555 // Now we need to define the native compilation tasks. The set of parameters to
 556 // native compilation depends on the target platform (and also to some extent what platform
 557 // you are compiling on). These settings are contained in various gradle files
 558 // such as mac.gradle and linux.gradle and armhf.gradle. Additionally, the developer
 559 // can specify COMPILE_FLAGS_FILE to be a URL or path to a different gradle file
 560 // that will contain the appropriate flags.
 561 defineProperty("COMPILE_FLAGS_FILES", COMPILE_TARGETS.split(",").collect {"buildSrc/${it.trim()}.gradle"}.join(","))
 562 if (COMPILE_TARGETS == "all") {
 563     def tmp = []
 564     File buildSrcDir = file("buildSrc")
 565     buildSrcDir.listFiles().each { File f ->
 566         if (f.isFile() && f.name.endsWith(".gradle") && !f.name.equals("build.gradle")) {
 567             def target = f.name.substring(0, f.name.lastIndexOf('.gradle')).toUpperCase(Locale.ROOT)
 568             apply from: f
 569             if (project.ext["${target}"].canBuild) {
 570                 tmp.add(target)
 571             }
 572         }
 573     }
 574     COMPILE_FLAGS_FILES = tmp.collect { "buildSrc/${it}.gradle"}.join(",")
 575     COMPILE_TARGETS = tmp.collect { "${it.toLowerCase()}"}.join(",")
 576 } else {
 577     COMPILE_FLAGS_FILES.split(",").each {
 578         logger.info("Applying COMPILE_FLAGS_FILE '$it'")
 579         apply from: it
 580     }
 581 }
 582 
 583 if (COMPILE_TARGETS != "") {
 584     def tmp = []
 585     COMPILE_TARGETS.split(",").each {target ->
 586         if (project.ext["${target.toUpperCase(Locale.ROOT)}"].canBuild) {
 587             tmp.add(target)
 588         }
 589     }
 590     COMPILE_TARGETS = tmp.collect { "${it.toLowerCase()}"}.join(",")
 591 }
 592 
 593 // Sanity check the expected properties all exist
 594 compileTargets { t ->
 595     // Every platform must define these variables
 596     if (!project.hasProperty(t.upper)) throw new Exception("ERROR: Incorrectly configured compile flags file, missing ${t.name} property")
 597     def props = project.ext[t.upper];
 598     ["compileSwing", "compileSWT", "compileFXPackager", "compileDesignTime", "libDest"].each { prop ->
 599         if (!props.containsKey(prop)) throw new Exception("ERROR: Incorrectly configured compile flags file, missing ${prop} property on ${t.name}")
 600     }
 601 }
 602 
 603 // Various build flags may be set by the different target files, such as
 604 // whether to build Swing, SWT, FXPackager, etc. We iterate over all
 605 // compile targets and look for these settings in our properties. Note that
 606 // these properties cannot be set from the command line, but are set by
 607 // the target build files such as armv6hf.gradle or mac.gradle.
 608 ext.COMPILE_SWING = false;
 609 ext.COMPILE_SWT = false;
 610 ext.COMPILE_FXPACKAGER = false;
 611 ext.COMPILE_DESIGN_TIME = false;
 612 compileTargets { t ->
 613     def targetProperties = project.rootProject.ext[t.upper]
 614 
 615     if (targetProperties.compileSwing) COMPILE_SWING = true
 616     if (targetProperties.compileSWT) COMPILE_SWT = true
 617     if (targetProperties.compileFXPackager) COMPILE_FXPACKAGER = true
 618     if (targetProperties.compileDesignTime) COMPILE_DESIGN_TIME = true
 619 
 620     if (!targetProperties.containsKey('compileWebnodeNative')) {
 621         // unless specified otherwise, we will compile native Webnode if IS_COMPILE_WEBKIT
 622         targetProperties.compileWebnodeNative = true
 623     }
 624 
 625     if (!targetProperties.containsKey('compileMediaNative')) {
 626         // unless specified otherwise, we will compile native Media if IS_COMPILE_MEDIA
 627         targetProperties.compileMediaNative = true
 628     }
 629 
 630     if (!targetProperties.containsKey('includeSWT')) targetProperties.includeSWT = true
 631     if (!targetProperties.containsKey('includeSwing')) targetProperties.includeSwing = true
 632     if (!targetProperties.containsKey('includeNull3d')) targetProperties.includeNull3d = true
 633     if (!targetProperties.containsKey('includeLens')) targetProperties.includeLens = false
 634     if (!targetProperties.containsKey('includeMonocle')) targetProperties.includeMonocle = false
 635     if (!targetProperties.containsKey('includeEGL')) targetProperties.includeEGL = false
 636 
 637     if (!targetProperties.containsKey('includeGTK')) targetProperties.includeGTK = IS_LINUX
 638 
 639     // This value is used to under ./build/${sdkDirName} to allow for
 640     // a common name for the hosted build (for use when building apps)
 641     // and a unique name for cross builds.
 642     if (rootProject.defaultHostTarget.equals(t.name)) { 
 643         // use a simple common default for the "host" build
 644         targetProperties.sdkDirName="sdk"
 645     } else {
 646         // and a more complex one for cross builds
 647         targetProperties.sdkDirName="${t.name}-sdk"
 648     }
 649 }
 650 
 651 /******************************************************************************
 652  *                                                                            *
 653  *                         Build Setup Sanity Checks                          *
 654  *                                                                            *
 655  *  Here we do a variety of checks so that if the version of Java you are     *
 656  *  building with is misconfigured, or you are using the wrong version of     *
 657  *  gradle, etc you will get some kind of helpful error / warning message     *
 658  *                                                                            *
 659  *****************************************************************************/
 660 
 661 // Verify that the architecture & OS are supported configurations. Note that
 662 // at present building on PI is not supported, but we would only need to make
 663 // some changes on assumptions on what should be built (like SWT / Swing) and
 664 // such and we could probably make it work.
 665 if (!IS_MAC && !IS_WINDOWS && !IS_LINUX) logger.error("Unsupported build OS ${OS_NAME}")
 666 if (IS_WINDOWS && OS_ARCH != "x86" && OS_ARCH != "amd64") {
 667     throw new Exception("Unknown and unsupported build architecture: $OS_ARCH")
 668 } else if (IS_MAC && OS_ARCH != "x86_64") {
 669     throw new Exception("Unknown and unsupported build architecture: $OS_ARCH")
 670 } else if (IS_LINUX && OS_ARCH != "i386" && OS_ARCH != "amd64") {
 671     throw new Exception("Unknown and unsupported build architecture: $OS_ARCH")
 672 }
 673 
 674 // Sanity check that we actually have a list of compile targets to execute
 675 if (COMPILE_TARGETS == null || COMPILE_TARGETS == "") {
 676     throw new Exception("Unable to determine compilation platform, must specify valid COMPILE_TARGETS!")
 677 }
 678 
 679 // Make sure JDK_HOME/bin/java exists
 680 if (!file(JAVA).exists()) throw new Exception("Missing or incorrect path to 'java': '$JAVA'. Perhaps bad JDK_HOME? $JDK_HOME")
 681 if (!file(JAVAC).exists()) throw new Exception("Missing or incorrect path to 'javac': '$JAVAC'. Perhaps bad JDK_HOME? $JDK_HOME")
 682 if (!file(JAVAH).exists()) throw new Exception("Missing or incorrect path to 'javah': '$JAVAH'. Perhaps bad JDK_HOME? $JDK_HOME")
 683 if (!file(JAVADOC).exists()) throw new Exception("Missing or incorrect path to 'javadoc': '$JAVADOC'. Perhaps bad JDK_HOME? $JDK_HOME")
 684 
 685 
 686 // Determine the verion of Java in JDK_HOME. It looks like this:
 687 //
 688 // $ java -version
 689 // java version "1.7.0_45"
 690 // Java(TM) SE Runtime Environment (build 1.7.0_45-b18)
 691 // Java HotSpot(TM) 64-Bit Server VM (build 24.45-b08, mixed mode)
 692 //
 693 // We need to parse the second line
 694 def inStream = new java.io.BufferedReader(new java.io.InputStreamReader(new java.lang.ProcessBuilder(JAVA, "-version").start().getErrorStream()));
 695 try {
 696     if (inStream.readLine() != null) {
 697         String v = inStream.readLine();
 698         if (v != null) {
 699             int ib = v.indexOf(" (build ");
 700             if (ib != -1) {
 701                 String ver = v.substring(ib + 8, v.size() - 1);
 702 
 703                 defineProperty("jdkRuntimeVersion", ver)
 704                 defineProperty("jdkVersion", jdkRuntimeVersion.split("-")[0])
 705                 defineProperty("jdkBuildNumber", jdkRuntimeVersion.substring(jdkRuntimeVersion.lastIndexOf("-b") + 2))
 706             }
 707         }
 708     }
 709 } finally {
 710     inStream.close();
 711 }
 712 if (!project.hasProperty("jdkRuntimeVersion")) throw new Exception("Unable to determine the version of Java in JDK_HOME at $JDK_HOME");
 713 
 714 
 715 
 716 // Verify that CONF is something useful
 717 if (CONF != "Release" && CONF != "Debug") logger.warn("Unknown configuration CONF='$CONF'. Treating as 'Release'")
 718 
 719 // If the number of compile threads is less than 1 then we have a problem!
 720 if (Integer.parseInt(NUM_COMPILE_THREADS.toString()) < 1) {
 721     logger.warn("NUM_COMPILE_THREADS was specified as '$NUM_COMPILE_THREADS' which is less than the minimum value of 1. " +
 722             "Building with a value of 1 instead.")
 723     NUM_COMPILE_THREADS = 1
 724 }
 725 
 726 // Check that Gradle 1.8 is in use.
 727 if (gradle.gradleVersion != "1.8") {
 728     def ver = gradle.gradleVersion.split("[\\.]");
 729     def gradleMajor = Integer.parseInt(ver[0]);
 730     def gradleMinor = Integer.parseInt(ver[1]);
 731     def err = "";
 732     if (gradleMajor != 1) {
 733         err = "Gradle major version is incompatible: ${gradle.gradleVersion}; supported version is 1.8";
 734     } else {
 735         if (gradleMinor < 8) {
 736             err = "Gradle version too old: ${gradle.gradleVersion}; must be at least 1.8"
 737         }
 738 
 739         // Blacklisted versions of gradle
 740         if (gradleMinor == 11) {
 741             err = "JavaFX fails to build with Gradle ${gradle.gradleVersion}; supported version is 1.8"
 742         }
 743     }
 744 
 745     if (IS_GRADLE_VERSION_CHECK && err != "") {
 746         fail(err);
 747     }
 748 
 749     logger.warn("*****************************************************************");
 750     logger.warn("Unsupported gradle version $gradle.gradleVersion in use.");
 751     logger.warn("Only version 1.8 is supported. Use this version at your own risk");
 752     if ( err != "") logger.warn(err);
 753     logger.warn("*****************************************************************");
 754 }
 755 
 756 /******************************************************************************
 757  *                                                                            *
 758  *                      Logging of Properties and Settings                    *
 759  *                                                                            *
 760  *  Log some of the settings we've determined. We could log more here, it     *
 761  *  doesn't really hurt.                                                      *
 762  *                                                                            *
 763  *****************************************************************************/
 764 
 765 logger.quiet("OS_NAME: $OS_NAME")
 766 logger.quiet("OS_ARCH: $OS_ARCH")
 767 logger.quiet("JAVA_HOME: $JAVA_HOME")
 768 logger.quiet("JDK_HOME: $JDK_HOME")
 769 logger.quiet("java.runtime.version: ${javaRuntimeVersion}")
 770 logger.quiet("java version: ${javaVersion}")
 771 logger.quiet("java build number: ${javaBuildNumber}")
 772 logger.quiet("jdk.runtime.version: ${jdkRuntimeVersion}")
 773 logger.quiet("jdk version: ${jdkVersion}")
 774 logger.quiet("jdk build number: ${jdkBuildNumber}")
 775 logger.quiet("minimum java build number: ${jfxBuildJdkBuildnumMin}")
 776 logger.quiet("NUM_COMPILE_THREADS: $NUM_COMPILE_THREADS")
 777 logger.quiet("COMPILE_TARGETS: $COMPILE_TARGETS")
 778 logger.quiet("COMPILE_FLAGS_FILES: $COMPILE_FLAGS_FILES")
 779 logger.quiet("HUDSON_JOB_NAME: $HUDSON_JOB_NAME")
 780 logger.quiet("HUDSON_BUILD_NUMBER: $HUDSON_BUILD_NUMBER")
 781 logger.quiet("PROMOTED_BUILD_NUMBER: $PROMOTED_BUILD_NUMBER")
 782 logger.quiet("PRODUCT_NAME: $PRODUCT_NAME")
 783 logger.quiet("RAW_VERSION: $RAW_VERSION")
 784 logger.quiet("RELEASE_NAME: $RELEASE_NAME")
 785 logger.quiet("RELEASE_MILESTONE: $RELEASE_MILESTONE")
 786 
 787 if (UPDATE_STUB_CACHE) {
 788     logger.quiet("UPDATE_STUB_CACHE: $UPDATE_STUB_CACHE")
 789 }
 790 
 791 /******************************************************************************
 792  *                                                                            *
 793  *                Definition of Native Code Compilation Tasks                 *
 794  *                                                                            *
 795  *    - JavaHeaderTask is used to run javah. The JAVAH property will point at *
 796  *      the version of javah to be used (i.e.: a path to javah)               *
 797  *    - CCTask compiles native code. Specifically it will compile .m, .c,     *
 798  *      .cpp, or .cc files. It uses the headers provided by the               *
 799  *      JavaHeaderTask plus additional platform specific headers. It will     *
 800  *      compile into .obj files.                                              *
 801  *    - LinkTask will perform native linking and create the .dll / .so /      *
 802  *      .dylib as necessary.                                                  *
 803  *                                                                            *
 804  *****************************************************************************/
 805 
 806 // Save a reference to the buildSrc.jar file because we need it for actually
 807 // compiling things, not just for the sake of this build script
 808 // (such as generating the builders, JSL files, etc)
 809 ext.BUILD_SRC = rootProject.files("buildSrc/build/libs/buildSrc.jar")
 810 
 811 /**
 812  * Convenience method for creating javah, cc, link, and "native" tasks in the given project. These
 813  * tasks are parameterized by name, so that we can produce, for example, javahGlass, ccGlass, etc
 814  * named tasks.
 815  * 
 816  * @param project The project to add tasks to
 817  * @param name The name of the project, such as "prism-common". This name is used
 818  *        in the name of the generated task, such as ccPrismCommon, and also
 819  *        in the name of the final library, such as libprism-common.dylib.
 820  */
 821 void addNative(Project project, String name) {
 822     // TODO if we want to handle 32/64 bit windows in the same build,
 823     // Then we will need to modify the win compile target to be win32 or win64
 824     def capitalName = name.split("-").collect{it.capitalize()}.join()
 825     def nativeTask = project.task("native$capitalName", group: "Build") {
 826         description = "Generates JNI headers, compiles, and builds native dynamic library for $name for all compile targets"
 827     }
 828     def cleanTask = project.task("cleanNative$capitalName", type: Delete, group: "Build") {
 829         description = "Clean native objects for $name"
 830     }
 831     if (project.hasProperty("nativeAllTask")) project.nativeAllTask.dependsOn nativeTask
 832     project.assemble.dependsOn(nativeTask)
 833     if (project.hasProperty("cleanNativeAllTask")) project.cleanNativeAllTask.dependsOn cleanTask
 834     
 835     // Each of the different compile targets will be placed in a sub directory
 836     // of these root dirs, with the name of the dir being the name of the target
 837     def headerRootDir = project.file("$project.buildDir/generated-src/headers/$name")
 838     def nativeRootDir = project.file("$project.buildDir/native/$name")
 839     def libRootDir = project.file("$project.buildDir/libs/$name")
 840     // For each compile target, create a javah / cc / link triplet
 841     compileTargets { t ->
 842         def targetProperties = project.rootProject.ext[t.upper]
 843         def library = targetProperties.library
 844         def properties = targetProperties.get(name)
 845         def nativeDir = file("$nativeRootDir/${t.name}")
 846         def headerDir = file("$headerRootDir/${t.name}")
 847 
 848         // If there is not a library clause in the properties, assume it is not wanted
 849         if (!targetProperties.containsKey(name)) {
 850             println("Ignoring native library ${name}. Not defined in ${t.name} project properties");
 851             return
 852         }
 853 
 854         // check for the property disable${name} = true
 855         def String disableKey = "disable${name}"
 856         def boolean disabled = targetProperties.containsKey(disableKey) ? targetProperties.get(disableKey) : false
 857         if (disabled) {
 858             println("Native library ${name} disabled in ${t.name} project properties");
 859             return
 860         }
 861         
 862         def javahTask = project.task("javah${t.capital}${capitalName}", type: JavaHeaderTask, dependsOn: project.classes, group: "Build") {
 863             description = "Generates JNI Headers for ${name} for ${t.name}"
 864             if (properties.javahSource == null) {
 865                 source(project.sourceSets.main.output.classesDir)
 866             } else {
 867                 source(properties.javahSource)
 868             }
 869             if (properties.javahClasspath == null) {
 870                 classpath = project.files(project.sourceSets.main.output.classesDir)
 871                 classpath += project.sourceSets.main.compileClasspath
 872             } else {
 873                 classpath = project.files(properties.javahClasspath)
 874             }
 875             output = headerDir
 876             include(properties.javahInclude)
 877             cleanTask.delete headerDir
 878         }
 879 
 880         def variants = properties.containsKey("variants") ? properties.variants : [""];
 881         variants.each { variant ->
 882             def variantProperties = variant == "" ? properties : properties.get(variant)
 883             def capitalVariant = variant.capitalize()
 884             def ccOutput = variant == "" ? nativeDir : file("$nativeDir/$variant")
 885             def ccTask = project.task("cc${t.capital}$capitalName$capitalVariant", type: CCTask, dependsOn: javahTask, group: "Build") {
 886                 description = "Compiles native sources for ${name} for ${t.name}${capitalVariant != '' ? ' for variant ' + capitalVariant : ''}"
 887                 matches = ".*\\.c|.*\\.cpp|.*\\.m|.*\\.cc"
 888                 headers = headerDir
 889                 output(ccOutput)
 890                 params.addAll(variantProperties.ccFlags)
 891                 compiler = variantProperties.compiler
 892                 source(variantProperties.nativeSource)
 893                 cleanTask.delete ccOutput
 894             }
 895             def linkTask = project.task("link${t.capital}$capitalName$capitalVariant", type: LinkTask, dependsOn: ccTask, group: "Build") {
 896                 description = "Creates native dynamic library for $name for ${t.name}${capitalVariant != '' ? ' for variant ' + capitalVariant : ''}"
 897                 objectDir = ccOutput
 898                 linkParams.addAll(variantProperties.linkFlags)
 899                 lib = file("$libRootDir/${t.name}/${variant == '' ? library(properties.lib) : library(variantProperties.lib)}")
 900                 linker = variantProperties.linker
 901                 cleanTask.delete "$libRootDir/${t.name}"
 902             }
 903             nativeTask.dependsOn(linkTask)
 904             if (IS_WINDOWS && t.name == "win") {
 905                 def rcTask = project.task("rc$capitalName$capitalVariant", type: CompileResourceTask, dependsOn: javahTask, group: "Build") {
 906                     description = "Compiles native sources for $name"
 907                     matches = ".*\\.rc"
 908                     compiler = variantProperties.rcCompiler
 909                     source(variantProperties.rcSource)
 910                     if (variantProperties.rcFlags) {
 911                         rcParams.addAll(variantProperties.rcFlags)
 912                     }
 913                     output(ccOutput)
 914                 }
 915                 linkTask.dependsOn rcTask;
 916             }
 917         }
 918 
 919         def useLipo = targetProperties.containsKey('useLipo') ? targetProperties.useLipo : false
 920         if (useLipo) {
 921             def lipoTask = project.task("lipo${t.capital}$capitalName", type: LipoTask, dependsOn: javahTask, group: "Build") {
 922                 description = "Creates native fat library for $name for ${t.name}"
 923                 libDir = file("$libRootDir/${t.name}")
 924                 lib = file("$libRootDir/${t.name}/${library(properties.lib)}")
 925             }
 926             nativeTask.dependsOn(lipoTask)
 927         }
 928     }
 929 }
 930 
 931 void addJSL(Project project, String name, String pkg, Closure compile) {
 932     def lowerName = name.toLowerCase()
 933 
 934     def compileCompilers = project.task("compile${name}Compilers", type: JavaCompile, dependsOn: project.compileJava) {
 935         description = "Compile the $name JSL Compilers"
 936         classpath = project.files(project.sourceSets.main.output.classesDir) +
 937                 rootProject.BUILD_SRC +
 938                 project.configurations.antlr3
 939         source = [project.file("src/main/jsl-$lowerName")]
 940         destinationDir = project.file("$project.buildDir/classes/jsl-compilers/$lowerName")
 941     }
 942 
 943     def generateShaders = project.task("generate${name}Shaders", dependsOn: compileCompilers) {
 944         description = "Generate $name shaders from JSL"
 945         def sourceDir = project.file("src/main/jsl-$lowerName")
 946         def destinationDir = project.file("$project.buildDir/generated-src/jsl-$lowerName")
 947         inputs.dir sourceDir
 948         outputs.dir destinationDir
 949         doLast {
 950             compile(sourceDir, destinationDir)
 951         }
 952     }
 953 
 954     project.task("compile${name}JavaShaders", type: JavaCompile, dependsOn: generateShaders) {
 955         description = "Compile the Java $name JSL shaders"
 956         classpath = project.files(project.sourceSets.main.output.classesDir) + rootProject.BUILD_SRC
 957         source = [project.file("$project.buildDir/generated-src/jsl-$lowerName")]
 958         destinationDir = project.file("$project.buildDir/classes/jsl-$lowerName")
 959     }
 960 
 961     def compileHLSLShaders = project.task("compile${name}HLSLShaders", dependsOn: generateShaders, type: CompileHLSLTask) {
 962         enabled = IS_WINDOWS
 963         description = "Compile $name HLSL files into .obj files"
 964         matches = ".*\\.hlsl"
 965         output project.file("$project.buildDir/hlsl/$name/$pkg")
 966         source project.file("$project.buildDir/generated-src/jsl-$lowerName/$pkg")
 967     }
 968 
 969     project.task("process${name}Shaders", dependsOn: [generateShaders, compileHLSLShaders], type: Copy, description: "Copy hlsl / frag shaders to build/resources/jsl-$lowerName") {
 970         from("$project.buildDir/hlsl/$name") {
 971             include "**/*.obj"
 972         }
 973         from("$project.buildDir/generated-src/jsl-$lowerName") {
 974             include("**/*.frag")
 975         }
 976         into "$project.buildDir/resources/jsl-$lowerName"
 977     }
 978 }
 979 
 980 /**
 981  * Parses a JDK version string. The string must be in one of the following
 982  * two formats:
 983  *
 984  *     major.minor.subminor
 985  * or
 986  *     major.minor.subminor_update
 987  *
 988  * In both cases a list of 4 integers is returned, with element 3 set to
 989  * 0 in the former case.
 990  */
 991 List parseJdkVersion(String version) {
 992     def arr = version.split("[_\\.]");
 993     def intArr = [];
 994     arr.each { s -> intArr += Integer.parseInt(s); }
 995     if (intArr.size() < 4) intArr += 0;
 996     return intArr;
 997 }
 998 
 999 /**
1000  * Returns -1, 0, or 1 depending on whether JDK version "a" is less than,
1001  * equal to, or grater than version "b".
1002  */
1003 int compareJdkVersion(String a, String b) {
1004     def aIntArr = parseJdkVersion(a);
1005     def bIntArr = parseJdkVersion(b);
1006 
1007     for (int i = 0; i < 4; i++) {
1008         if (aIntArr[i] < bIntArr[i]) return -1;
1009         if (aIntArr[i] > bIntArr[i]) return  1;
1010     }
1011     return 0;
1012 }
1013 
1014 // Task to verify the minimum level of Java needed to build JavaFX
1015 task verifyJava() {
1016     doLast {
1017         def status = compareJdkVersion(jdkVersion, jfxBuildJdkVersion);
1018         if (status < 0) {
1019             fail("java version mismatch: JDK version (${jdkVersion}) < minimum version (${jfxBuildJdkVersion})")
1020         } else if (status == 0) {
1021             def buildNum = Integer.parseInt(jdkBuildNumber)
1022             def minBuildNum = Integer.parseInt(jfxBuildJdkBuildnumMin)
1023             if (buildNum < minBuildNum) {
1024                 fail("JDK build number ($buildNum) < minimum build number ($minBuildNum)")
1025             }
1026         }
1027     }
1028 }
1029 
1030 // Task to check whether jfxrt.jar is present in the JDK
1031 task checkJfxrtJar {
1032     doLast {
1033         def jfxrtFile = new File("$JDK_HOME/jre/lib/ext/jfxrt.jar");
1034         if (jfxrtFile.exists()) {
1035             if (BUILD_CLOSED) {
1036                 fail("$jfxrtFile must be removed before building closed sdk")
1037             } else {
1038                 logger.warn("****************************************************************")
1039                 logger.warn("$jfxrtFile may interfere with testing or running applications against locally build jfxrt.jar")
1040                 logger.warn("****************************************************************")
1041             }
1042         }
1043     }
1044 }
1045 
1046 task updateCacheIfNeeded() {
1047     // an empty task we can add to as needed for UPDATE_STUB_CACHE
1048 }
1049 
1050 /*****************************************************************************
1051 *        Project definitions (dependencies, etc)                             *
1052 *****************************************************************************/
1053 
1054 void addJCov(p, test) {
1055     test.doFirst {
1056         def jcovJVMArgument =
1057                 "include=javafx," +
1058                 "include=com.sun.javafx," +
1059                 "include=com.sun.glass," +
1060                 "include=com.sun.openpisces," +
1061                 "include=com.sun.pisces," +
1062                 "include=com.sun.prism," +
1063                 "include=com.sun.scenario," +
1064                 "include=com.sun.webkit," +
1065                 "exclude=com," +
1066                 "exclude=java," +
1067                 "exclude=javax," +
1068                 "exclude=\"**.test\"," +
1069                 "exclude=\"**.*Test\"," +
1070                 "file=build/reports/jcov/report.xml," +
1071                 "merge=merge";
1072         test.jvmArgs("-javaagent:${p.configurations.testCompile.files.find { it.name.startsWith('jcov') }}=$jcovJVMArgument");
1073         p.mkdir p.file("build/reports/jcov")
1074     }
1075     test.doLast {
1076         def reportFile = p.file("build/reports/jcov/report.xml")
1077         if (reportFile.exists()) {
1078             p.javaexec {
1079                 workingDir = p.file("build/reports/jcov")
1080                 classpath = p.files(p.configurations.testCompile.files.find { it.name.startsWith('jcov') })
1081                 main = "com.sun.tdk.jcov.Helper"
1082                 args = [
1083                         "RepGen",
1084                         "-exclude", "\"**.test\"",
1085                         "-exclude", "\"**.*Test\"",
1086                         "-output", ".",
1087                         "-source", p.sourceSets.main.java.srcDirs.collect{p.file(it)}.join(":"),
1088                         "report.xml"
1089                 ]
1090             }
1091         }
1092     }
1093 }
1094 
1095 allprojects {
1096     // We want to configure all projects as java projects and use the same compile settings
1097     // etc, except for the root project which we just want to ignore (and for now media)
1098     if (project == rootProject) {
1099        return
1100     }
1101     if (project.path.startsWith(":apps")) {
1102         // Lets handle the apps tree differently, as it is a collection of ant builds,
1103         // and the ant importer collides with the 'apply plugin:java'
1104         return
1105     }
1106     // All of our projects are java projects
1107     apply plugin: "java"
1108     sourceCompatibility = 1.8
1109 
1110     // Setup the repositories that we'll download libraries from. Maven Central is
1111     // just easy for most things. The custom "ivy" repo is for downloading SWT. The way it
1112     // works is to setup the download URL such that it will resolve to the actual jar file
1113     // to download. See SWT_FILE_NAME for the name of the jar that will be used as the
1114     // "artifact" in the pattern below. Note that the closed builds use different repositories
1115     // so if you are debugging a closed-build artifact related build issue, check out the
1116     // closed gradle file instead.
1117     if (!BUILD_CLOSED) {
1118         repositories {
1119             mavenCentral()
1120             ivy {
1121                 url "http://download.eclipse.org/eclipse/updates/3.7/R-3.7.2-201202080800/plugins/"
1122                 layout "pattern", {
1123                     artifact "[artifact].[ext]"
1124                 }
1125             }
1126         }
1127     }
1128 
1129     // By default all of our projects require junit for testing so we can just
1130     // setup this dependency here.
1131     dependencies {
1132         testCompile group: "junit", name: "junit", version: "4.8.2"
1133         if (BUILD_CLOSED && DO_JCOV)  {
1134             testCompile name: "jcov"
1135         }
1136     }
1137 
1138     // Compile and run tests against the jfxrt.jar in the built sdk of the host machine
1139     def sdkDir = "${rootProject.buildDir}/sdk"
1140     def jfxrtJar = "$sdkDir/rt/lib/ext/jfxrt.jar"
1141 
1142     // At the moment the ASM library shipped with Gradle that is used to
1143     // discover the different test classes fails on Java 8, so in order
1144     // to have sourceCompatibility set to 1.8 I have to also turn scanForClasses off
1145     // and manually specify the includes / excludes. At the moment we use
1146     // Java 7 but when we switch to 8 this will be needed, and probably again when
1147     // we start building with Java 9.
1148     test {
1149         jvmArgs("-Djava.ext.dirs=");
1150         executable = JAVA;
1151         enableAssertions = true;
1152         testLogging.exceptionFormat = "full";
1153         scanForTestClasses = false;
1154         include("**/*Test.*");
1155         if (BUILD_CLOSED && DO_JCOV) {
1156             addJCov(project, test)
1157         }
1158         classpath = files("$jfxrtJar") + classpath
1159         if (IS_HEADLESS_TEST) {
1160             systemProperty 'glass.platform', 'Monocle'
1161             systemProperty 'monocle.platform', 'Headless'
1162             systemProperty 'prism.order', 'sw'
1163             systemProperty 'com.sun.javafx.gestures.zoom', 'true'
1164             systemProperty 'com.sun.javafx.gestures.rotate', 'true'
1165             systemProperty 'com.sun.javafx.gestures.scroll', 'true'
1166         }
1167     }
1168 
1169     compileTestJava {
1170         classpath = files("$jfxrtJar") + classpath
1171     }
1172 
1173     // Exclude any non-public-API classes from having javadoc generated. This block is used
1174     // when generating JavaDocs for a specific project. When generating the JavaDocs for the
1175     // entire SDK, a different javadoc command is used (see the javadoc task on the top level)
1176     javadoc {
1177         enabled = IS_BUILD_JAVADOC
1178         exclude("com/**/*", "javafx/scene/ParentDesignInfo*", "Compile*", "javafx/builder/**/*", "javafx/scene/accessibility/**/*");
1179         executable = JAVADOC;
1180         options.windowTitle("JavaFX Project ${project.name} ${RELEASE_NAME}")
1181         if (BUILD_CLOSED) {
1182             options.linksOffline(JDK_DOCS, JDK_DOCS_CLOSED);
1183         } else {
1184             options.links(JDK_DOCS);
1185         }
1186         options.addBooleanOption("XDignore.symbol.file").setValue(true);
1187         options.addBooleanOption("Xdoclint:none").setValue(!IS_DOC_LINT);
1188         options.addBooleanOption("javafx").setValue(true);
1189         options.addBooleanOption("use").setValue(true);
1190         // All doc-files are located in src/main/docs because Gradle's javadoc doesn't copy
1191         // over the doc-files if they are embedded with the sources. I find this arrangement
1192         // somewhat cleaner anyway (never was a fan of mixing javadoc files with the sources)
1193         doLast {
1194             copy {
1195                 from "src/main/docs"
1196                 into "$buildDir/docs/javadoc"
1197             }
1198         }
1199     }
1200 }
1201 
1202 // The "base" project is our first module and the most basic one required for
1203 // all other modules. It is useful even for non-GUI applications.
1204 project(":base") {
1205     dependencies {
1206         compile BUILD_SRC
1207     }
1208 
1209     // We need to take the VersionInfo.java file and replace the various
1210     // properties within it
1211     def replacements = [
1212         "BUILD_TIMESTAMP": new java.util.Date(),
1213         "HUDSON_JOB_NAME": HUDSON_JOB_NAME,
1214         "HUDSON_BUILD_NUMBER": HUDSON_BUILD_NUMBER,
1215         "PROMOTED_BUILD_NUMBER": PROMOTED_BUILD_NUMBER,
1216         "PRODUCT_NAME": PRODUCT_NAME,
1217         "RAW_VERSION": RAW_VERSION,
1218         "RELEASE_NAME": RELEASE_NAME,
1219         "RELEASE_MILESTONE": RELEASE_MILESTONE];
1220     task processVersionInfo(type: Copy, description: "Replace params in VersionInfo and copy file to destination") {
1221         doFirst { mkdir "$buildDir/generated-src/version-info" }
1222         from "src/main/version-info"
1223         into "$buildDir/generated-src/version-info/com/sun/javafx/runtime"
1224         filter {line->
1225             replacements.each() {k, v ->
1226                 line = line.replace("@$k@", v.toString());
1227             }
1228             line
1229         }
1230     }
1231 
1232     compileJava.dependsOn updateCacheIfNeeded
1233     compileJava.dependsOn verifyJava
1234 
1235     // Make sure to include $buildDir/generated-src/version-info that we previously created.
1236     // We DO NOT want to include src/main/version-info
1237     if (System.getProperty("jfx.build.jdk.defenders", "true").equals("true")) {
1238         sourceSets.main.java.srcDirs += "src/main/java8"
1239     } else {
1240         sourceSets.main.java.srcDirs += "src/main/java7"
1241     }
1242 
1243     if (IS_COMPILE_JFR) {
1244         sourceSets.main.java.srcDirs += "src/main/java-jfr"
1245     }
1246 
1247     sourceSets.main.java.srcDirs += "$buildDir/generated-src/version-info"
1248 
1249     compileJava.dependsOn processVersionInfo
1250 }
1251 
1252 // The graphics module is needed for any graphical JavaFX application. It requires
1253 // the base module and includes the scene graph, layout, css, prism, windowing, etc.
1254 // This is a fairly complicated module. There are many different types of native components
1255 // that all need to be compiled.
1256 project(":graphics") {
1257     // Workaround for lack of Antlr 3 support in Gradle. By defining a configuration,
1258     // we can then give it a class path and use that classpath to execute a java command
1259     getConfigurations().create("antlr3");
1260 
1261     sourceSets {
1262         main
1263         test
1264         stub
1265     }
1266 
1267     dependencies {
1268         compile project(":base"), BUILD_SRC
1269         compile name: SWT_FILE_NAME
1270         stubCompile group: "junit", name: "junit", version: "4.8.2",
1271         project(":base").sourceSets.test.output, sourceSets.main.output
1272         antlr3 group: "org.antlr", name: "antlr", version: "3.1.3"
1273         antlr3 group: "org.antlr", name: "antlr-runtime",  version: "3.1.3"
1274         antlr3 group: "org.antlr", name: "stringtemplate", version: "3.2"
1275     }
1276 
1277     // Create a single "native" task which will depend on all the individual native tasks for graphics
1278     project.ext.nativeAllTask = task("native", group: "Build", description: "Compiles and Builds all native libraries for Graphics");
1279     project.ext.cleanNativeAllTask = task("cleanNative", group: "Build", description: "Clean all native libraries and objects for Graphics");
1280 
1281     // Add tasks for native compilation
1282     addNative(project, "glass");
1283     addNative(project, "prism")
1284     addNative(project, "prismSW")
1285     addNative(project, "font")
1286     addNative(project, "iio")
1287     addNative(project, "prismES2")
1288 
1289     if (IS_COMPILE_PANGO) {
1290         addNative(project, "fontFreetype")
1291         addNative(project, "fontPango")
1292     }
1293 
1294     if (IS_WINDOWS) {
1295         addNative(project, "prismD3D")
1296         // TODO need to hook this up to be executed only if PassThroughVS.h is missing or PassThroughVS.hlsl is changed
1297         task generateD3DHeaders(group: "Build") {
1298             enabled = IS_WINDOWS
1299             dependsOn javahWinPrismD3D
1300             inputs.file "src/main/native-prism-d3d/hlsl/Mtl1PS.hlsl"
1301             inputs.file "src/main/native-prism-d3d/hlsl/Mtl1VS.hlsl"
1302             inputs.file "src/main/native-prism-d3d/PassThroughVS.hlsl"
1303             outputs.dir "$buildDir/headers/PrismD3D/"
1304             outputs.dir "$buildDir/headers/PrismD3D/hlsl/"
1305             description = "Generate headers by compiling hlsl files"
1306             doLast {
1307                 mkdir file("$buildDir/headers/PrismD3D/hlsl")
1308                 def PS_3D_SRC = file("src/main/native-prism-d3d/hlsl/Mtl1PS.hlsl")
1309                 def VS_3D_SRC = file("src/main/native-prism-d3d/hlsl/Mtl1VS.hlsl")
1310                 def PASSTHROUGH_VS_SRC = file("src/main/native-prism-d3d/PassThroughVS.hlsl")
1311                 def jobs = [
1312                         ["$FXC", "/nologo", "/T", "vs_3_0", "/Fh", "$buildDir/headers/PrismD3D/PassThroughVS.h", "/E", "passThrough", "$PASSTHROUGH_VS_SRC"],
1313                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS.h", "/DSpec=0", "/DSType=0", "$PS_3D_SRC"],
1314                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_i.h", "/DSpec=0", "/DSType=0", "/DIllumMap=1", "$PS_3D_SRC"],
1315                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s1n.h", "/DSpec=1", "/DSType=0", "$PS_3D_SRC"],
1316                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s2n.h", "/DSpec=2", "/DSType=0", "$PS_3D_SRC"],
1317                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s3n.h", "/DSpec=3", "/DSType=0", "$PS_3D_SRC"],
1318                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s1t.h", "/DSpec=1", "/DSType=1", "$PS_3D_SRC"],
1319                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s2t.h", "/DSpec=2", "/DSType=1", "$PS_3D_SRC"],
1320                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s3t.h", "/DSpec=3", "/DSType=1", "$PS_3D_SRC"],
1321                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s1c.h", "/DSpec=1", "/DSType=2", "$PS_3D_SRC"],
1322                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s2c.h", "/DSpec=2", "/DSType=2", "$PS_3D_SRC"],
1323                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s3c.h", "/DSpec=3", "/DSType=2", "$PS_3D_SRC"],
1324                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s1m.h", "/DSpec=1", "/DSType=3", "$PS_3D_SRC"],
1325                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s2m.h", "/DSpec=2", "/DSType=3", "$PS_3D_SRC"],
1326                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s3m.h", "/DSpec=3", "/DSType=3", "$PS_3D_SRC"],
1327                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b1n.h", "/DSpec=1", "/DSType=0", "/DBump=1", "$PS_3D_SRC"],
1328                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b2n.h", "/DSpec=2", "/DSType=0", "/DBump=1", "$PS_3D_SRC"],
1329                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b3n.h", "/DSpec=3", "/DSType=0", "/DBump=1", "$PS_3D_SRC"],
1330                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b1t.h", "/DSpec=1", "/DSType=1", "/DBump=1", "$PS_3D_SRC"],
1331                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b2t.h", "/DSpec=2", "/DSType=1", "/DBump=1", "$PS_3D_SRC"],
1332                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b3t.h", "/DSpec=3", "/DSType=1", "/DBump=1", "$PS_3D_SRC"],
1333                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b1c.h", "/DSpec=1", "/DSType=2", "/DBump=1", "$PS_3D_SRC"],
1334                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b2c.h", "/DSpec=2", "/DSType=2", "/DBump=1", "$PS_3D_SRC"],
1335                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b3c.h", "/DSpec=3", "/DSType=2", "/DBump=1", "$PS_3D_SRC"],
1336                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b1m.h", "/DSpec=1", "/DSType=3", "/DBump=1", "$PS_3D_SRC"],
1337                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b2m.h", "/DSpec=2", "/DSType=3", "/DBump=1", "$PS_3D_SRC"],
1338                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b3m.h", "/DSpec=3", "/DSType=3", "/DBump=1", "$PS_3D_SRC"],
1339                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s1ni.h", "/DSpec=1", "/DSType=0", "/DIllumMap=1", "$PS_3D_SRC"],
1340                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s2ni.h", "/DSpec=2", "/DSType=0", "/DIllumMap=1", "$PS_3D_SRC"],
1341                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s3ni.h", "/DSpec=3", "/DSType=0", "/DIllumMap=1", "$PS_3D_SRC"],
1342                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s1ti.h", "/DSpec=1", "/DSType=1", "/DIllumMap=1", "$PS_3D_SRC"],
1343                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s2ti.h", "/DSpec=2", "/DSType=1", "/DIllumMap=1", "$PS_3D_SRC"],
1344                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s3ti.h", "/DSpec=3", "/DSType=1", "/DIllumMap=1", "$PS_3D_SRC"],
1345                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s1ci.h", "/DSpec=1", "/DSType=2", "/DIllumMap=1", "$PS_3D_SRC"],
1346                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s2ci.h", "/DSpec=2", "/DSType=2", "/DIllumMap=1", "$PS_3D_SRC"],
1347                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s3ci.h", "/DSpec=3", "/DSType=2", "/DIllumMap=1", "$PS_3D_SRC"],
1348                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s1mi.h", "/DSpec=1", "/DSType=3", "/DIllumMap=1", "$PS_3D_SRC"],
1349                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s2mi.h", "/DSpec=2", "/DSType=3", "/DIllumMap=1", "$PS_3D_SRC"],
1350                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s3mi.h", "/DSpec=3", "/DSType=3", "/DIllumMap=1", "$PS_3D_SRC"],
1351                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b1ni.h", "/DSpec=1", "/DSType=0", "/DBump=1", "/DIllumMap=1", "$PS_3D_SRC"],
1352                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b2ni.h", "/DSpec=2", "/DSType=0", "/DBump=1", "/DIllumMap=1", "$PS_3D_SRC"],
1353                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b3ni.h", "/DSpec=3", "/DSType=0", "/DBump=1", "/DIllumMap=1", "$PS_3D_SRC"],
1354                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b1ti.h", "/DSpec=1", "/DSType=1", "/DBump=1", "/DIllumMap=1", "$PS_3D_SRC"],
1355                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b2ti.h", "/DSpec=2", "/DSType=1", "/DBump=1", "/DIllumMap=1", "$PS_3D_SRC"],
1356                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b3ti.h", "/DSpec=3", "/DSType=1", "/DBump=1", "/DIllumMap=1", "$PS_3D_SRC"],
1357                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b1ci.h", "/DSpec=1", "/DSType=2", "/DBump=1", "/DIllumMap=1", "$PS_3D_SRC"],
1358                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b2ci.h", "/DSpec=2", "/DSType=2", "/DBump=1", "/DIllumMap=1", "$PS_3D_SRC"],
1359                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b3ci.h", "/DSpec=3", "/DSType=2", "/DBump=1", "/DIllumMap=1", "$PS_3D_SRC"],
1360                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b1mi.h", "/DSpec=1", "/DSType=3", "/DBump=1", "/DIllumMap=1", "$PS_3D_SRC"],
1361                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b2mi.h", "/DSpec=2", "/DSType=3", "/DBump=1", "/DIllumMap=1", "$PS_3D_SRC"],
1362                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b3mi.h", "/DSpec=3", "/DSType=3", "/DBump=1", "/DIllumMap=1", "$PS_3D_SRC"],
1363                         ["$FXC", "/nologo", "/T", "vs_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1VS_Obj.h", "/DVertexType=ObjVertex", "$VS_3D_SRC"]
1364                 ]
1365                 final ExecutorService executor = Executors.newFixedThreadPool(Integer.parseInt(project.NUM_COMPILE_THREADS.toString()));
1366                 final CountDownLatch latch = new CountDownLatch(jobs.size());
1367                 List futures = new ArrayList<Future>();
1368                 jobs.each { cmd ->
1369                     futures.add(executor.submit(new Runnable() {
1370                         @Override public void run() {
1371                             try {
1372                                 exec {
1373                                     commandLine cmd
1374                                 }
1375                             } finally {
1376                                 latch.countDown();
1377                             }
1378                         }
1379                     }));
1380                 }
1381                 latch.await();
1382                 // Looking for whether an exception occurred while executing any of the futures.
1383                 // By calling "get()" on each future an exception will be thrown if one had occurred
1384                 // on the background thread.
1385                 futures.each {it.get();}
1386             }
1387         }
1388 
1389         ccWinPrismD3D.dependsOn generateD3DHeaders
1390     }
1391 
1392     // The Decora and Prism JSL files have to be generated in a very specific set of steps.
1393     //      1) Compile the *Compile.java classes. These live in src/main/jsl-* and will be
1394     //         output to $buildDir/classes/jsl-compilers/* (where * == decora or prism).
1395     //      2) Generate source files from the JSL files contained in src/main/jsl-*. These
1396     //         will be output to $buildDir/generated-src/jsl-*
1397     //      3) Compile the JSL Java sources in $buildDir/generated-src/jsl-* and put the output
1398     //         into classes/jsl-*
1399     //      4) Compile the native JSL sources in $buildDir/generated-src/jsl-* and put the obj
1400     //         files into native/jsl-* and the resulting library into libs/jsl-*.dll|so|dylib
1401     //      5) Modify the jar step to include classes/jsl-*
1402     // The native library must be copied over during SDK creation time in the "sdk" task. In
1403     // addition to these steps, the clean task is created. Note that I didn't bother to create
1404     // a new task for each of the decora files, preferring instead just to create a rule?? Also
1405     // need "clean" tasks for each compile task.
1406 
1407     addJSL(project, "Decora", "com/sun/scenario/effect/impl/hw/d3d/hlsl") { sourceDir, destinationDir ->
1408         [[fileName: "ColorAdjust", generator: "CompileJSL", outputs: "-all"],
1409          [fileName: "Brightpass", generator: "CompileJSL", outputs: "-all"],
1410          [fileName: "SepiaTone", generator: "CompileJSL", outputs: "-all"],
1411          [fileName: "PerspectiveTransform", generator: "CompileJSL", outputs: "-all"],
1412          [fileName: "DisplacementMap", generator: "CompileJSL", outputs: "-all"],
1413          [fileName: "InvertMask", generator: "CompileJSL", outputs: "-all"],
1414          [fileName: "Blend", generator: "CompileBlend", outputs: "-all"],
1415          [fileName: "PhongLighting", generator: "CompilePhong", outputs: "-all"],
1416          [fileName: "LinearConvolve", generator: "CompileLinearConvolve", outputs: "-hw"],
1417          [fileName: "LinearConvolveShadow", generator: "CompileLinearConvolve", outputs: "-hw"]].each { settings ->
1418             javaexec {
1419                 executable = JAVA
1420                 workingDir = "modules/graphics"
1421                 main = settings.generator
1422                 classpath = configurations.compile + configurations.antlr3
1423                 classpath += files("$buildDir/classes/main")
1424                 classpath += files("$buildDir/classes/jsl-compilers/decora")
1425                 args = ["-i", sourceDir, "-o", destinationDir, "-t", "-pkg", "com/sun/scenario/effect", "$settings.outputs", "$settings.fileName"]
1426                 jvmArgs "-Djava.ext.dirs="
1427             }
1428         }
1429     }
1430 
1431     task generateDecoraNativeHeaders(type: JavaHeaderTask, dependsOn: compileDecoraJavaShaders) {
1432         description = "Generates JNI Headers for Decora SSE Natives"
1433         source file("$buildDir/classes/jsl-decora")
1434         source file("$buildDir/classes/main")
1435         include("com/sun/scenario/effect/impl/sw/sse/*");
1436         classpath = files("$buildDir/classes/main", "$buildDir/classes/jsl-decora")
1437         output = file("$buildDir/generated-src/headers/jsl-decora")
1438     }
1439 
1440     task nativeDecora(dependsOn: compileDecoraHLSLShaders, group: "Build") {
1441         description = "Generates JNI headers, compiles, and builds native dynamic library for Decora"
1442     }
1443     task cleanNativeDecora(type: Delete, group: "Build") {
1444         description = "Clean native objects for Decora"
1445     }
1446 
1447     def headerDir = file("$buildDir/generated-src/headers/jsl-decora")
1448     def nativeRootDir = project.file("$project.buildDir/native/jsl-decora")
1449     def libRootDir = project.file("$project.buildDir/libs/jsl-decora")
1450     // For each compile target, create cc and link tasks
1451     compileTargets { t ->
1452         def target = t.name
1453         def upperTarget = t.upper
1454         def capitalTarget = t.capital
1455         def properties = rootProject.ext[upperTarget];
1456         def library = properties.library
1457         def ccOutput = file("$nativeRootDir/$target");
1458 
1459         def ccTask = task("compileDecoraNativeShaders$capitalTarget", type: CCTask, dependsOn: generateDecoraNativeHeaders) {
1460             description = "Compiles Decora SSE natives"
1461             matches = ".*\\.cc"
1462             source file("$buildDir/generated-src/jsl-decora")
1463             source file("modules/graphics/src/main/native-decora")
1464             headers = headerDir
1465             params.addAll(properties.decora.ccFlags)
1466             output(ccOutput)
1467             compiler = properties.decora.compiler
1468             cleanNativeDecora.delete ccOutput
1469         }
1470 
1471         def linkTask = task("linkDecoraNativeShaders$capitalTarget", type: LinkTask, dependsOn: ccTask) {
1472             description = "Creates native dynamic library for Decora SSE"
1473             objectDir = file("$nativeRootDir/$target")
1474             linkParams.addAll(properties.decora.linkFlags)
1475             lib = file("$libRootDir/$t.name/${library(properties.decora.lib)}")
1476             linker = properties.decora.linker
1477             cleanNativeDecora.delete "$libRootDir/$t.name/"
1478         }
1479 
1480         if (IS_WINDOWS && target == "win") {
1481             def rcTask = project.task("rcDecoraNativeShaders$capitalTarget", type: CompileResourceTask, dependsOn: generateDecoraNativeHeaders) {
1482                 description = "Compiles native sources for Decora SSE"
1483                 matches = ".*\\.rc"
1484                 compiler = properties.decora.rcCompiler
1485                 source(properties.decora.rcSource)
1486                 if (properties.decora.rcFlags) {
1487                     rcParams.addAll(properties.decora.rcFlags)
1488                 }
1489                 output(ccOutput)
1490             }
1491             linkTask.dependsOn rcTask;
1492         }
1493 
1494         nativeDecora.dependsOn(linkTask)
1495     }
1496 
1497     // Prism JSL
1498     addJSL(project, "Prism", "com/sun/prism/d3d/hlsl") { sourceDir, destinationDir ->
1499         def inputFiles = fileTree(dir: sourceDir)
1500         inputFiles.include "**/*.jsl"
1501         inputFiles.each { file ->
1502             javaexec {
1503                 executable = JAVA
1504                 workingDir = "modules/graphics"
1505                 main = "CompileJSL"
1506                 classpath = configurations.compile + configurations.antlr3
1507                 classpath += files("$buildDir/classes/jsl-compilers/prism", "modules/graphics/src/main/jsl-prism") // for the .stg
1508                 args = ["-i", sourceDir, "-o", destinationDir, "-t", "-pkg", "com/sun/prism", "-d3d", "-es2", "-name", "$file"]
1509                 jvmArgs "-Djava.ext.dirs="
1510             }
1511         }
1512     }
1513 
1514     classes.dependsOn compilePrismJavaShaders;
1515     nativePrism.dependsOn compilePrismHLSLShaders;
1516 
1517     project.nativeAllTask.dependsOn nativeDecora
1518     project.cleanNativeAllTask.dependsOn cleanNativeDecora
1519     assemble.dependsOn nativeDecora
1520     processResources.dependsOn processDecoraShaders, processPrismShaders
1521 
1522     test {
1523         jvmArgs "-Djava.ext.dirs=", "-Djavafx.toolkit=com.sun.javafx.pgstub.StubToolkit", "-DCSS_META_DATA_TEST_DIR=${file('$buildDir/classes/main/javafx')}"
1524         enableAssertions = true
1525         testLogging.exceptionFormat = "full"
1526         scanForTestClasses = false
1527         include "**/*Test.*"
1528         if (BUILD_CLOSED && DO_JCOV) {
1529             addJCov(project, test)
1530         }
1531     }
1532 
1533     // To enable the IDEs to all be happy (no red squiggles) we need to have the libraries
1534     // available in some known location. Maybe in the future the Gradle plugins to each
1535     // of the IDEs will be good enough that we won't need this hack anymore.
1536     classes << {
1537         // Copy all of the download libraries to the libs directory for the sake of the IDEs
1538         File libsDir = rootProject.file("build/libs");
1539         
1540         // In some IDEs (Eclipse for example), touching these libraries cauese a full build
1541         // within the IDE.  When gradle is used outside of the IDE, for example to build the
1542         // native code, a full rebuild is caused within the IDE.  The fix is to check for the 
1543         // lib directory and not copy the files
1544         //
1545         // This means that in order to update the dependent libraries for the IDE's, a clean
1546         // build is required
1547         //
1548         if (libsDir.exists()) return;
1549         libsDir.mkdirs();
1550         for (File f : [configurations.compile.files, configurations.antlr3.files].flatten()) {
1551             copy {
1552                 into libsDir
1553                 from f.getParentFile()
1554                 include "**/antlr-3.1.3.jar"
1555                 include "**/stringtemplate-3.2.jar"
1556                 include "**/antlr-runtime-3.1.3.jar"
1557                 includeEmptyDirs = false
1558             }
1559             // Have to rename the swt jar because it is some platform specific name but
1560             // for the sake of the IDEs we need to have a single stable name that works
1561             // on every platform
1562             copy {
1563                 into libsDir
1564                 from f.getParentFile()
1565                 include "**/*swt*.jar"
1566                 includeEmptyDirs = false
1567                 rename ".*swt.*jar", "swt-debug\\.jar"
1568             }
1569         }
1570     }
1571 }
1572 
1573 project(":controls") {
1574     dependencies {
1575         compile BUILD_SRC, project(":base"), project(":graphics"), project(":designTime")
1576         // TODO not sure how to specify this? processResources project(":base"), project(":graphics")
1577         testCompile project(":graphics").sourceSets.test.output
1578         testCompile project(":base").sourceSets.test.output
1579     }
1580 
1581     test {
1582         jvmArgs "-Djavafx.toolkit=com.sun.javafx.pgstub.StubToolkit"
1583     }
1584 
1585     // TODO Css2Bin really should be moved out and put into buildSrc if it can be
1586     // TODO could change script to dynamically locate all .css files and create bss for them, probably better
1587     // TODO also not sure there is any benefit to having css files in the jfxrt.jar at all
1588     processResources << {
1589         ["$buildDir/resources/main/com/sun/javafx/scene/control/skin/caspian/caspian.css",
1590         "$buildDir/resources/main/com/sun/javafx/scene/control/skin/caspian/caspian-no-transparency.css",
1591         "$buildDir/resources/main/com/sun/javafx/scene/control/skin/caspian/embedded-qvga.css",
1592         "$buildDir/resources/main/com/sun/javafx/scene/control/skin/caspian/embedded.css",
1593         "$buildDir/resources/main/com/sun/javafx/scene/control/skin/caspian/fxvk.css",
1594         "$buildDir/resources/main/com/sun/javafx/scene/control/skin/caspian/highcontrast.css",
1595         "$buildDir/resources/main/com/sun/javafx/scene/control/skin/modena/modena.css",
1596         "$buildDir/resources/main/com/sun/javafx/scene/control/skin/modena/modena-no-transparency.css",
1597         "$buildDir/resources/main/com/sun/javafx/scene/control/skin/modena/touch.css"].each { css ->
1598             javaexec {
1599                 executable = JAVA
1600                 workingDir = "modules/controls"
1601                 classpath files("$buildDir/classes/main",
1602                         project(":graphics").sourceSets.main.output,
1603                         project(":base").sourceSets.main.output)
1604                 main = "com.sun.javafx.css.parser.Css2Bin"
1605                 args css
1606                 jvmArgs "-Djava.ext.dirs="
1607             }
1608         }
1609     }
1610 }
1611 
1612 project(":extensions") {
1613     dependencies {
1614         compile BUILD_SRC, project(":base"), project(":graphics")
1615     }
1616 }
1617 
1618 project(":swing") {
1619     /* should not be built, but needed in builders and JMX
1620     tasks.all {
1621         if (!COMPILE_SWING) it.enabled = false
1622     }
1623     */
1624     dependencies {
1625         compile BUILD_SRC, project(":base"), project(":graphics")
1626     }
1627 }
1628 
1629 project(":swt") {
1630     tasks.all {
1631         if (!COMPILE_SWT) it.enabled = false
1632     }
1633     dependencies {
1634         compile BUILD_SRC, project(":base"), project(":graphics")
1635         compile name: SWT_FILE_NAME
1636     }
1637 }
1638 
1639 project(":fxml") {
1640     dependencies {
1641         compile BUILD_SRC, project(":base"), project(":graphics"),
1642                 project(":controls"), project(":swt"), project(":swing")
1643         testCompile project(":graphics").sourceSets.test.output
1644     }
1645     test {
1646         // StubToolkit is not *really* needed here, but because some code inadvertently invokes performance
1647         // tracker and this attempts to fire up the toolkit and this looks for native libraries and fails,
1648         // we have to use the stub toolkit for now.
1649         jvmArgs "-Djavafx.toolkit=com.sun.javafx.pgstub.StubToolkit"
1650         classpath += files("$JDK_HOME/jre/lib/ext/nashorn.jar")
1651     }
1652 }
1653 
1654 project(":builders") {
1655     sourceCompatibility = 1.7
1656 
1657     if (!COMPILE_SWING) sourceSets.main.java.exclude ("**/swing/**")
1658     if (!COMPILE_SWT)   sourceSets.main.java.exclude ("**/swt/**")
1659 
1660     dependencies {
1661         compile BUILD_SRC, project(":base"), project(":graphics"),
1662                 project(":controls"), project(":swt"), project(":swing"), project(":media"), project(":web")
1663         testCompile project(":graphics").sourceSets.test.output
1664     }
1665     test {
1666         // StubToolkit is not *really* needed here, but because some code inadvertently invokes performance
1667         // tracker and this attempts to fire up the toolkit and this looks for native libraries and fails,
1668         // we have to use the stub toolkit for now.
1669         jvmArgs "-Djavafx.toolkit=com.sun.javafx.pgstub.StubToolkit"
1670     }
1671 }
1672 
1673 project(":designTime") {
1674     tasks.all {
1675         if (!COMPILE_DESIGN_TIME) it.enabled = false
1676     }
1677     dependencies {
1678         compile project(":graphics")
1679     }
1680 }
1681 
1682 project(":jmx") {
1683     dependencies {
1684         compile project(":base")
1685         compile project(":graphics")
1686         compile project(":swing")
1687         compile project(":media")
1688     }
1689 
1690     // Tests are disabled until RT-33926 can be fixed
1691     test.enabled = false
1692 }
1693 
1694 // This project is for system tests that need to run with a full SDK.
1695 // Most of them display a stage or do other things that preclude running
1696 // them in a shared JVM or as part of the "smoke test" run (which must
1697 // not pop up any windows or use audio). As such, they are only enabled
1698 // when FULL_TEST is specified, and each test runs in its own JVM
1699 project(":systemTests") {
1700     test {
1701         enabled = IS_FULL_TEST
1702         if (!IS_USE_ROBOT) {
1703             // Disable all robot-based visual tests
1704             exclude("**/helloworld/*.*");
1705             exclude("**/javafx/embed/swing/*.*");
1706             exclude("**/javafx/scene/layout/*.*");
1707             exclude("**/test3d/*.*");
1708             exclude("**/painttest/*.*");
1709         }
1710         if (!IS_AWT_TEST) {
1711             // Disable all AWT-based tests
1712             exclude("**/javafx/embed/swing/*.*");
1713             exclude("**/com/sun/javafx/application/Swing*.*");
1714         }
1715         forkEvery = 1
1716     }
1717 }
1718 
1719 project(":fxpackager") {
1720     tasks.all {
1721         if (!COMPILE_FXPACKAGER) it.enabled = false
1722     }
1723     // fxpackager has a dependency on ant in order to build the ant jar,
1724     // and as such needs to point to the apache binary repository
1725     if (!BUILD_CLOSED) {
1726         repositories {
1727             maven {
1728                 url "https://repository.apache.org"
1729             }
1730         }
1731     }
1732 
1733     dependencies {
1734         compile group: "org.apache.ant", name: "ant", version: "1.8.2"
1735     }
1736 
1737     // When producing the jar, we need to relocate a few class files
1738     // from their normal location to a resources/classes or resources/web-files
1739     // location
1740     jar {
1741         includeEmptyDirs = false
1742         archiveName = "ant-javafx.jar"
1743         eachFile { FileCopyDetails details ->
1744             if (details.path.startsWith("com/javafx/main")) {
1745                 details.path = "resources/classes/$details.path"
1746             }
1747         }
1748     }
1749 
1750     // The "man" task will create a $buildDir/man containing the man
1751     // files for the system being built
1752     task man(type: Copy) {
1753         includeEmptyDirs = false
1754         enabled = (IS_LINUX || IS_MAC) && COMPILE_FXPACKAGER
1755         from "src/main/man"
1756         into "$buildDir/man"
1757         exclude "**/*.html"
1758         if (IS_MAC) exclude "**/ja_JP.UTF-8/**"
1759     }
1760     processResources.dependsOn man
1761 
1762     // Compile the native launchers. These are included in ant-javafx.jar
1763     // TODO should teach this to know 32 / 64 bit
1764     if (IS_WINDOWS && COMPILE_FXPACKAGER) {
1765         task compileWinLauncher(type: CCTask, group: "Build") {
1766             description = "Compiles native sources for the application co-bundle launcher";
1767             matches = "WinLauncher\\.cpp";
1768             params.addAll(WIN.launcher.ccFlags);
1769             output(file("$buildDir/native/WinLauncher"));
1770             source(file("src/main/native/launcher/win"));
1771             compiler = WIN.launcher.compiler
1772             exe = true;
1773             linkerOptions.addAll(WIN.launcher.linkFlags);
1774             doLast {
1775                 copy {
1776                     from "$buildDir/native/WinLauncher/WinLauncher.exe"
1777                     into "$buildDir/classes/main/com/oracle/tools/packager/windows"
1778                 }
1779             }
1780         }
1781         task compileWinLauncherSvc(type: CCTask, group: "Build") {
1782             description = "Compiles native sources for the application co-bundle launcher";
1783             matches = "WinLauncherSvc\\.cpp";
1784             params.addAll(WIN.launcher.ccFlags);
1785             output(file("$buildDir/native/WinLauncherSvc"));
1786             source(file("src/main/native/launcher/win"));
1787             compiler = WIN.launcher.compiler
1788             exe = true;
1789             linkerOptions.addAll(WIN.launcher.linkFlags);
1790             doLast {
1791                 copy {
1792                     from "$buildDir/native/WinLauncherSvc/WinLauncherSvc.exe"
1793                     into "$buildDir/classes/main/com/oracle/tools/packager/windows"
1794                 }
1795             }
1796         }
1797         task compileIconSwap(type: CCTask, group: "Build") {
1798             description = "Compiles native sources for the application co-bundle launcher"
1799             matches = "IconSwap\\.cpp"
1800             params.addAll(WIN.iconLauncher.ccFlags)
1801             output(file("$buildDir/native/IconSwap"))
1802             source file("src/main/native/launcher/win")
1803             compiler = WIN.launcher.compiler
1804             exe = true
1805             linkerOptions.addAll(WIN.iconLauncher.linkFlags)
1806             doLast {
1807                 copy {
1808                     from "$buildDir/native/IconSwap/IconSwap.exe"
1809                     into "$buildDir/classes/main/com/oracle/tools/packager/windows"
1810                 }
1811             }
1812         }
1813         task compileLauncher(dependsOn: [compileWinLauncher, compileWinLauncherSvc, compileIconSwap])
1814         jar.dependsOn compileLauncher;
1815     } else if (COMPILE_FXPACKAGER) {
1816         if (IS_MAC) {
1817             task compileLauncher(type: CCTask, group: "Build") {
1818                 description = "Compiles native sources for the application co-bundle launcher"
1819                 matches = ".*\\.m"
1820                 output(file("$buildDir/classes/main/com/oracle/tools/packager/mac"))
1821                 params.addAll(MAC.launcher.ccFlags)
1822                 source file("src/main/native/launcher/mac")
1823                 compiler = MAC.launcher.compiler
1824                 eachOutputFile = { f ->
1825                     return new File(f.getParent(), "JavaAppLauncher")
1826                 }
1827             }
1828             jar.dependsOn compileLauncher;
1829         } else {
1830             def ccTask = project.task("compileLauncher", type: CCTask, group: "Build") {
1831                 description = "Compiles native sources for the application co-bundle launcher"
1832                 matches = ".*\\.c"
1833                 output(file("$buildDir/native/launcher"))
1834                 params.addAll(LINUX.launcher.ccFlags)
1835                 compiler = LINUX.launcher.compiler
1836                 source file("src/main/native/launcher/linux")
1837             }
1838             def linkTask = project.task("linkLauncher", type: LinkTask, dependsOn: ccTask, group: "Build") {
1839                 description = "Creates native dynamic library for the application co-bundle launcher"
1840                 linker = LINUX.launcher.linker
1841                 linkParams.addAll(LINUX.launcher.linkFlags)
1842                 objectDir = file("$buildDir/native/launcher")
1843                 lib = file("$buildDir/classes/main/com/oracle/tools/packager/linux/JavaAppLauncher")
1844             }
1845             jar.dependsOn linkTask;
1846         }
1847     }
1848 
1849     // Builds the javapackager executable. For everything other than windows,
1850     // this is simply moving the existing shell script and ensuring it has proper
1851     // permissions. For Windows, this includes compiling the native executable
1852     if (IS_WINDOWS && COMPILE_FXPACKAGER){
1853         task buildJavaPackager(type: CCTask, group: "Build") {
1854             description = "Compiles native sources for javapackager.exe"
1855             matches = "javapackager\\.cpp"
1856             params.addAll(WIN.fxpackager.ccFlags)
1857             compiler = WIN.fxpackager.compiler
1858             output(file("$buildDir/native/javapackager"))
1859             source WIN.fxpackager.nativeSource
1860             doFirst {
1861                 copy {
1862                     mkdir "$buildDir/native"
1863                     mkdir "$buildDir/native/javapackager"
1864                     from file("src/main/native/javapackager/win/javapackager.manifest")
1865                     into file("$buildDir/native/javapackager")
1866                     filter { line->
1867                         line = line.replace("FXVERSION", "${RAW_VERSION}.${HUDSON_BUILD_NUMBER}");
1868                     }
1869                 }
1870             }
1871             doLast {
1872                 mkdir "$buildDir/native"
1873                 exec({
1874                     commandLine("$RC", "/nologo", "/l", "0x409", "/r", "/dJFX_DVERSION=8", "/dJFX_VERSION=8",
1875                             "/fo$buildDir/native/javapackager/javapackager.res",
1876                             "src/main/native/javapackager/win/javapackager.rc");
1877                     environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT);
1878                 });
1879             }
1880             doLast {
1881                 mkdir "$buildDir/javapackager"
1882                 exec({
1883                     commandLine("$WIN.fxpackager.linker", "/nologo", "/opt:REF", "/incremental:no", "/manifest", "kernel32.lib", "advapi32.lib",
1884                             "/out:$buildDir/native/javapackager/javapackager.exe",
1885                             "$buildDir/native/javapackager/javapackager.obj",
1886                             "$buildDir/native/javapackager/javapackager.res")
1887                     environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
1888                 })
1889             }
1890             doLast {
1891                 exec({
1892                     commandLine("$MC", "-manifest",
1893                                        "$buildDir/native/javapackager/javapackager.manifest",
1894                                        "-outputresource:$buildDir/native/javapackager/javapackager.exe")
1895                     environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
1896                 })
1897                 copy {
1898                     from file("$buildDir/native/javapackager/javapackager.exe")
1899                     into file("$buildDir/javapackager")
1900                 }
1901                 copy {
1902                     from file("$buildDir/native/javapackager/javapackager.exe")
1903                     into file("$buildDir/javapackager")
1904                     rename ('javapackager', 'javafxpackager')
1905                 }
1906             }
1907         }
1908     } else {
1909         task buildJavaPackager(group: "Build") {
1910             enabled = COMPILE_FXPACKAGER
1911             doLast {
1912                 copy {
1913                     from "src/main/native/javapackager/shell"
1914                     into "$buildDir/javapackager"
1915                     fileMode = 0755
1916                 }
1917                 copy {
1918                     from "src/main/native/javapackager/shell"
1919                     into "$buildDir/javapackager"
1920                     rename ('javapackager', 'javafxpackager')
1921                     fileMode = 0755
1922                 }
1923             }
1924         }
1925     }
1926 
1927     jar.dependsOn buildJavaPackager
1928 
1929     classes << {
1930         // Copy all of the download libraries to libs directory for the sake of the IDEs
1931         File libsDir = rootProject.file("build/libs");
1932         File antLib = new File(libsDir, "ant-1.8.2.jar")
1933         libsDir.mkdirs();
1934         for (File f : configurations.compile.files) {
1935             copy {
1936                 into libsDir
1937                 from f.getParentFile()
1938                 include "**/ant-1.8.2.jar"
1939                 includeEmptyDirs = false
1940             }
1941         }
1942     }
1943 
1944     task packagerFakeJar(type: Jar) {
1945         dependsOn compileTestJava
1946         from compileTestJava.destinationDir
1947         include "hello/**"
1948 
1949         destinationDir project.file("build/tmp/tests/appResources")
1950         archiveName "mainApp.jar"
1951         
1952         manifest {
1953             attributes(
1954                     "Main-Class": "hello.TestPackager",
1955                     "Custom-Attribute": " Is it stripped?"
1956             )
1957         }
1958 
1959         doFirst {
1960             copy {
1961                 from "$projectDir/src/main/resources/com/oracle/tools/packager/linux/javalogo_white_48.png"
1962                 from "$projectDir/src/main/resources/com/oracle/tools/packager/mac/GenericAppHiDPI.icns"
1963                 from "$projectDir/src/main/resources/com/oracle/tools/packager/windows/javalogo_white_48.ico"
1964                 from "$projectDir/src/test/resources/hello/java-logo2.gif"
1965                 from "$projectDir/../../LICENSE"
1966                 into project.file("$projectDir/build/tmp/tests/appResources")
1967             }
1968             copy {
1969                 from "$projectDir/../../LICENSE"
1970                 into project.file("$projectDir/build/tmp/tests/appResources")
1971                 rename '(.*)LICENSE', '$1LICENSE2'
1972             }
1973         }
1974     }
1975     
1976     test {
1977         dependsOn packagerFakeJar
1978         systemProperty "RETAIN_PACKAGER_TESTS", RETAIN_PACKAGER_TESTS
1979         systemProperty "FULL_TEST", FULL_TEST
1980     }
1981 }
1982 
1983 project(":media") {
1984     configurations {
1985         media
1986     }
1987 
1988     dependencies {
1989         compile BUILD_SRC, project(":base"), project(":graphics")
1990     }
1991 
1992     sourceSets {
1993         tools {
1994             java.srcDir "src/tools/java"
1995         }
1996     }
1997 
1998     compileToolsJava {
1999         enabled = IS_COMPILE_MEDIA
2000         classpath = sourceSets.main.output;
2001     }
2002 
2003     project.ext.makeJobsFlag = IS_WINDOWS && IS_DEBUG_NATIVE ? "-j1" : "-j5";
2004     project.ext.buildType = IS_DEBUG_NATIVE ? "Debug" : "Release";
2005 
2006     def nativeSrcDir = file("${projectDir}/src/main/native")
2007     def generatedHeadersDir = file("${buildDir}/generated-src/headers")
2008     
2009     task generateHeaders(dependsOn: compileJava) {
2010         enabled = IS_COMPILE_MEDIA
2011         doLast {
2012             def classpath = sourceSets.main.output;
2013             mkdir generatedHeadersDir;
2014 
2015             def classesList = ["com.sun.media.jfxmedia.logging.Logger",
2016                              "com.sun.media.jfxmedia.track.AudioTrack",
2017                              "com.sun.media.jfxmedia.control.VideoDataBuffer",
2018                              "com.sun.media.jfxmedia.control.VideoFormat\$FormatTypes",
2019                              "com.sun.media.jfxmediaimpl.NativeAudioClip",
2020                              "com.sun.media.jfxmediaimpl.NativeMediaPlayer",
2021                              "com.sun.media.jfxmediaimpl.NativeVideoBuffer",
2022                              "com.sun.media.jfxmediaimpl.platform.gstreamer.GSTPlatform",
2023                              "com.sun.media.jfxmediaimpl.platform.gstreamer.GSTMedia",
2024                              "com.sun.media.jfxmediaimpl.platform.gstreamer.GSTMediaPlayer",
2025                              "com.sun.media.jfxmediaimpl.platform.gstreamer.GSTAudioEqualizer",
2026                              "com.sun.media.jfxmediaimpl.platform.gstreamer.GSTEqualizerBand",
2027                              "com.sun.media.jfxmediaimpl.platform.gstreamer.GSTAudioSpectrum"]
2028             if (IS_MAC) {
2029                 classesList.addAll( ["com.sun.media.jfxmediaimpl.platform.osx.OSXPlatform",
2030                                      "com.sun.media.jfxmediaimpl.platform.osx.OSXMedia",
2031                                      "com.sun.media.jfxmediaimpl.platform.osx.OSXMediaPlayer"] );
2032             }
2033             exec {
2034                 commandLine ("${JAVAH}", "-J-Djava.ext.dirs=", "-d", "${generatedHeadersDir}", "-classpath", "${classpath.asPath}");
2035                 args classesList;
2036             }
2037         }
2038     }
2039     
2040     task generateMediaErrorHeader(dependsOn: [compileToolsJava, compileJava]) {
2041         enabled = IS_COMPILE_MEDIA
2042         doLast {
2043             def classpath = files(sourceSets.main.output, sourceSets.tools.output);
2044             def sourcepath = sourceSets.main.java.srcDirs;
2045             def headerpath = file("$generatedHeadersDir/jfxmedia_errors.h");
2046             def srcRoot = (sourcepath.toArray())[0];
2047 
2048             mkdir generatedHeadersDir;
2049 
2050             exec {
2051                 commandLine("$JAVA", "-Djava.ext.dirs=", "-classpath", "${classpath.asPath}");
2052                 args("headergen.HeaderGen", "$headerpath", "$srcRoot");
2053             }
2054         }
2055     }
2056 
2057     task buildNativeTargets {
2058         enabled = IS_COMPILE_MEDIA
2059     }
2060     
2061     compileTargets { t->        
2062         def targetProperties = project.rootProject.ext[t.upper]
2063         def nativeOutputDir = file("${buildDir}/native/${t.name}")
2064         def projectDir = t.name.startsWith("arm") ? "linux" : t.name
2065         def mediaProperties = targetProperties.media
2066         
2067         def buildNative = task("build${t.capital}Native", dependsOn: [generateHeaders, generateMediaErrorHeader]) {
2068             enabled = targetProperties.compileMediaNative
2069             if (!targetProperties.compileMediaNative) {
2070                 println("Not compiling native Media for ${t.name} per configuration request");
2071             } 
2072 
2073             doLast {
2074                 exec {
2075                     commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/jfxmedia/projects/${projectDir}")
2076                     args("JAVA_HOME=${JDK_HOME}", "GENERATED_HEADERS_DIR=${generatedHeadersDir}",
2077                          "OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}", "BASE_NAME=jfxmedia")
2078 
2079                     if (t.name == "win") {
2080                         environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
2081                         args(IS_64 ? "ARCH=x64" : "ARCH=x32", "RESOURCE=${nativeOutputDir}/${buildType}/${WIN.media.jfxmediaRcFile}")
2082                     } else {
2083                         args ("CC=${mediaProperties.compiler}", "LINK=${mediaProperties.linker}", "LIB=${mediaProperties.lib}")
2084 
2085                         if (t.name.startsWith("arm"))
2086                             args("EXTRA_CFLAGS=${mediaProperties.extra_cflags}", "EXTRA_LDFLAGS=${mediaProperties.extra_ldflags}")
2087                         else
2088                             args("HOST_COMPILE=1")
2089                     }
2090                 }
2091             }
2092         }        
2093         
2094         // check for the property disable${name} = true
2095         def boolean disabled = targetProperties.containsKey('disableMedia') ? targetProperties.get('disableMedia') : false
2096         if (!disabled) {
2097             // Building GStreamer
2098             def buildGStreamer = task("build${t.capital}GStreamer") {
2099                 enabled = IS_COMPILE_MEDIA
2100                 doLast {
2101                     exec {
2102                         commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/gstreamer/projects/${projectDir}/gstreamer-lite")
2103                         args("OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}", "BASE_NAME=gstreamer-lite")
2104 
2105                         if (t.name == "win") {
2106                             environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
2107                             args(IS_64 ? "ARCH=x64" : "ARCH=x32", "RESOURCE=${nativeOutputDir}/${buildType}/${WIN.media.gstreamerRcFile}")
2108                         } else
2109                             args ("CC=${mediaProperties.compiler}", "LINK=${mediaProperties.linker}", "LIB=${mediaProperties.lib}")
2110                     }
2111                 }
2112             }
2113 
2114             def buildPlugins = task("build${t.capital}Plugins", dependsOn: buildGStreamer) {
2115                 enabled = IS_COMPILE_MEDIA
2116 
2117                 if (!project.ext.properties.containsKey("ON2_SRCDIR"))
2118                     project.ext.ON2_SRCDIR = "";
2119 
2120                 if (!project.ext.properties.containsKey("ON2_LIB"))
2121                     project.ext.ON2_LIB = "";
2122 
2123                 doLast {
2124                     exec {
2125                         commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/gstreamer/projects/${projectDir}/fxplugins")
2126                         args("OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}", "BASE_NAME=fxplugins", 
2127                              "ON2_SRCDIR=${project.ext.ON2_SRCDIR}", "ON2_LIB=${project.ext.ON2_LIB}")
2128 
2129                         if (t.name == "win") {
2130                             Map winEnv = new HashMap(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
2131 
2132                             String sdkDir = System.getenv("BASECLASSES_SDK_DIR");
2133                             if (sdkDir == null)
2134                             {
2135                                 sdkDir = "C:/Program Files/Microsoft SDKs/Windows/v7.1" // Default value
2136                                 winEnv["BASECLASSES_SDK_DIR"] = sdkDir
2137                             }
2138                             environment(winEnv)
2139 
2140                             args(IS_64 ? "ARCH=x64" : "ARCH=x32", "RESOURCE=${nativeOutputDir}/${buildType}/${WIN.media.fxpluginsRcFile}")
2141                         } else
2142                             args ("CC=${mediaProperties.compiler}", "LINK=${mediaProperties.linker}", "LIB=${mediaProperties.lib}")
2143                     }
2144                 }
2145             }
2146             
2147             buildNative.dependsOn buildPlugins
2148 
2149             if (t.name == "linux") {
2150                 def buildAVPlugin = task( "buildAVPlugin", dependsOn: [buildPlugins]) {
2151                     enabled = IS_COMPILE_MEDIA
2152 
2153                     if (!project.ext.properties.containsKey("LIBAV"))
2154                         project.ext.LIBAV = "";
2155 
2156                     doLast {
2157                         // Building fxavcodec plugin (libav plugin)
2158                         exec {
2159                             commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/gstreamer/projects/linux/avplugin")
2160                             args("CC=${mediaProperties.compiler}", "OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}", 
2161                                      "BASE_NAME=avplugin", "LIBAV_DIR=${project.ext.LIBAV}")
2162                         }
2163                     }
2164                 }
2165                 buildNative.dependsOn buildAVPlugin
2166             }
2167 
2168             if (t.name == "win") {
2169                 def buildResources = task("buildResources") << {
2170                     def rcOutputDir = "${nativeOutputDir}/${buildType}"
2171                     mkdir rcOutputDir
2172                     exec {
2173                         environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
2174                         commandLine (WIN.media.rcCompiler)
2175                         args(WIN.media.glibRcFlags)
2176                         args("/Fo${rcOutputDir}/${WIN.media.glibRcFile}", WIN.media.rcSource)
2177                     }
2178 
2179                     exec {
2180                         environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
2181                         commandLine (WIN.media.rcCompiler)
2182                         args(WIN.media.gstreamerRcFlags)
2183                         args("/Fo${rcOutputDir}/${WIN.media.gstreamerRcFile}", WIN.media.rcSource)
2184                     }
2185 
2186                     exec {
2187                         environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
2188                         commandLine (WIN.media.rcCompiler)
2189                         args(WIN.media.fxpluginsRcFlags)
2190                         args("/Fo${rcOutputDir}/${WIN.media.fxpluginsRcFile}", WIN.media.rcSource)
2191                     }
2192 
2193                     exec {
2194                         environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
2195                         commandLine (WIN.media.rcCompiler)
2196                         args(WIN.media.jfxmediaRcFlags)
2197                         args("/Fo${rcOutputDir}/${WIN.media.jfxmediaRcFile}", WIN.media.rcSource)
2198                     }
2199                 }
2200                 
2201                 def buildGlib = task("build${t.capital}Glib", dependsOn: [buildResources]) {
2202                     enabled = IS_COMPILE_MEDIA
2203                     doLast {
2204                         exec {
2205                             environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
2206                             commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/gstreamer/projects/${projectDir}/glib-lite")
2207                             args("OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}", "BASE_NAME=glib-lite",
2208                                  IS_64 ? "ARCH=x64" : "ARCH=x32", "RESOURCE=${nativeOutputDir}/${buildType}/${WIN.media.glibRcFile}")
2209                         }
2210                     }
2211                 }
2212                 buildGStreamer.dependsOn buildGlib
2213                 
2214             } else if (t.name == "mac") {
2215                 def buildGlib = task("build${t.capital}Glib") {
2216                     enabled = IS_COMPILE_MEDIA
2217                     doLast {
2218                         exec {
2219                             commandLine ("make", "${makeJobsFlag}", "-C", "${nativeSrcDir}/gstreamer/projects/${projectDir}/glib-lite")
2220                             args("OUTPUT_DIR=${nativeOutputDir}", "BUILD_TYPE=${buildType}", "BASE_NAME=glib-lite")
2221                             args ("CC=${mediaProperties.compiler}", "LINK=${mediaProperties.linker}", "LIB=${mediaProperties.lib}")
2222                         }
2223                     }
2224                 }
2225                 buildGStreamer.dependsOn buildGlib
2226             }
2227         }
2228         
2229         buildNativeTargets.dependsOn buildNative
2230     }
2231  
2232     jar {
2233         exclude("headergen/**")
2234 
2235         dependsOn compileJava
2236         if (IS_COMPILE_MEDIA)
2237             dependsOn buildNativeTargets
2238     }
2239 }
2240 
2241 project(":web") {
2242     configurations {
2243         webkit
2244     }
2245     dependencies {
2246         compile project(":base"), project(":graphics"), project(":controls"), project(":media")
2247     }
2248     
2249     compileJava {
2250         if (IS_COMPILE_WEBKIT) {
2251             // These classes will be generated by native build
2252             sourceSets.main.java.exclude("com/sun/webkit/dom/**")
2253         }
2254     }
2255     
2256     task generateHeaders(dependsOn: compileJava) {
2257         doLast {
2258             def classpath = files("$buildDir/classes/main",
2259                                   project(":graphics").sourceSets.main.output.classesDir)
2260             def dest = file("$buildDir/generated-src/headers");
2261             mkdir dest;
2262             exec {
2263                 commandLine("$JAVAH", "-J-Djava.ext.dirs=", "-d", "$dest",
2264                             "-classpath", "${classpath.asPath}");
2265                 args("java.lang.Character",
2266                      "java.net.IDN",
2267                      "com.sun.webkit.ContextMenu",
2268                      "com.sun.webkit.ContextMenuItem",
2269                      "com.sun.webkit.CursorManager",
2270                      "com.sun.webkit.PageCache",
2271                      "com.sun.webkit.PopupMenu",
2272                      "com.sun.webkit.SharedBuffer",
2273                      "com.sun.webkit.WatchdogTimer",
2274                      "com.sun.webkit.WebPage",
2275                      "com.sun.webkit.LoadListenerClient",
2276                      "com.sun.webkit.event.WCFocusEvent",
2277                      "com.sun.webkit.event.WCKeyEvent",
2278                      "com.sun.webkit.event.WCMouseEvent",
2279                      "com.sun.webkit.event.WCMouseWheelEvent",
2280                      "com.sun.webkit.graphics.GraphicsDecoder",
2281                      "com.sun.webkit.graphics.RenderMediaControls",
2282                      "com.sun.webkit.graphics.RenderTheme",
2283                      "com.sun.webkit.graphics.ScrollBarTheme",
2284                      "com.sun.webkit.graphics.WCMediaPlayer",
2285                      "com.sun.webkit.graphics.WCGraphicsManager",
2286                      "com.sun.webkit.graphics.WCRenderQueue",
2287                      "com.sun.webkit.graphics.WCPath",
2288                      "com.sun.webkit.graphics.WCPathIterator",
2289                      "com.sun.webkit.Timer",
2290                      "com.sun.webkit.WCFrameView",
2291                      "com.sun.webkit.WCPasteboard",
2292                      "com.sun.webkit.WCPluginWidget",
2293                      "com.sun.webkit.dom.JSObject",
2294                      "com.sun.webkit.network.SocketStreamHandle",
2295                      "com.sun.webkit.network.URLLoader",
2296                      "com.sun.webkit.text.TextBreakIterator",
2297                      "com.sun.webkit.text.TextNormalizer");
2298             }
2299         }
2300     }
2301 
2302     task compileGenerated()
2303 
2304     compileTargets { t ->
2305         def targetProperties = project.rootProject.ext[t.upper]
2306         def classifier = (t.name != "linux" && t.name != "win") ? t.name :
2307                           IS_64 ? "${t.name}-amd64" : "${t.name}-i586"
2308         dependencies {
2309             webkit group: "com.sun.webkit", name: "webview-deps",
2310                    version: "1.2", classifier: "$classifier", ext: "zip"
2311         }
2312 
2313         def webkitOutputDir = "$buildDir/${t.name}"
2314         def webkitConfig = IS_DEBUG_NATIVE ? "Debug" : "Release"
2315 
2316         def compileNativeTask = task("compileNative${t.capital}", dependsOn: generateHeaders) << {
2317             println "Building Webkit configuration /$webkitConfig/ into $webkitOutputDir"
2318             
2319             def dependencyFile = configurations.webkit.filter(
2320                     { File f -> f.getName().contains(classifier) }
2321                 ).getSingleFile()
2322             ant.unzip(src:  dependencyFile,
2323                       dest: webkitOutputDir)
2324 
2325             exec {
2326                 workingDir("$projectDir/src/main/native")
2327                 commandLine("perl", "Tools/Scripts/set-webkit-configuration", "--$webkitConfig")
2328                 environment(["WEBKITOUTPUTDIR" : webkitOutputDir])
2329             }
2330 
2331             exec {
2332                 workingDir("$projectDir/src/main/native")
2333                 if (t.name == "win") {
2334                     String qtDir = cygpath(System.getenv().get("QTSDK_DIR"))
2335                     String parfaitPath = IS_COMPILE_PARFAIT ? System.getenv().get("PARFAIT_PATH") + ";" : "";
2336                     Map environmentSettings = new HashMap(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
2337                     environmentSettings["PATH"] = parfaitPath + "$WINDOWS_VS_PATH;$qtDir/bin;$qtDir/qt/bin"
2338                     environmentSettings["QMAKESPEC"] = "win32-msvc2008"
2339                     environment(environmentSettings)
2340                     /* To build with ICU:
2341                     1. Download http://javaweb.us.oracle.com/jcg/fx-webrevs/RT-17164/WebKitLibrariesICU.zip
2342                     and unzip it to WebKitLibraries folder.
2343                     2. Copy DLLs from
2344                     WebKitLibrariesICU.zip\WebKitLibraries\import\runtime
2345                     to %windir%\system32
2346                     3. Uncomment the line below
2347                      */
2348                     // args("--icu-unicode")
2349                 } else if (t.name == "mac") {
2350                     environment([
2351                         "QMAKESPEC"      : "macx-g++",
2352                         "QMAKE_CFLAGS"   : "-m64",
2353                         "QMAKE_LFLAGS"   : "-m64",
2354                     ])
2355                 } else if (t.name.startsWith("arm")) {
2356                     // ARM cross build
2357                     def webkitProperties = project.rootProject.ext[t.upper].webkit
2358                     def qmakeSpecDir = "$webkitOutputDir/qws/linux-cross-${t.name}-g++"
2359                     mkdir qmakeSpecDir
2360                     File qmakeSpec = new File("$qmakeSpecDir/qmake.conf")
2361                     qmakeSpec.append(
2362 """TARGET_PLATFORM         = unix
2363 include(/usr/share/qt4/mkspecs/common/linux.conf)
2364 include(/usr/share/qt4/mkspecs/common/g++.conf)
2365 include(/usr/share/qt4/mkspecs/common/qws.conf)
2366 QMAKE_CC                = $webkitProperties.compiler
2367 QMAKE_CXX               = $webkitProperties.linker
2368 QMAKE_LINK              = $webkitProperties.linker
2369 QMAKE_LINK_SHLIB        = $webkitProperties.linker
2370 QMAKE_AR                = $webkitProperties.ar cqs
2371 QMAKE_OBJCOPY           = $webkitProperties.objcopy
2372 QMAKE_STRIP             = $webkitProperties.strip
2373 QMAKE_CXXFLAGS          = $webkitProperties.ccFlags
2374 QMAKE_LFLAGS            = $webkitProperties.linkFlags
2375 load(qt_config)""")
2376                     environment([
2377                         "QMAKESPEC" : file(qmakeSpecDir).getAbsolutePath(),
2378                         "PATH"      : "$System.env.PATH:$webkitProperties.binDir",
2379                     ])
2380                     args("--nocache")
2381                 }
2382                 environment([
2383                     "JAVA_HOME"       : JDK_HOME,
2384                     "WEBKITOUTPUTDIR" : webkitOutputDir,
2385                 ])
2386 
2387                 if (IS_COMPILE_PARFAIT) {
2388                     environment([
2389                         "CC"        : "parfait-gcc",
2390                         "QMAKE_CC"  : "parfait-gcc",
2391                         "CXX"       : "parfait-g++",
2392                         "QMAKE_CXX" : "parfait-g++",
2393                         "CPP"       : "parfait-g++",
2394                         "cc"        : "parfait-gcc",
2395                         "LINK"      : "parfait-g++",
2396                         "QMAKE_LINK": "parfait-g++",
2397                     ])
2398                 }
2399                 commandLine("perl", "Tools/Scripts/build-webkit", "--java", "--imageio")
2400             }
2401 
2402             def library = rootProject.ext[t.upper].library
2403             copy {
2404                 from "$webkitOutputDir/$webkitConfig/lib/${library('jfxwebkit')}"
2405                 into "$buildDir/libs/${t.name}"
2406             }
2407             copy {
2408                 from "$webkitOutputDir/$webkitConfig/lib/${library('DumpRenderTreeJava')}"
2409                 into "$buildDir/test/${t.name}"
2410             }
2411         }
2412     
2413         if (IS_WINDOWS && t.name == "win") {
2414             def webkitProperties = project.rootProject.ext[t.upper].webkit
2415             def rcTask = project.task("rc${t.capital}", type: CompileResourceTask) {
2416                 compiler = webkitProperties.rcCompiler
2417                 source(webkitProperties.rcSource)
2418                 if (webkitProperties.rcFlags) {
2419                     rcParams.addAll(webkitProperties.rcFlags)
2420                 }
2421                 output(file("$webkitOutputDir/$webkitConfig/WebCore/obj"))
2422             }
2423             compileNativeTask.dependsOn rcTask
2424         }
2425         
2426         def compileGeneratedTask = task("compileGenerated${t.capital}", type: JavaCompile, dependsOn: compileNativeTask) {
2427             def gensrcDir = "$webkitOutputDir/$webkitConfig/WebCore/generated/java"
2428             doFirst {
2429                 copy {
2430                     from "$projectDir/src/main/java/com/sun/webkit/dom/EventListenerImpl.java"
2431                     into "$gensrcDir/com/sun/webkit/dom"
2432                 }
2433             }
2434             classpath = files(project(":graphics").sourceSets.main.output) // for JSObject
2435             source gensrcDir
2436             destinationDir = file("$buildDir/classes/main")
2437         }
2438 
2439         compileGenerated.dependsOn compileGeneratedTask
2440             
2441         if (!targetProperties.compileWebnodeNative) {
2442             println("Not compiling native Webkit for ${t.name} per configuration request");
2443             compileNativeTask.enabled = false
2444         }
2445     }
2446     
2447     def drtClasses = "com/sun/javafx/webkit/drt/**"
2448     jar.exclude(drtClasses)
2449     task drtJar(type: Jar, dependsOn: compileJava) {
2450         archiveName = "drt.jar"
2451         destinationDir = file("$buildDir/test")
2452         from "$buildDir/classes/main"
2453         include drtClasses
2454     }
2455 
2456     if (IS_COMPILE_WEBKIT) {
2457         jar.dependsOn compileGenerated, drtJar
2458     }
2459 }
2460 
2461 allprojects {
2462     // The following block is a workaround for the fact that presently Gradle
2463     // can't set the -XDignore.symbol.file flag, because it appears that the
2464     // javac API is lacking support for it. So what we'll do is find any Compile
2465     // task and manually provide the options necessary to fire up the
2466     // compiler with the right settings.
2467     //
2468     // Also, we need to remove jfxrt.jar from the ext classpath (if it is there)
2469     tasks.withType(Compile) { compile ->
2470         // It looks like we have to use ant to compile instead of the built-in gradle
2471         // compiler stuff because otherwise it won't compile on CYGWIN
2472         // TODO need to file issue with Gradle
2473         compile.options.useAnt = true
2474         compile.options.debug = true // we always generate debugging info in the class files
2475         compile.options.debugOptions.debugLevel = IS_DEBUG_JAVA ? "source,lines,vars" : "source,lines"
2476         compile.options.fork = true
2477         compile.options.forkOptions.executable = JAVAC
2478         compile.options.warnings = IS_LINT
2479         compile.options.useDepend = IS_USE_DEPEND
2480         compile.options.compilerArgs = ["-Djava.ext.dirs=", "-XDignore.symbol.file", "-encoding", "UTF-8"]
2481 
2482         // Add in the -Xlint options
2483         if (IS_LINT) {
2484             LINT.split("[, ]").each { s ->
2485                 compile.options.compilerArgs += "-Xlint:$s"
2486             }
2487         }
2488     }
2489 }
2490 
2491 /******************************************************************************
2492  *                                                                            *
2493  *                             Top Level Tasks                                *
2494  *                                                                            *
2495  *  These are the tasks which are defined only for the top level project and  *
2496  *  not for any sub projects. These are generally the entry point that is     *
2497  *  used by Hudson and by the continuous build system.                        *
2498  *                                                                            *
2499  *****************************************************************************/
2500 
2501 task clean() {
2502     group = "Basic"
2503     description = "Deletes the build directory and the build directory of all sub projects"
2504     getSubprojects().each { subProject ->
2505         dependsOn(subProject.getTasksByName("clean", true));
2506     }
2507     doLast {
2508         delete(buildDir);
2509     }
2510 }
2511 
2512 
2513 task javadoc(type: Javadoc) {
2514     enabled = IS_BUILD_JAVADOC
2515     group = "Basic"
2516     description = "Generates the JavaDoc for all the public API"
2517     executable = JAVADOC
2518     def projectsToDocument = [
2519             project(":base"), project(":graphics"), project(":controls"), project(":media"),
2520             project(":swing"), project(":swt"), project(":fxml"), project(":web")]
2521     source(projectsToDocument.collect({
2522         [it.sourceSets.main.java, "$it.buildDir/generated-src/builders"]
2523     }));
2524     setDestinationDir(new File(buildDir, 'javadoc'));
2525     // Might need a classpath
2526     classpath = files(projectsToDocument.collect { project ->
2527         project.sourceSets.main.compileClasspath
2528     });
2529     classpath += files(projectsToDocument.collect { project ->
2530         project.sourceSets.main.output
2531     });
2532     exclude("com/**/*", "javafx/scene/ParentDesignInfo*", "Compile*", "javafx/builder/**/*", "javafx/scene/accessibility/**/*");
2533     options.windowTitle("${javadocTitle}")
2534     options.header("${javadocHeader}")
2535     options.bottom("${javadocBottom}")
2536     if (BUILD_CLOSED) {
2537         options.linksOffline(JDK_DOCS, JDK_DOCS_CLOSED);
2538     } else {
2539         options.links(JDK_DOCS);
2540     }
2541     options.addBooleanOption("XDignore.symbol.file").setValue(true);
2542     options.addBooleanOption("Xdoclint:none").setValue(!IS_DOC_LINT);
2543     options.addBooleanOption("javafx").setValue(true);
2544     options.addBooleanOption("use").setValue(true);
2545     doLast {
2546         projectsToDocument.each { p ->
2547             copy {
2548                 from "$p.projectDir/src/main/docs"
2549                 into "$buildDir/javadoc"
2550             }
2551         }
2552     }
2553 
2554     dependsOn(projectsToDocument.collect { project -> project.getTasksByName("classes", true)});
2555 }
2556 
2557 task jfxrt() {
2558     rootProject.getTasksByName("compileTestJava", true).each { t ->
2559         if (t.enabled) t.dependsOn(jfxrt)
2560     }
2561 }
2562 
2563 task sdk() {
2564     dependsOn(checkJfxrtJar)
2565 
2566     rootProject.getTasksByName("test", true).each { t ->
2567         if (t.enabled) t.dependsOn(sdk)
2568     }
2569 }
2570 
2571 task appsjar() {
2572     dependsOn(sdk)
2573     // Note: the jar dependencies get added elsewhere see project(":apps")
2574 }
2575 
2576 // these are empty tasks, allowing us to depend on the task, which may have other
2577 // real work items added later.
2578 task copyAppsArtifacts() {
2579     dependsOn(appsjar)
2580 }
2581 
2582 task apps() {
2583     dependsOn(sdk)
2584     dependsOn(appsjar)
2585     dependsOn(copyAppsArtifacts)
2586 }
2587 
2588 task findbugs() {
2589     dependsOn(sdk)
2590 
2591     // TODO: implement this
2592     doLast {
2593         if (!BUILD_CLOSED) {
2594             println "findbugs task is not implemented"
2595         }
2596     }
2597 }
2598 
2599 // The following tasks are for the closed build only. They are a no-op for the open build
2600 
2601 task checkCache() {
2602     dependsOn(updateCacheIfNeeded)
2603 }
2604 
2605 // TODO: consider moving the "public-sdk" portion of this task here
2606 task publicExports() {
2607     doFirst {
2608         if (!IS_BUILD_JAVADOC) {
2609             fail("publicExports task requires: -PBUILD_JAVADOC=true")
2610         }
2611     }
2612     dependsOn(sdk)
2613     doLast {
2614         if (!BUILD_CLOSED) {
2615             println "publicExports task is only run for a closed build"
2616         }
2617     }
2618 }
2619 
2620 task perf() {
2621     dependsOn(sdk,apps)
2622     doLast {
2623         if (!BUILD_CLOSED) {
2624             println "perf task is only run for a closed build"
2625         }
2626     }
2627 }
2628 
2629 task zips() {
2630     doFirst {
2631         if (!IS_BUILD_JAVADOC) {
2632             fail("zips task requires: -PBUILD_JAVADOC=true")
2633         }
2634     }
2635     dependsOn(sdk,publicExports,apps,perf)
2636     doLast {
2637         if (!BUILD_CLOSED) {
2638             println "zips task is only run for a closed build"
2639         }
2640     }
2641 }
2642 
2643 task copySources(type: Copy) {
2644     enabled = IS_BUILD_SRC_ZIP
2645     def projectsToCopy = [
2646             project(":base"), project(":graphics"), project(":controls"),
2647             project(":swing"), project(":swt"), project(":fxml"),
2648             project(":builders"), project(":media"), project(":web")]
2649     from(projectsToCopy.collect({ proj ->
2650         files(proj.sourceSets.main.java.srcDirs)
2651     }))
2652     include "**/*.java"
2653     into "${buildDir}/javafx-src"
2654 }
2655 
2656 task zipSources(type: Zip) {
2657     enabled = IS_BUILD_SRC_ZIP
2658     dependsOn(copySources)
2659     archiveName = "javafx-src.zip"
2660     destinationDir = file("$buildDir")
2661     includeEmptyDirs = false
2662     from "${buildDir}/javafx-src"
2663 }
2664 
2665 task src {
2666     enabled = IS_BUILD_SRC_ZIP
2667     description = "Created the javafx-src.zip bundle"
2668     dependsOn(zipSources)
2669 }
2670 
2671 task all() {
2672     dependsOn(sdk,publicExports,apps,perf,zips)
2673 }
2674 
2675 compileTargets { t ->
2676     def targetProperties = project.ext[t.upper]
2677     def sdkDirName = targetProperties.sdkDirName
2678     def library = targetProperties.library
2679     // The jfxrt task is responsible for creating the jfxrt.jar. A developer may
2680     // have multiple SDK's on their system at any one time, depending on which
2681     // cross compiles they have done. For example, I might have:
2682     //      build/ios-sdk/rt/lib/ext/jfxrt.jar
2683     //      build/armhf-sdk/rt/lib/ext/jfxrt.jar
2684     // and so forth. The default host build will always install into 'sdk' 
2685     // allowing for uses where a known sdk path is needed (like IDEs)
2686     //      build/sdk/rt/lib/ext/jfxrt.jar
2687     // This arrangement allows for multiple independent SDKs to
2688     // exist on a developer's system.
2689     def jfxrtTask = task("jfxrt$t.capital", type: Jar) {
2690         group = "Basic"
2691         description = "Creates the jfxrt.jar for the $t.name target"
2692         archiveName = "build/${sdkDirName}/rt/lib/ext/jfxrt.jar";
2693         includeEmptyDirs = false
2694         from("modules/base/build/classes/main",
2695              "modules/base/build/resources/main",
2696              "modules/builders/build/classes/main",
2697              "modules/graphics/build/classes/main",
2698              "modules/graphics/build/resources/main",
2699              "modules/controls/build/classes/main",
2700              "modules/controls/build/resources/main",
2701              "modules/fxml/build/classes/main",
2702              "modules/fxml/build/resources/main",
2703              "modules/graphics/build/classes/jsl-decora",
2704              "modules/graphics/build/resources/jsl-decora",
2705              "modules/graphics/build/classes/jsl-prism",
2706              "modules/graphics/build/resources/jsl-prism",
2707              "modules/media/build/classes/main",
2708              "modules/media/build/resources/main")
2709         if (COMPILE_SWING) from ("modules/swing/build/classes/main", "modules/swing/build/resources/main")
2710 
2711         if (!IS_MAC) {
2712             exclude ("modules/media/build/classes/main/com/sun/media/jfxmediaimpl/platform/osx/**",
2713                      "com/sun/prism/es2/MacGL*",
2714                      "com/sun/glass/events/mac",
2715                      "com/sun/glass/ui/mac",
2716                      "com/sun/prism/es2/gl/mac"
2717                      )
2718         }
2719         if (!IS_WINDOWS) {
2720             exclude ("**/*.hlsl",
2721                      "com/sun/glass/ui/win",
2722                      "com/sun/prism/d3d",
2723                      "com/sun/prism/es2/gl/win",
2724                      "com/sun/prism/es2/WinGL*",
2725                      "com/sun/scenario/effect/impl/hw/d3d"
2726                      )
2727         }
2728         if (!targetProperties.includeGTK) { //usually IS_LINUX 
2729             exclude (
2730                      "com/sun/glass/ui/gtk",
2731                      "com/sun/prism/es2/EGL*",
2732                      "com/sun/prism/es2/gl/eglfb",
2733                      "com/sun/prism/es2/gl/eglx11",
2734                      "com/sun/prism/es2/gl/x11",
2735                      "com/sun/prism/es2/X11GL*"
2736                      )
2737         }
2738         if (!targetProperties.includeEGL) {
2739             exclude ("com/sun/prism/es2/EGL*")
2740         }
2741         if (!targetProperties.includeLens) {
2742             exclude ("com/sun/glass/ui/lens")
2743         }
2744         /* Note: Monocle is used in the test harness, and so should
2745          * not be excluded until the deploy phase
2746         if (!targetProperties.includeMonocle) {
2747             exclude ("com/sun/glass/ui/monocle")
2748         }
2749         */
2750         if (!targetProperties.includeNull3d) {
2751             // "com/sun/prism/null3d", // TODO This is used in dev builds but not the final sdk
2752             exclude ("com/sun/prism/null3d")
2753         }
2754         if (t.name != 'ios') {
2755             exclude ("modules/media/build/classes/main/com/sun/media/jfxmediaimpl/platform/ios/**",
2756                      "com/sun/glass/ui/ios",
2757                      "com/sun/prism/es2/IOS*"
2758                      )
2759         }
2760         if (t.name != 'android' && t.name != 'dalvik') {
2761             exclude ("com/sun/glass/ui/android/*")
2762         }
2763 
2764         if (t.name == 'android') {
2765             from ("modules/web/build/classes/android",
2766                   "modules/web/build/resources/android",
2767                   "modules/controls/build/classes/android",
2768                   "modules/controls/build/resources/android")
2769         } else if (t.name == 'ios') {
2770             from ("modules/web/build/classes/ios",
2771                   "modules/web/build/resources/ios",
2772                   "modules/extensions/build/classes/ios")
2773         } else {
2774             from ("modules/web/build/classes/main", "modules/web/build/resources/main")
2775         }
2776 
2777         exclude("**/javafx/embed/swt/**")
2778 
2779         if (!targetProperties.includeSWT) {
2780             exclude("com/sun/glass/ui/swt")
2781         }
2782 
2783         if (!targetProperties.includeSwing) {
2784             exclude("javafx/embed/swing")
2785         }
2786         exclude("js/**/*", // er...
2787                 "PrismLoaderBackend*", // More decora stuff
2788                 "**/*.stg",    // any glue files for decora must be excluded
2789                 "**/*.java");  // Builder java files are in build/classes and should be excluded
2790 
2791         // Filter out platform specific Java sources (glass) when compiling for other targets
2792         if (targetProperties.containsKey('jfxrtJarExcludes')) {
2793             exclude(targetProperties.jfxrtJarExcludes)
2794         }
2795 
2796         dependsOn(subprojects.collect { project -> project.getTasksByName("assemble", true)});
2797     }
2798     def jfxrtIndexTask = task("jfxrtIndex$t.capital") {
2799         //the following is a workaround for the lack of indexing in gradle 1.4 through 1.7
2800         dependsOn(jfxrtTask)
2801 
2802         doLast() {
2803             ant.jar (update: true, index: true, destfile: jfxrtTask.archiveName)
2804         }
2805     }
2806     jfxrt.dependsOn(jfxrtIndexTask)
2807 
2808     def jfxswtTask = task("jfxswt$t.capital", type: Jar) {
2809         enabled = COMPILE_SWT
2810         group = "Basic"
2811         description = "Creates the jfxswt.jar for the $t.name target"
2812         archiveName = "build/${sdkDirName}/rt/lib/jfxswt.jar";
2813         includeEmptyDirs = false
2814         from("modules/swt/build/classes/main");
2815         from("modules/builders/build/classes/main");
2816         include("**/javafx/embed/swt/**")
2817         exclude("**/*.java");  // Builder java files are in build/classes and should be excluded
2818 
2819         dependsOn(subprojects.collect { project -> project.getTasksByName("assemble", true)});
2820     }
2821     def jfxswtIndexTask = task("jfxswtIndex$t.capital") {
2822         //the following is a workaround for the lack of indexing in gradle 1.4 through 1.7
2823         dependsOn(jfxswtTask)
2824 
2825         doLast() {
2826             ant.jar (update: true, index: true, destfile: jfxswtTask.archiveName)
2827         }
2828     }
2829     jfxrt.dependsOn(jfxswtIndexTask)
2830 
2831     def jmxTask = task ("jmx${t.capital}", type: Jar) {
2832         group = "Basic"
2833         description = "Creates the javafx-mx.jar"
2834         archiveName = "build/${sdkDirName}/lib/javafx-mx.jar";
2835         includeEmptyDirs = false
2836         from "modules/jmx/build/classes/main"
2837         from "modules/jmx/build/resources/main"
2838         dependsOn project(":jmx").assemble
2839     }
2840 
2841     // The 'sdk' task will build the rest of the SDK, and depends on the 'jfxrtTask' task. After
2842     // executing this task the sdk bundle for the current COMPILE_TARGETS will be fully created.
2843     def sdkTask = task("sdk$t.capital") {
2844         group = "Basic"
2845         description = "Creates the SDK for $t.name"
2846         doLast {
2847             // TODO instead of using copy everywhere, I probably want to use "sync" instead?
2848             // Copy all of the .dll / .so / .dylib native libraries into build/sdk/rt/lib/
2849             copy {
2850                 def useLipo = targetProperties.containsKey('useLipo') ? targetProperties.useLipo : false
2851                 from("modules/graphics/build/libs/jsl-decora/${t.name}/${library(targetProperties.decora.lib)}")
2852                 def libs = ['font', 'prism', 'prismSW', 'prismES2', 'glass', 'iio']
2853                 if (IS_COMPILE_PANGO) {
2854                     libs += ['fontFreetype', 'fontPango'];
2855                 }
2856                 libs.each { lib ->
2857                     def variants = targetProperties[lib].containsKey('variants') && !useLipo ? targetProperties[lib].variants : [null]
2858                     variants.each { variant ->
2859                         def variantProperties = variant ? targetProperties[lib][variant] : targetProperties[lib]
2860                         println "modules/graphics/build/libs/$lib/$t.name/${library(variantProperties.lib)}"
2861                         from ("modules/graphics/build/libs/$lib/$t.name/${library(variantProperties.lib)}")
2862                     }
2863                 }
2864                 if (IS_WINDOWS) {
2865                     from ("modules/graphics/build/libs/prismD3D/${t.name}/${library(targetProperties.prismD3D.lib)}");
2866                 }
2867                 if (IS_COMPILE_WEBKIT) {
2868                     from ("modules/web/build/libs/${t.name}/${library('jfxwebkit')}")
2869                 } else {
2870                     if (t.name != "android" && t.name != "ios") {
2871                         from ("$LIBRARY_STUB/${library('jfxwebkit')}")
2872                     }
2873                 }
2874 
2875                 def mediaBuildType = project(":media").ext.buildType
2876                 if (IS_COMPILE_MEDIA) {
2877                     [ "fxplugins", "gstreamer-lite", "jfxmedia" ].each { name ->
2878                         from ("modules/media/build/native/${t.name}/${mediaBuildType}/${library(name)}") }
2879                     
2880                     if (t.name == "linux") from ("modules/media/build/native/${t.name}/${mediaBuildType}/${library("avplugin")}")
2881                     else from ("modules/media/build/native/${t.name}/${mediaBuildType}/${library("glib-lite")}")                        
2882                 } else {
2883                     [ "fxplugins", "gstreamer-lite", "jfxmedia" ].each { name ->
2884                         from ("$LIBRARY_STUB/${library(name)}") }
2885 
2886                     if (t.name == "linux") from ("$LIBRARY_STUB/${library("avplugin")}")
2887                     else from ("$LIBRARY_STUB/${library("glib-lite")}")
2888                 }
2889                 
2890                 def libDest = targetProperties.libDest
2891                 into ("build/${sdkDirName}/rt/$libDest")
2892             }
2893 
2894             // Create the javafx.properties file
2895             final File javafxProperties = file("build/${sdkDirName}/rt/lib/javafx.properties")
2896             javafxProperties.delete()
2897             javafxProperties << "javafx.runtime.version=$RAW_VERSION";
2898             javafxProperties << "\n"
2899             // Include any properties that have been defined (most likely in
2900             // one of the various platform gradle files)
2901             if (targetProperties.containsKey("javafxProperties")) {
2902                 javafxProperties << targetProperties.javafxProperties
2903                 javafxProperties << "\n"
2904             }
2905 
2906             // Embedded builds define this file as well
2907             if (targetProperties.containsKey("javafxPlatformProperties")) {
2908                 final File javafxPlatformProperties = file("build/${sdkDirName}/rt/lib/javafx.platform.properties")
2909                 javafxPlatformProperties.delete()
2910                 javafxPlatformProperties << targetProperties.javafxPlatformProperties
2911                 javafxPlatformProperties << "\n"
2912             }
2913 
2914             // Copy over the javadocs that were generated. This is done rather than just generating
2915             // the docs into the "right place" because for a cross-compile you only need one set of
2916             // docs but need to have a copy in each created sdk
2917             if (IS_BUILD_JAVADOC) {
2918                 copy {
2919                     from "build/javadoc"
2920                     into "build/${sdkDirName}/docs/api"
2921                 }
2922             }
2923 
2924             // Copy over the javafx-src bundle
2925             if (IS_BUILD_SRC_ZIP) {
2926                 copy {
2927                     from "build/javafx-src.zip"
2928                     into "build/${sdkDirName}"
2929                 }
2930             }
2931 
2932             // Copy over the fxpackager and rename as ant-javafx.jar
2933             copy {
2934                 from "modules/fxpackager/build/libs"
2935                 into "build/${sdkDirName}/lib"
2936             }
2937 
2938             // Copy over the FXPackager man files
2939             copy {
2940                 from "modules/fxpackager/build/man"
2941                 into "build/${sdkDirName}/man"
2942             }
2943 
2944             // Copy over the javapackager executable
2945             if (t.name == "win" || t.name == "linux" || t.name == "mac") {
2946                 copy {
2947                     from "modules/fxpackager/build/javapackager"
2948                     into "build/${sdkDirName}/bin"
2949                 }
2950             }
2951         }
2952         dependsOn(jmxTask);
2953         dependsOn(jfxrtIndexTask)
2954         dependsOn(jfxswtIndexTask)
2955         dependsOn(javadoc)
2956         dependsOn(src)
2957     }
2958 
2959     def generateSymbols = targetProperties.containsKey('generateSymbols') ? targetProperties.generateSymbols : false
2960     if (generateSymbols) {
2961         def exportedSymbolsTask = project.task("exportedSymbols${t.capital}", type: ExportedSymbolsTask, dependsOn: sdkTask, group: "Build") {
2962             description = "Generates exported symbols file for iOS build (from .a libraries)"
2963             def libDirName = "build/${sdkDirName}/rt/$targetProperties.libDest"
2964             libDir = file("$libDirName")
2965             outputFile = file("$libDirName/exported.symbols")
2966             excludes = targetProperties.generateSymbolsExcludes
2967         }
2968         sdk.dependsOn(exportedSymbolsTask)
2969     }
2970 
2971     sdk.dependsOn(sdkTask)
2972 }
2973 
2974     //task integrationCheck {
2975     //    group = "Basic"
2976     //    description = "Performs all the tasks necessary to ensure that the current build is ready for integration."
2977     //    dependsOn sdk
2978     //    dependsOn subprojects.collect { project -> project.getTasksByName("check", true)}
2979     //}
2980 
2981 /*
2982  * This clause changes the way we handle a build.gradle within ./apps
2983  * It does a few things:
2984  *   modifies the classpath used to include the built runttime classes
2985  *   provides for copying the build applications to the artifacts tree
2986  *
2987  * The applications to be built will be under ./apps, but also must
2988  * be listed in the applications listed in the setting variable: JFXApplications
2989  */
2990 ext.JFXRT_CP =
2991     files(
2992         project(":base").sourceSets.main.output.classesDir,
2993         project(":graphics").sourceSets.main.output.classesDir,
2994         project(":controls").sourceSets.main.output.classesDir,
2995         project(":fxml").sourceSets.main.output.classesDir,
2996         project(":swing").sourceSets.main.output.classesDir, //NOTE - used by 3Dviewer
2997         project(":builders").sourceSets.main.output.classesDir,
2998             "modules/media/build/classes/main",
2999             "modules/web/build/classes/main",
3000     )
3001 
3002 project(":apps") {
3003     // The apps build is Ant based, and gradle lets us "import" ant build.xml
3004     // into our configuration.
3005 
3006     ant.importBuild 'build.xml'
3007 
3008     compileTargets { t ->
3009         // The apps build is Ant based, and gradle lets us "import" ant apps/build.xml
3010         // into our configuration.
3011 
3012         // override the apps build.xml with an explicit pointer to our jar.
3013         def sdkDirName = rootProject.ext[t.upper].sdkDirName
3014         def jfxrtJar = "${rootProject.buildDir}/${sdkDirName}/rt/lib/ext/jfxrt.jar"
3015 
3016         def appsJar = project.task("appsJar${t.capital}") {
3017             doLast() {
3018               ant.properties['targetBld'] = "$t.name"
3019               if (!rootProject.ext[t.upper].compileSwing) {
3020                 ant.properties['JFX_CORE_ONLY'] = 'true'
3021               }
3022               ant.properties['jfxbuild.jfxrt.jar'] = jfxrtJar
3023               ant.properties['platforms.JDK_1.8.home'] = "${rootProject.ext.JDK_HOME}"
3024               ant.project.executeTarget("sampleAppsJar")
3025               ant.project.executeTarget("scenebuilderSampleAppsJar")
3026               if (!t.name.startsWith("arm")) {
3027                 ant.project.executeTarget("scenebuilderAppJar")
3028               }
3029             }
3030         }
3031         rootProject.appsjar.dependsOn(appsJar)
3032 
3033         def appsClean = project.task("appsClean${t.capital}") {
3034             doLast() {
3035               ant.properties['targetBld'] = "$t.name"
3036               ant.properties['platforms.JDK_1.8.home'] = "${rootProject.ext.JDK_HOME}"
3037               ant.project.executeTarget("sampleAppsClean")
3038               ant.project.executeTarget("scenebuilderSampleAppsClean")
3039               if (!t.name.startsWith("arm")) {
3040                 ant.project.executeTarget("scenebuilderAppClean")
3041               }
3042             }
3043         }
3044         rootProject.clean.dependsOn(appsClean)
3045     }
3046 }
3047 
3048 /******************************************************************************
3049  *                                                                            *
3050  *                              BUILD_CLOSED                                  *
3051  *                                                                            *
3052  * This next section should remain at the end of the build script. It allows  *
3053  * for a "supplemental" gradle file to be used to extend the normal build     *
3054  * structure. For example, this is used for passing a supplemental gradle     *
3055  * file for producing official JavaFX builds.                                 *
3056  *                                                                            *
3057  *****************************************************************************/
3058 
3059 if (BUILD_CLOSED) {
3060     apply from: supplementalBuildFile
3061 }
3062 
3063 task showFlags {
3064 }
3065 
3066 compileTargets { t ->
3067     // Every platform must define these variables
3068     def props = project.ext[t.upper];
3069     showFlags.dependsOn(
3070         project.task("showFlags$t.upper") {
3071             doLast() {
3072                 println "Properties set for $t.upper"
3073                 props.each { println it }
3074             }
3075         }
3076     )
3077 }