diff --git a/build.gradle b/build.gradle index 868243a..1d8100f 100644 --- a/build.gradle +++ b/build.gradle @@ -1,42 +1,30 @@ plugins { - id 'com.gradle.build-scan' version '2.1' - id 'java-gradle-plugin' - id 'com.github.hierynomus.license' version '0.15.0' - id 'com.gradle.plugin-publish' version '0.12.0' - id 'com.github.ben-manes.versions' version '0.20.0' - id 'maven-publish' + id 'com.gradle.plugin-publish' version '1.2.1' + id 'com.github.ben-manes.versions' version '0.47.0' + id 'com.github.hierynomus.license' version '0.16.1' } -buildScan { - termsOfServiceUrl = 'https://gradle.com/terms-of-service' - termsOfServiceAgree = 'yes' -} - -group 'org.openjfx' -version '0.0.15-SNAPSHOT' +group = 'org.openjfx' +version = '0.0.15-SNAPSHOT' -sourceCompatibility = 11 -targetCompatibility = 11 +java { + toolchain.languageVersion = JavaLanguageVersion.of(11) +} repositories { mavenCentral() - maven { - url "https://plugins.gradle.org/m2/" - } + gradlePluginPortal() } dependencies { - implementation gradleApi() - implementation 'com.google.gradle:osdetector-gradle-plugin:1.7.3' - implementation 'org.javamodularity:moduleplugin:1.8.12' - testImplementation gradleTestKit() - testImplementation 'org.junit.jupiter:junit-jupiter-api:5.3.2' - testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.3.2' + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.2' + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine' + testRuntimeOnly 'org.junit.platform:junit-platform-launcher' } -test { +tasks.named('test', Test) { useJUnitPlatform() } @@ -47,34 +35,24 @@ gradlePlugin { displayName = 'JavaFX Gradle Plugin' description = 'Plugin that makes it easy to work with JavaFX' implementationClass = 'org.openjfx.gradle.JavaFXPlugin' + website = 'https://github.com/openjfx/javafx-gradle-plugin' + vcsUrl = 'https://github.com/openjfx/javafx-gradle-plugin' + tags.set(['java', 'javafx']) } } } -pluginBundle { - website = 'https://github.com/openjfx/javafx-gradle-plugin' - vcsUrl = 'https://github.com/openjfx/javafx-gradle-plugin' - tags = [ 'java', 'javafx' ] -} - publishing { - publications { - maven(MavenPublication) { - groupId = project.group - artifactId = 'javafx-gradle-plugin' - version = project.version - - from components.java - } - } repositories { maven { - if (project.hasProperty('sonatypeUsername') && project.hasProperty('sonatypePassword')) { + url = "https://oss.sonatype.org/content/repositories/snapshots/" + def sonatypeUsername = providers.gradleProperty('sonatypeUsername') + def sonatypePassword = providers.gradleProperty('sonatypePassword') + if (sonatypeUsername.isPresent() && sonatypePassword.isPresent()) { credentials { - username project.property('sonatypeUsername') - password project.property('sonatypePassword') + username = sonatypeUsername.get() + password = sonatypePassword.get() } - url = "https://oss.sonatype.org/content/repositories/snapshots/" } } } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 1948b90..7f93135 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index c7dda25..ac72c34 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ -#Tue Nov 13 11:59:28 CET 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip +networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip diff --git a/gradlew b/gradlew index cccdd3d..0adc8e1 100755 --- a/gradlew +++ b/gradlew @@ -1,78 +1,127 @@ -#!/usr/bin/env sh +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -81,92 +130,120 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=$((i+1)) + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=$(save "$@") - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" fi +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index f955316..6689b85 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,84 +1,92 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle b/settings.gradle index 49bca9e..78a9ab0 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1,12 @@ +plugins { + id 'com.gradle.enterprise' version '3.14.1' +} + +gradleEnterprise { + buildScan { + termsOfServiceUrl = 'https://gradle.com/terms-of-service' + termsOfServiceAgree = 'yes' + } +} + rootProject.name = 'javafx-plugin' diff --git a/src/main/java/org/openjfx/gradle/JavaFXModule.java b/src/main/java/org/openjfx/gradle/JavaFXModule.java index 982d844..00079ce 100644 --- a/src/main/java/org/openjfx/gradle/JavaFXModule.java +++ b/src/main/java/org/openjfx/gradle/JavaFXModule.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Gluon + * Copyright (c) 2018, 2023, Gluon * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -31,7 +31,6 @@ import org.gradle.api.GradleException; -import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.Optional; @@ -53,7 +52,7 @@ public enum JavaFXModule { static final String PREFIX_MODULE = "javafx."; private static final String PREFIX_ARTIFACT = "javafx-"; - private List dependentModules; + private final List dependentModules; JavaFXModule(JavaFXModule...dependentModules) { this.dependentModules = List.of(dependentModules); @@ -88,7 +87,6 @@ public static Set getJavaFXModules(List moduleNames) { return moduleNames.stream() .map(JavaFXModule::fromModuleName) .flatMap(Optional::stream) - .flatMap(javaFXModule -> javaFXModule.getMavenDependencies().stream()) .collect(Collectors.toSet()); } @@ -105,10 +103,4 @@ public static void validateModules(List moduleNames) { public List getDependentModules() { return dependentModules; } - - public List getMavenDependencies() { - List dependencies = new ArrayList<>(dependentModules); - dependencies.add(0, this); - return dependencies; - } } diff --git a/src/main/java/org/openjfx/gradle/JavaFXOptions.java b/src/main/java/org/openjfx/gradle/JavaFXOptions.java index 9a117f8..ed21a13 100644 --- a/src/main/java/org/openjfx/gradle/JavaFXOptions.java +++ b/src/main/java/org/openjfx/gradle/JavaFXOptions.java @@ -29,35 +29,59 @@ */ package org.openjfx.gradle; -import org.gradle.api.Project; +import com.google.gradle.osdetector.OsDetector; +import org.gradle.api.artifacts.Configuration; +import org.gradle.api.artifacts.ConfigurationContainer; +import org.gradle.api.artifacts.dsl.DependencyHandler; +import org.gradle.api.artifacts.dsl.RepositoryHandler; import org.gradle.api.artifacts.repositories.FlatDirectoryArtifactRepository; +import org.gradle.api.model.ObjectFactory; +import org.gradle.api.tasks.SourceSetContainer; +import org.gradle.nativeplatform.MachineArchitecture; +import org.gradle.nativeplatform.OperatingSystemFamily; +import javax.inject.Inject; import java.io.File; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.stream.Stream; -import static org.openjfx.gradle.JavaFXModule.PREFIX_MODULE; +abstract public class JavaFXOptions { -public class JavaFXOptions { - - private static final String MAVEN_JAVAFX_ARTIFACT_GROUP_ID = "org.openjfx"; + static final String MAVEN_JAVAFX_ARTIFACT_GROUP_ID = "org.openjfx"; private static final String JAVAFX_SDK_LIB_FOLDER = "lib"; - private final Project project; private JavaFXPlatform platform; private String version = "17"; private String sdk; private String[] configurations = new String[] { "implementation" }; - private String[] lastUpdatedConfigurations; private List modules = new ArrayList<>(); private FlatDirectoryArtifactRepository customSDKArtifactRepository; - public JavaFXOptions(Project project) { - this.project = project; - this.platform = JavaFXPlatform.detect(project); + private final SourceSetContainer sourceSets; + private final Set seenConfigurations = new HashSet<>(); + + @Inject + abstract protected ObjectFactory getObjects(); + + @Inject + abstract protected RepositoryHandler getRepositories(); + + @Inject + abstract protected ConfigurationContainer getConfigurationContainer(); + + @Inject + abstract protected DependencyHandler getDependencies(); + + public JavaFXOptions(SourceSetContainer sourceSets, OsDetector osDetector) { + this.sourceSets = sourceSets; + platform = JavaFXPlatform.detect(osDetector); + setClasspathAttributesForAllSourceSets(); } public JavaFXPlatform getPlatform() { @@ -71,7 +95,23 @@ public JavaFXPlatform getPlatform() { */ public void setPlatform(String platform) { this.platform = JavaFXPlatform.fromString(platform); - updateJavaFXDependencies(); + setClasspathAttributesForAllSourceSets(); + } + + private void setClasspathAttributesForAllSourceSets() { + sourceSets.all(sourceSet -> { + setClasspathAttributes(getConfigurationContainer().getByName(sourceSet.getCompileClasspathConfigurationName())); + setClasspathAttributes(getConfigurationContainer().getByName(sourceSet.getRuntimeClasspathConfigurationName())); + }); + } + + private void setClasspathAttributes(Configuration classpath) { + classpath.getAttributes().attribute( + OperatingSystemFamily.OPERATING_SYSTEM_ATTRIBUTE, + getObjects().named(OperatingSystemFamily.class, platform.getOsFamily())); + classpath.getAttributes().attribute( + MachineArchitecture.ARCHITECTURE_ATTRIBUTE, + getObjects().named(MachineArchitecture.class, platform.getArch())); } public String getVersion() { @@ -80,7 +120,6 @@ public String getVersion() { public void setVersion(String version) { this.version = version; - updateJavaFXDependencies(); } /** @@ -90,7 +129,7 @@ public void setVersion(String version) { */ public void setSdk(String sdk) { this.sdk = sdk; - updateJavaFXDependencies(); + updateCustomSDKArtifactRepository(); } public String getSdk() { @@ -113,7 +152,12 @@ public void setConfiguration(String configuration) { */ public void setConfigurations(String[] configurations) { this.configurations = configurations; - updateJavaFXDependencies(); + for (String conf : configurations) { + if (!seenConfigurations.contains(conf)) { + declareFXDependencies(conf); + seenConfigurations.add(conf); + } + } } public String getConfiguration() { @@ -130,40 +174,56 @@ public List getModules() { public void setModules(List modules) { this.modules = modules; - updateJavaFXDependencies(); } public void modules(String...moduleNames) { setModules(List.of(moduleNames)); } - private void updateJavaFXDependencies() { - clearJavaFXDependencies(); + private void declareFXDependencies(String conf) { + // Use 'withDependencies' to declare the dependencies late (i.e., right before dependency resolution starts). + // This allows users to make multiple modifications to the 'configurations' list at arbitrary times during + // build configuration. + getConfigurationContainer().getByName(conf).withDependencies(dependencySet -> { + if (!List.of(configurations).contains(conf)) { + // configuration was removed: do nothing + return; + } - String[] configurations = getConfigurations(); - for (String conf : configurations) { - JavaFXModule.getJavaFXModules(this.modules).stream() - .sorted() - .forEach(javaFXModule -> { - if (customSDKArtifactRepository != null) { - project.getDependencies().add(conf, Map.of("name", javaFXModule.getModuleName())); - } else { - project.getDependencies().add(conf, - String.format("%s:%s:%s:%s", MAVEN_JAVAFX_ARTIFACT_GROUP_ID, javaFXModule.getArtifactName(), - getVersion(), getPlatform().getClassifier())); - } - }); - } - lastUpdatedConfigurations = configurations; + var javaFXModules = JavaFXModule.getJavaFXModules(this.modules); + if (customSDKArtifactRepository == null) { + javaFXModules.stream() + .sorted() + .forEach(javaFXModule -> + dependencySet.add(getDependencies().create( + MAVEN_JAVAFX_ARTIFACT_GROUP_ID + ":" + + javaFXModule.getArtifactName() + ":" + + getVersion()))); + } else { + // Use the list of dependencies of each module to also add direct dependencies for those. + // This is needed, because there is no information about transitive dependencies in the metadata + // of the modules (as there is no such metadata in the local sdk). + var javaFXModulesWithTransitives = Stream.concat( + javaFXModules.stream(), + javaFXModules.stream() + .flatMap(m -> m.getDependentModules().stream())) + .distinct() + .sorted(); + + javaFXModulesWithTransitives.forEach(javaFXModule -> + dependencySet.add(getDependencies().create( + Map.of("name", javaFXModule.getModuleName())))); + } + }); } - private void clearJavaFXDependencies() { + private void updateCustomSDKArtifactRepository() { if (customSDKArtifactRepository != null) { - project.getRepositories().remove(customSDKArtifactRepository); + getRepositories().remove(customSDKArtifactRepository); customSDKArtifactRepository = null; } - if (sdk != null && ! sdk.isEmpty()) { + if (sdk != null && !sdk.isEmpty()) { Map dirs = new HashMap<>(); dirs.put("name", "customSDKArtifactRepository"); if (sdk.endsWith(File.separator)) { @@ -171,23 +231,7 @@ private void clearJavaFXDependencies() { } else { dirs.put("dirs", sdk + File.separator + JAVAFX_SDK_LIB_FOLDER); } - customSDKArtifactRepository = project.getRepositories().flatDir(dirs); - } - - if (lastUpdatedConfigurations == null) { - return; - } - - for (String conf : lastUpdatedConfigurations) { - var configuration = project.getConfigurations().findByName(conf); - if (configuration != null) { - if (customSDKArtifactRepository != null) { - configuration.getDependencies() - .removeIf(dependency -> dependency.getName().startsWith(PREFIX_MODULE)); - } - configuration.getDependencies() - .removeIf(dependency -> MAVEN_JAVAFX_ARTIFACT_GROUP_ID.equals(dependency.getGroup())); - } + customSDKArtifactRepository = getRepositories().flatDir(dirs); } } } diff --git a/src/main/java/org/openjfx/gradle/JavaFXPlatform.java b/src/main/java/org/openjfx/gradle/JavaFXPlatform.java index 2b33ba3..a424a43 100644 --- a/src/main/java/org/openjfx/gradle/JavaFXPlatform.java +++ b/src/main/java/org/openjfx/gradle/JavaFXPlatform.java @@ -31,34 +31,47 @@ import com.google.gradle.osdetector.OsDetector; import org.gradle.api.GradleException; -import org.gradle.api.Project; +import org.gradle.nativeplatform.MachineArchitecture; +import org.gradle.nativeplatform.OperatingSystemFamily; import java.util.Arrays; import java.util.stream.Collectors; public enum JavaFXPlatform { - LINUX("linux", "linux-x86_64"), - LINUX_AARCH64("linux-aarch64", "linux-aarch_64"), - WINDOWS("win", "windows-x86_64"), - OSX("mac", "osx-x86_64"), - OSX_AARCH64("mac-aarch64", "osx-aarch_64"); + LINUX("linux", "linux-x86_64", OperatingSystemFamily.LINUX, MachineArchitecture.X86_64), + LINUX_AARCH64("linux-aarch64", "linux-aarch_64", OperatingSystemFamily.LINUX, MachineArchitecture.ARM64), + WINDOWS("win", "windows-x86_64", OperatingSystemFamily.WINDOWS, MachineArchitecture.X86_64), + OSX("mac", "osx-x86_64", OperatingSystemFamily.MACOS, MachineArchitecture.X86_64), + OSX_AARCH64("mac-aarch64", "osx-aarch_64", OperatingSystemFamily.MACOS, MachineArchitecture.ARM64); private final String classifier; private final String osDetectorClassifier; + private final String osFamily; + private final String arch; - JavaFXPlatform(String classifier, String osDetectorClassifier) { + JavaFXPlatform(String classifier, String osDetectorClassifier, String osFamily, String arch) { this.classifier = classifier; this.osDetectorClassifier = osDetectorClassifier; + this.osFamily = osFamily; + this.arch = arch; } public String getClassifier() { return classifier; } - public static JavaFXPlatform detect(Project project) { + public String getOsFamily() { + return osFamily; + } + + public String getArch() { + return arch; + } + + public static JavaFXPlatform detect(OsDetector osDetector) { - final String osClassifier = project.getExtensions().getByType(OsDetector.class).getClassifier(); + final String osClassifier = osDetector.getClassifier(); for (JavaFXPlatform platform: values()) { if (platform.osDetectorClassifier.equals(osClassifier)) { diff --git a/src/main/java/org/openjfx/gradle/JavaFXPlugin.java b/src/main/java/org/openjfx/gradle/JavaFXPlugin.java index 2b5e59d..47f040c 100644 --- a/src/main/java/org/openjfx/gradle/JavaFXPlugin.java +++ b/src/main/java/org/openjfx/gradle/JavaFXPlugin.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Gluon + * Copyright (c) 2018, 2023, Gluon * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,21 +29,100 @@ */ package org.openjfx.gradle; +import com.google.gradle.osdetector.OsDetector; import com.google.gradle.osdetector.OsDetectorPlugin; +import org.gradle.api.GradleException; +import org.gradle.api.NonNullApi; import org.gradle.api.Plugin; import org.gradle.api.Project; -import org.javamodularity.moduleplugin.ModuleSystemPlugin; -import org.openjfx.gradle.tasks.ExecTask; +import org.gradle.api.file.FileCollection; +import org.gradle.api.plugins.ApplicationPlugin; +import org.gradle.api.plugins.JavaBasePlugin; +import org.gradle.api.tasks.JavaExec; +import org.gradle.api.tasks.SourceSetContainer; +import org.gradle.util.GradleVersion; +import org.openjfx.gradle.metadatarule.JavaFXComponentMetadataRule; +import java.io.File; +import java.util.Arrays; +import java.util.List; + +import static org.openjfx.gradle.JavaFXOptions.MAVEN_JAVAFX_ARTIFACT_GROUP_ID; + +@NonNullApi public class JavaFXPlugin implements Plugin { @Override public void apply(Project project) { + if (GradleVersion.current().compareTo(GradleVersion.version("6.1")) < 0) { + throw new GradleException("This plugin requires Gradle 6.1+"); + } + + // Make sure 'java-base' is applied first, which makes the 'SourceSetContainer' available. + // More concrete Java plugins that build on top of 'java-base' – like 'java-library' or 'application' – + // will be applied by the user. + project.getPlugins().apply(JavaBasePlugin.class); + + // Use 'OsDetectorPlugin' to select the platform the build runs on as default. project.getPlugins().apply(OsDetectorPlugin.class); - project.getPlugins().apply(ModuleSystemPlugin.class); - project.getExtensions().create("javafx", JavaFXOptions.class, project); + JavaFXOptions javaFXOptions = project.getExtensions().create("javafx", JavaFXOptions.class, + project.getExtensions().getByType(SourceSetContainer.class), + project.getExtensions().getByType(OsDetector.class)); + + // Register 'JavaFXComponentMetadataRule' to add variant information to all JavaFX modules. + // Future JavaFX versions could publish this information using Gradle Metadata. + for (JavaFXModule javaFXModule: JavaFXModule.values()) { + project.getDependencies().getComponents().withModule( + MAVEN_JAVAFX_ARTIFACT_GROUP_ID + ":" + javaFXModule.getArtifactName(), + JavaFXComponentMetadataRule.class); + } + + // Only set the default 'configuration' to 'implementation' when the 'java' plugin is applied. + // Otherwise, it won't exist. (Note: 'java' is implicitly applied by 'application' or 'java-library' + // and other Java-base plugins like Kotlin JVM) + project.getPlugins().withId("java", p -> javaFXOptions.setConfiguration("implementation")); + + // Only do addition configuration of the ':run' task when the 'application' plugin is applied. + // Otherwise, that task does not exist. + project.getPlugins().withId("application", p -> { + project.getTasks().named(ApplicationPlugin.TASK_RUN_NAME, JavaExec.class, execTask -> { + if (GradleVersion.current().compareTo(GradleVersion.version("6.4")) >= 0 && execTask.getMainModule().isPresent()) { + return; // a module, as determined by Gradle core + } + + execTask.doFirst(a -> { + if (execTask.getExtensions().findByName("moduleOptions") != null) { + return; // a module, as determined by modularity plugin + } + + putJavaFXJarsOnModulePathForClasspathApplication(execTask, javaFXOptions); + }); + }); + }); + } + + /** + * Gradle does currently not put anything on the --module-path if the application itself is executed from + * the classpath. Hence, this patches the setup of Gradle's standard ':run' task to move all JavaFX Jars + * from '-classpath' to '-module-path'. This functionality is only relevant for NON-MODULAR apps. + */ + private static void putJavaFXJarsOnModulePathForClasspathApplication(JavaExec execTask, JavaFXOptions javaFXOptions) { + FileCollection classpath = execTask.getClasspath(); + + execTask.setClasspath(classpath.filter(jar -> !isJavaFXJar(jar, javaFXOptions.getPlatform()))); + var modulePath = classpath.filter(jar -> isJavaFXJar(jar, javaFXOptions.getPlatform())); + + execTask.getJvmArgumentProviders().add(() -> List.of( + "--module-path", modulePath.getAsPath(), + "--add-modules", String.join(",", javaFXOptions.getModules()) + )); + } - project.getTasks().create("configJavafxRun", ExecTask.class, project); + private static boolean isJavaFXJar(File jar, JavaFXPlatform platform) { + return jar.isFile() && + Arrays.stream(JavaFXModule.values()).anyMatch(javaFXModule -> + javaFXModule.compareJarFileName(platform, jar.getName()) || + javaFXModule.getModuleJarFileName().equals(jar.getName())); } } diff --git a/src/main/java/org/openjfx/gradle/metadatarule/JavaFXComponentMetadataRule.java b/src/main/java/org/openjfx/gradle/metadatarule/JavaFXComponentMetadataRule.java new file mode 100644 index 0000000..f69dc99 --- /dev/null +++ b/src/main/java/org/openjfx/gradle/metadatarule/JavaFXComponentMetadataRule.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2023, Gluon + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.openjfx.gradle.metadatarule; + +import org.gradle.api.artifacts.CacheableRule; +import org.gradle.api.artifacts.ComponentMetadataContext; +import org.gradle.api.artifacts.ComponentMetadataDetails; +import org.gradle.api.artifacts.ComponentMetadataRule; +import org.gradle.api.model.ObjectFactory; +import org.gradle.nativeplatform.MachineArchitecture; +import org.gradle.nativeplatform.OperatingSystemFamily; +import org.openjfx.gradle.JavaFXPlatform; + +import javax.inject.Inject; + +import static org.gradle.nativeplatform.MachineArchitecture.ARCHITECTURE_ATTRIBUTE; +import static org.gradle.nativeplatform.OperatingSystemFamily.OPERATING_SYSTEM_ATTRIBUTE; + +/** + * + * Component Metadata RulesAdding variants for native jars + * + */ +@CacheableRule +abstract public class JavaFXComponentMetadataRule implements ComponentMetadataRule { + + @Inject + abstract protected ObjectFactory getObjects(); + + @Override + public void execute(ComponentMetadataContext context) { + var details = context.getDetails(); + + for (JavaFXPlatform javaFXPlatform : JavaFXPlatform.values()) { + addJavaFXPlatformVariant(javaFXPlatform, details, "Compile", "compile"); + addJavaFXPlatformVariant(javaFXPlatform, details, "Runtime", "runtime"); + } + } + + private void addJavaFXPlatformVariant(JavaFXPlatform javaFXPlatform, ComponentMetadataDetails details, String nameSuffix, String baseVariant) { + var name = details.getId().getName(); + var version = details.getId().getVersion(); + + // Use 'maybeAddVariant'. As long as the metadata is sourced from POM, 'compile' and 'runtime' exist. + // These are used as base for the additional variants so that those variants have the same dependencies. + // If future JavaFX versions should publish the variants directly with Gradle metadata, the rule will + // have no effect on these future versions, as the variants will be named different. + details.maybeAddVariant(javaFXPlatform.getClassifier() + nameSuffix, baseVariant, variant -> { + variant.attributes(attributes -> { + attributes.attribute(OPERATING_SYSTEM_ATTRIBUTE, getObjects().named(OperatingSystemFamily.class, javaFXPlatform.getOsFamily())); + attributes.attribute(ARCHITECTURE_ATTRIBUTE, getObjects().named(MachineArchitecture.class, javaFXPlatform.getArch())); + }); + variant.withFiles(files -> { + files.removeAllFiles(); + files.addFile(name + "-" + version + "-" + javaFXPlatform.getClassifier() + ".jar"); + }); + }); + } +} diff --git a/src/main/java/org/openjfx/gradle/tasks/ExecTask.java b/src/main/java/org/openjfx/gradle/tasks/ExecTask.java deleted file mode 100644 index 6b31f84..0000000 --- a/src/main/java/org/openjfx/gradle/tasks/ExecTask.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (c) 2019, 2021, Gluon - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * * Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package org.openjfx.gradle.tasks; - -import org.gradle.api.DefaultTask; -import org.gradle.api.GradleException; -import org.gradle.api.Project; -import org.gradle.api.file.FileCollection; -import org.gradle.api.logging.Logger; -import org.gradle.api.logging.Logging; -import org.gradle.api.plugins.ApplicationPlugin; -import org.gradle.api.tasks.JavaExec; -import org.gradle.api.tasks.TaskAction; -import org.javamodularity.moduleplugin.extensions.RunModuleOptions; -import org.openjfx.gradle.JavaFXModule; -import org.openjfx.gradle.JavaFXOptions; -import org.openjfx.gradle.JavaFXPlatform; - -import javax.inject.Inject; -import java.io.File; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.TreeSet; - -public class ExecTask extends DefaultTask { - - private static final Logger LOGGER = Logging.getLogger(ExecTask.class); - - private final Project project; - private JavaExec execTask; - - @Inject - public ExecTask(Project project) { - this.project = project; - project.getPluginManager().withPlugin(ApplicationPlugin.APPLICATION_PLUGIN_NAME, e -> { - execTask = (JavaExec) project.getTasks().findByName(ApplicationPlugin.TASK_RUN_NAME); - if (execTask != null) { - execTask.dependsOn(this); - } else { - throw new GradleException("Run task not found."); - } - }); - } - - @TaskAction - public void action() { - if (execTask != null) { - JavaFXOptions javaFXOptions = project.getExtensions().getByType(JavaFXOptions.class); - JavaFXModule.validateModules(javaFXOptions.getModules()); - - var definedJavaFXModuleNames = new TreeSet<>(javaFXOptions.getModules()); - if (!definedJavaFXModuleNames.isEmpty()) { - RunModuleOptions moduleOptions = execTask.getExtensions().findByType(RunModuleOptions.class); - - final FileCollection classpathWithoutJavaFXJars = execTask.getClasspath().filter( - jar -> Arrays.stream(JavaFXModule.values()).noneMatch(javaFXModule -> jar.getName().contains(javaFXModule.getArtifactName())) - ); - final FileCollection javaFXPlatformJars = execTask.getClasspath().filter(jar -> isJavaFXJar(jar, javaFXOptions.getPlatform())); - - if (moduleOptions != null) { - LOGGER.info("Modular JavaFX application found"); - // Remove empty JavaFX jars from classpath - execTask.setClasspath(classpathWithoutJavaFXJars.plus(javaFXPlatformJars)); - definedJavaFXModuleNames.forEach(javaFXModule -> moduleOptions.getAddModules().add(javaFXModule)); - } else { - LOGGER.info("Non-modular JavaFX application found"); - // Remove all JavaFX jars from classpath - execTask.setClasspath(classpathWithoutJavaFXJars); - - var javaFXModuleJvmArgs = List.of("--module-path", javaFXPlatformJars.getAsPath()); - - var jvmArgs = new ArrayList(); - jvmArgs.add("--add-modules"); - jvmArgs.add(String.join(",", definedJavaFXModuleNames)); - - List execJvmArgs = execTask.getJvmArgs(); - if (execJvmArgs != null) { - jvmArgs.addAll(execJvmArgs); - } - jvmArgs.addAll(javaFXModuleJvmArgs); - - execTask.setJvmArgs(jvmArgs); - } - } - } else { - throw new GradleException("Run task not found. Please, make sure the Application plugin is applied"); - } - } - - private static boolean isJavaFXJar(File jar, JavaFXPlatform platform) { - return jar.isFile() && - Arrays.stream(JavaFXModule.values()).anyMatch(javaFXModule -> - javaFXModule.compareJarFileName(platform, jar.getName()) || - javaFXModule.getModuleJarFileName().equals(jar.getName())); - } -} diff --git a/src/main/resources/META-INF/gradle-plugins/org.openjfx.javafxplugin.properties b/src/main/resources/META-INF/gradle-plugins/org.openjfx.javafxplugin.properties deleted file mode 100644 index cc83c85..0000000 --- a/src/main/resources/META-INF/gradle-plugins/org.openjfx.javafxplugin.properties +++ /dev/null @@ -1,31 +0,0 @@ -# -# Copyright (c) 2018, Gluon -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, this -# list of conditions and the following disclaimer. -# -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# -# * Neither the name of the copyright holder nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# - -implementation-class=org.openjfx.gradle.JavaFXPlugin diff --git a/src/test/java/org/openjfx/gradle/JavaFXModuleTest.java b/src/test/java/org/openjfx/gradle/JavaFXModuleTest.java index fb5f1a3..4bc58bc 100644 --- a/src/test/java/org/openjfx/gradle/JavaFXModuleTest.java +++ b/src/test/java/org/openjfx/gradle/JavaFXModuleTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Gluon + * Copyright (c) 2018, 2023, Gluon * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -63,17 +63,6 @@ void getArtifactName() { assertEquals("javafx-base", JavaFXModule.BASE.getArtifactName()); } - @Test - void getDependencies() { - JavaFXModule module = JavaFXModule.CONTROLS; - - List dependencies = module.getMavenDependencies(); - assertTrue(dependencies.contains(module)); - for (JavaFXModule dependentModule : JavaFXModule.CONTROLS.getDependentModules()) { - assertTrue(dependencies.contains(dependentModule)); - } - } - @Test void validateWithValidModules() { var moduleNames = List.of(JavaFXModule.CONTROLS.getModuleName(), JavaFXModule.WEB.getModuleName()); diff --git a/src/test/java/org/openjfx/gradle/JavaFXPluginSmokeTest.java b/src/test/java/org/openjfx/gradle/JavaFXPluginSmokeTest.java index 277540c..a94d96f 100644 --- a/src/test/java/org/openjfx/gradle/JavaFXPluginSmokeTest.java +++ b/src/test/java/org/openjfx/gradle/JavaFXPluginSmokeTest.java @@ -29,49 +29,127 @@ */ package org.openjfx.gradle; +import org.gradle.testfixtures.ProjectBuilder; +import org.gradle.testkit.runner.BuildResult; import org.gradle.testkit.runner.GradleRunner; import org.gradle.testkit.runner.TaskOutcome; import org.junit.jupiter.api.Test; import java.io.File; +import java.lang.management.ManagementFactory; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; import static org.junit.jupiter.api.Assertions.assertEquals; -class JavaFXPluginSmokeTest { +abstract class JavaFXPluginSmokeTest { + + private static final String classifier; + + static { + var p = ProjectBuilder.builder().build(); + p.getPlugins().apply(JavaFXPlugin.class); + classifier = p.getExtensions().getByType(JavaFXOptions.class).getPlatform().getClassifier(); + } + + protected abstract String getGradleVersion(); + + protected String modularApplicationRuntime() { + return "modular-with-modularity-plugin.jar"; + } @Test void smokeTestModular() { - var result = GradleRunner.create() - .withProjectDir(new File("test-project")) - .withGradleVersion("6.0.1") - .withArguments("clean", "build", "run", "--stacktrace", "--refresh-dependencies") - .forwardOutput() - .build(); + var result = build(":modular:run"); + + assertEquals(TaskOutcome.SUCCESS, result.task(":modular:run").getOutcome()); + + assertEquals(List.of("javafx-base-17-" + classifier + ".jar", "javafx-controls-17-" + classifier + ".jar", "javafx-graphics-17-" + classifier + ".jar"), modulePath(result).get(0)); + assertEquals(List.of("javafx-base-17-" + classifier + ".jar", "javafx-controls-17-" + classifier + ".jar", "javafx-graphics-17-" + classifier + ".jar", "modular.jar"), modulePath(result).get(1)); - assertEquals(TaskOutcome.SUCCESS, result.task(":modular:run").getOutcome(), "Failed build!"); + assertEquals(List.of(), compileClassPath(result)); + assertEquals(List.of(), runtimeClassPath(result)); + } + + @Test + void smokeTestModularWithModularityPlugin() { + var result = build(":modular-with-modularity-plugin:run"); + + assertEquals(TaskOutcome.SUCCESS, result.task(":modular-with-modularity-plugin:run").getOutcome()); + + assertEquals(List.of("javafx-base-17-" + classifier + ".jar", "javafx-controls-17-" + classifier + ".jar", "javafx-graphics-17-" + classifier + ".jar"), modulePath(result).get(0)); + assertEquals(List.of("javafx-base-17-" + classifier + ".jar", "javafx-controls-17-" + classifier + ".jar", "javafx-graphics-17-" + classifier + ".jar", modularApplicationRuntime()), modulePath(result).get(1)); + + assertEquals(List.of(), compileClassPath(result)); + assertEquals(List.of(), runtimeClassPath(result)); } @Test void smokeTestNonModular() { - var result = GradleRunner.create() - .withProjectDir(new File("test-project")) - .withGradleVersion("6.0.1") - .withArguments("clean", "build", "run", "--stacktrace", "--refresh-dependencies") - .forwardOutput() - .build(); + var result = build(":non-modular:run"); + + assertEquals(TaskOutcome.SUCCESS, result.task(":non-modular:run").getOutcome()); - assertEquals(TaskOutcome.SUCCESS, result.task(":non-modular:run").getOutcome(), "Failed build!"); + assertEquals(List.of("javafx-base-17-" + classifier + ".jar", "javafx-controls-17-" + classifier + ".jar", "javafx-graphics-17-" + classifier + ".jar", "javafx-media-17-" + classifier + ".jar", "javafx-web-17-" + classifier + ".jar"), compileClassPath(result).get(0)); + assertEquals(List.of("main", "main"), runtimeClassPath(result).get(0)); + assertEquals(List.of("javafx-base-17-" + classifier + ".jar", "javafx-controls-17-" + classifier + ".jar", "javafx-graphics-17-" + classifier + ".jar", "javafx-media-17-" + classifier + ".jar", "javafx-web-17-" + classifier + ".jar"), modulePath(result).get(0)); } @Test void smokeTestTransitive() { - var result = GradleRunner.create() + var result = build(":transitive:run"); + + assertEquals(TaskOutcome.SUCCESS, result.task(":transitive:run").getOutcome()); + + assertEquals(List.of("charts-17.1.41.jar", "javafx-base-17-" + classifier + ".jar", "javafx-controls-17-" + classifier + ".jar", "javafx-graphics-17-" + classifier + ".jar"), compileClassPath(result).get(0)); + assertEquals(List.of("charts-17.1.41.jar", "countries-17.0.29.jar", "heatmap-17.0.17.jar", "logback-classic-1.2.6.jar", "logback-core-1.2.6.jar", "main", "main", "slf4j-api-1.7.32.jar", "toolbox-17.0.45.jar", "toolboxfx-17.0.37.jar"), runtimeClassPath(result).get(0)); + assertEquals(List.of("javafx-base-17.0.6-" + classifier + ".jar", "javafx-controls-17.0.6-" + classifier + ".jar", "javafx-graphics-17.0.6-" + classifier + ".jar", "javafx-swing-17.0.6-" + classifier + ".jar"), modulePath(result).get(0)); + } + + @Test + void smokeTestLocalSdk() { + var result = build(":local-sdk:build"); // do not ':run', as it won't run on any platform + + assertEquals(TaskOutcome.SUCCESS, result.task(":local-sdk:build").getOutcome()); + + assertEquals(List.of("javafx.base.jar", "javafx.controls.jar", "javafx.graphics.jar"), compileClassPath(result).get(0)); + assertEquals(List.of(), modulePath(result)); + } + + private static List> modulePath(BuildResult result) { + return path(result, "--module-path "); + } + + private static List> compileClassPath(BuildResult result) { + return path(result, "-classpath "); + } + + private static List> runtimeClassPath(BuildResult result) { + return path(result, "-cp "); + } + + private static List> path(BuildResult result, String pathArg) { + // Parse classpath or module path from Gradle's '--debug' output. + // The :compileJava and :run tasks log them on that logging level. + return result.getOutput().lines().filter(l -> l.contains(pathArg)).map(l -> { + int pathArgIndex = l.indexOf(pathArg) + pathArg.length(); + String pathString = l.substring(pathArgIndex, l.indexOf(" ", pathArgIndex)); + if (pathString.isBlank()) { + return List.of(); + } + String[] path = pathString.split(System.getProperty("path.separator")); + return Arrays.stream(path).map(jar -> new File(jar).getName()).sorted().collect(Collectors.toList()); + }).filter(p -> !p.isEmpty()).collect(Collectors.toList()); + } + + private BuildResult build(String task) { + return GradleRunner.create() .withProjectDir(new File("test-project")) - .withGradleVersion("6.0.1") - .withArguments("clean", "build", "run", "--stacktrace", "--refresh-dependencies") - .forwardOutput() + .withGradleVersion(getGradleVersion()) + .withPluginClasspath() + .withDebug(ManagementFactory.getRuntimeMXBean().getInputArguments().toString().contains("-agentlib:jdwp")) + .withArguments("clean", task, "--stacktrace", "--debug") .build(); - - assertEquals(TaskOutcome.SUCCESS, result.task(":transitive:run").getOutcome(), "Failed build!"); } } diff --git a/src/test/java/org/openjfx/gradle/JavaFXPluginSmokeTestGradle61.java b/src/test/java/org/openjfx/gradle/JavaFXPluginSmokeTestGradle61.java new file mode 100644 index 0000000..c8e4cb5 --- /dev/null +++ b/src/test/java/org/openjfx/gradle/JavaFXPluginSmokeTestGradle61.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2023, Gluon + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.openjfx.gradle; + +import org.junit.jupiter.api.Disabled; + +class JavaFXPluginSmokeTestGradle61 extends JavaFXPluginSmokeTest { + + @Override + protected String getGradleVersion() { + return "6.1"; + } + + @Override + protected String modularApplicationRuntime() { + return "main"; + } + + @Disabled + void smokeTestModular() { + // Support for building Java Modules was only added in Gradle 6.4 + } +} diff --git a/src/test/java/org/openjfx/gradle/JavaFXPluginSmokeTestGradle69.java b/src/test/java/org/openjfx/gradle/JavaFXPluginSmokeTestGradle69.java new file mode 100644 index 0000000..cc85100 --- /dev/null +++ b/src/test/java/org/openjfx/gradle/JavaFXPluginSmokeTestGradle69.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2023, Gluon + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.openjfx.gradle; + +class JavaFXPluginSmokeTestGradle69 extends JavaFXPluginSmokeTest { + + @Override + protected String getGradleVersion() { + return "6.9.4"; + } +} diff --git a/src/test/java/org/openjfx/gradle/JavaFXPluginSmokeTestGradle76.java b/src/test/java/org/openjfx/gradle/JavaFXPluginSmokeTestGradle76.java new file mode 100644 index 0000000..11d893b --- /dev/null +++ b/src/test/java/org/openjfx/gradle/JavaFXPluginSmokeTestGradle76.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2023, Gluon + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.openjfx.gradle; + +class JavaFXPluginSmokeTestGradle76 extends JavaFXPluginSmokeTest { + + @Override + protected String getGradleVersion() { + return "7.6.1"; + } +} diff --git a/src/test/java/org/openjfx/gradle/JavaFXPluginSmokeTestGradle83.java b/src/test/java/org/openjfx/gradle/JavaFXPluginSmokeTestGradle83.java new file mode 100644 index 0000000..5a47043 --- /dev/null +++ b/src/test/java/org/openjfx/gradle/JavaFXPluginSmokeTestGradle83.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2023, Gluon + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.openjfx.gradle; + +class JavaFXPluginSmokeTestGradle83 extends JavaFXPluginSmokeTest { + + @Override + protected String getGradleVersion() { + return "8.3"; + } +} diff --git a/test-project/build.gradle b/test-project/build.gradle index 459ec63..e7bfd1b 100644 --- a/test-project/build.gradle +++ b/test-project/build.gradle @@ -1,25 +1,12 @@ -buildscript { - repositories { - maven { - url "https://plugins.gradle.org/m2/" - } - maven { - url 'https://oss.sonatype.org/content/repositories/snapshots/' - } - } - dependencies { - classpath "org.openjfx:javafx-plugin:0.0.+" - } -} +import org.gradle.util.GradleVersion -subprojects { - apply plugin: 'application' - apply plugin: 'org.openjfx.javafxplugin' +ext.gradleModuleSupport = GradleVersion.current() >= GradleVersion.version("6.4") - sourceCompatibility = 11 - targetCompatibility = 11 +subprojects { + apply plugin: 'java' - repositories { - mavenCentral() + java { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 } } \ No newline at end of file diff --git a/test-project/local-sdk/build.gradle b/test-project/local-sdk/build.gradle new file mode 100644 index 0000000..c8ef160 --- /dev/null +++ b/test-project/local-sdk/build.gradle @@ -0,0 +1,17 @@ +plugins { + id 'application' + id 'org.openjfx.javafxplugin' +} + +application { + if (gradleModuleSupport) { + mainClass = 'org.openjfx.gradle.javafx.test.Main' + } else { + mainClassName = 'org.openjfx.gradle.javafx.test.Main' + } +} + +javafx { + modules = ['javafx.controls'] + sdk = "javafx-sdk-17.0.8" +} diff --git a/test-project/local-sdk/javafx-sdk-17.0.8/lib/javafx.base.jar b/test-project/local-sdk/javafx-sdk-17.0.8/lib/javafx.base.jar new file mode 100644 index 0000000..f700e0c Binary files /dev/null and b/test-project/local-sdk/javafx-sdk-17.0.8/lib/javafx.base.jar differ diff --git a/test-project/local-sdk/javafx-sdk-17.0.8/lib/javafx.controls.jar b/test-project/local-sdk/javafx-sdk-17.0.8/lib/javafx.controls.jar new file mode 100644 index 0000000..84b35dc Binary files /dev/null and b/test-project/local-sdk/javafx-sdk-17.0.8/lib/javafx.controls.jar differ diff --git a/test-project/local-sdk/javafx-sdk-17.0.8/lib/javafx.graphics.jar b/test-project/local-sdk/javafx-sdk-17.0.8/lib/javafx.graphics.jar new file mode 100644 index 0000000..88192b6 Binary files /dev/null and b/test-project/local-sdk/javafx-sdk-17.0.8/lib/javafx.graphics.jar differ diff --git a/test-project/local-sdk/src/main/java/org/openjfx/gradle/javafx/test/Main.java b/test-project/local-sdk/src/main/java/org/openjfx/gradle/javafx/test/Main.java new file mode 100644 index 0000000..11d1e75 --- /dev/null +++ b/test-project/local-sdk/src/main/java/org/openjfx/gradle/javafx/test/Main.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2023, Gluon + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.openjfx.gradle.javafx.test; + +import javafx.application.Application; +import javafx.scene.Scene; +import javafx.scene.control.Label; +import javafx.scene.layout.StackPane; +import javafx.stage.Stage; + +public class Main extends Application { + + @Override + public void start(Stage primaryStage) { + StackPane root = new StackPane(new Label("Hello World!")); + + Scene scene = new Scene(root, 800, 600); + + primaryStage.setScene(scene); + primaryStage.show(); + + new Thread(() -> { + try { + Thread.sleep(500); + } catch (InterruptedException e) { + throw new RuntimeException("Should not happen!"); + } + + System.exit(0); + }).start(); + } +} \ No newline at end of file diff --git a/test-project/modular-with-modularity-plugin/build.gradle b/test-project/modular-with-modularity-plugin/build.gradle new file mode 100644 index 0000000..9b43841 --- /dev/null +++ b/test-project/modular-with-modularity-plugin/build.gradle @@ -0,0 +1,22 @@ +plugins { + id 'application' + id 'org.openjfx.javafxplugin' + id 'org.javamodularity.moduleplugin' version '1.8.12' +} + +repositories.mavenCentral() + +if (gradleModuleSupport) java.modularity.inferModulePath = false + +application { + if (gradleModuleSupport) { + mainModule = 'org.openjfx.gradle.javafx.test' + mainClass = 'org.openjfx.gradle.javafx.test.Main' + } else { + mainClassName = 'org.openjfx.gradle.javafx.test.Main' + } +} + +javafx { + modules = ['javafx.controls'] +} diff --git a/test-project/modular-with-modularity-plugin/src/main/java/module-info.java b/test-project/modular-with-modularity-plugin/src/main/java/module-info.java new file mode 100644 index 0000000..e827f3a --- /dev/null +++ b/test-project/modular-with-modularity-plugin/src/main/java/module-info.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2023, Gluon + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +module org.openjfx.gradle.javafx.test { + requires javafx.controls; + + exports org.openjfx.gradle.javafx.test; +} \ No newline at end of file diff --git a/test-project/modular-with-modularity-plugin/src/main/java/org/openjfx/gradle/javafx/test/Main.java b/test-project/modular-with-modularity-plugin/src/main/java/org/openjfx/gradle/javafx/test/Main.java new file mode 100644 index 0000000..11d1e75 --- /dev/null +++ b/test-project/modular-with-modularity-plugin/src/main/java/org/openjfx/gradle/javafx/test/Main.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2023, Gluon + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.openjfx.gradle.javafx.test; + +import javafx.application.Application; +import javafx.scene.Scene; +import javafx.scene.control.Label; +import javafx.scene.layout.StackPane; +import javafx.stage.Stage; + +public class Main extends Application { + + @Override + public void start(Stage primaryStage) { + StackPane root = new StackPane(new Label("Hello World!")); + + Scene scene = new Scene(root, 800, 600); + + primaryStage.setScene(scene); + primaryStage.show(); + + new Thread(() -> { + try { + Thread.sleep(500); + } catch (InterruptedException e) { + throw new RuntimeException("Should not happen!"); + } + + System.exit(0); + }).start(); + } +} \ No newline at end of file diff --git a/test-project/modular/build.gradle b/test-project/modular/build.gradle index 3dfee46..7dc4101 100644 --- a/test-project/modular/build.gradle +++ b/test-project/modular/build.gradle @@ -1,4 +1,20 @@ -mainClassName = 'org.openjfx.gradle.javafx.test/org.openjfx.gradle.javafx.test.Main' +plugins { + id 'application' + id 'org.openjfx.javafxplugin' +} + +repositories.mavenCentral() + +if (gradleModuleSupport) java.modularity.inferModulePath = true + +application { + if (gradleModuleSupport) { + mainModule = 'org.openjfx.gradle.javafx.test' + mainClass = 'org.openjfx.gradle.javafx.test.Main' + } else { + mainClassName = 'org.openjfx.gradle.javafx.test.Main' + } +} javafx { modules = ['javafx.controls'] diff --git a/test-project/modular/src/main/java/module-info.java b/test-project/modular/src/main/java/module-info.java index 7c06d5b..e827f3a 100644 --- a/test-project/modular/src/main/java/module-info.java +++ b/test-project/modular/src/main/java/module-info.java @@ -1,3 +1,32 @@ +/* + * Copyright (c) 2023, Gluon + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ module org.openjfx.gradle.javafx.test { requires javafx.controls; diff --git a/test-project/modular/src/main/java/org/openjfx/gradle/javafx/test/Main.java b/test-project/modular/src/main/java/org/openjfx/gradle/javafx/test/Main.java index cdeb22e..11d1e75 100644 --- a/test-project/modular/src/main/java/org/openjfx/gradle/javafx/test/Main.java +++ b/test-project/modular/src/main/java/org/openjfx/gradle/javafx/test/Main.java @@ -1,3 +1,32 @@ +/* + * Copyright (c) 2023, Gluon + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package org.openjfx.gradle.javafx.test; import javafx.application.Application; diff --git a/test-project/non-modular/build.gradle b/test-project/non-modular/build.gradle index cef1ed9..009941b 100644 --- a/test-project/non-modular/build.gradle +++ b/test-project/non-modular/build.gradle @@ -1,4 +1,18 @@ -mainClassName = 'org.openjfx.gradle.javafx.test.Main' +plugins { + id 'application' + id 'org.openjfx.javafxplugin' version '0.0.14' + id 'org.javamodularity.moduleplugin' version '1.8.12' +} + +repositories.mavenCentral() + +application { + if (gradleModuleSupport) { + mainClass = 'org.openjfx.gradle.javafx.test.Main' + } else { + mainClassName = 'org.openjfx.gradle.javafx.test.Main' + } +} javafx { modules = [ 'javafx.controls', 'javafx.web' ] diff --git a/test-project/non-modular/src/main/java/org/openjfx/gradle/javafx/test/Main.java b/test-project/non-modular/src/main/java/org/openjfx/gradle/javafx/test/Main.java index cdeb22e..11d1e75 100644 --- a/test-project/non-modular/src/main/java/org/openjfx/gradle/javafx/test/Main.java +++ b/test-project/non-modular/src/main/java/org/openjfx/gradle/javafx/test/Main.java @@ -1,3 +1,32 @@ +/* + * Copyright (c) 2023, Gluon + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package org.openjfx.gradle.javafx.test; import javafx.application.Application; diff --git a/test-project/settings.gradle b/test-project/settings.gradle index 96a142a..faf5558 100644 --- a/test-project/settings.gradle +++ b/test-project/settings.gradle @@ -1,5 +1,7 @@ rootProject.name = 'javafxplugintests' +include 'local-sdk' include 'modular' +include 'modular-with-modularity-plugin' include 'non-modular' include 'transitive' \ No newline at end of file diff --git a/test-project/transitive/build.gradle b/test-project/transitive/build.gradle index 4991c60..23caa69 100644 --- a/test-project/transitive/build.gradle +++ b/test-project/transitive/build.gradle @@ -1,4 +1,24 @@ -mainClassName = 'org.openjfx.gradle.javafx.test.Main' +plugins { + id 'application' + id 'org.openjfx.javafxplugin' +} + +repositories.mavenCentral { + metadataSources { + // Gradle Metadata is broken for 'eu.hansolo.fx:charts:17.1.41'. It's fixed in '17.1.51', + // but that version depends on JavaFX 20, and we want to stick with 17 for now in the test. + mavenPom() + ignoreGradleMetadataRedirection() + } +} + +application { + if (gradleModuleSupport) { + mainClass = 'org.openjfx.gradle.javafx.test.Main' + } else { + mainClassName = 'org.openjfx.gradle.javafx.test.Main' + } +} javafx { version = '17' @@ -6,6 +26,6 @@ javafx { } dependencies { - // has dependency on javafx-controls-11.0.2 - compile 'org.controlsfx:controlsfx:11.0.1' + // has runtime dependency on javafx-base-17.0.6, javafx-controls-17.0.6, javafx-graphics-17.0.6, javafx-swing-17.0.6 + implementation 'eu.hansolo.fx:charts:17.1.41' } diff --git a/test-project/transitive/src/main/java/org/openjfx/gradle/javafx/test/Main.java b/test-project/transitive/src/main/java/org/openjfx/gradle/javafx/test/Main.java index cdeb22e..11d1e75 100644 --- a/test-project/transitive/src/main/java/org/openjfx/gradle/javafx/test/Main.java +++ b/test-project/transitive/src/main/java/org/openjfx/gradle/javafx/test/Main.java @@ -1,3 +1,32 @@ +/* + * Copyright (c) 2023, Gluon + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package org.openjfx.gradle.javafx.test; import javafx.application.Application;