| @@ -1,57 +1,57 | |||||
| 1 | plugins { |
|
1 | plugins { | |
| 2 | id "java-library" |
|
2 | id "java-library" | |
| 3 | id "ivy-publish" |
|
3 | id "ivy-publish" | |
| 4 | } |
|
4 | } | |
| 5 |
|
5 | |||
| 6 | description = "Shared Gradle build utilities used by Implab plugins" |
|
6 | description = "Shared Gradle build utilities used by Implab plugins" | |
| 7 |
|
7 | |||
| 8 | java { |
|
8 | java { | |
| 9 | withJavadocJar() |
|
9 | withJavadocJar() | |
| 10 | withSourcesJar() |
|
10 | withSourcesJar() | |
| 11 | toolchain { |
|
11 | toolchain { | |
| 12 | languageVersion = JavaLanguageVersion.of(21) |
|
12 | languageVersion = JavaLanguageVersion.of(21) | |
| 13 | } |
|
13 | } | |
| 14 | } |
|
14 | } | |
| 15 |
|
15 | |||
| 16 | dependencies { |
|
16 | dependencies { | |
| 17 | compileOnly libs.jdt.annotations |
|
17 | compileOnly libs.jdt.annotations | |
| 18 |
|
18 | |||
| 19 | api gradleApi(), |
|
19 | api gradleApi(), | |
| 20 | libs.bundles.jackson |
|
20 | libs.bundles.jackson | |
| 21 |
|
21 | |||
| 22 | testImplementation gradleTestKit() |
|
22 | testImplementation gradleTestKit() | |
| 23 | testImplementation "org.junit.jupiter:junit-jupiter-api:5.11.4" |
|
23 | testImplementation "org.junit.jupiter:junit-jupiter-api:5.11.4" | |
| 24 | testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:5.11.4" |
|
24 | testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:5.11.4" | |
| 25 | testRuntimeOnly "org.junit.platform:junit-platform-launcher:1.11.4" |
|
25 | testRuntimeOnly "org.junit.platform:junit-platform-launcher:1.11.4" | |
| 26 | } |
|
26 | } | |
| 27 |
|
27 | |||
| 28 | task printVersion{ |
|
28 | task printVersion{ | |
| 29 | doLast { |
|
29 | doLast { | |
| 30 | println "project: $project.group:$project.name:$project.version" |
|
30 | println "project: $project.group:$project.name:$project.version" | |
| 31 | println "jar: ${->jar.archiveFileName.get()}" |
|
31 | println "jar: ${->jar.archiveFileName.get()}" | |
| 32 | } |
|
32 | } | |
| 33 | } |
|
33 | } | |
| 34 |
|
34 | |||
| 35 | test { |
|
35 | test { | |
| 36 | useJUnitPlatform() |
|
36 | useJUnitPlatform() | |
| 37 | } |
|
37 | } | |
| 38 |
|
38 | |||
| 39 | publishing { |
|
39 | publishing { | |
| 40 | repositories { |
|
40 | repositories { | |
| 41 | ivy { |
|
41 | ivy { | |
| 42 | url "${System.properties["user.home"]}/ivy-repo" |
|
42 | url = "${System.properties["user.home"]}/ivy-repo" | |
| 43 | } |
|
43 | } | |
| 44 | } |
|
44 | } | |
| 45 | publications { |
|
45 | publications { | |
| 46 | ivy(IvyPublication) { |
|
46 | ivy(IvyPublication) { | |
| 47 | from components.java |
|
47 | from components.java | |
| 48 | descriptor.description { |
|
48 | descriptor.description { | |
| 49 | text = providers.provider({ description }) |
|
49 | text = providers.provider({ description }) | |
| 50 | } |
|
50 | } | |
| 51 | descriptor.license { |
|
51 | descriptor.license { | |
| 52 | name = "BSD-2-Clause" |
|
52 | name = "BSD-2-Clause" | |
| 53 | url = "https://spdx.org/licenses/BSD-2-Clause.html" |
|
53 | url = "https://spdx.org/licenses/BSD-2-Clause.html" | |
| 54 | } |
|
54 | } | |
| 55 | } |
|
55 | } | |
| 56 | } |
|
56 | } | |
| 57 | } |
|
57 | } | |
| 1 | NO CONTENT: modified file, binary diff hidden |
|
NO CONTENT: modified file, binary diff hidden |
| @@ -1,7 +1,7 | |||||
| 1 | distributionBase=GRADLE_USER_HOME |
|
1 | distributionBase=GRADLE_USER_HOME | |
| 2 | distributionPath=wrapper/dists |
|
2 | distributionPath=wrapper/dists | |
| 3 |
distributionUrl=https\://services.gradle.org/distributions/gradle- |
|
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-bin.zip | |
| 4 | networkTimeout=10000 |
|
4 | networkTimeout=10000 | |
| 5 | validateDistributionUrl=true |
|
5 | validateDistributionUrl=true | |
| 6 | zipStoreBase=GRADLE_USER_HOME |
|
6 | zipStoreBase=GRADLE_USER_HOME | |
| 7 | zipStorePath=wrapper/dists |
|
7 | zipStorePath=wrapper/dists | |
| @@ -1,249 +1,252 | |||||
| 1 | #!/bin/sh |
|
1 | #!/bin/sh | |
| 2 |
|
2 | |||
| 3 | # |
|
3 | # | |
| 4 | # Copyright Β© 2015-2021 the original authors. |
|
4 | # Copyright Β© 2015-2021 the original authors. | |
| 5 | # |
|
5 | # | |
| 6 | # Licensed under the Apache License, Version 2.0 (the "License"); |
|
6 | # Licensed under the Apache License, Version 2.0 (the "License"); | |
| 7 | # you may not use this file except in compliance with the License. |
|
7 | # you may not use this file except in compliance with the License. | |
| 8 | # You may obtain a copy of the License at |
|
8 | # You may obtain a copy of the License at | |
| 9 | # |
|
9 | # | |
| 10 | # https://www.apache.org/licenses/LICENSE-2.0 |
|
10 | # https://www.apache.org/licenses/LICENSE-2.0 | |
| 11 | # |
|
11 | # | |
| 12 | # Unless required by applicable law or agreed to in writing, software |
|
12 | # Unless required by applicable law or agreed to in writing, software | |
| 13 | # distributed under the License is distributed on an "AS IS" BASIS, |
|
13 | # distributed under the License is distributed on an "AS IS" BASIS, | |
| 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 15 | # See the License for the specific language governing permissions and |
|
15 | # See the License for the specific language governing permissions and | |
| 16 | # limitations under the License. |
|
16 | # limitations under the License. | |
| 17 | # |
|
17 | # | |
|
|
18 | # SPDX-License-Identifier: Apache-2.0 | |||
|
|
19 | # | |||
| 18 |
|
20 | |||
| 19 | ############################################################################## |
|
21 | ############################################################################## | |
| 20 | # |
|
22 | # | |
| 21 | # Gradle start up script for POSIX generated by Gradle. |
|
23 | # Gradle start up script for POSIX generated by Gradle. | |
| 22 | # |
|
24 | # | |
| 23 | # Important for running: |
|
25 | # Important for running: | |
| 24 | # |
|
26 | # | |
| 25 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is |
|
27 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is | |
| 26 | # noncompliant, but you have some other compliant shell such as ksh or |
|
28 | # noncompliant, but you have some other compliant shell such as ksh or | |
| 27 | # bash, then to run this script, type that shell name before the whole |
|
29 | # bash, then to run this script, type that shell name before the whole | |
| 28 | # command line, like: |
|
30 | # command line, like: | |
| 29 | # |
|
31 | # | |
| 30 | # ksh Gradle |
|
32 | # ksh Gradle | |
| 31 | # |
|
33 | # | |
| 32 | # Busybox and similar reduced shells will NOT work, because this script |
|
34 | # Busybox and similar reduced shells will NOT work, because this script | |
| 33 | # requires all of these POSIX shell features: |
|
35 | # requires all of these POSIX shell features: | |
| 34 | # * functions; |
|
36 | # * functions; | |
| 35 | # * expansions Β«$varΒ», Β«${var}Β», Β«${var:-default}Β», Β«${var+SET}Β», |
|
37 | # * expansions Β«$varΒ», Β«${var}Β», Β«${var:-default}Β», Β«${var+SET}Β», | |
| 36 | # Β«${var#prefix}Β», Β«${var%suffix}Β», and Β«$( cmd )Β»; |
|
38 | # Β«${var#prefix}Β», Β«${var%suffix}Β», and Β«$( cmd )Β»; | |
| 37 | # * compound commands having a testable exit status, especially Β«caseΒ»; |
|
39 | # * compound commands having a testable exit status, especially Β«caseΒ»; | |
| 38 | # * various built-in commands including Β«commandΒ», Β«setΒ», and Β«ulimitΒ». |
|
40 | # * various built-in commands including Β«commandΒ», Β«setΒ», and Β«ulimitΒ». | |
| 39 | # |
|
41 | # | |
| 40 | # Important for patching: |
|
42 | # Important for patching: | |
| 41 | # |
|
43 | # | |
| 42 | # (2) This script targets any POSIX shell, so it avoids extensions provided |
|
44 | # (2) This script targets any POSIX shell, so it avoids extensions provided | |
| 43 | # by Bash, Ksh, etc; in particular arrays are avoided. |
|
45 | # by Bash, Ksh, etc; in particular arrays are avoided. | |
| 44 | # |
|
46 | # | |
| 45 | # The "traditional" practice of packing multiple parameters into a |
|
47 | # The "traditional" practice of packing multiple parameters into a | |
| 46 | # space-separated string is a well documented source of bugs and security |
|
48 | # space-separated string is a well documented source of bugs and security | |
| 47 | # problems, so this is (mostly) avoided, by progressively accumulating |
|
49 | # problems, so this is (mostly) avoided, by progressively accumulating | |
| 48 | # options in "$@", and eventually passing that to Java. |
|
50 | # options in "$@", and eventually passing that to Java. | |
| 49 | # |
|
51 | # | |
| 50 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, |
|
52 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, | |
| 51 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; |
|
53 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; | |
| 52 | # see the in-line comments for details. |
|
54 | # see the in-line comments for details. | |
| 53 | # |
|
55 | # | |
| 54 | # There are tweaks for specific operating systems such as AIX, CygWin, |
|
56 | # There are tweaks for specific operating systems such as AIX, CygWin, | |
| 55 | # Darwin, MinGW, and NonStop. |
|
57 | # Darwin, MinGW, and NonStop. | |
| 56 | # |
|
58 | # | |
| 57 | # (3) This script is generated from the Groovy template |
|
59 | # (3) This script is generated from the Groovy template | |
| 58 |
# https://github.com/gradle/gradle/blob/HEAD/ |
|
60 | # https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt | |
| 59 | # within the Gradle project. |
|
61 | # within the Gradle project. | |
| 60 | # |
|
62 | # | |
| 61 | # You can find Gradle at https://github.com/gradle/gradle/. |
|
63 | # You can find Gradle at https://github.com/gradle/gradle/. | |
| 62 | # |
|
64 | # | |
| 63 | ############################################################################## |
|
65 | ############################################################################## | |
| 64 |
|
66 | |||
| 65 | # Attempt to set APP_HOME |
|
67 | # Attempt to set APP_HOME | |
| 66 |
|
68 | |||
| 67 | # Resolve links: $0 may be a link |
|
69 | # Resolve links: $0 may be a link | |
| 68 | app_path=$0 |
|
70 | app_path=$0 | |
| 69 |
|
71 | |||
| 70 | # Need this for daisy-chained symlinks. |
|
72 | # Need this for daisy-chained symlinks. | |
| 71 | while |
|
73 | while | |
| 72 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path |
|
74 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path | |
| 73 | [ -h "$app_path" ] |
|
75 | [ -h "$app_path" ] | |
| 74 | do |
|
76 | do | |
| 75 | ls=$( ls -ld "$app_path" ) |
|
77 | ls=$( ls -ld "$app_path" ) | |
| 76 | link=${ls#*' -> '} |
|
78 | link=${ls#*' -> '} | |
| 77 | case $link in #( |
|
79 | case $link in #( | |
| 78 | /*) app_path=$link ;; #( |
|
80 | /*) app_path=$link ;; #( | |
| 79 | *) app_path=$APP_HOME$link ;; |
|
81 | *) app_path=$APP_HOME$link ;; | |
| 80 | esac |
|
82 | esac | |
| 81 | done |
|
83 | done | |
| 82 |
|
84 | |||
| 83 | # This is normally unused |
|
85 | # This is normally unused | |
| 84 | # shellcheck disable=SC2034 |
|
86 | # shellcheck disable=SC2034 | |
| 85 | APP_BASE_NAME=${0##*/} |
|
87 | APP_BASE_NAME=${0##*/} | |
| 86 | # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) |
|
88 | # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) | |
| 87 |
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && p |
|
89 | APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s | |
|
|
90 | ' "$PWD" ) || exit | |||
| 88 |
|
91 | |||
| 89 | # Use the maximum available, or set MAX_FD != -1 to use that value. |
|
92 | # Use the maximum available, or set MAX_FD != -1 to use that value. | |
| 90 | MAX_FD=maximum |
|
93 | MAX_FD=maximum | |
| 91 |
|
94 | |||
| 92 | warn () { |
|
95 | warn () { | |
| 93 | echo "$*" |
|
96 | echo "$*" | |
| 94 | } >&2 |
|
97 | } >&2 | |
| 95 |
|
98 | |||
| 96 | die () { |
|
99 | die () { | |
| 97 | echo |
|
100 | echo | |
| 98 | echo "$*" |
|
101 | echo "$*" | |
| 99 | echo |
|
102 | echo | |
| 100 | exit 1 |
|
103 | exit 1 | |
| 101 | } >&2 |
|
104 | } >&2 | |
| 102 |
|
105 | |||
| 103 | # OS specific support (must be 'true' or 'false'). |
|
106 | # OS specific support (must be 'true' or 'false'). | |
| 104 | cygwin=false |
|
107 | cygwin=false | |
| 105 | msys=false |
|
108 | msys=false | |
| 106 | darwin=false |
|
109 | darwin=false | |
| 107 | nonstop=false |
|
110 | nonstop=false | |
| 108 | case "$( uname )" in #( |
|
111 | case "$( uname )" in #( | |
| 109 | CYGWIN* ) cygwin=true ;; #( |
|
112 | CYGWIN* ) cygwin=true ;; #( | |
| 110 | Darwin* ) darwin=true ;; #( |
|
113 | Darwin* ) darwin=true ;; #( | |
| 111 | MSYS* | MINGW* ) msys=true ;; #( |
|
114 | MSYS* | MINGW* ) msys=true ;; #( | |
| 112 | NONSTOP* ) nonstop=true ;; |
|
115 | NONSTOP* ) nonstop=true ;; | |
| 113 | esac |
|
116 | esac | |
| 114 |
|
117 | |||
| 115 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar |
|
118 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar | |
| 116 |
|
119 | |||
| 117 |
|
120 | |||
| 118 | # Determine the Java command to use to start the JVM. |
|
121 | # Determine the Java command to use to start the JVM. | |
| 119 | if [ -n "$JAVA_HOME" ] ; then |
|
122 | if [ -n "$JAVA_HOME" ] ; then | |
| 120 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then |
|
123 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then | |
| 121 | # IBM's JDK on AIX uses strange locations for the executables |
|
124 | # IBM's JDK on AIX uses strange locations for the executables | |
| 122 | JAVACMD=$JAVA_HOME/jre/sh/java |
|
125 | JAVACMD=$JAVA_HOME/jre/sh/java | |
| 123 | else |
|
126 | else | |
| 124 | JAVACMD=$JAVA_HOME/bin/java |
|
127 | JAVACMD=$JAVA_HOME/bin/java | |
| 125 | fi |
|
128 | fi | |
| 126 | if [ ! -x "$JAVACMD" ] ; then |
|
129 | if [ ! -x "$JAVACMD" ] ; then | |
| 127 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME |
|
130 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME | |
| 128 |
|
131 | |||
| 129 | Please set the JAVA_HOME variable in your environment to match the |
|
132 | Please set the JAVA_HOME variable in your environment to match the | |
| 130 | location of your Java installation." |
|
133 | location of your Java installation." | |
| 131 | fi |
|
134 | fi | |
| 132 | else |
|
135 | else | |
| 133 | JAVACMD=java |
|
136 | JAVACMD=java | |
| 134 | if ! command -v java >/dev/null 2>&1 |
|
137 | if ! command -v java >/dev/null 2>&1 | |
| 135 | then |
|
138 | then | |
| 136 | die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. |
|
139 | die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. | |
| 137 |
|
140 | |||
| 138 | Please set the JAVA_HOME variable in your environment to match the |
|
141 | Please set the JAVA_HOME variable in your environment to match the | |
| 139 | location of your Java installation." |
|
142 | location of your Java installation." | |
| 140 | fi |
|
143 | fi | |
| 141 | fi |
|
144 | fi | |
| 142 |
|
145 | |||
| 143 | # Increase the maximum file descriptors if we can. |
|
146 | # Increase the maximum file descriptors if we can. | |
| 144 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then |
|
147 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then | |
| 145 | case $MAX_FD in #( |
|
148 | case $MAX_FD in #( | |
| 146 | max*) |
|
149 | max*) | |
| 147 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. |
|
150 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. | |
| 148 | # shellcheck disable=SC2039,SC3045 |
|
151 | # shellcheck disable=SC2039,SC3045 | |
| 149 | MAX_FD=$( ulimit -H -n ) || |
|
152 | MAX_FD=$( ulimit -H -n ) || | |
| 150 | warn "Could not query maximum file descriptor limit" |
|
153 | warn "Could not query maximum file descriptor limit" | |
| 151 | esac |
|
154 | esac | |
| 152 | case $MAX_FD in #( |
|
155 | case $MAX_FD in #( | |
| 153 | '' | soft) :;; #( |
|
156 | '' | soft) :;; #( | |
| 154 | *) |
|
157 | *) | |
| 155 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. |
|
158 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. | |
| 156 | # shellcheck disable=SC2039,SC3045 |
|
159 | # shellcheck disable=SC2039,SC3045 | |
| 157 | ulimit -n "$MAX_FD" || |
|
160 | ulimit -n "$MAX_FD" || | |
| 158 | warn "Could not set maximum file descriptor limit to $MAX_FD" |
|
161 | warn "Could not set maximum file descriptor limit to $MAX_FD" | |
| 159 | esac |
|
162 | esac | |
| 160 | fi |
|
163 | fi | |
| 161 |
|
164 | |||
| 162 | # Collect all arguments for the java command, stacking in reverse order: |
|
165 | # Collect all arguments for the java command, stacking in reverse order: | |
| 163 | # * args from the command line |
|
166 | # * args from the command line | |
| 164 | # * the main class name |
|
167 | # * the main class name | |
| 165 | # * -classpath |
|
168 | # * -classpath | |
| 166 | # * -D...appname settings |
|
169 | # * -D...appname settings | |
| 167 | # * --module-path (only if needed) |
|
170 | # * --module-path (only if needed) | |
| 168 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. |
|
171 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. | |
| 169 |
|
172 | |||
| 170 | # For Cygwin or MSYS, switch paths to Windows format before running java |
|
173 | # For Cygwin or MSYS, switch paths to Windows format before running java | |
| 171 | if "$cygwin" || "$msys" ; then |
|
174 | if "$cygwin" || "$msys" ; then | |
| 172 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) |
|
175 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) | |
| 173 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) |
|
176 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) | |
| 174 |
|
177 | |||
| 175 | JAVACMD=$( cygpath --unix "$JAVACMD" ) |
|
178 | JAVACMD=$( cygpath --unix "$JAVACMD" ) | |
| 176 |
|
179 | |||
| 177 | # Now convert the arguments - kludge to limit ourselves to /bin/sh |
|
180 | # Now convert the arguments - kludge to limit ourselves to /bin/sh | |
| 178 | for arg do |
|
181 | for arg do | |
| 179 | if |
|
182 | if | |
| 180 | case $arg in #( |
|
183 | case $arg in #( | |
| 181 | -*) false ;; # don't mess with options #( |
|
184 | -*) false ;; # don't mess with options #( | |
| 182 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath |
|
185 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath | |
| 183 | [ -e "$t" ] ;; #( |
|
186 | [ -e "$t" ] ;; #( | |
| 184 | *) false ;; |
|
187 | *) false ;; | |
| 185 | esac |
|
188 | esac | |
| 186 | then |
|
189 | then | |
| 187 | arg=$( cygpath --path --ignore --mixed "$arg" ) |
|
190 | arg=$( cygpath --path --ignore --mixed "$arg" ) | |
| 188 | fi |
|
191 | fi | |
| 189 | # Roll the args list around exactly as many times as the number of |
|
192 | # Roll the args list around exactly as many times as the number of | |
| 190 | # args, so each arg winds up back in the position where it started, but |
|
193 | # args, so each arg winds up back in the position where it started, but | |
| 191 | # possibly modified. |
|
194 | # possibly modified. | |
| 192 | # |
|
195 | # | |
| 193 | # NB: a `for` loop captures its iteration list before it begins, so |
|
196 | # NB: a `for` loop captures its iteration list before it begins, so | |
| 194 | # changing the positional parameters here affects neither the number of |
|
197 | # changing the positional parameters here affects neither the number of | |
| 195 | # iterations, nor the values presented in `arg`. |
|
198 | # iterations, nor the values presented in `arg`. | |
| 196 | shift # remove old arg |
|
199 | shift # remove old arg | |
| 197 | set -- "$@" "$arg" # push replacement arg |
|
200 | set -- "$@" "$arg" # push replacement arg | |
| 198 | done |
|
201 | done | |
| 199 | fi |
|
202 | fi | |
| 200 |
|
203 | |||
| 201 |
|
204 | |||
| 202 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. |
|
205 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. | |
| 203 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' |
|
206 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' | |
| 204 |
|
207 | |||
| 205 | # Collect all arguments for the java command: |
|
208 | # Collect all arguments for the java command: | |
| 206 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, |
|
209 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, | |
| 207 | # and any embedded shellness will be escaped. |
|
210 | # and any embedded shellness will be escaped. | |
| 208 | # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be |
|
211 | # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be | |
| 209 | # treated as '${Hostname}' itself on the command line. |
|
212 | # treated as '${Hostname}' itself on the command line. | |
| 210 |
|
213 | |||
| 211 | set -- \ |
|
214 | set -- \ | |
| 212 | "-Dorg.gradle.appname=$APP_BASE_NAME" \ |
|
215 | "-Dorg.gradle.appname=$APP_BASE_NAME" \ | |
| 213 | -classpath "$CLASSPATH" \ |
|
216 | -classpath "$CLASSPATH" \ | |
| 214 | org.gradle.wrapper.GradleWrapperMain \ |
|
217 | org.gradle.wrapper.GradleWrapperMain \ | |
| 215 | "$@" |
|
218 | "$@" | |
| 216 |
|
219 | |||
| 217 | # Stop when "xargs" is not available. |
|
220 | # Stop when "xargs" is not available. | |
| 218 | if ! command -v xargs >/dev/null 2>&1 |
|
221 | if ! command -v xargs >/dev/null 2>&1 | |
| 219 | then |
|
222 | then | |
| 220 | die "xargs is not available" |
|
223 | die "xargs is not available" | |
| 221 | fi |
|
224 | fi | |
| 222 |
|
225 | |||
| 223 | # Use "xargs" to parse quoted args. |
|
226 | # Use "xargs" to parse quoted args. | |
| 224 | # |
|
227 | # | |
| 225 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed. |
|
228 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed. | |
| 226 | # |
|
229 | # | |
| 227 | # In Bash we could simply go: |
|
230 | # In Bash we could simply go: | |
| 228 | # |
|
231 | # | |
| 229 | # readarray ARGS < <( xargs -n1 <<<"$var" ) && |
|
232 | # readarray ARGS < <( xargs -n1 <<<"$var" ) && | |
| 230 | # set -- "${ARGS[@]}" "$@" |
|
233 | # set -- "${ARGS[@]}" "$@" | |
| 231 | # |
|
234 | # | |
| 232 | # but POSIX shell has neither arrays nor command substitution, so instead we |
|
235 | # but POSIX shell has neither arrays nor command substitution, so instead we | |
| 233 | # post-process each arg (as a line of input to sed) to backslash-escape any |
|
236 | # post-process each arg (as a line of input to sed) to backslash-escape any | |
| 234 | # character that might be a shell metacharacter, then use eval to reverse |
|
237 | # character that might be a shell metacharacter, then use eval to reverse | |
| 235 | # that process (while maintaining the separation between arguments), and wrap |
|
238 | # that process (while maintaining the separation between arguments), and wrap | |
| 236 | # the whole thing up as a single "set" statement. |
|
239 | # the whole thing up as a single "set" statement. | |
| 237 | # |
|
240 | # | |
| 238 | # This will of course break if any of these variables contains a newline or |
|
241 | # This will of course break if any of these variables contains a newline or | |
| 239 | # an unmatched quote. |
|
242 | # an unmatched quote. | |
| 240 | # |
|
243 | # | |
| 241 |
|
244 | |||
| 242 | eval "set -- $( |
|
245 | eval "set -- $( | |
| 243 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | |
|
246 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | | |
| 244 | xargs -n1 | |
|
247 | xargs -n1 | | |
| 245 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | |
|
248 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | | |
| 246 | tr '\n' ' ' |
|
249 | tr '\n' ' ' | |
| 247 | )" '"$@"' |
|
250 | )" '"$@"' | |
| 248 |
|
251 | |||
| 249 | exec "$JAVACMD" "$@" |
|
252 | exec "$JAVACMD" "$@" | |
| @@ -1,92 +1,94 | |||||
| 1 | @rem |
|
1 | @rem | |
| 2 | @rem Copyright 2015 the original author or authors. |
|
2 | @rem Copyright 2015 the original author or authors. | |
| 3 | @rem |
|
3 | @rem | |
| 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); |
|
4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); | |
| 5 | @rem you may not use this file except in compliance with the License. |
|
5 | @rem you may not use this file except in compliance with the License. | |
| 6 | @rem You may obtain a copy of the License at |
|
6 | @rem You may obtain a copy of the License at | |
| 7 | @rem |
|
7 | @rem | |
| 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 |
|
8 | @rem https://www.apache.org/licenses/LICENSE-2.0 | |
| 9 | @rem |
|
9 | @rem | |
| 10 | @rem Unless required by applicable law or agreed to in writing, software |
|
10 | @rem Unless required by applicable law or agreed to in writing, software | |
| 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, |
|
11 | @rem distributed under the License is distributed on an "AS IS" BASIS, | |
| 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 13 | @rem See the License for the specific language governing permissions and |
|
13 | @rem See the License for the specific language governing permissions and | |
| 14 | @rem limitations under the License. |
|
14 | @rem limitations under the License. | |
| 15 | @rem |
|
15 | @rem | |
|
|
16 | @rem SPDX-License-Identifier: Apache-2.0 | |||
|
|
17 | @rem | |||
| 16 |
|
18 | |||
| 17 | @if "%DEBUG%"=="" @echo off |
|
19 | @if "%DEBUG%"=="" @echo off | |
| 18 | @rem ########################################################################## |
|
20 | @rem ########################################################################## | |
| 19 | @rem |
|
21 | @rem | |
| 20 | @rem Gradle startup script for Windows |
|
22 | @rem Gradle startup script for Windows | |
| 21 | @rem |
|
23 | @rem | |
| 22 | @rem ########################################################################## |
|
24 | @rem ########################################################################## | |
| 23 |
|
25 | |||
| 24 | @rem Set local scope for the variables with windows NT shell |
|
26 | @rem Set local scope for the variables with windows NT shell | |
| 25 | if "%OS%"=="Windows_NT" setlocal |
|
27 | if "%OS%"=="Windows_NT" setlocal | |
| 26 |
|
28 | |||
| 27 | set DIRNAME=%~dp0 |
|
29 | set DIRNAME=%~dp0 | |
| 28 | if "%DIRNAME%"=="" set DIRNAME=. |
|
30 | if "%DIRNAME%"=="" set DIRNAME=. | |
| 29 | @rem This is normally unused |
|
31 | @rem This is normally unused | |
| 30 | set APP_BASE_NAME=%~n0 |
|
32 | set APP_BASE_NAME=%~n0 | |
| 31 | set APP_HOME=%DIRNAME% |
|
33 | set APP_HOME=%DIRNAME% | |
| 32 |
|
34 | |||
| 33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. |
|
35 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. | |
| 34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi |
|
36 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi | |
| 35 |
|
37 | |||
| 36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. |
|
38 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. | |
| 37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" |
|
39 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" | |
| 38 |
|
40 | |||
| 39 | @rem Find java.exe |
|
41 | @rem Find java.exe | |
| 40 | if defined JAVA_HOME goto findJavaFromJavaHome |
|
42 | if defined JAVA_HOME goto findJavaFromJavaHome | |
| 41 |
|
43 | |||
| 42 | set JAVA_EXE=java.exe |
|
44 | set JAVA_EXE=java.exe | |
| 43 | %JAVA_EXE% -version >NUL 2>&1 |
|
45 | %JAVA_EXE% -version >NUL 2>&1 | |
| 44 | if %ERRORLEVEL% equ 0 goto execute |
|
46 | if %ERRORLEVEL% equ 0 goto execute | |
| 45 |
|
47 | |||
| 46 | echo. 1>&2 |
|
48 | echo. 1>&2 | |
| 47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 |
|
49 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 | |
| 48 | echo. 1>&2 |
|
50 | echo. 1>&2 | |
| 49 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 |
|
51 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 | |
| 50 | echo location of your Java installation. 1>&2 |
|
52 | echo location of your Java installation. 1>&2 | |
| 51 |
|
53 | |||
| 52 | goto fail |
|
54 | goto fail | |
| 53 |
|
55 | |||
| 54 | :findJavaFromJavaHome |
|
56 | :findJavaFromJavaHome | |
| 55 | set JAVA_HOME=%JAVA_HOME:"=% |
|
57 | set JAVA_HOME=%JAVA_HOME:"=% | |
| 56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe |
|
58 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe | |
| 57 |
|
59 | |||
| 58 | if exist "%JAVA_EXE%" goto execute |
|
60 | if exist "%JAVA_EXE%" goto execute | |
| 59 |
|
61 | |||
| 60 | echo. 1>&2 |
|
62 | echo. 1>&2 | |
| 61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 |
|
63 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 | |
| 62 | echo. 1>&2 |
|
64 | echo. 1>&2 | |
| 63 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 |
|
65 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 | |
| 64 | echo location of your Java installation. 1>&2 |
|
66 | echo location of your Java installation. 1>&2 | |
| 65 |
|
67 | |||
| 66 | goto fail |
|
68 | goto fail | |
| 67 |
|
69 | |||
| 68 | :execute |
|
70 | :execute | |
| 69 | @rem Setup the command line |
|
71 | @rem Setup the command line | |
| 70 |
|
72 | |||
| 71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar |
|
73 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar | |
| 72 |
|
74 | |||
| 73 |
|
75 | |||
| 74 | @rem Execute Gradle |
|
76 | @rem Execute Gradle | |
| 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* |
|
77 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* | |
| 76 |
|
78 | |||
| 77 | :end |
|
79 | :end | |
| 78 | @rem End local scope for the variables with windows NT shell |
|
80 | @rem End local scope for the variables with windows NT shell | |
| 79 | if %ERRORLEVEL% equ 0 goto mainEnd |
|
81 | if %ERRORLEVEL% equ 0 goto mainEnd | |
| 80 |
|
82 | |||
| 81 | :fail |
|
83 | :fail | |
| 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of |
|
84 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of | |
| 83 | rem the _cmd.exe /c_ return code! |
|
85 | rem the _cmd.exe /c_ return code! | |
| 84 | set EXIT_CODE=%ERRORLEVEL% |
|
86 | set EXIT_CODE=%ERRORLEVEL% | |
| 85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 |
|
87 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 | |
| 86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% |
|
88 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% | |
| 87 | exit /b %EXIT_CODE% |
|
89 | exit /b %EXIT_CODE% | |
| 88 |
|
90 | |||
| 89 | :mainEnd |
|
91 | :mainEnd | |
| 90 | if "%OS%"=="Windows_NT" endlocal |
|
92 | if "%OS%"=="Windows_NT" endlocal | |
| 91 |
|
93 | |||
| 92 | :omega |
|
94 | :omega | |
| @@ -1,24 +1,24 | |||||
| 1 | /* |
|
1 | /* | |
| 2 | * This settings file was generated by the Gradle 'init' task. |
|
2 | * This settings file was generated by the Gradle 'init' task. | |
| 3 | * |
|
3 | * | |
| 4 | * The settings file is used to specify which projects to include in your build. |
|
4 | * The settings file is used to specify which projects to include in your build. | |
| 5 | * In a single project build this file can be empty or even removed. |
|
5 | * In a single project build this file can be empty or even removed. | |
| 6 | * |
|
6 | * | |
| 7 | * Detailed information about configuring a multi-project build in Gradle can be found |
|
7 | * Detailed information about configuring a multi-project build in Gradle can be found | |
| 8 | * in the user guide at https://docs.gradle.org/3.5/userguide/multi_project_builds.html |
|
8 | * in the user guide at https://docs.gradle.org/3.5/userguide/multi_project_builds.html | |
| 9 | */ |
|
9 | */ | |
| 10 |
|
10 | |||
| 11 | dependencyResolutionManagement { |
|
11 | dependencyResolutionManagement { | |
| 12 | repositories { |
|
12 | repositories { | |
| 13 | mavenCentral() |
|
13 | mavenCentral() | |
| 14 | mavenLocal() |
|
14 | mavenLocal() | |
| 15 | ivy { |
|
15 | ivy { | |
| 16 | url "${System.properties["user.home"]}/ivy-repo" |
|
16 | url = "${System.properties["user.home"]}/ivy-repo" | |
| 17 | } |
|
17 | } | |
| 18 | } |
|
18 | } | |
| 19 | } |
|
19 | } | |
| 20 |
|
20 | |||
| 21 | rootProject.name = 'gradle-common' |
|
21 | rootProject.name = 'gradle-common' | |
| 22 |
|
22 | |||
| 23 | include 'common' |
|
23 | include 'common' | |
| 24 | include 'variants' |
|
24 | include 'variants' | |
| @@ -1,61 +1,61 | |||||
| 1 | plugins { |
|
1 | plugins { | |
| 2 | id "java-library" |
|
2 | id "java-library" | |
| 3 | id "ivy-publish" |
|
3 | id "ivy-publish" | |
| 4 | } |
|
4 | } | |
| 5 |
|
5 | |||
| 6 | description = "Variant, source-set, and outgoing artifact model plugins for Gradle builds" |
|
6 | description = "Variant, source-set, and outgoing artifact model plugins for Gradle builds" | |
| 7 |
|
7 | |||
| 8 | java { |
|
8 | java { | |
| 9 | withJavadocJar() |
|
9 | withJavadocJar() | |
| 10 | withSourcesJar() |
|
10 | withSourcesJar() | |
| 11 | toolchain { |
|
11 | toolchain { | |
| 12 | languageVersion = JavaLanguageVersion.of(21) |
|
12 | languageVersion = JavaLanguageVersion.of(21) | |
| 13 | } |
|
13 | } | |
| 14 | } |
|
14 | } | |
| 15 |
|
15 | |||
| 16 | dependencies { |
|
16 | dependencies { | |
| 17 | compileOnly libs.jdt.annotations |
|
17 | compileOnly libs.jdt.annotations | |
| 18 |
|
18 | |||
| 19 | api gradleApi(), |
|
19 | api gradleApi(), | |
| 20 | project(":common") |
|
20 | project(":common") | |
| 21 |
|
21 | |||
| 22 | testImplementation gradleTestKit() |
|
22 | testImplementation gradleTestKit() | |
| 23 | testImplementation "org.junit.jupiter:junit-jupiter-api:5.11.4" |
|
23 | testImplementation "org.junit.jupiter:junit-jupiter-api:5.11.4" | |
| 24 | testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:5.11.4" |
|
24 | testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:5.11.4" | |
| 25 | testRuntimeOnly "org.junit.platform:junit-platform-launcher:1.11.4" |
|
25 | testRuntimeOnly "org.junit.platform:junit-platform-launcher:1.11.4" | |
| 26 | } |
|
26 | } | |
| 27 |
|
27 | |||
| 28 | task printVersion{ |
|
28 | task printVersion{ | |
| 29 | doLast { |
|
29 | doLast { | |
| 30 | println "project: $project.group:$project.name:$project.version" |
|
30 | println "project: $project.group:$project.name:$project.version" | |
| 31 | println "jar: ${->jar.archiveFileName.get()}" |
|
31 | println "jar: ${->jar.archiveFileName.get()}" | |
| 32 | } |
|
32 | } | |
| 33 | } |
|
33 | } | |
| 34 |
|
34 | |||
| 35 | test { |
|
35 | test { | |
| 36 | useJUnitPlatform() |
|
36 | useJUnitPlatform() | |
| 37 | } |
|
37 | } | |
| 38 |
|
38 | |||
| 39 | javadoc { |
|
39 | javadoc { | |
| 40 | exclude "**/internal/**" |
|
40 | exclude "**/internal/**" | |
| 41 | } |
|
41 | } | |
| 42 |
|
42 | |||
| 43 | publishing { |
|
43 | publishing { | |
| 44 | repositories { |
|
44 | repositories { | |
| 45 | ivy { |
|
45 | ivy { | |
| 46 | url "${System.properties["user.home"]}/ivy-repo" |
|
46 | url = "${System.properties["user.home"]}/ivy-repo" | |
| 47 | } |
|
47 | } | |
| 48 | } |
|
48 | } | |
| 49 | publications { |
|
49 | publications { | |
| 50 | ivy(IvyPublication) { |
|
50 | ivy(IvyPublication) { | |
| 51 | from components.java |
|
51 | from components.java | |
| 52 | descriptor.description { |
|
52 | descriptor.description { | |
| 53 | text = providers.provider({ description }) |
|
53 | text = providers.provider({ description }) | |
| 54 | } |
|
54 | } | |
| 55 | descriptor.license { |
|
55 | descriptor.license { | |
| 56 | name = "BSD-2-Clause" |
|
56 | name = "BSD-2-Clause" | |
| 57 | url = "https://spdx.org/licenses/BSD-2-Clause.html" |
|
57 | url = "https://spdx.org/licenses/BSD-2-Clause.html" | |
| 58 | } |
|
58 | } | |
| 59 | } |
|
59 | } | |
| 60 | } |
|
60 | } | |
| 61 | } |
|
61 | } | |
| @@ -1,98 +1,123 | |||||
| 1 | package org.implab.gradle.variants; |
|
1 | package org.implab.gradle.variants; | |
| 2 |
|
2 | |||
| 3 | import static org.junit.jupiter.api.Assertions.assertTrue; |
|
3 | import static org.junit.jupiter.api.Assertions.assertTrue; | |
| 4 |
|
4 | |||
| 5 | import java.io.File; |
|
5 | import java.io.File; | |
| 6 | import java.io.IOException; |
|
6 | import java.io.IOException; | |
| 7 | import java.nio.file.Files; |
|
7 | import java.nio.file.Files; | |
| 8 | import java.nio.file.Path; |
|
8 | import java.nio.file.Path; | |
| 9 | import java.util.LinkedHashSet; |
|
9 | import java.util.LinkedHashSet; | |
| 10 | import java.util.List; |
|
10 | import java.util.List; | |
| 11 | import java.util.stream.Collectors; |
|
11 | import java.util.stream.Collectors; | |
|
|
12 | import java.util.regex.Pattern; | |||
| 12 |
|
13 | |||
| 13 | import org.gradle.testkit.runner.GradleRunner; |
|
14 | import org.gradle.testkit.runner.GradleRunner; | |
| 14 | import org.gradle.testkit.runner.UnexpectedBuildFailure; |
|
15 | import org.gradle.testkit.runner.UnexpectedBuildFailure; | |
| 15 | import org.implab.gradle.common.core.lang.Deferred; |
|
16 | import org.implab.gradle.common.core.lang.Deferred; | |
| 16 | import org.implab.gradle.variants.sources.GenericSourceSet; |
|
17 | import org.implab.gradle.variants.sources.GenericSourceSet; | |
| 17 | import org.junit.jupiter.api.io.TempDir; |
|
18 | import org.junit.jupiter.api.io.TempDir; | |
| 18 |
|
19 | |||
| 19 | abstract class AbstractFunctionalTest { |
|
20 | abstract class AbstractFunctionalTest { | |
| 20 | private static final String SETTINGS_FILE = "settings.gradle"; |
|
21 | private static final String SETTINGS_FILE = "settings.gradle"; | |
| 21 | private static final String BUILD_FILE = "build.gradle"; |
|
22 | private static final String BUILD_FILE = "build.gradle"; | |
|
|
23 | private static final Pattern INCLUDE_DECLARATION = Pattern.compile("^include(?:\\s|\\().*"); | |||
|
|
24 | private static final Pattern QUOTED_LITERAL = Pattern.compile("['\"]([^'\"]+)['\"]"); | |||
| 22 |
|
25 | |||
| 23 | @TempDir |
|
26 | @TempDir | |
| 24 | Path testProjectDir; |
|
27 | Path testProjectDir; | |
| 25 |
|
28 | |||
| 26 | protected void writeSettings(String rootProjectName) throws IOException { |
|
29 | protected void writeSettings(String rootProjectName) throws IOException { | |
| 27 | writeFile(SETTINGS_FILE, "rootProject.name = '" + rootProjectName + "'\n"); |
|
30 | writeFile(SETTINGS_FILE, "rootProject.name = '" + rootProjectName + "'\n"); | |
| 28 | } |
|
31 | } | |
| 29 |
|
32 | |||
| 30 | protected void writeBuildFile(String body) throws IOException { |
|
33 | protected void writeBuildFile(String body) throws IOException { | |
| 31 | writeFile(BUILD_FILE, buildscriptClasspathBlock() + "\n" + body); |
|
34 | writeFile(BUILD_FILE, buildscriptClasspathBlock() + "\n" + body); | |
| 32 | } |
|
35 | } | |
| 33 |
|
36 | |||
| 34 | protected GradleRunner runner(String... arguments) { |
|
37 | protected GradleRunner runner(String... arguments) { | |
| 35 | return GradleRunner.create() |
|
38 | return GradleRunner.create() | |
| 36 | .withProjectDir(testProjectDir.toFile()) |
|
39 | .withProjectDir(testProjectDir.toFile()) | |
| 37 | .withArguments(arguments) |
|
40 | .withArguments(arguments) | |
| 38 | .forwardOutput(); |
|
41 | .forwardOutput(); | |
| 39 | } |
|
42 | } | |
| 40 |
|
43 | |||
| 41 | protected void assertBuildFails(String expectedError, String... arguments) { |
|
44 | protected void assertBuildFails(String expectedError, String... arguments) { | |
| 42 | var ex = org.junit.jupiter.api.Assertions.assertThrows( |
|
45 | var ex = org.junit.jupiter.api.Assertions.assertThrows( | |
| 43 | UnexpectedBuildFailure.class, |
|
46 | UnexpectedBuildFailure.class, | |
| 44 | () -> runner(arguments).build()); |
|
47 | () -> runner(arguments).build()); | |
| 45 |
|
48 | |||
| 46 | var output = ex.getBuildResult().getOutput(); |
|
49 | var output = ex.getBuildResult().getOutput(); | |
| 47 | assertTrue(output.contains(expectedError), () -> "Expected [" + expectedError + "] in output:\n" + output); |
|
50 | assertTrue(output.contains(expectedError), () -> "Expected [" + expectedError + "] in output:\n" + output); | |
| 48 | } |
|
51 | } | |
| 49 |
|
52 | |||
| 50 | private static String buildscriptClasspathBlock() { |
|
53 | private static String buildscriptClasspathBlock() { | |
| 51 | var classpath = pluginClasspath().stream() |
|
54 | var classpath = pluginClasspath().stream() | |
| 52 | .map(file -> "'" + file.getAbsolutePath().replace("\\", "\\\\") + "'") |
|
55 | .map(file -> "'" + file.getAbsolutePath().replace("\\", "\\\\") + "'") | |
| 53 | .collect(Collectors.joining(", ")); |
|
56 | .collect(Collectors.joining(", ")); | |
| 54 |
|
57 | |||
| 55 | return """ |
|
58 | return """ | |
| 56 | buildscript { |
|
59 | buildscript { | |
| 57 | dependencies { |
|
60 | dependencies { | |
| 58 | classpath files(%s) |
|
61 | classpath files(%s) | |
| 59 | } |
|
62 | } | |
| 60 | } |
|
63 | } | |
| 61 | """.formatted(classpath); |
|
64 | """.formatted(classpath); | |
| 62 | } |
|
65 | } | |
| 63 |
|
66 | |||
| 64 | private static List<File> pluginClasspath() { |
|
67 | private static List<File> pluginClasspath() { | |
| 65 | try { |
|
68 | try { | |
| 66 | var files = new LinkedHashSet<File>(); |
|
69 | var files = new LinkedHashSet<File>(); | |
| 67 | files.add(codeSource(VariantSourcesPlugin.class)); |
|
70 | files.add(codeSource(VariantSourcesPlugin.class)); | |
| 68 | files.add(resourceRoot("META-INF/gradle-plugins/org.implab.gradle-variants.properties")); |
|
71 | files.add(resourceRoot("META-INF/gradle-plugins/org.implab.gradle-variants.properties")); | |
| 69 | files.add(codeSource(GenericSourceSet.class)); |
|
72 | files.add(codeSource(GenericSourceSet.class)); | |
| 70 | files.add(codeSource(Deferred.class)); |
|
73 | files.add(codeSource(Deferred.class)); | |
| 71 | return List.copyOf(files); |
|
74 | return List.copyOf(files); | |
| 72 | } catch (Exception e) { |
|
75 | } catch (Exception e) { | |
| 73 | throw new RuntimeException("Unable to build plugin classpath for test", e); |
|
76 | throw new RuntimeException("Unable to build plugin classpath for test", e); | |
| 74 | } |
|
77 | } | |
| 75 | } |
|
78 | } | |
| 76 |
|
79 | |||
| 77 | private static File codeSource(Class<?> type) throws Exception { |
|
80 | private static File codeSource(Class<?> type) throws Exception { | |
| 78 | return Path.of(type.getProtectionDomain().getCodeSource().getLocation().toURI()).toFile(); |
|
81 | return Path.of(type.getProtectionDomain().getCodeSource().getLocation().toURI()).toFile(); | |
| 79 | } |
|
82 | } | |
| 80 |
|
83 | |||
| 81 | private static File resourceRoot(String resourceName) throws Exception { |
|
84 | private static File resourceRoot(String resourceName) throws Exception { | |
| 82 | var url = VariantSourcesPlugin.class.getClassLoader().getResource(resourceName); |
|
85 | var url = VariantSourcesPlugin.class.getClassLoader().getResource(resourceName); | |
| 83 | if (url == null) |
|
86 | if (url == null) | |
| 84 | throw new IllegalStateException("Classpath resource isn't found: " + resourceName); |
|
87 | throw new IllegalStateException("Classpath resource isn't found: " + resourceName); | |
| 85 |
|
88 | |||
| 86 | var path = Path.of(url.toURI()); |
|
89 | var path = Path.of(url.toURI()); | |
| 87 | var segments = resourceName.split("/").length; |
|
90 | var segments = resourceName.split("/").length; | |
| 88 | for (var i = 0; i < segments; i++) |
|
91 | for (var i = 0; i < segments; i++) | |
| 89 | path = path.getParent(); |
|
92 | path = path.getParent(); | |
| 90 | return path.toFile(); |
|
93 | return path.toFile(); | |
| 91 | } |
|
94 | } | |
| 92 |
|
95 | |||
| 93 | protected void writeFile(String relativePath, String content) throws IOException { |
|
96 | protected void writeFile(String relativePath, String content) throws IOException { | |
| 94 | Path path = testProjectDir.resolve(relativePath); |
|
97 | Path path = testProjectDir.resolve(relativePath); | |
| 95 | Files.createDirectories(path.getParent()); |
|
98 | Files.createDirectories(path.getParent()); | |
| 96 | Files.writeString(path, content); |
|
99 | Files.writeString(path, content); | |
|
|
100 | ||||
|
|
101 | if (SETTINGS_FILE.equals(relativePath)) | |||
|
|
102 | ensureIncludedProjectDirectories(content); | |||
|
|
103 | } | |||
|
|
104 | ||||
|
|
105 | private void ensureIncludedProjectDirectories(String settingsContent) throws IOException { | |||
|
|
106 | for (var line : settingsContent.split("\\R")) { | |||
|
|
107 | var trimmed = line.strip(); | |||
|
|
108 | if (!INCLUDE_DECLARATION.matcher(trimmed).matches()) | |||
|
|
109 | continue; | |||
|
|
110 | ||||
|
|
111 | var matcher = QUOTED_LITERAL.matcher(trimmed); | |||
|
|
112 | while (matcher.find()) { | |||
|
|
113 | var projectPath = matcher.group(1); | |||
|
|
114 | if (projectPath.startsWith(":")) | |||
|
|
115 | projectPath = projectPath.substring(1); | |||
|
|
116 | if (projectPath.isBlank()) | |||
|
|
117 | continue; | |||
|
|
118 | ||||
|
|
119 | Files.createDirectories(testProjectDir.resolve(projectPath.replace(':', File.separatorChar))); | |||
|
|
120 | } | |||
|
|
121 | } | |||
| 97 | } |
|
122 | } | |
| 98 | } |
|
123 | } | |
| @@ -1,867 +1,867 | |||||
| 1 | package org.implab.gradle.variants; |
|
1 | package org.implab.gradle.variants; | |
| 2 |
|
2 | |||
| 3 | import static org.junit.jupiter.api.Assertions.assertTrue; |
|
3 | import static org.junit.jupiter.api.Assertions.assertTrue; | |
| 4 |
|
4 | |||
| 5 | import org.gradle.testkit.runner.BuildResult; |
|
5 | import org.gradle.testkit.runner.BuildResult; | |
| 6 | import org.gradle.testkit.runner.TaskOutcome; |
|
6 | import org.gradle.testkit.runner.TaskOutcome; | |
| 7 | import org.junit.jupiter.api.Test; |
|
7 | import org.junit.jupiter.api.Test; | |
| 8 |
|
8 | |||
| 9 | class VariantArtifactsPluginFunctionalTest extends AbstractFunctionalTest { |
|
9 | class VariantArtifactsPluginFunctionalTest extends AbstractFunctionalTest { | |
| 10 |
|
10 | |||
| 11 | @Test |
|
11 | @Test | |
| 12 | void gradleReferenceLazyOutgoingConfigurationAllowsSecondaryArtifactSelection() throws Exception { |
|
12 | void gradleReferenceLazyOutgoingConfigurationAllowsSecondaryArtifactSelection() throws Exception { | |
| 13 | writeFile("settings.gradle", """ |
|
13 | writeFile("settings.gradle", """ | |
| 14 | rootProject.name = 'gradle-reference-outgoing-resolution' |
|
14 | rootProject.name = 'gradle-reference-outgoing-resolution' | |
| 15 | include 'producer', 'consumer' |
|
15 | include 'producer', 'consumer' | |
| 16 | """); |
|
16 | """); | |
| 17 | writeFile("producer/inputs/typesPackage", "types\n"); |
|
17 | writeFile("producer/inputs/typesPackage", "types\n"); | |
| 18 | writeFile("producer/inputs/js", "js\n"); |
|
18 | writeFile("producer/inputs/js", "js\n"); | |
| 19 | writeBuildFile(""" |
|
19 | writeBuildFile(""" | |
| 20 | import org.gradle.api.attributes.Attribute |
|
20 | import org.gradle.api.attributes.Attribute | |
| 21 |
|
21 | |||
| 22 | def variantAttr = Attribute.of('test.variant', String) |
|
22 | def variantAttr = Attribute.of('test.variant', String) | |
| 23 | def slotAttr = Attribute.of('test.slot', String) |
|
23 | def slotAttr = Attribute.of('test.slot', String) | |
| 24 |
|
24 | |||
| 25 | project(':producer') { |
|
25 | project(':producer') { | |
| 26 | def browserElements = configurations.consumable('browserElements') |
|
26 | def browserElements = configurations.consumable('browserElements') | |
| 27 |
|
27 | |||
| 28 | println('reference: registered browserElements provider') |
|
28 | println('reference: registered browserElements provider') | |
| 29 |
|
29 | |||
| 30 | browserElements.configure { configuration -> |
|
30 | browserElements.configure { configuration -> | |
| 31 | println('reference: configuring browserElements') |
|
31 | println('reference: configuring browserElements') | |
| 32 |
|
32 | |||
| 33 | configuration.attributes.attribute(variantAttr, 'browser') |
|
33 | configuration.attributes.attribute(variantAttr, 'browser') | |
| 34 | configuration.outgoing.attributes.attribute(slotAttr, 'typesPackage') |
|
34 | configuration.outgoing.attributes.attribute(slotAttr, 'typesPackage') | |
| 35 | configuration.outgoing.artifact(layout.projectDirectory.file('inputs/typesPackage')) |
|
35 | configuration.outgoing.artifact(layout.projectDirectory.file('inputs/typesPackage')) | |
| 36 |
|
36 | |||
| 37 | configuration.outgoing.variants.create('js') { secondary -> |
|
37 | configuration.outgoing.variants.create('js') { secondary -> | |
| 38 | println('reference: creating js outgoing variant') |
|
38 | println('reference: creating js outgoing variant') | |
| 39 |
|
39 | |||
| 40 | secondary.attributes.attribute(slotAttr, 'js') |
|
40 | secondary.attributes.attribute(slotAttr, 'js') | |
| 41 | secondary.artifact(layout.projectDirectory.file('inputs/js')) |
|
41 | secondary.artifact(layout.projectDirectory.file('inputs/js')) | |
| 42 | } |
|
42 | } | |
| 43 | } |
|
43 | } | |
| 44 | } |
|
44 | } | |
| 45 |
|
45 | |||
| 46 | project(':consumer') { |
|
46 | project(':consumer') { | |
| 47 | configurations { |
|
47 | configurations { | |
| 48 | compileView { |
|
48 | compileView { | |
| 49 | canBeResolved = true |
|
49 | canBeResolved = true | |
| 50 | canBeConsumed = false |
|
50 | canBeConsumed = false | |
| 51 | canBeDeclared = true |
|
51 | canBeDeclared = true | |
| 52 | attributes { |
|
52 | attributes { | |
| 53 | attribute(variantAttr, 'browser') |
|
53 | attribute(variantAttr, 'browser') | |
| 54 | attribute(slotAttr, 'typesPackage') |
|
54 | attribute(slotAttr, 'typesPackage') | |
| 55 | } |
|
55 | } | |
| 56 | } |
|
56 | } | |
| 57 | } |
|
57 | } | |
| 58 |
|
58 | |||
| 59 | dependencies { |
|
59 | dependencies { | |
| 60 | compileView project(':producer') |
|
60 | compileView project(':producer') | |
| 61 | } |
|
61 | } | |
| 62 |
|
62 | |||
| 63 | tasks.register('probe') { |
|
63 | tasks.register('probe') { | |
| 64 | doLast { |
|
64 | doLast { | |
| 65 | println('reference: resolving primary files') |
|
65 | println('reference: resolving primary files') | |
| 66 |
|
66 | |||
| 67 | def compileFiles = configurations.compileView.files.collect { it.name }.sort().join(',') |
|
67 | def compileFiles = configurations.compileView.files.collect { it.name }.sort().join(',') | |
| 68 |
|
68 | |||
| 69 | println('reference: resolving secondary files') |
|
69 | println('reference: resolving secondary files') | |
| 70 |
|
70 | |||
| 71 | def jsFiles = configurations.compileView.incoming.artifactView { |
|
71 | def jsFiles = configurations.compileView.incoming.artifactView { | |
| 72 | attributes { |
|
72 | attributes { | |
| 73 | attribute(slotAttr, 'js') |
|
73 | attribute(slotAttr, 'js') | |
| 74 | } |
|
74 | } | |
| 75 | }.files.files.collect { it.name }.sort().join(',') |
|
75 | }.files.files.collect { it.name }.sort().join(',') | |
| 76 |
|
76 | |||
| 77 | println('compileFiles=' + compileFiles) |
|
77 | println('compileFiles=' + compileFiles) | |
| 78 | println('jsFiles=' + jsFiles) |
|
78 | println('jsFiles=' + jsFiles) | |
| 79 | } |
|
79 | } | |
| 80 | } |
|
80 | } | |
| 81 | } |
|
81 | } | |
| 82 | """); |
|
82 | """); | |
| 83 |
|
83 | |||
| 84 | BuildResult result = runner(":consumer:probe").build(); |
|
84 | BuildResult result = runner(":consumer:probe").build(); | |
| 85 | var output = result.getOutput(); |
|
85 | var output = result.getOutput(); | |
| 86 | var registered = output.indexOf("reference: registered browserElements provider"); |
|
86 | var registered = output.indexOf("reference: registered browserElements provider"); | |
| 87 | var resolvingPrimary = output.indexOf("reference: resolving primary files"); |
|
87 | var resolvingPrimary = output.indexOf("reference: resolving primary files"); | |
| 88 | var configuring = output.indexOf("reference: configuring browserElements"); |
|
88 | var configuring = output.indexOf("reference: configuring browserElements"); | |
| 89 | var creatingSecondary = output.indexOf("reference: creating js outgoing variant"); |
|
89 | var creatingSecondary = output.indexOf("reference: creating js outgoing variant"); | |
| 90 | var resolvingSecondary = output.indexOf("reference: resolving secondary files"); |
|
90 | var resolvingSecondary = output.indexOf("reference: resolving secondary files"); | |
| 91 |
|
91 | |||
| 92 | assertTrue(registered >= 0); |
|
92 | assertTrue(registered >= 0); | |
| 93 | assertTrue(resolvingPrimary >= 0); |
|
93 | assertTrue(resolvingPrimary >= 0); | |
| 94 | assertTrue(configuring >= 0); |
|
94 | assertTrue(configuring >= 0); | |
| 95 | assertTrue(creatingSecondary >= 0); |
|
95 | assertTrue(creatingSecondary >= 0); | |
| 96 | assertTrue(resolvingSecondary >= 0); |
|
96 | assertTrue(resolvingSecondary >= 0); | |
| 97 | assertTrue(registered < resolvingPrimary); |
|
97 | assertTrue(registered < resolvingPrimary); | |
| 98 | assertTrue(resolvingPrimary < configuring); |
|
98 | assertTrue(resolvingPrimary < configuring); | |
| 99 | assertTrue(configuring < creatingSecondary); |
|
99 | assertTrue(configuring < creatingSecondary); | |
| 100 | assertTrue(creatingSecondary < resolvingSecondary); |
|
100 | assertTrue(creatingSecondary < resolvingSecondary); | |
| 101 | assertTrue(output.contains("compileFiles=typesPackage")); |
|
101 | assertTrue(output.contains("compileFiles=typesPackage")); | |
| 102 | assertTrue(output.contains("jsFiles=js")); |
|
102 | assertTrue(output.contains("jsFiles=js")); | |
| 103 | } |
|
103 | } | |
| 104 |
|
104 | |||
| 105 | @Test |
|
105 | @Test | |
| 106 |
void gradleReferenceRegisteredSecondaryArtifactVariant |
|
106 | void gradleReferenceRegisteredSecondaryArtifactVariantAllowsSecondaryArtifactSelection() throws Exception { | |
| 107 | // Gradle issue: https://github.com/gradle/gradle/issues/27441 |
|
|||
| 108 | // Registered outgoing artifact variants are not realized before dependency resolution. |
|
|||
| 109 | writeFile("settings.gradle", """ |
|
107 | writeFile("settings.gradle", """ | |
| 110 | rootProject.name = 'gradle-reference-registered-secondary-variant' |
|
108 | rootProject.name = 'gradle-reference-registered-secondary-variant' | |
| 111 | include 'producer', 'consumer' |
|
109 | include 'producer', 'consumer' | |
| 112 | """); |
|
110 | """); | |
| 113 | writeFile("producer/inputs/typesPackage", "types\n"); |
|
111 | writeFile("producer/inputs/typesPackage", "types\n"); | |
| 114 | writeFile("producer/inputs/js", "js\n"); |
|
112 | writeFile("producer/inputs/js", "js\n"); | |
| 115 | writeFile("build.gradle", """ |
|
113 | writeFile("build.gradle", """ | |
| 116 | import org.gradle.api.attributes.Attribute |
|
114 | import org.gradle.api.attributes.Attribute | |
| 117 |
|
115 | |||
| 118 | def variantAttr = Attribute.of('test.variant', String) |
|
116 | def variantAttr = Attribute.of('test.variant', String) | |
| 119 | def slotAttr = Attribute.of('test.slot', String) |
|
117 | def slotAttr = Attribute.of('test.slot', String) | |
| 120 |
|
118 | |||
| 121 | project(':producer') { |
|
119 | project(':producer') { | |
| 122 | def browserElements = configurations.consumable('browserElements') |
|
120 | def browserElements = configurations.consumable('browserElements') | |
| 123 |
|
121 | |||
| 124 | browserElements.configure { configuration -> |
|
122 | browserElements.configure { configuration -> | |
| 125 | configuration.attributes.attribute(variantAttr, 'browser') |
|
123 | configuration.attributes.attribute(variantAttr, 'browser') | |
| 126 | configuration.outgoing.attributes.attribute(slotAttr, 'typesPackage') |
|
124 | configuration.outgoing.attributes.attribute(slotAttr, 'typesPackage') | |
| 127 | configuration.outgoing.artifact(layout.projectDirectory.file('inputs/typesPackage')) |
|
125 | configuration.outgoing.artifact(layout.projectDirectory.file('inputs/typesPackage')) | |
| 128 |
|
126 | |||
| 129 | configuration.outgoing.variants.register('js') { secondary -> |
|
127 | configuration.outgoing.variants.register('js') { secondary -> | |
| 130 | secondary.attributes.attribute(slotAttr, 'js') |
|
128 | secondary.attributes.attribute(slotAttr, 'js') | |
| 131 | secondary.artifact(layout.projectDirectory.file('inputs/js')) |
|
129 | secondary.artifact(layout.projectDirectory.file('inputs/js')) | |
| 132 | } |
|
130 | } | |
| 133 | } |
|
131 | } | |
| 134 | } |
|
132 | } | |
| 135 |
|
133 | |||
| 136 | project(':consumer') { |
|
134 | project(':consumer') { | |
| 137 | configurations { |
|
135 | configurations { | |
| 138 | compileView { |
|
136 | compileView { | |
| 139 | canBeResolved = true |
|
137 | canBeResolved = true | |
| 140 | canBeConsumed = false |
|
138 | canBeConsumed = false | |
| 141 | canBeDeclared = true |
|
139 | canBeDeclared = true | |
| 142 | attributes { |
|
140 | attributes { | |
| 143 | attribute(variantAttr, 'browser') |
|
141 | attribute(variantAttr, 'browser') | |
| 144 | attribute(slotAttr, 'typesPackage') |
|
142 | attribute(slotAttr, 'typesPackage') | |
| 145 | } |
|
143 | } | |
| 146 | } |
|
144 | } | |
| 147 | } |
|
145 | } | |
| 148 |
|
146 | |||
| 149 | dependencies { |
|
147 | dependencies { | |
| 150 | compileView project(':producer') |
|
148 | compileView project(':producer') | |
| 151 | } |
|
149 | } | |
| 152 |
|
150 | |||
| 153 | tasks.register('probe') { |
|
151 | tasks.register('probe') { | |
| 154 | doLast { |
|
152 | doLast { | |
| 155 | def compileFiles = configurations.compileView.files.collect { it.name }.sort().join(',') |
|
153 | def compileFiles = configurations.compileView.files.collect { it.name }.sort().join(',') | |
| 156 | def jsFiles = configurations.compileView.incoming.artifactView { |
|
154 | def jsFiles = configurations.compileView.incoming.artifactView { | |
| 157 | attributes { |
|
155 | attributes { | |
| 158 | attribute(slotAttr, 'js') |
|
156 | attribute(slotAttr, 'js') | |
| 159 | } |
|
157 | } | |
| 160 | }.files.files.collect { it.name }.sort().join(',') |
|
158 | }.files.files.collect { it.name }.sort().join(',') | |
| 161 |
|
159 | |||
| 162 | println('compileFiles=' + compileFiles) |
|
160 | println('compileFiles=' + compileFiles) | |
| 163 | println('jsFiles=' + jsFiles) |
|
161 | println('jsFiles=' + jsFiles) | |
| 164 | } |
|
162 | } | |
| 165 | } |
|
163 | } | |
| 166 | } |
|
164 | } | |
| 167 | """); |
|
165 | """); | |
| 168 |
|
166 | |||
| 169 | assertBuildFails("Cannot create variant 'js' after dependency configuration ':producer:browserElements' has been resolved", |
|
167 | BuildResult result = runner(":consumer:probe").build(); | |
| 170 | ":consumer:probe"); |
|
168 | ||
|
|
169 | assertTrue(result.getOutput().contains("compileFiles=typesPackage")); | |||
|
|
170 | assertTrue(result.getOutput().contains("jsFiles=js")); | |||
| 171 | } |
|
171 | } | |
| 172 |
|
172 | |||
| 173 | @Test |
|
173 | @Test | |
| 174 | void materializesPrimaryAndSecondarySlotsAndInvokesOutgoingHooks() throws Exception { |
|
174 | void materializesPrimaryAndSecondarySlotsAndInvokesOutgoingHooks() throws Exception { | |
| 175 | writeSettings("variant-artifacts-slots"); |
|
175 | writeSettings("variant-artifacts-slots"); | |
| 176 | writeFile("inputs/base.js", "console.log('base')\n"); |
|
176 | writeFile("inputs/base.js", "console.log('base')\n"); | |
| 177 | writeFile("inputs/amd.js", "console.log('amd')\n"); |
|
177 | writeFile("inputs/amd.js", "console.log('amd')\n"); | |
| 178 | writeFile("inputs/mainJs.txt", "mainJs marker\n"); |
|
178 | writeFile("inputs/mainJs.txt", "mainJs marker\n"); | |
| 179 | writeFile("inputs/amdJs.txt", "amdJs marker\n"); |
|
179 | writeFile("inputs/amdJs.txt", "amdJs marker\n"); | |
| 180 | writeBuildFile(""" |
|
180 | writeBuildFile(""" | |
| 181 | import org.gradle.api.attributes.Attribute |
|
181 | import org.gradle.api.attributes.Attribute | |
| 182 |
|
182 | |||
| 183 | apply plugin: org.implab.gradle.variants.VariantArtifactsPlugin |
|
183 | apply plugin: org.implab.gradle.variants.VariantArtifactsPlugin | |
| 184 |
|
184 | |||
| 185 | def variantAttr = Attribute.of('test.variant', String) |
|
185 | def variantAttr = Attribute.of('test.variant', String) | |
| 186 | def slotAttr = Attribute.of('test.slot', String) |
|
186 | def slotAttr = Attribute.of('test.slot', String) | |
| 187 |
|
187 | |||
| 188 | variants.layers.create('mainBase') |
|
188 | variants.layers.create('mainBase') | |
| 189 | variants.layers.create('mainAmd') |
|
189 | variants.layers.create('mainAmd') | |
| 190 | variants.roles.create('main') |
|
190 | variants.roles.create('main') | |
| 191 | variants.roles.create('test') |
|
191 | variants.roles.create('test') | |
| 192 | variants.variant('browser') { |
|
192 | variants.variant('browser') { | |
| 193 | role('main') { |
|
193 | role('main') { | |
| 194 | layers('mainBase', 'mainAmd') |
|
194 | layers('mainBase', 'mainAmd') | |
| 195 | } |
|
195 | } | |
| 196 | } |
|
196 | } | |
| 197 |
|
197 | |||
| 198 | variantSources { |
|
198 | variantSources { | |
| 199 | layer('mainBase') { |
|
199 | layer('mainBase') { | |
| 200 | sourceSet { |
|
200 | sourceSet { | |
| 201 | declareOutputs('js') |
|
201 | declareOutputs('js') | |
| 202 | registerOutput('js', layout.projectDirectory.file('inputs/base.js')) |
|
202 | registerOutput('js', layout.projectDirectory.file('inputs/base.js')) | |
| 203 | } |
|
203 | } | |
| 204 | } |
|
204 | } | |
| 205 | layer('mainAmd') { |
|
205 | layer('mainAmd') { | |
| 206 | sourceSet { |
|
206 | sourceSet { | |
| 207 | declareOutputs('js') |
|
207 | declareOutputs('js') | |
| 208 | registerOutput('js', layout.projectDirectory.file('inputs/amd.js')) |
|
208 | registerOutput('js', layout.projectDirectory.file('inputs/amd.js')) | |
| 209 | } |
|
209 | } | |
| 210 | } |
|
210 | } | |
| 211 | } |
|
211 | } | |
| 212 |
|
212 | |||
| 213 | variantArtifacts { |
|
213 | variantArtifacts { | |
| 214 | variant('browser') { |
|
214 | variant('browser') { | |
| 215 | primarySlot('mainJs') { |
|
215 | primarySlot('mainJs') { | |
| 216 | fromRole('main') { |
|
216 | fromRole('main') { | |
| 217 | output('js') |
|
217 | output('js') | |
| 218 | } |
|
218 | } | |
| 219 | from(layout.projectDirectory.file('inputs/mainJs.txt')) |
|
219 | from(layout.projectDirectory.file('inputs/mainJs.txt')) | |
| 220 | } |
|
220 | } | |
| 221 | slot('amdJs') { |
|
221 | slot('amdJs') { | |
| 222 | fromLayer('mainAmd') { |
|
222 | fromLayer('mainAmd') { | |
| 223 | output('js') |
|
223 | output('js') | |
| 224 | } |
|
224 | } | |
| 225 | from(layout.projectDirectory.file('inputs/amdJs.txt')) |
|
225 | from(layout.projectDirectory.file('inputs/amdJs.txt')) | |
| 226 | } |
|
226 | } | |
| 227 | } |
|
227 | } | |
| 228 |
|
228 | |||
| 229 | whenOutgoingConfiguration { publication -> |
|
229 | whenOutgoingConfiguration { publication -> | |
| 230 | publication.configuration { |
|
230 | publication.configuration { | |
| 231 | attributes.attribute(variantAttr, publication.variant.name) |
|
231 | attributes.attribute(variantAttr, publication.variant.name) | |
| 232 | } |
|
232 | } | |
| 233 | } |
|
233 | } | |
| 234 |
|
234 | |||
| 235 | whenOutgoingSlot { publication -> |
|
235 | whenOutgoingSlot { publication -> | |
| 236 | def slotName = publication.artifactSlot.slot.name |
|
236 | def slotName = publication.artifactSlot.slot.name | |
| 237 | publication.artifactAttributes { |
|
237 | publication.artifactAttributes { | |
| 238 | attribute(slotAttr, slotName) |
|
238 | attribute(slotAttr, slotName) | |
| 239 | } |
|
239 | } | |
| 240 | } |
|
240 | } | |
| 241 | } |
|
241 | } | |
| 242 |
|
242 | |||
| 243 | tasks.register('probe') { |
|
243 | tasks.register('probe') { | |
| 244 | dependsOn 'assembleVariantArtifactSlot_v7_browser_s6_mainJs' |
|
244 | dependsOn 'assembleVariantArtifactSlot_v7_browser_s6_mainJs' | |
| 245 | dependsOn 'assembleVariantArtifactSlot_v7_browser_s5_amdJs' |
|
245 | dependsOn 'assembleVariantArtifactSlot_v7_browser_s5_amdJs' | |
| 246 |
|
246 | |||
| 247 | doLast { |
|
247 | doLast { | |
| 248 | def mainDir = layout.buildDirectory.dir('variant-assemblies/browser/mainJs').get().asFile |
|
248 | def mainDir = layout.buildDirectory.dir('variant-assemblies/browser/mainJs').get().asFile | |
| 249 | def amdDir = layout.buildDirectory.dir('variant-assemblies/browser/amdJs').get().asFile |
|
249 | def amdDir = layout.buildDirectory.dir('variant-assemblies/browser/amdJs').get().asFile | |
| 250 |
|
250 | |||
| 251 | assert new File(mainDir, 'base.js').exists() |
|
251 | assert new File(mainDir, 'base.js').exists() | |
| 252 | assert new File(mainDir, 'amd.js').exists() |
|
252 | assert new File(mainDir, 'amd.js').exists() | |
| 253 | assert new File(mainDir, 'mainJs.txt').exists() |
|
253 | assert new File(mainDir, 'mainJs.txt').exists() | |
| 254 |
|
254 | |||
| 255 | assert !new File(amdDir, 'base.js').exists() |
|
255 | assert !new File(amdDir, 'base.js').exists() | |
| 256 | assert new File(amdDir, 'amd.js').exists() |
|
256 | assert new File(amdDir, 'amd.js').exists() | |
| 257 | assert new File(amdDir, 'amdJs.txt').exists() |
|
257 | assert new File(amdDir, 'amdJs.txt').exists() | |
| 258 |
|
258 | |||
| 259 | def elements = configurations.getByName('browserElements') |
|
259 | def elements = configurations.getByName('browserElements') | |
| 260 | def amdVariant = elements.outgoing.variants.getByName('amdJs') |
|
260 | def amdVariant = elements.outgoing.variants.getByName('amdJs') | |
| 261 |
|
261 | |||
| 262 | println('variantAttr=' + elements.attributes.getAttribute(variantAttr)) |
|
262 | println('variantAttr=' + elements.attributes.getAttribute(variantAttr)) | |
| 263 | println('primarySlotAttr=' + elements.outgoing.attributes.getAttribute(slotAttr)) |
|
263 | println('primarySlotAttr=' + elements.outgoing.attributes.getAttribute(slotAttr)) | |
| 264 | println('amdSlotAttr=' + amdVariant.attributes.getAttribute(slotAttr)) |
|
264 | println('amdSlotAttr=' + amdVariant.attributes.getAttribute(slotAttr)) | |
| 265 | println('configurations=' + configurations.matching { it.name == 'browserElements' }.collect { it.name }.join(',')) |
|
265 | println('configurations=' + configurations.matching { it.name == 'browserElements' }.collect { it.name }.join(',')) | |
| 266 | println('secondaryVariants=' + elements.outgoing.variants.collect { it.name }.sort().join(',')) |
|
266 | println('secondaryVariants=' + elements.outgoing.variants.collect { it.name }.sort().join(',')) | |
| 267 | } |
|
267 | } | |
| 268 | } |
|
268 | } | |
| 269 | """); |
|
269 | """); | |
| 270 |
|
270 | |||
| 271 | BuildResult result = runner("probe").build(); |
|
271 | BuildResult result = runner("probe").build(); | |
| 272 |
|
272 | |||
| 273 | assertTrue(result.getOutput().contains("variantAttr=browser")); |
|
273 | assertTrue(result.getOutput().contains("variantAttr=browser")); | |
| 274 | assertTrue(result.getOutput().contains("primarySlotAttr=mainJs")); |
|
274 | assertTrue(result.getOutput().contains("primarySlotAttr=mainJs")); | |
| 275 | assertTrue(result.getOutput().contains("amdSlotAttr=amdJs")); |
|
275 | assertTrue(result.getOutput().contains("amdSlotAttr=amdJs")); | |
| 276 | assertTrue(result.getOutput().contains("configurations=browserElements")); |
|
276 | assertTrue(result.getOutput().contains("configurations=browserElements")); | |
| 277 | assertTrue(result.getOutput().contains("secondaryVariants=amdJs")); |
|
277 | assertTrue(result.getOutput().contains("secondaryVariants=amdJs")); | |
| 278 | assertTrue(result.task(":probe").getOutcome() == TaskOutcome.SUCCESS); |
|
278 | assertTrue(result.task(":probe").getOutcome() == TaskOutcome.SUCCESS); | |
| 279 | } |
|
279 | } | |
| 280 |
|
280 | |||
| 281 | @Test |
|
281 | @Test | |
| 282 | void outgoingSlotHookFollowsMaterializedGradleArtifactVariants() throws Exception { |
|
282 | void outgoingSlotHookFollowsMaterializedGradleArtifactVariants() throws Exception { | |
| 283 | writeSettings("variant-artifacts-materialized-gradle-variant"); |
|
283 | writeSettings("variant-artifacts-materialized-gradle-variant"); | |
| 284 | writeFile("inputs/typesPackage", "types\n"); |
|
284 | writeFile("inputs/typesPackage", "types\n"); | |
| 285 | writeFile("inputs/js", "js\n"); |
|
285 | writeFile("inputs/js", "js\n"); | |
| 286 | writeBuildFile(""" |
|
286 | writeBuildFile(""" | |
| 287 | import org.gradle.api.attributes.Attribute |
|
287 | import org.gradle.api.attributes.Attribute | |
| 288 |
|
288 | |||
| 289 | apply plugin: org.implab.gradle.variants.VariantArtifactsPlugin |
|
289 | apply plugin: org.implab.gradle.variants.VariantArtifactsPlugin | |
| 290 |
|
290 | |||
| 291 | def slotAttr = Attribute.of('test.slot', String) |
|
291 | def slotAttr = Attribute.of('test.slot', String) | |
| 292 |
|
292 | |||
| 293 | variants.layers.create('main') |
|
293 | variants.layers.create('main') | |
| 294 | variants.roles.create('main') |
|
294 | variants.roles.create('main') | |
| 295 | variants.variant('browser') { |
|
295 | variants.variant('browser') { | |
| 296 | role('main') { |
|
296 | role('main') { | |
| 297 | layers('main') |
|
297 | layers('main') | |
| 298 | } |
|
298 | } | |
| 299 | } |
|
299 | } | |
| 300 |
|
300 | |||
| 301 | variantArtifacts { |
|
301 | variantArtifacts { | |
| 302 | variant('browser') { |
|
302 | variant('browser') { | |
| 303 | primarySlot('typesPackage') { |
|
303 | primarySlot('typesPackage') { | |
| 304 | from(layout.projectDirectory.file('inputs/typesPackage')) |
|
304 | from(layout.projectDirectory.file('inputs/typesPackage')) | |
| 305 | } |
|
305 | } | |
| 306 | } |
|
306 | } | |
| 307 |
|
307 | |||
| 308 | whenOutgoingConfiguration { publication -> |
|
308 | whenOutgoingConfiguration { publication -> | |
| 309 | publication.configuration { |
|
309 | publication.configuration { | |
| 310 | outgoing.variants.create('js') { secondary -> |
|
310 | outgoing.variants.create('js') { secondary -> | |
| 311 | secondary.artifact(layout.projectDirectory.file('inputs/js')) |
|
311 | secondary.artifact(layout.projectDirectory.file('inputs/js')) | |
| 312 | } |
|
312 | } | |
| 313 | } |
|
313 | } | |
| 314 | } |
|
314 | } | |
| 315 |
|
315 | |||
| 316 | whenOutgoingSlot { publication -> |
|
316 | whenOutgoingSlot { publication -> | |
| 317 | publication.artifactAttributes { |
|
317 | publication.artifactAttributes { | |
| 318 | attribute(slotAttr, publication.artifactSlot.slot.name) |
|
318 | attribute(slotAttr, publication.artifactSlot.slot.name) | |
| 319 | } |
|
319 | } | |
| 320 | } |
|
320 | } | |
| 321 | } |
|
321 | } | |
| 322 |
|
322 | |||
| 323 | tasks.register('probe') { |
|
323 | tasks.register('probe') { | |
| 324 | doLast { |
|
324 | doLast { | |
| 325 | def elements = configurations.getByName('browserElements') |
|
325 | def elements = configurations.getByName('browserElements') | |
| 326 | def jsVariant = elements.outgoing.variants.getByName('js') |
|
326 | def jsVariant = elements.outgoing.variants.getByName('js') | |
| 327 |
|
327 | |||
| 328 | println('primarySlotAttr=' + elements.outgoing.attributes.getAttribute(slotAttr)) |
|
328 | println('primarySlotAttr=' + elements.outgoing.attributes.getAttribute(slotAttr)) | |
| 329 | println('jsSlotAttr=' + jsVariant.attributes.getAttribute(slotAttr)) |
|
329 | println('jsSlotAttr=' + jsVariant.attributes.getAttribute(slotAttr)) | |
| 330 | } |
|
330 | } | |
| 331 | } |
|
331 | } | |
| 332 | """); |
|
332 | """); | |
| 333 |
|
333 | |||
| 334 | BuildResult result = runner("probe").build(); |
|
334 | BuildResult result = runner("probe").build(); | |
| 335 |
|
335 | |||
| 336 | assertTrue(result.getOutput().contains("primarySlotAttr=typesPackage")); |
|
336 | assertTrue(result.getOutput().contains("primarySlotAttr=typesPackage")); | |
| 337 | assertTrue(result.getOutput().contains("jsSlotAttr=js")); |
|
337 | assertTrue(result.getOutput().contains("jsSlotAttr=js")); | |
| 338 | assertTrue(result.task(":probe").getOutcome() == TaskOutcome.SUCCESS); |
|
338 | assertTrue(result.task(":probe").getOutcome() == TaskOutcome.SUCCESS); | |
| 339 | } |
|
339 | } | |
| 340 |
|
340 | |||
| 341 | @Test |
|
341 | @Test | |
| 342 | void allowsSingleSlotVariantWithoutExplicitPrimarySlot() throws Exception { |
|
342 | void allowsSingleSlotVariantWithoutExplicitPrimarySlot() throws Exception { | |
| 343 | writeSettings("variant-artifacts-single-slot"); |
|
343 | writeSettings("variant-artifacts-single-slot"); | |
| 344 | writeBuildFile(""" |
|
344 | writeBuildFile(""" | |
| 345 | apply plugin: org.implab.gradle.variants.VariantArtifactsPlugin |
|
345 | apply plugin: org.implab.gradle.variants.VariantArtifactsPlugin | |
| 346 |
|
346 | |||
| 347 | variants.layers.create('main') |
|
347 | variants.layers.create('main') | |
| 348 | variants.roles.create('main') |
|
348 | variants.roles.create('main') | |
| 349 | variants.variant('browser') { |
|
349 | variants.variant('browser') { | |
| 350 | role('main') { |
|
350 | role('main') { | |
| 351 | layers('main') |
|
351 | layers('main') | |
| 352 | } |
|
352 | } | |
| 353 | } |
|
353 | } | |
| 354 |
|
354 | |||
| 355 | variantSources.layer('main') { |
|
355 | variantSources.layer('main') { | |
| 356 | sourceSet { |
|
356 | sourceSet { | |
| 357 | declareOutputs('types') |
|
357 | declareOutputs('types') | |
| 358 | } |
|
358 | } | |
| 359 | } |
|
359 | } | |
| 360 |
|
360 | |||
| 361 | variantArtifacts { |
|
361 | variantArtifacts { | |
| 362 | variant('browser') { |
|
362 | variant('browser') { | |
| 363 | slot('typesPackage') { |
|
363 | slot('typesPackage') { | |
| 364 | fromVariant { |
|
364 | fromVariant { | |
| 365 | output('types') |
|
365 | output('types') | |
| 366 | } |
|
366 | } | |
| 367 | } |
|
367 | } | |
| 368 | } |
|
368 | } | |
| 369 | } |
|
369 | } | |
| 370 |
|
370 | |||
| 371 | tasks.register('probe') { |
|
371 | tasks.register('probe') { | |
| 372 | doLast { |
|
372 | doLast { | |
| 373 | variantArtifacts.whenAvailable { ctx -> |
|
373 | variantArtifacts.whenAvailable { ctx -> | |
| 374 | def browser = objects.named(org.implab.gradle.variants.core.Variant, 'browser') |
|
374 | def browser = objects.named(org.implab.gradle.variants.core.Variant, 'browser') | |
| 375 | println('primary=' + ctx.findOutgoing(browser).get().primarySlot.get().name) |
|
375 | println('primary=' + ctx.findOutgoing(browser).get().primarySlot.get().name) | |
| 376 | } |
|
376 | } | |
| 377 | } |
|
377 | } | |
| 378 | } |
|
378 | } | |
| 379 | """); |
|
379 | """); | |
| 380 |
|
380 | |||
| 381 | BuildResult result = runner("probe").build(); |
|
381 | BuildResult result = runner("probe").build(); | |
| 382 |
|
382 | |||
| 383 | assertTrue(result.getOutput().contains("primary=typesPackage")); |
|
383 | assertTrue(result.getOutput().contains("primary=typesPackage")); | |
| 384 | } |
|
384 | } | |
| 385 |
|
385 | |||
| 386 | @Test |
|
386 | @Test | |
| 387 | void materializesDirectSlotInputsWithoutVariantSourceBindings() throws Exception { |
|
387 | void materializesDirectSlotInputsWithoutVariantSourceBindings() throws Exception { | |
| 388 | writeSettings("variant-artifacts-direct-input"); |
|
388 | writeSettings("variant-artifacts-direct-input"); | |
| 389 | writeFile("inputs/bundle.js", "console.log('bundle')\n"); |
|
389 | writeFile("inputs/bundle.js", "console.log('bundle')\n"); | |
| 390 | writeBuildFile(""" |
|
390 | writeBuildFile(""" | |
| 391 | apply plugin: org.implab.gradle.variants.VariantArtifactsPlugin |
|
391 | apply plugin: org.implab.gradle.variants.VariantArtifactsPlugin | |
| 392 |
|
392 | |||
| 393 | variants.layers.create('main') |
|
393 | variants.layers.create('main') | |
| 394 | variants.roles.create('main') |
|
394 | variants.roles.create('main') | |
| 395 | variants.variant('browser') { |
|
395 | variants.variant('browser') { | |
| 396 | role('main') { |
|
396 | role('main') { | |
| 397 | layers('main') |
|
397 | layers('main') | |
| 398 | } |
|
398 | } | |
| 399 | } |
|
399 | } | |
| 400 |
|
400 | |||
| 401 | variantArtifacts { |
|
401 | variantArtifacts { | |
| 402 | variant('browser') { |
|
402 | variant('browser') { | |
| 403 | primarySlot('bundle') { |
|
403 | primarySlot('bundle') { | |
| 404 | from(layout.projectDirectory.file('inputs/bundle.js')) |
|
404 | from(layout.projectDirectory.file('inputs/bundle.js')) | |
| 405 | } |
|
405 | } | |
| 406 | } |
|
406 | } | |
| 407 | } |
|
407 | } | |
| 408 |
|
408 | |||
| 409 | tasks.register('probe') { |
|
409 | tasks.register('probe') { | |
| 410 | dependsOn 'assembleVariantArtifactSlot_v7_browser_s6_bundle' |
|
410 | dependsOn 'assembleVariantArtifactSlot_v7_browser_s6_bundle' | |
| 411 |
|
411 | |||
| 412 | doLast { |
|
412 | doLast { | |
| 413 | def bundleDir = layout.buildDirectory.dir('variant-assemblies/browser/bundle').get().asFile |
|
413 | def bundleDir = layout.buildDirectory.dir('variant-assemblies/browser/bundle').get().asFile | |
| 414 | assert new File(bundleDir, 'bundle.js').exists() |
|
414 | assert new File(bundleDir, 'bundle.js').exists() | |
| 415 | } |
|
415 | } | |
| 416 | } |
|
416 | } | |
| 417 | """); |
|
417 | """); | |
| 418 |
|
418 | |||
| 419 | BuildResult result = runner("probe").build(); |
|
419 | BuildResult result = runner("probe").build(); | |
| 420 |
|
420 | |||
| 421 | assertTrue(result.task(":probe").getOutcome() == TaskOutcome.SUCCESS); |
|
421 | assertTrue(result.task(":probe").getOutcome() == TaskOutcome.SUCCESS); | |
| 422 | } |
|
422 | } | |
| 423 |
|
423 | |||
| 424 | @Test |
|
424 | @Test | |
| 425 | void publishesTaskProducedFileArtifactDirectly() throws Exception { |
|
425 | void publishesTaskProducedFileArtifactDirectly() throws Exception { | |
| 426 | writeFile("settings.gradle", """ |
|
426 | writeFile("settings.gradle", """ | |
| 427 | rootProject.name = 'variant-artifacts-task-produced-file' |
|
427 | rootProject.name = 'variant-artifacts-task-produced-file' | |
| 428 | include 'producer', 'consumer' |
|
428 | include 'producer', 'consumer' | |
| 429 | """); |
|
429 | """); | |
| 430 | writeBuildFile(""" |
|
430 | writeBuildFile(""" | |
| 431 | import org.gradle.api.DefaultTask |
|
431 | import org.gradle.api.DefaultTask | |
| 432 | import org.gradle.api.attributes.Attribute |
|
432 | import org.gradle.api.attributes.Attribute | |
| 433 | import org.gradle.api.file.RegularFileProperty |
|
433 | import org.gradle.api.file.RegularFileProperty | |
| 434 | import org.gradle.api.tasks.OutputFile |
|
434 | import org.gradle.api.tasks.OutputFile | |
| 435 | import org.gradle.api.tasks.TaskAction |
|
435 | import org.gradle.api.tasks.TaskAction | |
| 436 |
|
436 | |||
| 437 | def variantAttr = Attribute.of('test.variant', String) |
|
437 | def variantAttr = Attribute.of('test.variant', String) | |
| 438 | def slotAttr = Attribute.of('test.slot', String) |
|
438 | def slotAttr = Attribute.of('test.slot', String) | |
| 439 |
|
439 | |||
| 440 | abstract class WritePackageMetadata extends DefaultTask { |
|
440 | abstract class WritePackageMetadata extends DefaultTask { | |
| 441 | @OutputFile |
|
441 | @OutputFile | |
| 442 | abstract RegularFileProperty getOutputFile() |
|
442 | abstract RegularFileProperty getOutputFile() | |
| 443 |
|
443 | |||
| 444 | @TaskAction |
|
444 | @TaskAction | |
| 445 | void write() { |
|
445 | void write() { | |
| 446 | def file = outputFile.get().asFile |
|
446 | def file = outputFile.get().asFile | |
| 447 | file.parentFile.mkdirs() |
|
447 | file.parentFile.mkdirs() | |
| 448 | file.text = '{"name":"demo"}\\n' |
|
448 | file.text = '{"name":"demo"}\\n' | |
| 449 | } |
|
449 | } | |
| 450 | } |
|
450 | } | |
| 451 |
|
451 | |||
| 452 | project(':producer') { |
|
452 | project(':producer') { | |
| 453 | apply plugin: org.implab.gradle.variants.VariantArtifactsPlugin |
|
453 | apply plugin: org.implab.gradle.variants.VariantArtifactsPlugin | |
| 454 |
|
454 | |||
| 455 | variants.layers.create('main') |
|
455 | variants.layers.create('main') | |
| 456 | variants.roles.create('main') |
|
456 | variants.roles.create('main') | |
| 457 | variants.variant('browser') { |
|
457 | variants.variant('browser') { | |
| 458 | role('main') { |
|
458 | role('main') { | |
| 459 | layers('main') |
|
459 | layers('main') | |
| 460 | } |
|
460 | } | |
| 461 | } |
|
461 | } | |
| 462 |
|
462 | |||
| 463 | def writePackageMetadata = tasks.register('writePackageMetadata', WritePackageMetadata) { |
|
463 | def writePackageMetadata = tasks.register('writePackageMetadata', WritePackageMetadata) { | |
| 464 | outputFile.set(layout.buildDirectory.file('generated/package.json')) |
|
464 | outputFile.set(layout.buildDirectory.file('generated/package.json')) | |
| 465 | } |
|
465 | } | |
| 466 |
|
466 | |||
| 467 | variantArtifacts { |
|
467 | variantArtifacts { | |
| 468 | variant('browser') { |
|
468 | variant('browser') { | |
| 469 | primarySlot('packageMetadata') { |
|
469 | primarySlot('packageMetadata') { | |
| 470 | producedBy(writePackageMetadata) { |
|
470 | producedBy(writePackageMetadata) { | |
| 471 | outputFile |
|
471 | outputFile | |
| 472 | } |
|
472 | } | |
| 473 | } |
|
473 | } | |
| 474 | } |
|
474 | } | |
| 475 |
|
475 | |||
| 476 | whenOutgoingConfiguration { publication -> |
|
476 | whenOutgoingConfiguration { publication -> | |
| 477 | publication.configuration { |
|
477 | publication.configuration { | |
| 478 | attributes.attribute(variantAttr, publication.variant.name) |
|
478 | attributes.attribute(variantAttr, publication.variant.name) | |
| 479 | } |
|
479 | } | |
| 480 | } |
|
480 | } | |
| 481 |
|
481 | |||
| 482 | whenOutgoingSlot { publication -> |
|
482 | whenOutgoingSlot { publication -> | |
| 483 | publication.artifactAttributes { |
|
483 | publication.artifactAttributes { | |
| 484 | attribute(slotAttr, publication.artifactSlot.slot.name) |
|
484 | attribute(slotAttr, publication.artifactSlot.slot.name) | |
| 485 | } |
|
485 | } | |
| 486 | } |
|
486 | } | |
| 487 | } |
|
487 | } | |
| 488 |
|
488 | |||
| 489 | tasks.register('checkNoManagedAssembly') { |
|
489 | tasks.register('checkNoManagedAssembly') { | |
| 490 | doLast { |
|
490 | doLast { | |
| 491 | def assemblyTasks = tasks.names |
|
491 | def assemblyTasks = tasks.names | |
| 492 | .findAll { it.startsWith('assembleVariantArtifactSlot') } |
|
492 | .findAll { it.startsWith('assembleVariantArtifactSlot') } | |
| 493 | .sort() |
|
493 | .sort() | |
| 494 | println('producerAssemblyTasks=' + assemblyTasks.join(',')) |
|
494 | println('producerAssemblyTasks=' + assemblyTasks.join(',')) | |
| 495 | assert assemblyTasks.empty |
|
495 | assert assemblyTasks.empty | |
| 496 | } |
|
496 | } | |
| 497 | } |
|
497 | } | |
| 498 | } |
|
498 | } | |
| 499 |
|
499 | |||
| 500 | project(':consumer') { |
|
500 | project(':consumer') { | |
| 501 | configurations { |
|
501 | configurations { | |
| 502 | compileView { |
|
502 | compileView { | |
| 503 | canBeResolved = true |
|
503 | canBeResolved = true | |
| 504 | canBeConsumed = false |
|
504 | canBeConsumed = false | |
| 505 | canBeDeclared = true |
|
505 | canBeDeclared = true | |
| 506 | attributes { |
|
506 | attributes { | |
| 507 | attribute(variantAttr, 'browser') |
|
507 | attribute(variantAttr, 'browser') | |
| 508 | attribute(slotAttr, 'packageMetadata') |
|
508 | attribute(slotAttr, 'packageMetadata') | |
| 509 | } |
|
509 | } | |
| 510 | } |
|
510 | } | |
| 511 | } |
|
511 | } | |
| 512 |
|
512 | |||
| 513 | dependencies { |
|
513 | dependencies { | |
| 514 | compileView project(':producer') |
|
514 | compileView project(':producer') | |
| 515 | } |
|
515 | } | |
| 516 |
|
516 | |||
| 517 | tasks.register('probe') { |
|
517 | tasks.register('probe') { | |
| 518 | dependsOn configurations.compileView |
|
518 | dependsOn configurations.compileView | |
| 519 | dependsOn ':producer:checkNoManagedAssembly' |
|
519 | dependsOn ':producer:checkNoManagedAssembly' | |
| 520 |
|
520 | |||
| 521 | doLast { |
|
521 | doLast { | |
| 522 | def files = configurations.compileView.files |
|
522 | def files = configurations.compileView.files | |
| 523 | println('resolvedFiles=' + files.collect { it.name }.sort().join(',')) |
|
523 | println('resolvedFiles=' + files.collect { it.name }.sort().join(',')) | |
| 524 | println('metadata=' + files.iterator().next().text.trim()) |
|
524 | println('metadata=' + files.iterator().next().text.trim()) | |
| 525 | } |
|
525 | } | |
| 526 | } |
|
526 | } | |
| 527 | } |
|
527 | } | |
| 528 | """); |
|
528 | """); | |
| 529 |
|
529 | |||
| 530 | BuildResult result = runner(":consumer:probe").build(); |
|
530 | BuildResult result = runner(":consumer:probe").build(); | |
| 531 |
|
531 | |||
| 532 | assertTrue(result.getOutput().contains("producerAssemblyTasks=")); |
|
532 | assertTrue(result.getOutput().contains("producerAssemblyTasks=")); | |
| 533 | assertTrue(result.getOutput().contains("resolvedFiles=package.json")); |
|
533 | assertTrue(result.getOutput().contains("resolvedFiles=package.json")); | |
| 534 | assertTrue(result.getOutput().contains("metadata={\"name\":\"demo\"}")); |
|
534 | assertTrue(result.getOutput().contains("metadata={\"name\":\"demo\"}")); | |
| 535 | assertTrue(result.task(":producer:writePackageMetadata").getOutcome() == TaskOutcome.SUCCESS); |
|
535 | assertTrue(result.task(":producer:writePackageMetadata").getOutcome() == TaskOutcome.SUCCESS); | |
| 536 | assertTrue(result.task(":consumer:probe").getOutcome() == TaskOutcome.SUCCESS); |
|
536 | assertTrue(result.task(":consumer:probe").getOutcome() == TaskOutcome.SUCCESS); | |
| 537 | } |
|
537 | } | |
| 538 |
|
538 | |||
| 539 | @Test |
|
539 | @Test | |
| 540 | void failsWhenTaskProducedArtifactIsMixedWithContributionAssembly() throws Exception { |
|
540 | void failsWhenTaskProducedArtifactIsMixedWithContributionAssembly() throws Exception { | |
| 541 | writeSettings("variant-artifacts-mixed-assembly-mode"); |
|
541 | writeSettings("variant-artifacts-mixed-assembly-mode"); | |
| 542 | writeFile("inputs/marker.txt", "marker\n"); |
|
542 | writeFile("inputs/marker.txt", "marker\n"); | |
| 543 | writeBuildFile(""" |
|
543 | writeBuildFile(""" | |
| 544 | import org.gradle.api.DefaultTask |
|
544 | import org.gradle.api.DefaultTask | |
| 545 | import org.gradle.api.file.RegularFileProperty |
|
545 | import org.gradle.api.file.RegularFileProperty | |
| 546 | import org.gradle.api.tasks.OutputFile |
|
546 | import org.gradle.api.tasks.OutputFile | |
| 547 | import org.gradle.api.tasks.TaskAction |
|
547 | import org.gradle.api.tasks.TaskAction | |
| 548 |
|
548 | |||
| 549 | apply plugin: org.implab.gradle.variants.VariantArtifactsPlugin |
|
549 | apply plugin: org.implab.gradle.variants.VariantArtifactsPlugin | |
| 550 |
|
550 | |||
| 551 | abstract class WritePackageMetadata extends DefaultTask { |
|
551 | abstract class WritePackageMetadata extends DefaultTask { | |
| 552 | @OutputFile |
|
552 | @OutputFile | |
| 553 | abstract RegularFileProperty getOutputFile() |
|
553 | abstract RegularFileProperty getOutputFile() | |
| 554 |
|
554 | |||
| 555 | @TaskAction |
|
555 | @TaskAction | |
| 556 | void write() { |
|
556 | void write() { | |
| 557 | outputFile.get().asFile.text = '{}\\n' |
|
557 | outputFile.get().asFile.text = '{}\\n' | |
| 558 | } |
|
558 | } | |
| 559 | } |
|
559 | } | |
| 560 |
|
560 | |||
| 561 | variants.layers.create('main') |
|
561 | variants.layers.create('main') | |
| 562 | variants.roles.create('main') |
|
562 | variants.roles.create('main') | |
| 563 | variants.variant('browser') { |
|
563 | variants.variant('browser') { | |
| 564 | role('main') { |
|
564 | role('main') { | |
| 565 | layers('main') |
|
565 | layers('main') | |
| 566 | } |
|
566 | } | |
| 567 | } |
|
567 | } | |
| 568 |
|
568 | |||
| 569 | def writePackageMetadata = tasks.register('writePackageMetadata', WritePackageMetadata) { |
|
569 | def writePackageMetadata = tasks.register('writePackageMetadata', WritePackageMetadata) { | |
| 570 | outputFile.set(layout.buildDirectory.file('generated/package.json')) |
|
570 | outputFile.set(layout.buildDirectory.file('generated/package.json')) | |
| 571 | } |
|
571 | } | |
| 572 |
|
572 | |||
| 573 | variantArtifacts { |
|
573 | variantArtifacts { | |
| 574 | variant('browser') { |
|
574 | variant('browser') { | |
| 575 | primarySlot('packageMetadata') { |
|
575 | primarySlot('packageMetadata') { | |
| 576 | producedBy(writePackageMetadata) { |
|
576 | producedBy(writePackageMetadata) { | |
| 577 | outputFile |
|
577 | outputFile | |
| 578 | } |
|
578 | } | |
| 579 | from(layout.projectDirectory.file('inputs/marker.txt')) |
|
579 | from(layout.projectDirectory.file('inputs/marker.txt')) | |
| 580 | } |
|
580 | } | |
| 581 | } |
|
581 | } | |
| 582 | } |
|
582 | } | |
| 583 | """); |
|
583 | """); | |
| 584 |
|
584 | |||
| 585 | assertBuildFails("cannot mix task-produced artifact and contribution-based assembly", "help"); |
|
585 | assertBuildFails("cannot mix task-produced artifact and contribution-based assembly", "help"); | |
| 586 | } |
|
586 | } | |
| 587 |
|
587 | |||
| 588 | @Test |
|
588 | @Test | |
| 589 | void combinesDirectAndTopologyAwareSlotInputs() throws Exception { |
|
589 | void combinesDirectAndTopologyAwareSlotInputs() throws Exception { | |
| 590 | writeSettings("variant-artifacts-combined-inputs"); |
|
590 | writeSettings("variant-artifacts-combined-inputs"); | |
| 591 | writeFile("inputs/base.js", "console.log('base')\n"); |
|
591 | writeFile("inputs/base.js", "console.log('base')\n"); | |
| 592 | writeFile("inputs/marker.txt", "marker\n"); |
|
592 | writeFile("inputs/marker.txt", "marker\n"); | |
| 593 | writeBuildFile(""" |
|
593 | writeBuildFile(""" | |
| 594 | apply plugin: org.implab.gradle.variants.VariantArtifactsPlugin |
|
594 | apply plugin: org.implab.gradle.variants.VariantArtifactsPlugin | |
| 595 |
|
595 | |||
| 596 | variants.layers.create('main') |
|
596 | variants.layers.create('main') | |
| 597 | variants.roles.create('main') |
|
597 | variants.roles.create('main') | |
| 598 | variants.variant('browser') { |
|
598 | variants.variant('browser') { | |
| 599 | role('main') { |
|
599 | role('main') { | |
| 600 | layers('main') |
|
600 | layers('main') | |
| 601 | } |
|
601 | } | |
| 602 | } |
|
602 | } | |
| 603 |
|
603 | |||
| 604 | variantSources.layer('main') { |
|
604 | variantSources.layer('main') { | |
| 605 | sourceSet { |
|
605 | sourceSet { | |
| 606 | declareOutputs('js') |
|
606 | declareOutputs('js') | |
| 607 | registerOutput('js', layout.projectDirectory.file('inputs/base.js')) |
|
607 | registerOutput('js', layout.projectDirectory.file('inputs/base.js')) | |
| 608 | } |
|
608 | } | |
| 609 | } |
|
609 | } | |
| 610 |
|
610 | |||
| 611 | variantArtifacts { |
|
611 | variantArtifacts { | |
| 612 | variant('browser') { |
|
612 | variant('browser') { | |
| 613 | primarySlot('bundle') { |
|
613 | primarySlot('bundle') { | |
| 614 | fromVariant { |
|
614 | fromVariant { | |
| 615 | output('js') |
|
615 | output('js') | |
| 616 | } |
|
616 | } | |
| 617 | from(layout.projectDirectory.file('inputs/marker.txt')) |
|
617 | from(layout.projectDirectory.file('inputs/marker.txt')) | |
| 618 | } |
|
618 | } | |
| 619 | } |
|
619 | } | |
| 620 | } |
|
620 | } | |
| 621 |
|
621 | |||
| 622 | tasks.register('probe') { |
|
622 | tasks.register('probe') { | |
| 623 | dependsOn 'assembleVariantArtifactSlot_v7_browser_s6_bundle' |
|
623 | dependsOn 'assembleVariantArtifactSlot_v7_browser_s6_bundle' | |
| 624 |
|
624 | |||
| 625 | doLast { |
|
625 | doLast { | |
| 626 | def bundleDir = layout.buildDirectory.dir('variant-assemblies/browser/bundle').get().asFile |
|
626 | def bundleDir = layout.buildDirectory.dir('variant-assemblies/browser/bundle').get().asFile | |
| 627 | assert new File(bundleDir, 'base.js').exists() |
|
627 | assert new File(bundleDir, 'base.js').exists() | |
| 628 | assert new File(bundleDir, 'marker.txt').exists() |
|
628 | assert new File(bundleDir, 'marker.txt').exists() | |
| 629 | } |
|
629 | } | |
| 630 | } |
|
630 | } | |
| 631 | """); |
|
631 | """); | |
| 632 |
|
632 | |||
| 633 | BuildResult result = runner("probe").build(); |
|
633 | BuildResult result = runner("probe").build(); | |
| 634 |
|
634 | |||
| 635 | assertTrue(result.task(":probe").getOutcome() == TaskOutcome.SUCCESS); |
|
635 | assertTrue(result.task(":probe").getOutcome() == TaskOutcome.SUCCESS); | |
| 636 | } |
|
636 | } | |
| 637 |
|
637 | |||
| 638 | @Test |
|
638 | @Test | |
| 639 | void failsOnUnknownVariantReference() throws Exception { |
|
639 | void failsOnUnknownVariantReference() throws Exception { | |
| 640 | writeSettings("variant-artifacts-missing-variant"); |
|
640 | writeSettings("variant-artifacts-missing-variant"); | |
| 641 | writeBuildFile(""" |
|
641 | writeBuildFile(""" | |
| 642 | apply plugin: org.implab.gradle.variants.VariantArtifactsPlugin |
|
642 | apply plugin: org.implab.gradle.variants.VariantArtifactsPlugin | |
| 643 |
|
643 | |||
| 644 | variants.layers.create('main') |
|
644 | variants.layers.create('main') | |
| 645 |
|
645 | |||
| 646 | variantArtifacts { |
|
646 | variantArtifacts { | |
| 647 | variant('browser') { |
|
647 | variant('browser') { | |
| 648 | slot('mainJs') { |
|
648 | slot('mainJs') { | |
| 649 | fromVariant { |
|
649 | fromVariant { | |
| 650 | output('js') |
|
650 | output('js') | |
| 651 | } |
|
651 | } | |
| 652 | } |
|
652 | } | |
| 653 | } |
|
653 | } | |
| 654 | } |
|
654 | } | |
| 655 | """); |
|
655 | """); | |
| 656 |
|
656 | |||
| 657 | assertBuildFails("isn't declared", "help"); |
|
657 | assertBuildFails("isn't declared", "help"); | |
| 658 | } |
|
658 | } | |
| 659 |
|
659 | |||
| 660 | @Test |
|
660 | @Test | |
| 661 | void failsOnUnknownRoleReference() throws Exception { |
|
661 | void failsOnUnknownRoleReference() throws Exception { | |
| 662 | writeSettings("variant-artifacts-missing-role"); |
|
662 | writeSettings("variant-artifacts-missing-role"); | |
| 663 | writeBuildFile(""" |
|
663 | writeBuildFile(""" | |
| 664 | apply plugin: org.implab.gradle.variants.VariantArtifactsPlugin |
|
664 | apply plugin: org.implab.gradle.variants.VariantArtifactsPlugin | |
| 665 |
|
665 | |||
| 666 | variants.layers.create('main') |
|
666 | variants.layers.create('main') | |
| 667 | variants.roles.create('main') |
|
667 | variants.roles.create('main') | |
| 668 | variants.variant('browser') { |
|
668 | variants.variant('browser') { | |
| 669 | role('main') { |
|
669 | role('main') { | |
| 670 | layers('main') |
|
670 | layers('main') | |
| 671 | } |
|
671 | } | |
| 672 | } |
|
672 | } | |
| 673 |
|
673 | |||
| 674 | variantArtifacts { |
|
674 | variantArtifacts { | |
| 675 | variant('browser') { |
|
675 | variant('browser') { | |
| 676 | slot('mainJs') { |
|
676 | slot('mainJs') { | |
| 677 | fromRole('test') { |
|
677 | fromRole('test') { | |
| 678 | output('js') |
|
678 | output('js') | |
| 679 | } |
|
679 | } | |
| 680 | } |
|
680 | } | |
| 681 | } |
|
681 | } | |
| 682 | } |
|
682 | } | |
| 683 | """); |
|
683 | """); | |
| 684 |
|
684 | |||
| 685 | assertBuildFails("Role projection for variant 'browser' and role 'test' not found", "help"); |
|
685 | assertBuildFails("Role projection for variant 'browser' and role 'test' not found", "help"); | |
| 686 | } |
|
686 | } | |
| 687 |
|
687 | |||
| 688 | @Test |
|
688 | @Test | |
| 689 | void failsWhenPrimarySlotIsMissingForMultipleSlots() throws Exception { |
|
689 | void failsWhenPrimarySlotIsMissingForMultipleSlots() throws Exception { | |
| 690 | writeSettings("variant-artifacts-missing-primary"); |
|
690 | writeSettings("variant-artifacts-missing-primary"); | |
| 691 | writeBuildFile(""" |
|
691 | writeBuildFile(""" | |
| 692 | apply plugin: org.implab.gradle.variants.VariantArtifactsPlugin |
|
692 | apply plugin: org.implab.gradle.variants.VariantArtifactsPlugin | |
| 693 |
|
693 | |||
| 694 | variants.layers.create('main') |
|
694 | variants.layers.create('main') | |
| 695 | variants.roles.create('main') |
|
695 | variants.roles.create('main') | |
| 696 | variants.variant('browser') { |
|
696 | variants.variant('browser') { | |
| 697 | role('main') { |
|
697 | role('main') { | |
| 698 | layers('main') |
|
698 | layers('main') | |
| 699 | } |
|
699 | } | |
| 700 | } |
|
700 | } | |
| 701 |
|
701 | |||
| 702 | variantSources.layer('main') { |
|
702 | variantSources.layer('main') { | |
| 703 | sourceSet { |
|
703 | sourceSet { | |
| 704 | declareOutputs('types', 'js') |
|
704 | declareOutputs('types', 'js') | |
| 705 | } |
|
705 | } | |
| 706 | } |
|
706 | } | |
| 707 |
|
707 | |||
| 708 | variantArtifacts { |
|
708 | variantArtifacts { | |
| 709 | variant('browser') { |
|
709 | variant('browser') { | |
| 710 | slot('typesPackage') { |
|
710 | slot('typesPackage') { | |
| 711 | fromVariant { |
|
711 | fromVariant { | |
| 712 | output('types') |
|
712 | output('types') | |
| 713 | } |
|
713 | } | |
| 714 | } |
|
714 | } | |
| 715 | slot('js') { |
|
715 | slot('js') { | |
| 716 | fromVariant { |
|
716 | fromVariant { | |
| 717 | output('js') |
|
717 | output('js') | |
| 718 | } |
|
718 | } | |
| 719 | } |
|
719 | } | |
| 720 | } |
|
720 | } | |
| 721 | } |
|
721 | } | |
| 722 |
|
722 | |||
| 723 | tasks.register('probe') { |
|
723 | tasks.register('probe') { | |
| 724 | doLast { |
|
724 | doLast { | |
| 725 | variantArtifacts.whenAvailable { ctx -> |
|
725 | variantArtifacts.whenAvailable { ctx -> | |
| 726 | def browser = objects.named(org.implab.gradle.variants.core.Variant, 'browser') |
|
726 | def browser = objects.named(org.implab.gradle.variants.core.Variant, 'browser') | |
| 727 | ctx.findOutgoing(browser).get().primarySlot.get() |
|
727 | ctx.findOutgoing(browser).get().primarySlot.get() | |
| 728 | } |
|
728 | } | |
| 729 | } |
|
729 | } | |
| 730 | } |
|
730 | } | |
| 731 | """); |
|
731 | """); | |
| 732 |
|
732 | |||
| 733 | assertBuildFails("Multiple slots declared for browser, please specify primary slot explicitly", "probe"); |
|
733 | assertBuildFails("Multiple slots declared for browser, please specify primary slot explicitly", "probe"); | |
| 734 | } |
|
734 | } | |
| 735 |
|
735 | |||
| 736 | @Test |
|
736 | @Test | |
| 737 | void failsOnLayerReferenceOutsideVariantTopology() throws Exception { |
|
737 | void failsOnLayerReferenceOutsideVariantTopology() throws Exception { | |
| 738 | writeSettings("variant-artifacts-layer-outside-topology"); |
|
738 | writeSettings("variant-artifacts-layer-outside-topology"); | |
| 739 | writeBuildFile(""" |
|
739 | writeBuildFile(""" | |
| 740 | apply plugin: org.implab.gradle.variants.VariantArtifactsPlugin |
|
740 | apply plugin: org.implab.gradle.variants.VariantArtifactsPlugin | |
| 741 |
|
741 | |||
| 742 | variants.layers.create('mainBase') |
|
742 | variants.layers.create('mainBase') | |
| 743 | variants.layers.create('extra') |
|
743 | variants.layers.create('extra') | |
| 744 | variants.roles.create('main') |
|
744 | variants.roles.create('main') | |
| 745 | variants.variant('browser') { |
|
745 | variants.variant('browser') { | |
| 746 | role('main') { |
|
746 | role('main') { | |
| 747 | layers('mainBase') |
|
747 | layers('mainBase') | |
| 748 | } |
|
748 | } | |
| 749 | } |
|
749 | } | |
| 750 |
|
750 | |||
| 751 | variantArtifacts { |
|
751 | variantArtifacts { | |
| 752 | variant('browser') { |
|
752 | variant('browser') { | |
| 753 | slot('extraJs') { |
|
753 | slot('extraJs') { | |
| 754 | fromLayer('extra') { |
|
754 | fromLayer('extra') { | |
| 755 | output('js') |
|
755 | output('js') | |
| 756 | } |
|
756 | } | |
| 757 | } |
|
757 | } | |
| 758 | } |
|
758 | } | |
| 759 | } |
|
759 | } | |
| 760 | """); |
|
760 | """); | |
| 761 |
|
761 | |||
| 762 | assertBuildFails("Compile unit for variant 'browser' and layer 'extra' not found", "help"); |
|
762 | assertBuildFails("Compile unit for variant 'browser' and layer 'extra' not found", "help"); | |
| 763 | } |
|
763 | } | |
| 764 |
|
764 | |||
| 765 | @Test |
|
765 | @Test | |
| 766 | void preservesPrimaryResolutionAndAllowsSecondaryArtifactSelection() throws Exception { |
|
766 | void preservesPrimaryResolutionAndAllowsSecondaryArtifactSelection() throws Exception { | |
| 767 | writeFile("settings.gradle", """ |
|
767 | writeFile("settings.gradle", """ | |
| 768 | rootProject.name = 'variant-artifacts-resolution' |
|
768 | rootProject.name = 'variant-artifacts-resolution' | |
| 769 | include 'producer', 'consumer' |
|
769 | include 'producer', 'consumer' | |
| 770 | """); |
|
770 | """); | |
| 771 | writeFile("producer/inputs/types.d.ts", "export type Foo = string\n"); |
|
771 | writeFile("producer/inputs/types.d.ts", "export type Foo = string\n"); | |
| 772 | writeFile("producer/inputs/index.js", "export const foo = 'bar'\n"); |
|
772 | writeFile("producer/inputs/index.js", "export const foo = 'bar'\n"); | |
| 773 | writeBuildFile(""" |
|
773 | writeBuildFile(""" | |
| 774 | import org.gradle.api.attributes.Attribute |
|
774 | import org.gradle.api.attributes.Attribute | |
| 775 |
|
775 | |||
| 776 | def variantAttr = Attribute.of('test.variant', String) |
|
776 | def variantAttr = Attribute.of('test.variant', String) | |
| 777 | def slotAttr = Attribute.of('test.slot', String) |
|
777 | def slotAttr = Attribute.of('test.slot', String) | |
| 778 |
|
778 | |||
| 779 | subprojects { |
|
779 | subprojects { | |
| 780 | apply plugin: org.implab.gradle.variants.VariantArtifactsPlugin |
|
780 | apply plugin: org.implab.gradle.variants.VariantArtifactsPlugin | |
| 781 | } |
|
781 | } | |
| 782 |
|
782 | |||
| 783 | project(':producer') { |
|
783 | project(':producer') { | |
| 784 | variants.layers.create('main') |
|
784 | variants.layers.create('main') | |
| 785 | variants.roles.create('main') |
|
785 | variants.roles.create('main') | |
| 786 | variants.variant('browser') { |
|
786 | variants.variant('browser') { | |
| 787 | role('main') { |
|
787 | role('main') { | |
| 788 | layers('main') |
|
788 | layers('main') | |
| 789 | } |
|
789 | } | |
| 790 | } |
|
790 | } | |
| 791 |
|
791 | |||
| 792 | variantSources.layer('main') { |
|
792 | variantSources.layer('main') { | |
| 793 | sourceSet { |
|
793 | sourceSet { | |
| 794 | declareOutputs('types', 'js') |
|
794 | declareOutputs('types', 'js') | |
| 795 | registerOutput('types', layout.projectDirectory.file('inputs/types.d.ts')) |
|
795 | registerOutput('types', layout.projectDirectory.file('inputs/types.d.ts')) | |
| 796 | registerOutput('js', layout.projectDirectory.file('inputs/index.js')) |
|
796 | registerOutput('js', layout.projectDirectory.file('inputs/index.js')) | |
| 797 | } |
|
797 | } | |
| 798 | } |
|
798 | } | |
| 799 |
|
799 | |||
| 800 | variantArtifacts { |
|
800 | variantArtifacts { | |
| 801 | variant('browser') { |
|
801 | variant('browser') { | |
| 802 | primarySlot('typesPackage') { |
|
802 | primarySlot('typesPackage') { | |
| 803 | fromVariant { |
|
803 | fromVariant { | |
| 804 | output('types') |
|
804 | output('types') | |
| 805 | } |
|
805 | } | |
| 806 | } |
|
806 | } | |
| 807 | slot('js') { |
|
807 | slot('js') { | |
| 808 | fromVariant { |
|
808 | fromVariant { | |
| 809 | output('js') |
|
809 | output('js') | |
| 810 | } |
|
810 | } | |
| 811 | } |
|
811 | } | |
| 812 | } |
|
812 | } | |
| 813 |
|
813 | |||
| 814 | whenOutgoingConfiguration { publication -> |
|
814 | whenOutgoingConfiguration { publication -> | |
| 815 | publication.configuration { |
|
815 | publication.configuration { | |
| 816 | attributes.attribute(variantAttr, publication.variant.name) |
|
816 | attributes.attribute(variantAttr, publication.variant.name) | |
| 817 | } |
|
817 | } | |
| 818 | } |
|
818 | } | |
| 819 |
|
819 | |||
| 820 | whenOutgoingSlot { publication -> |
|
820 | whenOutgoingSlot { publication -> | |
| 821 | publication.artifactAttributes { |
|
821 | publication.artifactAttributes { | |
| 822 | attribute(slotAttr, publication.artifactSlot.slot.name) |
|
822 | attribute(slotAttr, publication.artifactSlot.slot.name) | |
| 823 | } |
|
823 | } | |
| 824 | } |
|
824 | } | |
| 825 | } |
|
825 | } | |
| 826 |
|
826 | |||
| 827 | } |
|
827 | } | |
| 828 |
|
828 | |||
| 829 | project(':consumer') { |
|
829 | project(':consumer') { | |
| 830 | configurations { |
|
830 | configurations { | |
| 831 | compileView { |
|
831 | compileView { | |
| 832 | canBeResolved = true |
|
832 | canBeResolved = true | |
| 833 | canBeConsumed = false |
|
833 | canBeConsumed = false | |
| 834 | canBeDeclared = true |
|
834 | canBeDeclared = true | |
| 835 | attributes { |
|
835 | attributes { | |
| 836 | attribute(variantAttr, 'browser') |
|
836 | attribute(variantAttr, 'browser') | |
| 837 | attribute(slotAttr, 'typesPackage') |
|
837 | attribute(slotAttr, 'typesPackage') | |
| 838 | } |
|
838 | } | |
| 839 | } |
|
839 | } | |
| 840 | } |
|
840 | } | |
| 841 |
|
841 | |||
| 842 | dependencies { |
|
842 | dependencies { | |
| 843 | compileView project(':producer') |
|
843 | compileView project(':producer') | |
| 844 | } |
|
844 | } | |
| 845 |
|
845 | |||
| 846 | tasks.register('probe') { |
|
846 | tasks.register('probe') { | |
| 847 | doLast { |
|
847 | doLast { | |
| 848 | def compileFiles = configurations.compileView.files.collect { it.name }.sort().join(',') |
|
848 | def compileFiles = configurations.compileView.files.collect { it.name }.sort().join(',') | |
| 849 | def jsFiles = configurations.compileView.incoming.artifactView { |
|
849 | def jsFiles = configurations.compileView.incoming.artifactView { | |
| 850 | attributes { |
|
850 | attributes { | |
| 851 | attribute(slotAttr, 'js') |
|
851 | attribute(slotAttr, 'js') | |
| 852 | } |
|
852 | } | |
| 853 | }.files.files.collect { it.name }.sort().join(',') |
|
853 | }.files.files.collect { it.name }.sort().join(',') | |
| 854 |
|
854 | |||
| 855 | println('compileFiles=' + compileFiles) |
|
855 | println('compileFiles=' + compileFiles) | |
| 856 | println('jsFiles=' + jsFiles) |
|
856 | println('jsFiles=' + jsFiles) | |
| 857 | } |
|
857 | } | |
| 858 | } |
|
858 | } | |
| 859 | } |
|
859 | } | |
| 860 | """); |
|
860 | """); | |
| 861 |
|
861 | |||
| 862 | BuildResult result = runner(":consumer:probe").build(); |
|
862 | BuildResult result = runner(":consumer:probe").build(); | |
| 863 |
|
863 | |||
| 864 | assertTrue(result.getOutput().contains("compileFiles=typesPackage")); |
|
864 | assertTrue(result.getOutput().contains("compileFiles=typesPackage")); | |
| 865 | assertTrue(result.getOutput().contains("jsFiles=js")); |
|
865 | assertTrue(result.getOutput().contains("jsFiles=js")); | |
| 866 | } |
|
866 | } | |
| 867 | } |
|
867 | } | |
General Comments 0
You need to be logged in to leave comments.
Login now
