       1 /*
       2  * Copyright (c) 2013, 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     ByteArrayOutputStream out = new ByteArrayOutputStream();
     114     logger.info("Converting path '$path' via cygpath")
     115     exec {
     116         standardOutput = out
     117         commandLine "cmd", "/c", "cygpath", "-m", path
     118     }
     119     return out.toString().trim();
     120 }
     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()
     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, BINARY_STUB, 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("JAVA_HOME"))
     264 ext.JAVA_HOME = envJavaHome == null || envJavaHome.equals("") ? System.getProperty("java.home") : envJavaHome
     265 def javaHomeFile = file(JAVA_HOME)
     266 defineProperty("JDK_HOME",
     267         javaHomeFile.name == "jre" ?
     268         javaHomeFile.getParent().toString() :
     269         javaHomeFile.name.startsWith("jre") ?
     270         new File(javaHomeFile.getParent(), "jdk1.${javaHomeFile.name.substring(3)}.0").toString() :
     271         JAVA_HOME) // we have to bail and set it to something and this is as good as any!
     272 defineProperty("JAVA", cygpath("$JDK_HOME/bin/java${IS_WINDOWS ? '.exe' : ''}"))
     273 defineProperty("JAVAC", cygpath("$JDK_HOME/bin/javac${IS_WINDOWS ? '.exe' : ''}"))
     274 defineProperty("JAVAH", cygpath("$JDK_HOME/bin/javah${IS_WINDOWS ? '.exe' : ''}"))
     275 defineProperty("JAVADOC", cygpath("$JDK_HOME/bin/javadoc${IS_WINDOWS ? '.exe' : ''}"))
     276 defineProperty("JDK_DOCS", "http://download.oracle.com/javase/7/docs/api")
     277
     278 defineProperty("javaRuntimeVersion", System.getProperty("java.runtime.version"))
     279 defineProperty("javaVersion", javaRuntimeVersion.split("[_\\-]")[0])
     280 defineProperty("javaBuildNumber", javaRuntimeVersion.substring(javaRuntimeVersion.lastIndexOf("-b") + 2))
     281
     282 loadProperties("$projectDir/build.properties")
     283
     284 def String closedCacheStubRuntime = cygpath("$projectDir") + "/../caches/sdk/rt"
     285 defineProperty("STUB_RUNTIME", BUILD_CLOSED ? closedCacheStubRuntime : cygpath("$JDK_HOME/jre"))
     286 defineProperty("BINARY_STUB", "$STUB_RUNTIME/lib/ext/jfxrt.jar")
     287 defineProperty("LIBRARY_STUB", IS_MAC ? "$STUB_RUNTIME/lib" :
     288                                IS_WINDOWS ? "$STUB_RUNTIME/bin" :
     289                                "$STUB_RUNTIME/lib/$OS_ARCH")
     290 ext.BINARY_STUB = "".equals(BINARY_STUB) ? null : files(BINARY_STUB)
     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 // COMPILE_WEBKIT specifies whether to build all of webkit. COMPILE_GSTREAMER
     301 // specifies whether to build GStreamer. Both of these can be set by a
     302 // command line property
     303 defineProperty("COMPILE_WEBKIT", "false")
     304 defineProperty("COMPILE_GSTREAMER", "false")
     305 if (COMPILE_WEBKIT instanceof String) ext.COMPILE_WEBKIT = Boolean.parseBoolean(COMPILE_WEBKIT)
     306 if (COMPILE_GSTREAMER instanceof String) ext.COMPILE_GSTREAMER = Boolean.parseBoolean(COMPILE_GSTREAMER)
     307
     308 // COMPILE_PANGO specifies whether to build javafx-font-pango.
     309 defineProperty("COMPILE_PANGO", "false")
     310 if (COMPILE_PANGO instanceof String) ext.COMPILE_PANGO = Boolean.parseBoolean(COMPILE_PANGO)
     311
     312
     313 // Define the SWT.jar that we are going to have to download during the build process based
     314 // on what platform we are compiling from (not based on our target).
     315 ext.SWT_FILE_NAME = IS_MAC ? "org.eclipse.swt.cocoa.macosx.x86_64_3.7.2.v3740f" :
     316     IS_WINDOWS && IS_64 ? "org.eclipse.swt.win32.win32.x86_64_3.7.2.v3740f" :
     317     IS_WINDOWS && !IS_64 ? "org.eclipse.swt.win32.win32.x86_3.7.2.v3740f" :
     318     IS_LINUX && IS_64 ? "org.eclipse.swt.gtk.linux.x86_64_3.7.2.v3740f" :
     319     IS_LINUX && !IS_64 ? "org.eclipse.swt.gtk.linux.x86_3.7.2.v3740f" : ""
     320
     321 // Build javadocs only if BUILD_JAVADOC=true
     322 def buildJavadoc = false;
     323 if (hasProperty("BUILD_JAVADOC")) {
     324     buildJavadoc = Boolean.parseBoolean(BUILD_JAVADOC);
     325 }
     326 ext.BUILD_JAVADOC = buildJavadoc;
     327
     328 // Specify the build configuration (Release or Debug)
     329 defineProperty("CONF", "Release")
     330 ext.IS_DEBUG = CONF == "Debug"
     331
     332 // Defines the compiler warning levels to use. If empty, then no warnings are generated. If
     333 // not empty, then the expected syntax is as a space or comma separated list of names, such
     334 // as defined in the javac documentation.
     335 defineProperty("LINT", "none")
     336 ext.IS_LINT = LINT != "none"
     337
     338 defineProperty("DOC_LINT", "none")
     339 ext.IS_DOC_LINT = DOC_LINT != "none"
     340
     341 // Specifies whether to use the "useDepend" option when compiling Java sources
     342 defineProperty("USE_DEPEND", "true")
     343 ext.USE_DEPEND = Boolean.parseBoolean(USE_DEPEND)
     344
     345 // Specifies whether to generate code coverage statistics when running tests
     346 defineProperty("JCOV", "false")
     347 ext.DO_JCOV = Boolean.parseBoolean(JCOV)
     348
     349 // Define the number of threads to use when compiling (specifically for native compilation)
     350 defineProperty("NUM_COMPILE_THREADS", "${Runtime.runtime.availableProcessors()}")
     351
     352 // Define settings used when creating the VersionInfo. These settings are generally left alone
     353 // by developers and set only from Hudson. We have to manually rev this version number from
     354 // release to release.
     355 //
     356 defineProperty("HUDSON_JOB_NAME", "not_hudson")
     357 defineProperty("HUDSON_BUILD_NUMBER","0000")
     358 defineProperty("PROMOTED_BUILD_NUMBER", "00")
     359 defineProperty("PRODUCT_NAME", "OpenJFX")
     360 // TODO: set the values of RAW_VERSION, RELEASE_NAME, and RELEASE_MILESTONE based on the
     361 // settings in build.properties
     362 defineProperty("RAW_VERSION", "8.0.0")
     363 defineProperty("RELEASE_NAME", "8.0")
     364 defineProperty("RELEASE_MILESTONE", "ea")
     365
     366 // Check whether the COMPILE_TARGETS property has been specified (if so, it was done by
     367 // the user and not by this script). If it has not been defined then default
     368 // to building the normal desktop build for this machine
     369 project.ext.set("defaultHostTarget", IS_MAC ? "mac" : IS_WINDOWS ? "win" : IS_LINUX ? "linux" : "");
     370 defineProperty("COMPILE_TARGETS", "$defaultHostTarget")
     371
     372 // Location of the cross compile tools
     373 def importCrossTools = BUILD_CLOSED ? true : false;
     374 if (!importCrossTools && hasProperty("IMPORT_CROSS_TOOLS")) {
     375     importCrossTools = Boolean.parseBoolean(BUILD_CLOSED);
     376 }
     377 ext.IMPORT_CROSS_TOOLS = importCrossTools
     378
     379 def crossToolsDir = "../crosslibs"
     380 if (hasProperty("CROSS_TOOLS_DIR")) {
     381     crossToolsDir = CROSS_TOOLS_DIR
     382 }
     383 ext.CROSS_TOOLS_DIR = file(crossToolsDir)
     384
     385 /**
     386  * Fetch/Check that external tools are present for the build. This method
     387  * will conditionally download the packages from project defined ivy repositories
     388  * and unpack them into the specified destdir
     389  *
     390  * @param configName A unique name to distinguish the configuration (ie "ARMSFV6")
     391  * @param packages A list of required packages (with extensions .tgz, .zip)
     392  * @param destdir where the packages should be unpacked
     393  * @param doFetch if true, the named packages will be download
     394  */
     395 void fetchExternalTools(String configName, List packages, File destdir, boolean doFetch) {
     396     if (doFetch) {
     397         // create a unique configuration for this fetch
     398         def String fetchToolsConfig = "fetchTools$configName"
     399         rootProject.configurations.create(fetchToolsConfig)
     400
     401         def List<String> fetchedPackages = []
     402         def int fetchCount = 0
     403
     404         packages.each { pkgname->
     405             def int dotdex = pkgname.lastIndexOf('.')
     406             def int dashdex = pkgname.lastIndexOf('-')
     407             def String basename = pkgname.substring(0,dashdex)
     408             def String ver = pkgname.substring(dashdex+1,dotdex)
     409             def String ext = pkgname.substring(dotdex+1)
     410             def File pkgdir = file("$destdir/$basename-$ver")
     411
     412             if (!pkgdir.isDirectory()) {
     413                 rootProject.dependencies.add(fetchToolsConfig, "javafx:$basename:$ver", {
     414                     artifact {
     415                         name = basename
     416                         version = ver
     417                         type = ext
     418                     }
     419                 })
     420                 println "adding $pkgname as a downloadable item did not find $pkgdir"
     421                 fetchedPackages.add(pkgname)
     422                 fetchCount++
     423             }
     424         }
     425
     426         //fetch all the missing packages
     427         if (fetchedPackages.size > 0) {
     428             destdir.mkdirs()
     429
     430             logger.quiet "fetching missing packages $fetchedPackages"
     431             copy {
     432                 from rootProject.configurations[fetchToolsConfig]
     433                 into destdir
     434             }
     435
     436             // unpack the fetched packages
     437             fetchedPackages.each { pkgname->
     438                 logger.quiet "expanding the package $pkgname"
     439                 def srcball = file("${destdir}/${pkgname}")
     440
     441                 if (!srcball.exists()) {
     442                     throw new GradleException("Failed to fetch $pkgname");
     443                 }
     444
     445                 def String basename = pkgname.substring(0,pkgname.lastIndexOf("."))
     446                 def File pkgdir = file("$destdir/$basename")
     447
     448                 if (pkgname.endsWith(".tgz")) {
     449                     if (IS_LINUX || IS_MAC) {
     450                         // use native tar to support symlinks
     451                         pkgdir.mkdirs()
     452                         exec {
     453                             workingDir pkgdir
     454                             commandLine "tar", "zxf", "${srcball}"
     455                          }
     456                     } else {
     457                         copy {
     458                             from tarTree(resources.gzip("${srcball}"))
     459                             into pkgdir
     460                         }
     461                     }
     462                 } else if (pkgname.endsWith(".zip")) {
     463                      copy {
     464                          from zipTree("${srcball}")
     465                          into pkgdir
     466                      }
     467                 } else {
     468                     throw new GradleException("Unhandled pacakge type for compile package ${pkgname}")
     469                 }
     470                 srcball.deleteOnExit();
     471             }
     472         } else {
     473             logger.quiet "all tool packages are present $packages"
     474         }
     475     } else { // !doFetch - so just check they are present
     476         // check that all the dirs are really there
     477         def List<String> errors = []
     478         packages.each { pkgname->
     479             def String basename = pkgname.substring(0,pkgname.lastIndexOf("."))
     480             def File pkgdir = file("$destdir/$basename")
     481
     482             if (!pkgdir.isDirectory()) {
     483                 errors.add(pkgname)
     484             }
     485         }
     486         if (errors.size > 0) {
     487             throw new GradleException("Error: missing tool packages: $errors")
     488         } else {
     489             logger.quiet "all tool packages are present $packages"
     490         }
     491     }
     492 }
     493
     494 // Now we need to define the native compilation tasks. The set of parameters to
     495 // native compilation depends on the target platform (and also to some extent what platform
     496 // you are compiling on). These settings are contained in various gradle files
     497 // such as mac.gradle and linux.gradle and armhf.gradle. Additionally, the developer
     498 // can specify COMPILE_FLAGS_FILE to be a URL or path to a different gradle file
     499 // that will contain the appropriate flags.
     500 defineProperty("COMPILE_FLAGS_FILES", COMPILE_TARGETS.split(",").collect {"buildSrc/${it.trim()}.gradle"}.join(","))
     501 if (COMPILE_TARGETS == "all") {
     502     def tmp = []
     503     File buildSrcDir = file("buildSrc")
     504     buildSrcDir.listFiles().each { File f ->
     505         if (f.isFile() && f.name.endsWith(".gradle") && !f.name.equals("build.gradle")) {
     506             def target = f.name.substring(0, f.name.lastIndexOf('.gradle')).toUpperCase()
     507             apply from: f
     508             if (project.ext["${target}"].canBuild) {
     509                 tmp.add(target)
     510             }
     511         }
     512     }
     513     COMPILE_FLAGS_FILES = tmp.collect { "buildSrc/${it}.gradle"}.join(",")
     514     COMPILE_TARGETS = tmp.collect { "${it.toLowerCase()}"}.join(",")
     515 } else {
     516     COMPILE_FLAGS_FILES.split(",").each {
     517         logger.info("Applying COMPILE_FLAGS_FILE '$it'")
     518         apply from: it
     519     }
     520 }
     521
     522 if (COMPILE_TARGETS != "") {
     523     def tmp = []
     524     COMPILE_TARGETS.split(",").each {target ->
     525         if (project.ext["${target.toUpperCase()}"].canBuild) {
     526             tmp.add(target)
     527         }
     528     }
     529     COMPILE_TARGETS = tmp.collect { "${it.toLowerCase()}"}.join(",")
     530 }
     531
     532 // Sanity check the expected properties all exist
     533 compileTargets { t ->
     534     // Every platform must define these variables
     535     if (!project.hasProperty(t.upper)) throw new Exception("ERROR: Incorrectly configured compile flags file, missing ${t.name} property")
     536     def props = project.ext[t.upper];
     537     ["jfxrtJarExcludes", "compileSwing", "compileSWT", "compileFXPackager", "compileDesignTime", "libDest"].each { prop ->
     538         if (!props.containsKey(prop)) throw new Exception("ERROR: Incorrectly configured compile flags file, missing ${prop} property on ${t.name}")
     539     }
     540 }
     541
     542 // Various build flags may be set by the different target files, such as
     543 // whether to build Swing, SWT, FXPackager, etc. We iterate over all
     544 // compile targets and look for these settings in our properties. Note that
     545 // these properties cannot be set from the command line, but are set by
     546 // the target build files such as armv6hf.gradle or mac.gradle.
     547 ext.COMPILE_SWING = false;
     548 ext.COMPILE_SWT = false;
     549 ext.COMPILE_FXPACKAGER = false;
     550 ext.COMPILE_DESIGN_TIME = false;
     551 compileTargets { t ->
     552     if (project.ext[t.upper].compileSwing) COMPILE_SWING = true
     553     if (project.ext[t.upper].compileSWT) COMPILE_SWT = true
     554     if (project.ext[t.upper].compileFXPackager) COMPILE_FXPACKAGER = true
     555     if (project.ext[t.upper].compileDesignTime) COMPILE_DESIGN_TIME = true
     556 }
     557
     558 /******************************************************************************
     559  *                                                                            *
     560  *                         Build Setup Sanity Checks                          *
     561  *                                                                            *
     562  *  Here we do a variety of checks so that if the version of Java you are     *
     563  *  building with is misconfigured, or you are using the wrong version of     *
     564  *  gradle, etc you will get some kind of helpful error / warning message     *
     565  *                                                                            *
     566  *****************************************************************************/
     567
     568 // Verify that the architecture & OS are supported configurations. Note that
     569 // at present building on PI is not supported, but we would only need to make
     570 // some changes on assumptions on what should be built (like SWT / Swing) and
     571 // such and we could probably make it work.
     572 if (!IS_MAC && !IS_WINDOWS && !IS_LINUX) logger.error("Unsupported build OS ${OS_NAME}")
     573 if (IS_WINDOWS && OS_ARCH != "x86" && OS_ARCH != "amd64") {
     574     throw new Exception("Unknown and unsupported build architecture: $OS_ARCH")
     575 } else if (IS_MAC && OS_ARCH != "x86_64") {
     576     throw new Exception("Unknown and unsupported build architecture: $OS_ARCH")
     577 } else if (IS_LINUX && OS_ARCH != "i386" && OS_ARCH != "amd64") {
     578     throw new Exception("Unknown and unsupported build architecture: $OS_ARCH")
     579 }
     580
     581 // Sanity check that we actually have a list of compile targets to execute
     582 if (COMPILE_TARGETS == null || COMPILE_TARGETS == "") {
     583     throw new Exception("Unable to determine compilation platform, must specify valid COMPILE_TARGETS!")
     584 }
     585
     586 // Make sure JAVA_HOME/bin/java exists
     587 if (!file(JAVA).exists()) throw new Exception("Missing or incorrect path to 'java': '$JAVA'. Perhaps bad JDK_HOME? $JDK_HOME")
     588 if (!file(JAVAC).exists()) throw new Exception("Missing or incorrect path to 'javac': '$JAVAC'. Perhaps bad JDK_HOME? $JDK_HOME")
     589 if (!file(JAVAH).exists()) throw new Exception("Missing or incorrect path to 'javah': '$JAVAH'. Perhaps bad JDK_HOME? $JDK_HOME")
     590 if (!file(JAVADOC).exists()) throw new Exception("Missing or incorrect path to 'javadoc': '$JAVADOC'. Perhaps bad JDK_HOME? $JDK_HOME")
     591 if (BINARY_STUB != null && !BINARY_STUB.getSingleFile().exists()) logger.warn("Missing or incorrect path to 'jfxrt.jar': '${BINARY_STUB.asPath}'. Perhaps bad JDK_HOME? $JDK_HOME")
     592
     593 // Verify that CONF is something useful
     594 if (CONF != "Release" && CONF != "Debug") logger.warn("Unknown configuration CONF='$CONF'. Treating as 'Release'")
     595
     596 // If the number of compile threads is less than 1 then we have a problem!
     597 if (Integer.parseInt(NUM_COMPILE_THREADS.toString()) < 1) {
     598     logger.warn("NUM_COMPILE_THREADS was specified as '$NUM_COMPILE_THREADS' which is less than the minimum value of 1. " +
     599             "Building with a value of 1 instead.")
     600     NUM_COMPILE_THREADS = 1
     601 }
     602
     603 // Check that Gradle 1.4 is in use. We haven't tried any other versions.
     604 if (gradle.gradleVersion != "1.4") {
     605     logger.warn("Unsupported gradle version $gradle.gradleVersion in use. Only 1.4 is supported")
     606 }
     607
     608 /******************************************************************************
     609  *                                                                            *
     610  *                      Logging of Properties and Settings                    *
     611  *                                                                            *
     612  *  Log some of the settings we've determined. We could log more here, it     *
     613  *  doesn't really hurt.                                                      *
     614  *                                                                            *
     615  *****************************************************************************/
     616
     617 logger.quiet("OS_NAME: $OS_NAME")
     618 logger.quiet("OS_ARCH: $OS_ARCH")
     619 logger.quiet("JAVA_HOME: $JAVA_HOME")
     620 logger.quiet("JDK_HOME: $JDK_HOME")
     621 logger.quiet("java.runtime.version: ${javaRuntimeVersion}")
     622 logger.quiet("java version: ${javaVersion}")
     623 logger.quiet("java build number: ${javaBuildNumber}")
     624 logger.quiet("minimum java build number: ${jfxBuildJdkBuildnumMin}")
     625 logger.quiet("COMPILE_TARGETS: $COMPILE_TARGETS")
     626 logger.quiet("COMPILE_FLAGS_FILES: $COMPILE_FLAGS_FILES")
     627 logger.quiet("BINARY_STUB: ${BINARY_STUB == null ? '' : BINARY_STUB.asPath}")
     628 logger.quiet("HUDSON_JOB_NAME: $HUDSON_JOB_NAME")
     629 logger.quiet("HUDSON_BUILD_NUMBER: $HUDSON_BUILD_NUMBER")
     630 logger.quiet("PROMOTED_BUILD_NUMBER: $PROMOTED_BUILD_NUMBER")
     631 logger.quiet("PRODUCT_NAME: $PRODUCT_NAME")
     632 logger.quiet("RAW_VERSION: $RAW_VERSION")
     633 logger.quiet("RELEASE_NAME: $RELEASE_NAME")
     634 logger.quiet("RELEASE_MILESTONE: $RELEASE_MILESTONE")
     635
     636 if (UPDATE_STUB_CACHE) {
     637     logger.quiet("UPDATE_STUB_CACHE: $UPDATE_STUB_CACHE")
     638 }
     639
     640 /******************************************************************************
     641  *                                                                            *
     642  *                Definition of Native Code Compilation Tasks                 *
     643  *                                                                            *
     644  *    - JavaHeaderTask is used to run javah. The JAVAH property will point at *
     645  *      the version of javah to be used (i.e.: a path to javah)               *
     646  *    - CCTask compiles native code. Specifically it will compile .m, .c,     *
     647  *      .cpp, or .cc files. It uses the headers provided by the               *
     648  *      JavaHeaderTask plus additional platform specific headers. It will     *
     649  *      compile into .obj files.                                              *
     650  *    - LinkTask will perform native linking and create the .dll / .so /      *
     651  *      .dylib as necessary.                                                  *
     652  *                                                                            *
     653  *****************************************************************************/
     654
     655 // Save a reference to the buildSrc.jar file because we need it for actually
     656 // compiling things, not just for the sake of this build script
     657 // (such as generating the builders, JSL files, etc)
     658 ext.BUILD_SRC = rootProject.files("buildSrc/build/libs/buildSrc.jar")
     659
     660 /**
     661  * Convenience method for creating javah, cc, link, and "native" tasks in the given project. These
     662  * tasks are parameterized by name, so that we can produce, for example, javahGlass, ccGlass, etc
     663  * named tasks.
     664  *
     665  * @param project The project to add tasks to
     666  * @param name The name of the project, such as "prism-common". This name is used
     667  *        in the name of the generated task, such as ccPrismCommon, and also
     668  *        in the name of the final library, such as libprism-common.dylib.
     669  * @param optional If the task is optional or not
     670  */
     671 void addNative(Project project, String name, boolean optional = false) {
     672     addNative(project, name, null, optional)
     673 }
     674
     675 /**
     676  * Convenience method for creating javah, cc, link, and "native" tasks in the given project. These
     677  * tasks are parameterized by name, so that we can produce, for example, javahGlass, ccGlass, etc
     678  * named tasks.
     679  *
     680  * @param project The project to add tasks to
     681  * @param name The name of the project, such as "prism-common". This name is used
     682  *        in the name of the generated task, such as ccPrismCommon, and also
     683  *        in the name of the final library, such as libprism-common.dylib.
     684  * @param list of compile targets. Library is applicable only for these targets.
     685  * @param optional If the task is optional or not
     686  */
     687 void addNative(Project project, String name, List<String> includeTargets, boolean optional = false) {
     688     // TODO if we want to handle 32/64 bit windows in the same build,
     689     // Then we will need to modify the win compile target to be win32 or win64
     690     def capitalName = name.split("-").collect{it.capitalize()}.join()
     691     def nativeTask = project.task("native$capitalName", group: "Build") {
     692         description = "Generates JNI headers, compiles, and builds native dynamic library for $name for all compile targets"
     693     }
     694     def cleanTask = project.task("cleanNative$capitalName", type: Delete, group: "Build") {
     695         description = "Clean native objects for $name"
     696     }
     697     if (project.hasProperty("nativeAllTask")) project.nativeAllTask.dependsOn nativeTask
     698     if (!optional) {
     699         project.assemble.dependsOn(nativeTask)
     700     }
     701     if (project.hasProperty("cleanNativeAllTask")) project.cleanNativeAllTask.dependsOn cleanTask
     702
     703     // Each of the different compile targets will be placed in a sub directory
     704     // of these root dirs, with the name of the dir being the name of the target
     705     def headerRootDir = project.file("$project.buildDir/generated-src/headers/$name")
     706     def nativeRootDir = project.file("$project.buildDir/native/$name")
     707     def libRootDir = project.file("$project.buildDir/libs/$name")
     708     // For each compile target, create a javah / cc / link triplet
     709     compileTargets { t ->
     710         if (includeTargets != null && !includeTargets.contains(t.name)) {
     711             return
     712         }
     713         def targetProperties = project.rootProject.ext[t.upper]
     714         def library = targetProperties.library
     715         def properties = targetProperties.get(name)
     716         def nativeDir = file("$nativeRootDir/${t.name}")
     717         def headerDir = file("$headerRootDir/${t.name}")
     718
     719         def javahTask = project.task("javah${t.capital}${capitalName}", type: JavaHeaderTask, dependsOn: project.classes, group: "Build") {
     720             description = "Generates JNI Headers for ${name} for ${t.name}"
     721             if (properties.javahSource == null) {
     722                 source(project.sourceSets.main.output.classesDir)
     723             } else {
     724                 source(properties.javahSource)
     725             }
     726             if (properties.javahClasspath == null) {
     727                 classpath = project.files(project.sourceSets.main.output.classesDir)
     728             } else {
     729                 classpath = project.files(properties.javahClasspath)
     730             }
     731             if (rootProject.BINARY_STUB != null) classpath += rootProject.BINARY_STUB
     732             output = headerDir
     733             include(properties.javahInclude)
     734         }
     735
     736         def variants = properties.containsKey("variants") ? properties.variants : [""];
     737         variants.each { variant ->
     738             def variantProperties = variant == "" ? properties : properties.get(variant)
     739             def capitalVariant = variant.capitalize()
     740             def ccOutput = variant == "" ? nativeDir : file("$nativeDir/$variant")
     741             def ccTask = project.task("cc${t.capital}$capitalName$capitalVariant", type: CCTask, dependsOn: javahTask, group: "Build") {
     742                 description = "Compiles native sources for ${name} for ${t.name}${capitalVariant != '' ? ' for variant ' + capitalVariant : ''}"
     743                 matches = ".*\\.c|.*\\.cpp|.*\\.m|.*\\.cc"
     744                 headers = headerDir
     745                 output(ccOutput)
     746                 params.addAll(variantProperties.ccFlags)
     747                 compiler = variantProperties.compiler
     748                 source(variantProperties.nativeSource)
     749                 cleanTask.delete ccOutput
     750             }
     751             def linkTask = project.task("link${t.capital}$capitalName$capitalVariant", type: LinkTask, dependsOn: ccTask, group: "Build") {
     752                 description = "Creates native dynamic library for $name for ${t.name}${capitalVariant != '' ? ' for variant ' + capitalVariant : ''}"
     753                 objectDir = ccOutput
     754                 linkParams.addAll(variantProperties.linkFlags)
     755                 lib = file("$libRootDir/${t.name}/${variant == '' ? library(properties.lib) : library(variantProperties.lib)}")
     756                 linker = variantProperties.linker
     757                 cleanTask.delete "$libRootDir/${t.name}"
     758             }
     759             nativeTask.dependsOn(linkTask)
     760             if (IS_WINDOWS && t.name == "win") {
     761                 def rcTask = project.task("rc$capitalName$capitalVariant", type: CompileResourceTask, dependsOn: javahTask, group: "Build") {
     762                     description = "Compiles native sources for $name"
     763                     matches = ".*\\.rc|.*\\.cur"
     764                     def rcOutput = file("$nativeRootDir/win")
     765                     output(rcOutput)
     766                     cleanTask.delete rcOutput
     767                 }
     768                 linkTask.dependsOn rcTask;
     769             }
     770         }
     771
     772         def useLipo = targetProperties.containsKey('useLipo') ? targetProperties.useLipo : false
     773         if (useLipo) {
     774             def lipoTask = project.task("lipo${t.capital}$capitalName", type: LipoTask, dependsOn: javahTask, group: "Build") {
     775                 description = "Creates native fat library for $name for ${t.name}"
     776                 libDir = file("$libRootDir/${t.name}")
     777                 lib = file("$libRootDir/${t.name}/${library(properties.lib)}")
     778             }
     779             nativeTask.dependsOn(lipoTask)
     780         }
     781     }
     782 }
     783
     784 void addJSL(Project project, String name, String pkg, Closure compile) {
     785     def lowerName = name.toLowerCase()
     786
     787     def compileCompilers = project.task("compile${name}Compilers", type: JavaCompile, dependsOn: project.compileJava) {
     788         description = "Compile the $name JSL Compilers"
     789         classpath = project.files(project.sourceSets.main.output.classesDir) +
     790                 rootProject.BUILD_SRC +
     791                 project.configurations.antlr3
     792         source = [project.file("src/main/jsl-$lowerName")]
     793         destinationDir = project.file("$project.buildDir/classes/jsl-compilers/$lowerName")
     794     }
     795
     796     def generateShaders = project.task("generate${name}Shaders", dependsOn: compileCompilers) {
     797         description = "Generate $name shaders from JSL"
     798         def sourceDir = project.file("src/main/jsl-$lowerName")
     799         def destinationDir = project.file("$project.buildDir/generated-src/jsl-$lowerName")
     800         inputs.dir sourceDir
     801         outputs.dir destinationDir
     802         doLast {
     803             compile(sourceDir, destinationDir)
     804         }
     805     }
     806
     807     project.task("compile${name}JavaShaders", type: JavaCompile, dependsOn: generateShaders) {
     808         description = "Compile the Java $name JSL shaders"
     809         classpath = project.files(project.sourceSets.main.output.classesDir) + rootProject.BUILD_SRC
     810         source = [project.file("$project.buildDir/generated-src/jsl-$lowerName")]
     811         destinationDir = project.file("$project.buildDir/classes/jsl-$lowerName")
     812     }
     813
     814     def compileHLSLShaders = project.task("compile${name}HLSLShaders", dependsOn: generateShaders, type: CompileHLSLTask) {
     815         enabled = IS_WINDOWS
     816         description = "Compile $name HLSL files into .obj files"
     817         matches = ".*\\.hlsl"
     818         output project.file("$project.buildDir/hlsl/$name/$pkg")
     819         source project.file("$project.buildDir/generated-src/jsl-$lowerName/$pkg")
     820     }
     821
     822     project.task("process${name}Shaders", dependsOn: [generateShaders, compileHLSLShaders], type: Copy, description: "Copy hlsl / frag shaders to build/resources/jsl-$lowerName") {
     823         from("$project.buildDir/hlsl/$name") {
     824             include "**/*.obj"
     825         }
     826         from("$project.buildDir/generated-src/jsl-$lowerName") {
     827             include("**/*.frag")
     828         }
     829         into "$project.buildDir/resources/jsl-$lowerName"
     830     }
     831 }
     832
     833 // Task to verify the minimum level of Java needed to build JavaFX
     834 task verifyJava() {
     835     doLast {
     836         if (javaVersion != jfxBuildJdkVersion) {
     837             fail("java version mismatch: ${javaVersion} must be ${jfxBuildJdkVersion}")
     838         }
     839         def buildNum = Integer.parseInt(javaBuildNumber)
     840         def minBuildNum = Integer.parseInt(jfxBuildJdkBuildnumMin)
     841         if (buildNum < minBuildNum) {
     842             fail("java build number ($buildNum) < minimum build number ($minBuildNum)")
     843         }
     844     }
     845 }
     846
     847 // Task to check whether jfxrt.jar is present in the JDK
     848 task checkJfxrtJar {
     849     doLast {
     850         def jfxrtFile = new File("$JAVA_HOME/jre/lib/ext/jfxrt.jar");
     851         if (jfxrtFile.exists()) {
     852             if (BUILD_CLOSED) {
     853                 fail("$jfxrtFile must be removed before building closed sdk")
     854             } else {
     855                 logger.warn("****************************************************************")
     856                 logger.warn("$jfxrtFile may interfere with testing or running applications against locally build jfxrt.jar")
     857                 logger.warn("****************************************************************")
     858             }
     859         }
     860     }
     861 }
     862
     863 task updateCacheIfNeeded() {
     864     // an empty task we can add to as needed for UPDATE_STUB_CACHE
     865 }
     866
     867 /*****************************************************************************
     868 *        Project definitions (dependencies, etc)                             *
     869 *****************************************************************************/
     870
     871 void addJCov(p, test) {
     872     test.doFirst {
     873         def jcovJVMArgument =
     874                 "include=javafx," +
     875                 "include=com.sun.javafx," +
     876                 "include=com.sun.glass," +
     877                 "include=com.sun.openpisces," +
     878                 "include=com.sun.pisces," +
     879                 "include=com.sun.prism," +
     880                 "include=com.sun.scenario," +
     881                 "include=com.sun.webkit," +
     882                 "exclude=com," +
     883                 "exclude=java," +
     884                 "exclude=javax," +
     885                 "exclude=\"**.test\"," +
     886                 "exclude=\"**.*Test\"," +
     887                 "file=build/reports/jcov/report.xml," +
     888                 "merge=merge";
     889         test.jvmArgs("-javaagent:${p.configurations.testCompile.files.find { it.name.startsWith('jcov') }}=$jcovJVMArgument");
     890         p.mkdir p.file("build/reports/jcov")
     891     }
     892     test.doLast {
     893         def reportFile = p.file("build/reports/jcov/report.xml")
     894         if (reportFile.exists()) {
     895             p.javaexec {
     896                 workingDir = p.file("build/reports/jcov")
     897                 classpath = p.files(p.configurations.testCompile.files.find { it.name.startsWith('jcov') })
     898                 main = "com.sun.tdk.jcov.Helper"
     899                 args = [
     900                         "RepGen",
     901                         "-exclude", "\"**.test\"",
     902                         "-exclude", "\"**.*Test\"",
     903                         "-output", ".",
     904                         "-source", p.sourceSets.main.java.srcDirs.collect{p.file(it)}.join(":"),
     905                         "report.xml"
     906                 ]
     907             }
     908         }
     909     }
     910 }
     911
     912 allprojects {
     913     // We want to configure all projects as java projects and use the same compile settings
     914     // etc, except for the root project which we just want to ignore (and for now media)
     915     if (project == rootProject || project.name == "media") return
     916     // All of our projects are java projects
     917     apply plugin: "java"
     918     sourceCompatibility = 1.8
     919
     920     // Setup the repositories that we'll download libraries from. Maven Central is
     921     // just easy for most things. The custom "ivy" repo is for downloading SWT. The way it
     922     // works is to setup the download URL such that it will resolve to the actual jar file
     923     // to download. See SWT_FILE_NAME for the name of the jar that will be used as the
     924     // "artifact" in the pattern below. Note that the closed builds use different repositories
     925     // so if you are debugging a closed-build artifact related build issue, check out the
     926     // closed gradle file instead.
     927     if (!BUILD_CLOSED) {
     928         repositories {
     929             mavenCentral()
     930             ivy {
     931                 url "http://download.eclipse.org/eclipse/updates/3.7/R-3.7.2-201202080800/plugins/"
     932                 layout "pattern", {
     933                     artifact "[artifact].[ext]"
     934                 }
     935             }
     936         }
     937     }
     938
     939     // By default all of our projects require junit for testing so we can just
     940     // setup this dependency here.
     941     dependencies {
     942         testCompile group: "junit", name: "junit", version: "4.8.2"
     943         if (BUILD_CLOSED && DO_JCOV)  {
     944             testCompile name: "jcov"
     945         }
     946     }
     947
     948     // At the moment the ASM library shipped with Gradle that is used to
     949     // discover the different test classes fails on Java 8, so in order
     950     // to have sourceCompatibility set to 1.8 I have to also turn scanForClasses off
     951     // and manually specify the includes / excludes. At the moment we use
     952     // Java 7 but when we switch to 8 this will be needed, and probably again when
     953     // we start building with Java 9.
     954     test {
     955         jvmArgs("-Djava.ext.dirs=");
     956         if (rootProject.BINARY_STUB != null) classpath += rootProject.BINARY_STUB;
     957         executable = JAVA;
     958         enableAssertions = true;
     959         testLogging.exceptionFormat = "full";
     960         scanForTestClasses = false;
     961         include("**/*Test.*");
     962         exclude("**/DepthTest.*");
     963         exclude("**/*Abstract*.*");
     964         if (BUILD_CLOSED && DO_JCOV) {
     965             addJCov(project, test)
     966         }
     967     }
     968
     969     // Exclude any non-public-API classes from having javadoc generated. This block is used
     970     // when generating JavaDocs for a specific project. When generating the JavaDocs for the
     971     // entire SDK, a different javadoc command is used (see the javadoc task on the top level)
     972     javadoc {
     973         enabled = BUILD_JAVADOC
     974         exclude("com/**/*", "javafx/scene/ParentDesignInfo*", "Compile*", "javafx/builder/**/*");
     975         executable = JAVADOC;
     976         options.windowTitle("JavaFX Project ${project.name} ${RELEASE_NAME}")
     977         options.links(JDK_DOCS);
     978         options.addBooleanOption("XDignore.symbol.file").setValue(true);
     979         options.addBooleanOption("Xdoclint:none").setValue(!IS_DOC_LINT);
     980         options.addBooleanOption("javafx").setValue(true);
     981         // All doc-files are located in src/main/docs because Gradle's javadoc doesn't copy
     982         // over the doc-files if they are embedded with the sources. I find this arrangement
     983         // somewhat cleaner anyway (never was a fan of mixing javadoc files with the sources)
     984         doLast {
     985             copy {
     986                 from "src/main/docs"
     987                 into "$buildDir/docs/javadoc"
     988             }
     989         }
     990     }
     991 }
     992
     993 // The "base" project is our first module and the most basic one required for
     994 // all other modules. It is useful even for non-GUI applications.
     995 project(":base") {
     996     dependencies {
     997         compile BUILD_SRC
     998     }
     999
    1000     // We need to take the VersionInfo.java file and replace the various
    1001     // properties within it
    1002     def replacements = [
    1003         "BUILD_TIMESTAMP": new java.util.Date(),
    1004         "HUDSON_JOB_NAME": HUDSON_JOB_NAME,
    1005         "HUDSON_BUILD_NUMBER": HUDSON_BUILD_NUMBER,
    1006         "PROMOTED_BUILD_NUMBER": PROMOTED_BUILD_NUMBER,
    1007         "PRODUCT_NAME": PRODUCT_NAME,
    1008         "RAW_VERSION": RAW_VERSION,
    1009         "RELEASE_NAME": RELEASE_NAME,
    1010         "RELEASE_MILESTONE": RELEASE_MILESTONE];
    1011     task processVersionInfo(type: Copy, description: "Replace params in VersionInfo and copy file to destination") {
    1012         doFirst { mkdir "$buildDir/generated-src/version-info" }
    1013         from "src/main/version-info"
    1014         into "$buildDir/generated-src/version-info/com/sun/javafx/runtime"
    1015         filter {line->
    1016             replacements.each() {k, v ->
    1017                 line = line.replace("@$k@", v.toString());
    1018             }
    1019             line
    1020         }
    1021     }
    1022
    1023     compileJava.dependsOn updateCacheIfNeeded
    1024     compileJava.dependsOn verifyJava
    1025
    1026     // Make sure to include $buildDir/generated-src/version-info that we previously created.
    1027     // We DO NOT want to include src/main/version-info
    1028     sourceSets.main.java.srcDirs = ["src/main/java", "$buildDir/generated-src/version-info"]
    1029     compileJava.dependsOn processVersionInfo
    1030 }
    1031
    1032 // The graphics module is needed for any graphical JavaFX application. It requires
    1033 // the base module and includes the scene graph, layout, css, prism, windowing, etc.
    1034 // This is a fairly complicated module. There are many different types of native components
    1035 // that all need to be compiled.
    1036 project(":graphics") {
    1037     // Workaround for lack of Antlr 3 support in Gradle. By defining a configuration,
    1038     // we can then give it a class path and use that classpath to execute a java command
    1039     getConfigurations().add("antlr3");
    1040
    1041     sourceSets {
    1042         main
    1043         test
    1044         stub
    1045     }
    1046
    1047     dependencies {
    1048         compile project(":base"), BUILD_SRC
    1049         compile name: SWT_FILE_NAME
    1050         stubCompile group: "junit", name: "junit", version: "4.8.2",
    1051         project(":base").sourceSets.test.output, sourceSets.main.output
    1052         antlr3 group: "org.antlr", name: "antlr", version: "3.1.3"
    1053         antlr3 group: "org.antlr", name: "antlr-runtime",  version: "3.1.3"
    1054         antlr3 group: "org.antlr", name: "stringtemplate", version: "3.2"
    1055     }
    1056
    1057     // Create a single "native" task which will depend on all the individual native tasks for graphics
    1058     project.ext.nativeAllTask = task("native", group: "Build", description: "Compiles and Builds all native libraries for Graphics");
    1059     project.ext.cleanNativeAllTask = task("cleanNative", group: "Build", description: "Clean all native libraries and objects for Graphics");
    1060
    1061     // Add tasks for native compilation
    1062     addNative(project, "glass");
    1063     addNative(project, "prism")
    1064     addNative(project, "prismSW")
    1065     addNative(project, "font")
    1066     addNative(project, "iio")
    1067     addNative(project, "prismES2")
    1068
    1069     // Currently lets not build pango by default
    1070     if (IS_LINUX) {
    1071         addNative(project, "fontPango", ["linux","armv6hf", "armv6sf"],!COMPILE_PANGO)
    1072     }
    1073
    1074     if (IS_WINDOWS) {
    1075         addNative(project, "prismD3D")
    1076         // TODO need to hook this up to be executed only if PassThroughVS.h is missing or PassThroughVS.hlsl is changed
    1077         task generateD3DHeaders(group: "Build") {
    1078             enabled = IS_WINDOWS
    1079             dependsOn javahWinPrismD3D
    1080             description = "Generate headers by compiling hlsl files"
    1081             doLast {
    1082                 mkdir file("$buildDir/headers/PrismD3D/hlsl")
    1083                 def PS_3D_SRC = file("src/main/native-prism-d3d/hlsl/Mtl1PS.hlsl")
    1084                 def VS_3D_SRC = file("src/main/native-prism-d3d/hlsl/Mtl1VS.hlsl")
    1085                 def PASSTHROUGH_VS_SRC = file("src/main/native-prism-d3d/PassThroughVS.hlsl")
    1086                 def jobs = [
    1087                         ["$FXC", "/nologo", "/T", "vs_3_0", "/Fh", "$buildDir/headers/PrismD3D/PassThroughVS.h", "/E", "passThrough", "$PASSTHROUGH_VS_SRC"],
    1088                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS.h", "/DSpec=0", "/DSType=0", "$PS_3D_SRC"],
    1089                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_i.h", "/DSpec=0", "/DSType=0", "/DIllumMap=1", "$PS_3D_SRC"],
    1090                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s1n.h", "/DSpec=1", "/DSType=0", "$PS_3D_SRC"],
    1091                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s2n.h", "/DSpec=2", "/DSType=0", "$PS_3D_SRC"],
    1092                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s3n.h", "/DSpec=3", "/DSType=0", "$PS_3D_SRC"],
    1093                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s1a.h", "/DSpec=1", "/DSType=1", "$PS_3D_SRC"],
    1094                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s2a.h", "/DSpec=2", "/DSType=1", "$PS_3D_SRC"],
    1095                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s3a.h", "/DSpec=3", "/DSType=1", "$PS_3D_SRC"],
    1096                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s1s.h", "/DSpec=1", "/DSType=2", "$PS_3D_SRC"],
    1097                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s2s.h", "/DSpec=2", "/DSType=2", "$PS_3D_SRC"],
    1098                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s3s.h", "/DSpec=3", "/DSType=2", "$PS_3D_SRC"],
    1099                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b1n.h", "/DSpec=1", "/DSType=0", "/DBump=1", "$PS_3D_SRC"],
    1100                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b2n.h", "/DSpec=2", "/DSType=0", "/DBump=1", "$PS_3D_SRC"],
    1101                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b3n.h", "/DSpec=3", "/DSType=0", "/DBump=1", "$PS_3D_SRC"],
    1102                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b1a.h", "/DSpec=1", "/DSType=1", "/DBump=1", "$PS_3D_SRC"],
    1103                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b2a.h", "/DSpec=2", "/DSType=1", "/DBump=1", "$PS_3D_SRC"],
    1104                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b3a.h", "/DSpec=3", "/DSType=1", "/DBump=1", "$PS_3D_SRC"],
    1105                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b1s.h", "/DSpec=1", "/DSType=2", "/DBump=1", "$PS_3D_SRC"],
    1106                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b2s.h", "/DSpec=2", "/DSType=2", "/DBump=1", "$PS_3D_SRC"],
    1107                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b3s.h", "/DSpec=3", "/DSType=2", "/DBump=1", "$PS_3D_SRC"],
    1108                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s1ni.h", "/DSpec=1", "/DSType=0", "/DIllumMap=1", "$PS_3D_SRC"],
    1109                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s2ni.h", "/DSpec=2", "/DSType=0", "/DIllumMap=1", "$PS_3D_SRC"],
    1110                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s3ni.h", "/DSpec=3", "/DSType=0", "/DIllumMap=1", "$PS_3D_SRC"],
    1111                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s1ai.h", "/DSpec=1", "/DSType=1", "/DIllumMap=1", "$PS_3D_SRC"],
    1112                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s2ai.h", "/DSpec=2", "/DSType=1", "/DIllumMap=1", "$PS_3D_SRC"],
    1113                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s3ai.h", "/DSpec=3", "/DSType=1", "/DIllumMap=1", "$PS_3D_SRC"],
    1114                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s1si.h", "/DSpec=1", "/DSType=2", "/DIllumMap=1", "$PS_3D_SRC"],
    1115                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s2si.h", "/DSpec=2", "/DSType=2", "/DIllumMap=1", "$PS_3D_SRC"],
    1116                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_s3si.h", "/DSpec=3", "/DSType=2", "/DIllumMap=1", "$PS_3D_SRC"],
    1117                         ["$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"],
    1118                         ["$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"],
    1119                         ["$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"],
    1120                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b1ai.h", "/DSpec=1", "/DSType=1", "/DBump=1", "/DIllumMap=1", "$PS_3D_SRC"],
    1121                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b2ai.h", "/DSpec=2", "/DSType=1", "/DBump=1", "/DIllumMap=1", "$PS_3D_SRC"],
    1122                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b3ai.h", "/DSpec=3", "/DSType=1", "/DBump=1", "/DIllumMap=1", "$PS_3D_SRC"],
    1123                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b1si.h", "/DSpec=1", "/DSType=2", "/DBump=1", "/DIllumMap=1", "$PS_3D_SRC"],
    1124                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b2si.h", "/DSpec=2", "/DSType=2", "/DBump=1", "/DIllumMap=1", "$PS_3D_SRC"],
    1125                         ["$FXC", "/nologo", "/T", "ps_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1PS_b3si.h", "/DSpec=3", "/DSType=2", "/DBump=1", "/DIllumMap=1", "$PS_3D_SRC"],
    1126                         ["$FXC", "/nologo", "/T", "vs_2_0", "/Fh", "$buildDir/headers/PrismD3D/hlsl/Mtl1VS_Obj.h", "/DVertexType=ObjVertex", "$VS_3D_SRC"]
    1127                 ]
    1128                 final ExecutorService executor = Executors.newFixedThreadPool(Integer.parseInt(project.NUM_COMPILE_THREADS.toString()));
    1129                 final CountDownLatch latch = new CountDownLatch(jobs.size());
    1130                 List futures = new ArrayList<Future>();
    1131                 jobs.each { cmd ->
    1132                     futures.add(executor.submit(new Runnable() {
    1133                         @Override public void run() {
    1134                             try {
    1135                                 exec {
    1136                                     commandLine cmd
    1137                                 }
    1138                             } finally {
    1139                                 latch.countDown();
    1140                             }
    1141                         }
    1142                     }));
    1143                 }
    1144                 latch.await();
    1145                 // Looking for whether an exception occurred while executing any of the futures.
    1146                 // By calling "get()" on each future an exception will be thrown if one had occurred
    1147                 // on the background thread.
    1148                 futures.each {it.get();}
    1149             }
    1150         }
    1151
    1152         ccWinPrismD3D.dependsOn generateD3DHeaders
    1153     }
    1154
    1155     // The Decora and Prism JSL files have to be generated in a very specific set of steps.
    1156     //      1) Compile the *Compile.java classes. These live in src/main/jsl-* and will be
    1157     //         output to $buildDir/classes/jsl-compilers/* (where * == decora or prism).
    1158     //      2) Generate source files from the JSL files contained in src/main/jsl-*. These
    1159     //         will be output to $buildDir/generated-src/jsl-*
    1160     //      3) Compile the JSL Java sources in $buildDir/generated-src/jsl-* and put the output
    1161     //         into classes/jsl-*
    1162     //      4) Compile the native JSL sources in $buildDir/generated-src/jsl-* and put the obj
    1163     //         files into native/jsl-* and the resulting library into libs/jsl-*.dll|so|dylib
    1164     //      5) Modify the jar step to include classes/jsl-*
    1165     // The native library must be copied over during SDK creation time in the "sdk" task. In
    1166     // addition to these steps, the clean task is created. Note that I didn't bother to create
    1167     // a new task for each of the decora files, preferring instead just to create a rule?? Also
    1168     // need "clean" tasks for each compile task.
    1169
    1170     addJSL(project, "Decora", "com/sun/scenario/effect/impl/hw/d3d/hlsl") { sourceDir, destinationDir ->
    1171         [[fileName: "ColorAdjust", generator: "CompileJSL", outputs: "-all"],
    1172          [fileName: "Brightpass", generator: "CompileJSL", outputs: "-all"],
    1173          [fileName: "SepiaTone", generator: "CompileJSL", outputs: "-all"],
    1174          [fileName: "PerspectiveTransform", generator: "CompileJSL", outputs: "-all"],
    1175          [fileName: "DisplacementMap", generator: "CompileJSL", outputs: "-all"],
    1176          [fileName: "InvertMask", generator: "CompileJSL", outputs: "-all"],
    1177          [fileName: "Blend", generator: "CompileBlend", outputs: "-all"],
    1178          [fileName: "PhongLighting", generator: "CompilePhong", outputs: "-all"],
    1179          [fileName: "LinearConvolve", generator: "CompileLinearConvolve", outputs: "-hw"],
    1180          [fileName: "LinearConvolveShadow", generator: "CompileLinearConvolve", outputs: "-hw"]].each { settings ->
    1181             javaexec {
    1182                 executable = JAVA
    1183                 workingDir = "modules/graphics"
    1184                 main = settings.generator
    1185                 classpath = configurations.compile + configurations.antlr3
    1186                 classpath += files("$buildDir/classes/main")
    1187                 classpath += files("$buildDir/classes/jsl-compilers/decora")
    1188                 args = ["-i", sourceDir, "-o", destinationDir, "-t", "-pkg", "com/sun/scenario/effect", "$settings.outputs", "$settings.fileName"]
    1189                 jvmArgs "-Djava.ext.dirs="
    1190             }
    1191         }
    1192     }
    1193
    1194     task generateDecoraNativeHeaders(type: JavaHeaderTask, dependsOn: compileDecoraJavaShaders) {
    1195         description = "Generates JNI Headers for Decora SSE Natives"
    1196         source file("$buildDir/classes/jsl-decora")
    1197         source file("$buildDir/classes/main")
    1198         include("com/sun/scenario/effect/impl/sw/sse/*");
    1199         classpath = files("$buildDir/classes/main", "$buildDir/classes/jsl-decora")
    1200         output = file("$buildDir/generated-src/headers/jsl-decora")
    1201     }
    1202
    1203     task nativeDecora(dependsOn: compileDecoraHLSLShaders, group: "Build") {
    1204         description = "Generates JNI headers, compiles, and builds native dynamic library for Decora"
    1205     }
    1206     task cleanNativeDecora(type: Delete, group: "Build") {
    1207         description = "Clean native objects for Decora"
    1208     }
    1209
    1210     def headerDir = file("$buildDir/generated-src/headers/jsl-decora")
    1211     def nativeRootDir = project.file("$project.buildDir/native/jsl-decora")
    1212     def libRootDir = project.file("$project.buildDir/libs/jsl-decora")
    1213     // For each compile target, create cc and link tasks
    1214     compileTargets { t ->
    1215         def target = t.name
    1216         def upperTarget = t.upper
    1217         def capitalTarget = t.capital
    1218         def properties = rootProject.ext[upperTarget];
    1219         def library = properties.library
    1220
    1221         def ccTask = task("compileDecoraNativeShaders$capitalTarget", type: CCTask, dependsOn: generateDecoraNativeHeaders) {
    1222             description = "Compiles Decora SSE natives"
    1223             matches = ".*\\.cc"
    1224             source file("$buildDir/generated-src/jsl-decora")
    1225             source file("modules/graphics/src/main/native-decora")
    1226             headers = headerDir
    1227             params.addAll(properties.decora.ccFlags)
    1228             output(file("$nativeRootDir/$target"))
    1229             compiler = properties.decora.compiler
    1230             cleanNativeDecora.delete file("$nativeRootDir/$target")
    1231         }
    1232
    1233         def linkTask = task("linkDecoraNativeShaders$capitalTarget", type: LinkTask, dependsOn: ccTask) {
    1234             description = "Creates native dynamic library for Decora SSE"
    1235             objectDir = file("$nativeRootDir/$target")
    1236             linkParams.addAll(properties.decora.linkFlags)
    1237             lib = file("$libRootDir/$t.name/${library(properties.decora.lib)}")
    1238             linker = properties.decora.linker
    1239             cleanNativeDecora.delete "$libRootDir/$t.name/"
    1240         }
    1241
    1242         nativeDecora.dependsOn(linkTask)
    1243     }
    1244
    1245     // Prism JSL
    1246     addJSL(project, "Prism", "com/sun/prism/d3d/hlsl") { sourceDir, destinationDir ->
    1247         def inputFiles = fileTree(dir: sourceDir)
    1248         inputFiles.include "**/*.jsl"
    1249         inputFiles.each { file ->
    1250             javaexec {
    1251                 executable = JAVA
    1252                 workingDir = "modules/graphics"
    1253                 main = "CompileJSL"
    1254                 classpath = configurations.compile + configurations.antlr3
    1255                 classpath += files("$buildDir/classes/jsl-compilers/prism", "modules/graphics/src/main/jsl-prism") // for the .stg
    1256                 args = ["-i", sourceDir, "-o", destinationDir, "-t", "-pkg", "com/sun/prism", "-d3d", "-es2", "-name", "$file"]
    1257                 jvmArgs "-Djava.ext.dirs="
    1258             }
    1259         }
    1260     }
    1261
    1262     classes.dependsOn compilePrismJavaShaders;
    1263     nativePrism.dependsOn compilePrismHLSLShaders;
    1264
    1265     project.nativeAllTask.dependsOn nativeDecora
    1266     project.cleanNativeAllTask.dependsOn cleanNativeDecora
    1267     assemble.dependsOn nativeDecora
    1268     processResources.dependsOn processDecoraShaders, processPrismShaders
    1269
    1270     test {
    1271         jvmArgs "-Djava.ext.dirs=", "-Djavafx.toolkit=com.sun.javafx.pgstub.StubToolkit", "-DCSS_META_DATA_TEST_DIR=${file('$buildDir/classes/main/javafx')}"
    1272         enableAssertions = true
    1273         testLogging.exceptionFormat = "full"
    1274         scanForTestClasses = false
    1275         include "**/*Test.*"
    1276         exclude "**/*Abstract*.*"
    1277         if (BUILD_CLOSED && DO_JCOV) {
    1278             addJCov(project, test)
    1279         }
    1280     }
    1281
    1282     // To enable the IDEs to all be happy (no red squiggles) we need to have the libraries
    1283     // available in some known location. Maybe in the future the Gradle plugins to each
    1284     // of the IDEs will be good enough that we won't need this hack anymore.
    1285     classes << {
    1286         // Copy all of the download libraries to the libs directory for the sake of the IDEs
    1287         File libsDir = rootProject.file("build/libs");
    1288         libsDir.mkdirs();
    1289         for (File f : [configurations.compile.files, configurations.antlr3.files].flatten()) {
    1290             copy {
    1291                 into libsDir
    1292                 from f.getParentFile()
    1293                 include "**/antlr-3.1.3.jar"
    1294                 include "**/stringtemplate-3.2.jar"
    1295                 include "**/antlr-runtime-3.1.3.jar"
    1296                 includeEmptyDirs = false
    1297             }
    1298             // Have to rename the swt jar because it is some platform specific name but
    1299             // for the sake of the IDEs we need to have a single stable name that works
    1300             // on every platform
    1301             copy {
    1302                 into libsDir
    1303                 from f.getParentFile()
    1304                 include "**/*swt*.jar"
    1305                 includeEmptyDirs = false
    1306                 rename ".*swt.*jar", "swt-debug\\.jar"
    1307             }
    1308         }
    1309     }
    1310 }
    1311
    1312 project(":controls") {
    1313     dependencies {
    1314         compile BUILD_SRC, project(":base"), project(":graphics"), project(":designTime")
    1315         // TODO not sure how to specify this? processResources project(":base"), project(":graphics")
    1316         testCompile project(":graphics").sourceSets.test.output
    1317         testCompile project(":base").sourceSets.test.output
    1318     }
    1319
    1320     test {
    1321         jvmArgs "-Djavafx.toolkit=com.sun.javafx.pgstub.StubToolkit"
    1322     }
    1323
    1324     // TODO Css2Bin really should be moved out and put into buildSrc if it can be
    1325     // TODO could change script to dynamically locate all .css files and create bss for them, probably better
    1326     // TODO also not sure there is any benefit to having css files in the jfxrt.jar at all
    1327     processResources << {
    1328         ["$buildDir/resources/main/com/sun/javafx/scene/control/skin/caspian/caspian.css",
    1329         "$buildDir/resources/main/com/sun/javafx/scene/control/skin/caspian/embedded-qvga.css",
    1330         "$buildDir/resources/main/com/sun/javafx/scene/control/skin/caspian/embedded.css",
    1331         "$buildDir/resources/main/com/sun/javafx/scene/control/skin/caspian/fxvk.css",
    1332         "$buildDir/resources/main/com/sun/javafx/scene/control/skin/caspian/highcontrast.css",
    1333         "$buildDir/resources/main/com/sun/javafx/scene/control/skin/modena/modena.css",
    1334         "$buildDir/resources/main/com/sun/javafx/scene/control/skin/modena/touch.css"].each { css ->
    1335             javaexec {
    1336                 executable = JAVA
    1337                 workingDir = "modules/controls"
    1338                 classpath files("$buildDir/classes/main",
    1339                         project(":graphics").sourceSets.main.output,
    1340                         project(":base").sourceSets.main.output)
    1341                 main = "com.sun.javafx.css.parser.Css2Bin"
    1342                 args css
    1343                 jvmArgs "-Djava.ext.dirs="
    1344             }
    1345         }
    1346     }
    1347 }
    1348
    1349 project(":swing") {
    1350     /* should not be built, but needed in builders and JMX
    1351     tasks.all {
    1352         if (!COMPILE_SWING) it.enabled = false
    1353     }
    1354     */
    1355     dependencies {
    1356         compile BUILD_SRC, project(":base"), project(":graphics")
    1357     }
    1358 }
    1359
    1360 project(":swt") {
    1361     tasks.all {
    1362         if (!COMPILE_SWT) it.enabled = false
    1363     }
    1364     dependencies {
    1365         compile BUILD_SRC, project(":base"), project(":graphics")
    1366         compile name: SWT_FILE_NAME
    1367     }
    1368 }
    1369
    1370 project(":fxml") {
    1371     dependencies {
    1372         compile BUILD_SRC, project(":base"), project(":graphics"),
    1373                 project(":controls"), project(":swt"), project(":swing")
    1374         testCompile project(":graphics").sourceSets.test.output
    1375     }
    1376     test {
    1377         // StubToolkit is not *really* needed here, but because some code inadvertently invokes performance
    1378         // tracker and this attempts to fire up the toolkit and this looks for native libraries and fails,
    1379         // we have to use the stub toolkit for now.
    1380         jvmArgs "-Djavafx.toolkit=com.sun.javafx.pgstub.StubToolkit"
    1381     }
    1382 }
    1383
    1384 project(":builders") {
    1385     sourceCompatibility = 1.7
    1386
    1387     if (!COMPILE_SWING)  sourceSets.main.java.exclude ("**/swing/**")
    1388     if (!COMPILE_SWT)    sourceSets.main.java.exclude ("**/swt/**")
    1389     if (!COMPILE_WEBKIT) sourceSets.main.java.exclude ("**/web/**")
    1390     if (!BUILD_CLOSED)   sourceSets.main.java.exclude ("**/media/**")
    1391
    1392     dependencies {
    1393         compile BUILD_SRC, project(":base"), project(":graphics"),
    1394                 project(":controls"), project(":swt"), project(":swing"), project(":web")
    1395         testCompile project(":graphics").sourceSets.test.output
    1396     }
    1397     test {
    1398         // StubToolkit is not *really* needed here, but because some code inadvertently invokes performance
    1399         // tracker and this attempts to fire up the toolkit and this looks for native libraries and fails,
    1400         // we have to use the stub toolkit for now.
    1401         jvmArgs "-Djavafx.toolkit=com.sun.javafx.pgstub.StubToolkit"
    1402     }
    1403 }
    1404
    1405 project(":designTime") {
    1406     tasks.all {
    1407         if (!COMPILE_DESIGN_TIME) it.enabled = false
    1408     }
    1409     dependencies {
    1410         compile project(":graphics")
    1411     }
    1412 }
    1413
    1414 project(":fxpackager") {
    1415     tasks.all {
    1416         if (!COMPILE_FXPACKAGER) it.enabled = false
    1417     }
    1418     // fxpackager has a dependency on ant in order to build the ant jar,
    1419     // and as such needs to point to the apache binary repository
    1420     if (!BUILD_CLOSED) {
    1421         repositories {
    1422             maven {
    1423                 url "https://repository.apache.org"
    1424             }
    1425         }
    1426     }
    1427
    1428     dependencies {
    1429         compile group: "org.apache.ant", name: "ant", version: "1.8.2"
    1430     }
    1431
    1432     // When producing the jar, we need to relocate a few class files
    1433     // from their normal location to a resources/classes or resources/web-files
    1434     // location
    1435     jar {
    1436         includeEmptyDirs = false
    1437         archiveName = "ant-javafx.jar"
    1438         eachFile { FileCopyDetails details ->
    1439             if (details.path.startsWith("com/javafx/main")) {
    1440                 details.path = "resources/classes/$details.path"
    1441             } else if (details.path.startsWith("web-files")) {
    1442                 details.path = "resources/$details.path"
    1443             }
    1444         }
    1445     }
    1446
    1447     // The "man" task will create a $buildDir/man containing the man
    1448     // files for the system being built
    1449     task man(type: Copy) {
    1450         includeEmptyDirs = false
    1451         enabled = (IS_LINUX || IS_MAC) && COMPILE_FXPACKAGER
    1452         from "src/main/man"
    1453         into "$buildDir/man"
    1454         exclude "**/*.html"
    1455         if (IS_MAC) exclude "**/ja_JP.UTF-8/**"
    1456     }
    1457     processResources.dependsOn man
    1458
    1459     // Compile the native launchers. These are included in ant-javafx.jar
    1460     // TODO should teach this to know 32 / 64 bit
    1461     if (IS_WINDOWS && COMPILE_FXPACKAGER) {
    1462         task compileWinLauncher(type: CCTask, group: "Build") {
    1463             description = "Compiles native sources for the application co-bundle launcher";
    1464             matches = "WinLauncher\\.cpp";
    1465             params.addAll(WIN.launcher.ccFlags);
    1466             output(file("$buildDir/native/WinLauncher"));
    1467             source(file("src/main/native/launcher/win"));
    1468             compiler = WIN.launcher.compiler
    1469             exe = true;
    1470             linkerOptions.addAll(WIN.launcher.linkFlags);
    1471             doLast {
    1472                 copy {
    1473                     from "$buildDir/native/WinLauncher/WinLauncher.exe"
    1474                     into "$buildDir/classes/main/com/sun/javafx/tools/resource/windows"
    1475                 }
    1476             }
    1477         }
    1478         task compileIconSwap(type: CCTask, group: "Build") {
    1479             description = "Compiles native sources for the application co-bundle launcher"
    1480             matches = "IconSwap\\.cpp"
    1481             params.addAll(WIN.iconLauncher.ccFlags)
    1482             output(file("$buildDir/native/IconSwap"))
    1483             source file("src/main/native/launcher/win")
    1484             compiler = WIN.launcher.compiler
    1485             exe = true
    1486             linkerOptions.addAll(WIN.iconLauncher.linkFlags)
    1487             doLast {
    1488                 copy {
    1489                     from "$buildDir/native/IconSwap/IconSwap.exe"
    1490                     into "$buildDir/classes/main/com/sun/javafx/tools/resource/windows"
    1491                 }
    1492             }
    1493         }
    1494         task compileLauncher(dependsOn: [compileWinLauncher, compileIconSwap])
    1495         jar.dependsOn compileLauncher;
    1496     } else if (COMPILE_FXPACKAGER) {
    1497         if (IS_MAC) {
    1498             task compileLauncher(type: CCTask, group: "Build") {
    1499                 description = "Compiles native sources for the application co-bundle launcher"
    1500                 matches = ".*\\.m"
    1501                 output(file("$buildDir/classes/main/com/sun/javafx/tools/resource/mac"))
    1502                 params.addAll(MAC.launcher.ccFlags)
    1503                 source file("src/main/native/launcher/mac")
    1504                 compiler = MAC.launcher.compiler
    1505                 eachOutputFile = { f ->
    1506                     return new File(f.getParent(), "JavaAppLauncher")
    1507                 }
    1508             }
    1509             jar.dependsOn compileLauncher;
    1510         } else {
    1511             def ccTask = project.task("compileLauncher", type: CCTask, group: "Build") {
    1512                 description = "Compiles native sources for the application co-bundle launcher"
    1513                 matches = ".*\\.c"
    1514                 output(file("$buildDir/native/launcher"))
    1515                 params.addAll(LINUX.launcher.ccFlags)
    1516                 compiler = LINUX.launcher.compiler
    1517                 source file("src/main/native/launcher/linux")
    1518             }
    1519             def linkTask = project.task("linkLauncher", type: LinkTask, dependsOn: ccTask, group: "Build") {
    1520                 description = "Creates native dynamic library for the application co-bundle launcher"
    1521                 linker = LINUX.launcher.linker
    1522                 linkParams.addAll(LINUX.launcher.linkFlags)
    1523                 objectDir = file("$buildDir/native/launcher")
    1524                 lib = file("$buildDir/classes/main/com/sun/javafx/tools/resource/linux/JavaAppLauncher")
    1525             }
    1526             jar.dependsOn linkTask;
    1527         }
    1528     }
    1529
    1530     // Builds the javafxpackager executable. For everything other than windows,
    1531     // this is simply moving the existing shell script and ensuring it has proper
    1532     // permissions. For Windows, this includes compiling the native executable
    1533     if (IS_WINDOWS && COMPILE_FXPACKAGER){
    1534         task buildJavaFXPackager(type: CCTask, group: "Build") {
    1535             description = "Compiles native sources for javafxpackager.exe"
    1536             matches = "javafxpackager\\.cpp"
    1537             params.addAll(WIN.fxpackager.ccFlags)
    1538             compiler = WIN.fxpackager.compiler
    1539             output(file("$buildDir/native/javafxpackager"))
    1540             source WIN.fxpackager.nativeSource
    1541             doLast {
    1542                 mkdir "$buildDir/native"
    1543                 exec({
    1544                     commandLine("$RC", "/nologo", "/l", "0x409", "/r", "/dJFX_DVERSION=8", "/dJFX_VERSION=8",
    1545                             "/fo$buildDir/native/javafxpackager/javafxpackager.res",
    1546                             "src/main/native/javafxpackager/win/javafxpackager.rc");
    1547                     environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT);
    1548                 });
    1549             }
    1550             doLast {
    1551                 mkdir "$buildDir/javafxpackager"
    1552                 exec({
    1553                     commandLine("$WIN.fxpackager.linker", "/nologo", "/opt:REF", "/incremental:no", "/manifest", "kernel32.lib", "advapi32.lib",
    1554                             "/out:$buildDir/native/javafxpackager/javafxpackager.exe",
    1555                             "$buildDir/native/javafxpackager/javafxpackager.obj",
    1556                             "$buildDir/native/javafxpackager/javafxpackager.res")
    1557                     environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
    1558                 })
    1559             }
    1560             doLast {
    1561                 copy {
    1562                     from file("src/main/native/javafxpackager/win/javafxpackager.manifest")
    1563                     into file("$buildDir/native/javafxpackager")
    1564                 }
    1565                 // TODO, not sure MT.exe is actually being used currently, so for now skipping.
    1566 //                exec({
    1567 //                    commandLine("$MT -nologo -manifest $buildDir/native/javafxpackager/javafxpackager.manifest")
    1568 //                    environment(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
    1569 //                })
    1570                 copy {
    1571                     from file("$buildDir/native/javafxpackager/javafxpackager.exe")
    1572                     into file("$buildDir/javafxpackager")
    1573                 }
    1574             }
    1575         }
    1576     } else {
    1577         task buildJavaFXPackager(group: "Build") << {
    1578             enabled = COMPILE_FXPACKAGER
    1579             copy {
    1580                 from "src/main/native/javafxpackager/shell"
    1581                 into "$buildDir/javafxpackager"
    1582                 fileMode = 0755
    1583             }
    1584         }
    1585     }
    1586
    1587     jar.dependsOn buildJavaFXPackager
    1588
    1589     classes << {
    1590         // Copy all of the download libraries to libs directory for the sake of the IDEs
    1591         File libsDir = rootProject.file("build/libs");
    1592         File antLib = new File(libsDir, "ant-1.8.2.jar")
    1593         libsDir.mkdirs();
    1594         for (File f : configurations.compile.files) {
    1595             copy {
    1596                 into libsDir
    1597                 from f.getParentFile()
    1598                 include "**/ant-1.8.2.jar"
    1599                 includeEmptyDirs = false
    1600             }
    1601         }
    1602     }
    1603 }
    1604
    1605 allprojects {
    1606     // The following block is a workaround for the fact that presently Gradle
    1607     // can't set the -XDignore.symbol.file flag, because it appears that the
    1608     // javac API is lacking support for it. So what we'll do is find any Compile
    1609     // task and manually provide the options necessary to fire up the
    1610     // compiler with the right settings.
    1611     //
    1612     // Also, we need to remove jfxrt.jar from the ext classpath (if it is there)
    1613     // and instead each module that depends on closed bits is going to need to
    1614     // add BINARY_STUB to its list of dependencies.
    1615     tasks.withType(Compile) { compile ->
    1616         // It looks like we have to use ant to compile instead of the built-in gradle
    1617         // compiler stuff because otherwise it won't compile on CYGWIN
    1618         // TODO need to file issue with Gradle
    1619         compile.options.useAnt = true
    1620         compile.options.debug = true // we always generate debugging info in the class files
    1621         compile.options.debugOptions.debugLevel = IS_DEBUG ? "source,lines,vars" : "source,lines"
    1622         compile.options.fork = true
    1623         compile.options.forkOptions.executable = JAVAC
    1624         compile.options.warnings = IS_LINT
    1625         compile.options.useDepend = USE_DEPEND
    1626         compile.options.compilerArgs = ["-Djava.ext.dirs=", "-XDignore.symbol.file", "-encoding", "UTF-8"]
    1627
    1628         // Add in the -Xlint options
    1629         if (IS_LINT) {
    1630             LINT.split("[, ]").each { s ->
    1631                 compile.options.compilerArgs += "-Xlint:$s"
    1632             }
    1633         }
    1634
    1635         // Somewhat dangerous in case there is a java source set other than "test" or "stub" or "main"!
    1636         // Note that the compileFooJava task is automatically created whenever a source set is
    1637         // defined. So the "test" source set automatically creates a "compileTestJava" task (among others).
    1638         if (name == "compileTestJava") {
    1639             classpath = sourceSets.test.compileClasspath
    1640             if (rootProject.BINARY_STUB != null) classpath += rootProject.BINARY_STUB
    1641         } else if (name == "compileJava") {
    1642             // Not everything needs the builder processor
    1643             classpath = sourceSets.main.compileClasspath
    1644             if (rootProject.BINARY_STUB != null) classpath += rootProject.BINARY_STUB
    1645         } else {
    1646             logger.info("Not using BINARY_STUB in compilation: $name")
    1647         }
    1648     }
    1649 }
    1650
    1651 /******************************************************************************
    1652  *                                                                            *
    1653  *                             Top Level Tasks                                *
    1654  *                                                                            *
    1655  *  These are the tasks which are defined only for the top level project and  *
    1656  *  not for any sub projects. These are generally the entry point that is     *
    1657  *  used by Hudson and by the continuous build system.                        *
    1658  *                                                                            *
    1659  *****************************************************************************/
    1660
    1661 task clean() {
    1662     group = "Basic"
    1663     description = "Deletes the build directory and the build directory of all sub projects"
    1664     getSubprojects().each { subProject ->
    1665         dependsOn(subProject.getTasksByName("clean", true));
    1666     }
    1667     doLast {
    1668         delete(buildDir);
    1669     }
    1670 }
    1671
    1672 task javadoc(type: Javadoc) {
    1673     enabled = BUILD_JAVADOC
    1674     group = "Basic"
    1675     description = "Generates the JavaDoc for all the public API"
    1676     executable = JAVADOC
    1677     def projectsToDocument = [
    1678             project(":base"), project(":graphics"), project(":controls"),
    1679             project(":swing"), project(":swt"), project(":fxml"), project(":web")]
    1680     source(projectsToDocument.collect({
    1681         [it.sourceSets.main.java, "$it.buildDir/generated-src/builders"]
    1682     }));
    1683     setDestinationDir(new File(buildDir, 'javadoc'));
    1684     // Might need a classpath
    1685     classpath = files(projectsToDocument.collect { project ->
    1686         project.sourceSets.main.compileClasspath
    1687     });
    1688     classpath += files(projectsToDocument.collect { project ->
    1689         project.sourceSets.main.output
    1690     });
    1691     exclude("com/**/*", "javafx/scene/ParentDesignInfo*", "Compile*", "javafx/builder/**/*");
    1692     options.windowTitle("JavaFX ${RELEASE_NAME}")
    1693     options.links(JDK_DOCS);
    1694     options.addBooleanOption("XDignore.symbol.file").setValue(true);
    1695     options.addBooleanOption("Xdoclint:none").setValue(!IS_DOC_LINT);
    1696     options.addBooleanOption("javafx").setValue(true);
    1697     doLast {
    1698         projectsToDocument.each { p ->
    1699             copy {
    1700                 from "$p.projectDir/src/main/docs"
    1701                 into "$buildDir/javadoc"
    1702             }
    1703         }
    1704     }
    1705
    1706     dependsOn(projectsToDocument.collect { project -> project.getTasksByName("classes", true)});
    1707 }
    1708
    1709 task jfxrt()
    1710
    1711 task sdk() {
    1712     dependsOn(checkJfxrtJar)
    1713 }
    1714
    1715 // this is empty, allowing us to depend on the task, which may have other
    1716 // real intances added later.
    1717 task copyAppsArtifacts()
    1718
    1719 task apps() {
    1720     dependsOn(sdk)
    1721     dependsOn(copyAppsArtifacts)
    1722 }
    1723
    1724 task fullTest() {
    1725 // TODO: WHY DOES THE FOLLOWING NOT WORK???
    1726 //    dependsOn(test)
    1727
    1728     // TODO additional tests
    1729     doLast {
    1730         println "fullTest task is not implemented"
    1731     }
    1732 }
    1733
    1734 task findbugs() {
    1735     dependsOn(sdk)
    1736
    1737     // TODO: implement this
    1738     doLast {
    1739         if (!BUILD_CLOSED) {
    1740             println "findbugs task is not implemented"
    1741         }
    1742     }
    1743 }
    1744
    1745 // The following tasks are for the closed build only. They are a no-op for the open build
    1746
    1747 task checkCache() {
    1748     dependsOn(updateCacheIfNeeded)
    1749 }
    1750
    1751 // TODO: consider moving the "public-sdk" portion of this task here
    1752 task publicExports() {
    1753     doFirst {
    1754         if (!BUILD_JAVADOC) {
    1755             fail("publicExports task requires: -PBUILD_JAVADOC=true")
    1756         }
    1757     }
    1758     dependsOn(sdk)
    1759     doLast {
    1760         if (!BUILD_CLOSED) {
    1761             println "publicExports task is only run for a closed build"
    1762         }
    1763     }
    1764 }
    1765
    1766 task perf() {
    1767     dependsOn(sdk,apps)
    1768     doLast {
    1769         if (!BUILD_CLOSED) {
    1770             println "perf task is only run for a closed build"
    1771         }
    1772     }
    1773 }
    1774
    1775 task zips() {
    1776     doFirst {
    1777         if (!BUILD_JAVADOC) {
    1778             fail("zips task requires: -PBUILD_JAVADOC=true")
    1779         }
    1780     }
    1781     dependsOn(sdk,publicExports,apps,perf)
    1782     doLast {
    1783         if (!BUILD_CLOSED) {
    1784             println "zips task is only run for a closed build"
    1785         }
    1786     }
    1787 }
    1788
    1789 task all() {
    1790     dependsOn(sdk,publicExports,apps,perf,zips)
    1791 }
    1792
    1793 compileTargets { t ->
    1794     def targetProperties = project.ext[t.upper]
    1795     def library = targetProperties.library
    1796     // The jfxrt task is responsible for creating the jfxrt.jar. A developer may
    1797     // have multiple SDK's on their system at any one time, depending on which
    1798     // cross compiles they have done. For example, I might have:
    1799     //      build/mac-sdk/rt/lib/ext/jfxrt.jar
    1800     //      build/ios-sdk/rt/lib/ext/jfxrt.jar
    1801     //      build/win-sdk/rt/lib/ext/jfxrt.jar
    1802     //      build/armhf-sdk/rt/lib/ext/jfxrt.jar
    1803     //
    1804     // and so forth. This arrangement allows for multiple independent SDKs to
    1805     // exist on a developer's system.
    1806     def jfxrtTask = task("jfxrt$t.capital", type: Jar) {
    1807         group = "Basic"
    1808         description = "Creates the jfxrt.jar for the $t.name target"
    1809         archiveName = "build/${t.name}-sdk/rt/lib/ext/jfxrt.jar";
    1810         includeEmptyDirs = false
    1811         from("modules/base/build/classes/main",
    1812              "modules/base/build/resources/main",
    1813              "modules/builders/build/classes/main",
    1814              "modules/graphics/build/classes/main",
    1815              "modules/graphics/build/resources/main",
    1816              "modules/controls/build/classes/main",
    1817              "modules/controls/build/resources/main",
    1818              "modules/fxml/build/classes/main",
    1819              "modules/fxml/build/resources/main",
    1820              "modules/graphics/build/classes/jsl-decora",
    1821              "modules/graphics/build/resources/jsl-decora",
    1822              "modules/graphics/build/classes/jsl-prism",
    1823              "modules/graphics/build/resources/jsl-prism");
    1824         if (COMPILE_SWING) from ("modules/swing/build/classes/main", "modules/swing/build/resources/main")
    1825         if (COMPILE_SWT) from ("modules/swt/build/classes/main", "modules/swt/build/resources/main")
    1826         if (t.name == 'android') {
    1827             from ("modules/web/build/classes/android",
    1828                   "modules/web/build/resources/android",
    1829                   "modules/controls/build/classes/android",
    1830                   "modules/controls/build/resources/android")
    1831         } else if (t.name == 'ios') {
    1832             from ("modules/web/build/classes/ios", "modules/web/build/resources/ios")
    1833         } else {
    1834             from ("modules/web/build/classes/main", "modules/web/build/resources/main")
    1835         }
    1836         exclude("js/**/*", // er...
    1837                 "PrismLoaderBackend*", // More decora stuff
    1838                 "**/*.stg",    // any glue files for decora must be excluded
    1839                 "**/*.java");  // Builder java files are in build/classes and should be excluded
    1840
    1841         // Filter out platform specific Java sources (glass) when compiling for other targets
    1842         exclude(targetProperties.jfxrtJarExcludes)
    1843
    1844         dependsOn(subprojects.collect { project -> project.getTasksByName("assemble", true)});
    1845     }
    1846     def jfxrtIndexTask = task("jfxrtIndex$t.capital") {
    1847         //the following is a workaround for the lack of indexing in gradle 1.4 through 1.7
    1848         dependsOn(jfxrtTask)
    1849
    1850         doLast() {
    1851             ant.jar (update: true, index: true, destfile: jfxrtTask.archiveName)
    1852         }
    1853     }
    1854     jfxrt.dependsOn(jfxrtIndexTask)
    1855
    1856     // The 'sdk' task will build the rest of the SDK, and depends on the 'jfxrtTask' task. After
    1857     // executing this task the sdk bundle for the current COMPILE_TARGETS will be fully created.
    1858     def sdkTask = task("sdk$t.capital") {
    1859         group = "Basic"
    1860         description = "Creates the SDK for $t.name"
    1861         doLast {
    1862             // TODO instead of using copy everywhere, I probably want to use "sync" instead?
    1863             // Copy all of the .dll / .so / .dylib native libraries into build/sdk/rt/lib/
    1864             copy {
    1865                 def useLipo = targetProperties.containsKey('useLipo') ? targetProperties.useLipo : false
    1866                 from("modules/graphics/build/libs/jsl-decora/${t.name}/${library(targetProperties.decora.lib)}")
    1867                 def libs = ['font', 'prism', 'prismSW', 'prismES2', 'glass', 'iio']
    1868                 if (COMPILE_PANGO) {
    1869                     libs += 'fontPango';
    1870                 }
    1871                 libs.each { lib ->
    1872                     def variants = targetProperties[lib].containsKey('variants') && !useLipo ? targetProperties[lib].variants : [null]
    1873                     variants.each { variant ->
    1874                         def variantProperties = variant ? targetProperties[lib][variant] : targetProperties[lib]
    1875                         println "modules/graphics/build/libs/$lib/$t.name/${library(variantProperties.lib)}"
    1876                         from ("modules/graphics/build/libs/$lib/$t.name/${library(variantProperties.lib)}")
    1877                     }
    1878                 }
    1879                 if (IS_WINDOWS) {
    1880                     from ("modules/graphics/build/libs/prismD3D/${t.name}/${library(targetProperties.prismD3D.lib)}");
    1881                 }
    1882                 if (COMPILE_WEBKIT) {
    1883                     from ("modules/web/build/libs/${t.name}/${library('jfxwebkit')}")
    1884                 } else {
    1885                     if (t.name == "android") {
    1886                         //don't copy anything, use built in webkit.
    1887                     }
    1888                     else if (IS_MAC && COMPILE_TARGETS != "ios") from ("$LIBRARY_STUB/libjfxwebkit.dylib")
    1889                     else if (IS_WINDOWS) {
    1890                         from ("$LIBRARY_STUB/jfxwebkit.dll")
    1891                         from ("$LIBRARY_STUB/libxml2.dll")
    1892                         from ("$LIBRARY_STUB/libxslt.dll")
    1893                     }
    1894                     else from ("$LIBRARY_STUB/libjfxwebkit.so")
    1895                 }
    1896                 def libDest = targetProperties.libDest
    1897                 into ("build/${t.name}-sdk/rt/$libDest")
    1898             }
    1899
    1900             // Create the javafx.properties file
    1901             final File javafxProperties = file("build/${t.name}-sdk/rt/lib/javafx.properties")
    1902             javafxProperties.delete()
    1903             javafxProperties << "javafx.runtime.version=$RAW_VERSION";
    1904             // Include any properties that have been defined (most likely in
    1905             // one of the various platform gradle files)
    1906             if (targetProperties.containsKey("javafxProperties")) {
    1907                 javafxProperties << "\n"
    1908                 javafxProperties << targetProperties.javafxProperties
    1909             }
    1910
    1911             // Embedded builds define this file as well
    1912             if (targetProperties.containsKey("javafxPlatformProperties")) {
    1913                 final File javafxPlatformProperties = file("build/${t.name}-sdk/rt/lib/javafx.platform.properties")
    1914                 javafxPlatformProperties.delete()
    1915                 javafxPlatformProperties << targetProperties.javafxPlatformProperties
    1916             }
    1917
    1918             // Copy over the javadocs that were generated. This is done rather than just generating
    1919             // the docs into the "right place" because for a cross-compile you only need one set of
    1920             // docs but need to have a copy in each created sdk
    1921             if (BUILD_JAVADOC) {
    1922                 copy {
    1923                     from "build/javadoc"
    1924                     into "build/${t.name}-sdk/docs/api"
    1925                 }
    1926             }
    1927
    1928             // Copy over the fxpackager and rename as ant-javafx.jar
    1929             copy {
    1930                 from "modules/fxpackager/build/libs"
    1931                 into "build/${t.name}-sdk/lib"
    1932             }
    1933
    1934             // Copy over the FXPackager man files
    1935             copy {
    1936                 from "modules/fxpackager/build/man"
    1937                 into "build/${t.name}-sdk/man"
    1938             }
    1939
    1940             // Copy over the javafxpackager executable
    1941             if (t.name == "win" || t.name == "linux" || t.name == "mac") {
    1942                 copy {
    1943                     from "modules/fxpackager/build/javafxpackager"
    1944                     into "build/${t.name}-sdk/bin"
    1945                 }
    1946             }
    1947         }
    1948         dependsOn(jfxrtTask)
    1949         dependsOn(javadoc)
    1950     }
    1951
    1952     def generateSymbols = targetProperties.containsKey('generateSymbols') ? targetProperties.generateSymbols : false
    1953     if (generateSymbols) {
    1954         def exportedSymbolsTask = project.task("exportedSymbols${t.capital}", type: ExportedSymbolsTask, dependsOn: sdkTask, group: "Build") {
    1955             description = "Generates exported symbols file for iOS build (from .a libraries)"
    1956             def libDirName = "build/${t.name}-sdk/rt/$targetProperties.libDest"
    1957             libDir = file("$libDirName")
    1958             outputFile = file("$libDirName/exported.symbols")
    1959             excludes = targetProperties.generateSymbolsExcludes
    1960         }
    1961         sdk.dependsOn(exportedSymbolsTask)
    1962     }
    1963
    1964     sdk.dependsOn(sdkTask)
    1965 }
    1966
    1967     //task integrationCheck {
    1968     //    group = "Basic"
    1969     //    description = "Performs all the tasks necessary to ensure that the current build is ready for integration."
    1970     //    dependsOn sdk
    1971     //    dependsOn subprojects.collect { project -> project.getTasksByName("check", true)}
    1972     //}
    1973
    1974 /*
    1975  * This clause changes the way we handle a build.gradle within ./apps
    1976  * It does a few things:
    1977  *   modifies the classpath used to include the built runttime classes
    1978  *   provides for copying the build applications to the artifacts tree
    1979  *
    1980  * The applications to be built will be under ./apps, but also must
    1981  * be listed in the applications listed in the setting variable: JFXApplications
    1982  */
    1983 ext.JFXRT_CP =
    1984     files(
    1985         project(":base").sourceSets.main.output.classesDir,
    1986         project(":graphics").sourceSets.main.output.classesDir,
    1987         project(":controls").sourceSets.main.output.classesDir,
    1988         project(":fxml").sourceSets.main.output.classesDir,
    1989         project(":swing").sourceSets.main.output.classesDir, //NOTE - used by 3Dviewer
    1990         //project(":swt").sourceSets.main.output.classesDir,
    1991         project(":builders").sourceSets.main.output.classesDir,
    1992             "modules/media/build/classes/main",
    1993             "modules/web/build/classes/main",
    1994     )
    1995
    1996 if (BINARY_STUB != null) {
    1997     JFXRT_CP += BINARY_STUB
    1998 }
    1999
    2000 childProjects["apps"].subprojects {
    2001     afterEvaluate { project ->
    2002         // this check is to make sure we are using a java or application plugin
    2003         // in our child projects of ./apps
    2004         if (project.hasProperty("jar") && project.hasProperty("compileJava")) {
    2005             def srcdir = new File ("$project.projectDir/src");
    2006
    2007             if (srcdir.exists()) {
    2008                 // augment the classpath with our build system classpath
    2009                 // which will include our local jfxrt.jar
    2010                 project.compileJava {
    2011                     // TODO: don't know how to do this correctly
    2012                     //dependsOn project(":graphics").classes, project(":controls").classes, project(":base").classes
    2013                     doFirst {
    2014                         classpath = rootProject.JFXRT_CP + sourceSets.main.compileClasspath
    2015                     }
    2016                 }
    2017                 test.exclude("**/*");
    2018             } else {
    2019                 // no source, but still a 'java' plugin, so just disable it
    2020                 project.tasks.all {
    2021                     it.enabled = false
    2022                 }
    2023             }
    2024         }
    2025     }
    2026 }
    2027
    2028 /******************************************************************************
    2029  *                                                                            *
    2030  *                              BUILD_CLOSED                                  *
    2031  *                                                                            *
    2032  * This next section should remain at the end of the build script. It allows  *
    2033  * for a "supplemental" gradle file to be used to extend the normal build     *
    2034  * structure. For example, this is used for passing a supplemental gradle     *
    2035  * file for producing official JavaFX builds.                                 *
    2036  *                                                                            *
    2037  *****************************************************************************/
    2038
    2039 if (BUILD_CLOSED) {
    2040     apply from: supplementalBuildFile
    2041 }
    2042
    2043 // This project has to be defined after [supplementalBuildFile]
    2044 // because it depends on media tasks
    2045 project(":web") {
    2046     configurations {
    2047         webkit
    2048     }
    2049     dependencies {
    2050         compile project(":base"), project(":graphics"), project(":controls")
    2051         testCompile files("../../../artifacts/sdk/rt/lib/ext/jfxrt.jar")
    2052     }
    2053
    2054     compileJava.enabled = COMPILE_WEBKIT
    2055     if (BUILD_CLOSED) {
    2056         compileJava.dependsOn compileMediaJava
    2057         compileJava.classpath += files(
    2058                 "../media/build/classes/main",
    2059                 "$jfxTopDir/media/jfxmedia/dist/jfxmedia.jar")
    2060     }
    2061
    2062     task generateHeaders(dependsOn: compileJava) {
    2063         doLast {
    2064             def classpath = files("$buildDir/classes/main",
    2065                                   project(":graphics").sourceSets.main.output.classesDir)
    2066             def dest = file("$buildDir/generated-src/headers");
    2067             mkdir dest;
    2068             exec {
    2069                 commandLine("$JAVAH", "-J-Djava.ext.dirs=", "-d", "$dest",
    2070                             "-classpath", "${classpath.asPath}");
    2071                 args("java.lang.Character",
    2072                      "java.net.IDN",
    2073                      "com.sun.webkit.ContextMenu",
    2074                      "com.sun.webkit.ContextMenuItem",
    2075                      "com.sun.webkit.CursorManager",
    2076                      "com.sun.webkit.PageCache",
    2077                      "com.sun.webkit.PopupMenu",
    2078                      "com.sun.webkit.SharedBuffer",
    2079                      "com.sun.webkit.WebPage",
    2080                      "com.sun.webkit.LoadListenerClient",
    2081                      "com.sun.webkit.event.WCFocusEvent",
    2082                      "com.sun.webkit.event.WCKeyEvent",
    2083                      "com.sun.webkit.event.WCMouseEvent",
    2084                      "com.sun.webkit.event.WCMouseWheelEvent",
    2085                      "com.sun.webkit.graphics.GraphicsDecoder",
    2086                      "com.sun.webkit.graphics.RenderMediaControls",
    2087                      "com.sun.webkit.graphics.RenderTheme",
    2088                      "com.sun.webkit.graphics.ScrollBarTheme",
    2089                      "com.sun.webkit.graphics.WCMediaPlayer",
    2090                      "com.sun.webkit.graphics.WCGraphicsManager",
    2091                      "com.sun.webkit.graphics.WCRenderQueue",
    2092                      "com.sun.webkit.graphics.WCPath",
    2093                      "com.sun.webkit.graphics.WCPathIterator",
    2094                      "com.sun.webkit.Timer",
    2095                      "com.sun.webkit.WCFrameView",
    2096                      "com.sun.webkit.WCPasteboard",
    2097                      "com.sun.webkit.WCPluginWidget",
    2098                      "com.sun.webkit.dom.JSObject",
    2099                      "com.sun.webkit.network.SocketStreamHandle",
    2100                      "com.sun.webkit.network.URLLoader",
    2101                      "com.sun.webkit.text.TextBreakIterator",
    2102                      "com.sun.webkit.text.TextNormalizer");
    2103             }
    2104         }
    2105     }
    2106
    2107     task compileGenerated()
    2108
    2109     compileTargets { t ->
    2110         def classifier = (t.name != "linux" && t.name != "win") ? t.name :
    2111                           IS_64 ? "${t.name}-amd64" : "${t.name}-i586"
    2112         dependencies {
    2113             webkit group: "com.sun.webkit", name: "webview-deps",
    2114                    version: "1.2", classifier: "$classifier", ext: "zip"
    2115         }
    2116
    2117         def webkitOutputDir = "$buildDir/${t.name}"
    2118
    2119         def compileNativeTask = task("compileNative${t.capital}", dependsOn: generateHeaders) << {
    2120             println "Building Webkit configuration /$CONF/ into $webkitOutputDir"
    2121
    2122             def dependencyFile = configurations.webkit.filter(
    2123                     { File f -> f.getName().contains(classifier) }
    2124                 ).getSingleFile()
    2125             ant.unzip(src:  dependencyFile,
    2126                       dest: webkitOutputDir)
    2127
    2128             exec {
    2129                 workingDir("$projectDir/src/main/native")
    2130                 commandLine("perl", "Tools/Scripts/set-webkit-configuration", "--$CONF")
    2131                 environment(["WEBKITOUTPUTDIR" : webkitOutputDir])
    2132             }
    2133
    2134             exec {
    2135                 workingDir("$projectDir/src/main/native")
    2136                 if (t.name == "win") {
    2137                     String qtDir = cygpath(System.getenv().get("QTSDK_DIR"))
    2138                     Map environmentSettings = new HashMap(WINDOWS_NATIVE_COMPILE_ENVIRONMENT)
    2139                     environmentSettings["PATH"] = "$WINDOWS_VS_PATH;$qtDir/bin;$qtDir/qt/bin"
    2140                     environmentSettings["QMAKESPEC"] = "win32-msvc2008"
    2141                     environment(environmentSettings)
    2142                     /* To build with ICU:
    2143                     1. Download http://javaweb.us.oracle.com/jcg/fx-webrevs/RT-17164/WebKitLibrariesICU.zip
    2144                     and unzip it to WebKitLibraries folder.
    2145                     2. Copy DLLs from
    2146                     WebKitLibrariesICU.zip\WebKitLibraries\import\runtime
    2147                     to %windir%\system32
    2148                     3. Uncomment the line below
    2149                      */
    2150                     // args("--icu-unicode")
    2151                 } else if (t.name == "mac") {
    2152                     environment([
    2153                         "QMAKESPEC"      : "macx-g++",
    2154                         "QMAKE_CFLAGS"   : "-m64",
    2155                         "QMAKE_LFLAGS"   : "-m64",
    2156                     ])
    2157                 } else if (t.name.startsWith("arm")) {
    2158                     // ARM cross build
    2159                     def webkitProperties = project.rootProject.ext[t.upper].webkit
    2160                     def qmakeSpecDir = "$webkitOutputDir/qws/linux-cross-${t.name}-g++"
    2161                     mkdir qmakeSpecDir
    2162                     File qmakeSpec = new File("$qmakeSpecDir/qmake.conf")
    2163                     qmakeSpec.append(
    2164 """TARGET_PLATFORM         = unix
    2165 include(/usr/share/qt4/mkspecs/common/linux.conf)
    2166 include(/usr/share/qt4/mkspecs/common/g++.conf)
    2167 include(/usr/share/qt4/mkspecs/common/qws.conf)
    2168 QMAKE_CC                = $webkitProperties.compiler
    2169 QMAKE_CXX               = $webkitProperties.linker
    2170 QMAKE_LINK              = $webkitProperties.linker
    2171 QMAKE_LINK_SHLIB        = $webkitProperties.linker
    2172 QMAKE_AR                = $webkitProperties.ar cqs
    2173 QMAKE_OBJCOPY           = $webkitProperties.objcopy
    2174 QMAKE_STRIP             = $webkitProperties.strip
    2175 QMAKE_CXXFLAGS          = $webkitProperties.ccFlags
    2176 QMAKE_LFLAGS            = $webkitProperties.linkFlags
    2177 load(qt_config)""")
    2178                     environment([
    2179                         "QMAKESPEC" : file(qmakeSpecDir).getAbsolutePath(),
    2180                         "PATH"      : "$System.env.PATH:$webkitProperties.binDir",
    2181                     ])
    2182                     args("--nocache")
    2183                 }
    2184                 environment([
    2185                     "JAVA_HOME"       : JAVA_HOME,
    2186                     "WEBKITOUTPUTDIR" : webkitOutputDir,
    2187                 ])
    2188                 commandLine("perl", "Tools/Scripts/build-webkit", "--java", "--imageio")
    2189             }
    2190
    2191             def library = rootProject.ext[t.upper].library
    2192             copy {
    2193                 from "$webkitOutputDir/$CONF/lib/${library('jfxwebkit')}"
    2194                 into "$buildDir/libs/${t.name}"
    2195             }
    2196             copy {
    2197                 from "$webkitOutputDir/$CONF/lib/${library('DumpRenderTreeJava')}"
    2198                 into "$buildDir/test/${t.name}"
    2199             }
    2200         }
    2201
    2202         def compileGeneratedTask = task("compileGenerated${t.capital}", type: JavaCompile, dependsOn: compileNativeTask) {
    2203             def gensrcDir = "$webkitOutputDir/$CONF/WebCore/generated/java"
    2204             doFirst {
    2205                 copy {
    2206                     from "$projectDir/src/main/native/Source/WebCore/bindings/java/EventListenerImpl.java"
    2207                     into "$gensrcDir/com/sun/webkit/dom"
    2208                 }
    2209             }
    2210             classpath = files(project(":graphics").sourceSets.main.output) // for JSObject
    2211             source gensrcDir
    2212             destinationDir = file("$buildDir/classes/main")
    2213         }
    2214
    2215         compileGenerated.dependsOn compileGeneratedTask
    2216     }
    2217
    2218     def drtClasses = "com/sun/javafx/webkit/drt/**"
    2219     jar.exclude(drtClasses)
    2220     task drtJar(type: Jar, dependsOn: compileJava) {
    2221         archiveName = "drt.jar"
    2222         destinationDir = file("$buildDir/test")
    2223         from "$buildDir/classes/main"
    2224         include drtClasses
    2225     }
    2226
    2227     task copyClassesFromBinaryStub << {
    2228         copy {
    2229             from zipTree(rootProject.BINARY_STUB.getSingleFile())
    2230             into "$buildDir/classes/main"
    2231             include("javafx/scene/web/**",
    2232                 "com/sun/javafx/scene/web/**",
    2233                 "com/sun/webkit/**",
    2234                 "com/sun/javafx/webkit/**",
    2235                 "netscape/javascript/**",
    2236                 "com/sun/javafx/sg/prism/NGWebView*")
    2237         }
    2238     }
    2239
    2240     if (COMPILE_WEBKIT) {
    2241         jar.dependsOn compileGenerated, drtJar
    2242     } else {
    2243         jar.dependsOn copyClassesFromBinaryStub
    2244     }
    2245 }
    2246
    2247 task showFlags {
    2248 }
    2249
    2250 compileTargets { t ->
    2251     // Every platform must define these variables
    2252     def props = project.ext[t.upper];
    2253     showFlags.dependsOn(
    2254         project.task("showFlags$t.upper") {
    2255             doLast() {
    2256                 println "Properties set for $t.upper"
    2257                 props.each { println it }
    2258             }
    2259         }
    2260     )
    2261 }