1717package org .gradlex .javamodule .packaging ;
1818
1919import org .gradle .api .Action ;
20+ import org .gradle .api .NamedDomainObjectContainer ;
21+ import org .gradle .api .NonNullApi ;
2022import org .gradle .api .Project ;
2123import org .gradle .api .Task ;
2224import org .gradle .api .artifacts .Configuration ;
3335import org .gradle .api .plugins .ApplicationPlugin ;
3436import org .gradle .api .plugins .JavaApplication ;
3537import org .gradle .api .plugins .JavaPluginExtension ;
38+ import org .gradle .api .plugins .jvm .JvmTestSuite ;
3639import org .gradle .api .provider .Property ;
3740import org .gradle .api .tasks .JavaExec ;
3841import org .gradle .api .tasks .SourceSet ;
4245import org .gradle .jvm .toolchain .JavaToolchainService ;
4346import org .gradle .nativeplatform .MachineArchitecture ;
4447import org .gradle .nativeplatform .OperatingSystemFamily ;
48+ import org .gradle .testing .base .TestSuite ;
4549import org .gradlex .javamodule .packaging .model .Target ;
4650import org .gradlex .javamodule .packaging .tasks .Jpackage ;
4751
5761import static org .gradle .nativeplatform .OperatingSystemFamily .OPERATING_SYSTEM_ATTRIBUTE ;
5862import static org .gradle .nativeplatform .OperatingSystemFamily .WINDOWS ;
5963
64+ @ NonNullApi
6065abstract public class JavaModulePackagingExtension {
6166 private static final Attribute <Boolean > JAVA_MODULE_ATTRIBUTE = Attribute .of ("javaModule" , Boolean .class );
6267 private static final String INTERNAL = "internal" ;
@@ -69,6 +74,8 @@ abstract public class JavaModulePackagingExtension {
6974 abstract public DirectoryProperty getJpackageResources ();
7075 abstract public ConfigurableFileCollection getResources ();
7176
77+ private final NamedDomainObjectContainer <Target > targets = getObjects ().domainObjectContainer (Target .class );
78+
7279 @ Inject
7380 abstract protected JavaToolchainService getJavaToolchains ();
7481
@@ -78,10 +85,59 @@ abstract public class JavaModulePackagingExtension {
7885 @ Inject
7986 abstract protected Project getProject ();
8087
81- public void target (String label , Action <? super Target > action ) {
82- Target target = getObjects ().newInstance (Target .class , label );
88+
89+ public Target target (String label ) {
90+ return target (label , target -> {});
91+ }
92+
93+ public Target target (String label , Action <? super Target > action ) {
94+ Target target ;
95+ if (targets .getNames ().contains (label )) {
96+ target = targets .getByName (label );
97+ } else {
98+ target = targets .create (label , this ::newTarget );
99+ }
100+
83101 action .execute (target );
102+ return target ;
103+ }
104+
105+ public Target primaryTarget (Target target ) {
106+ SourceSetContainer sourceSets = getProject ().getExtensions ().getByType (SourceSetContainer .class );
107+ ConfigurationContainer configurations = getProject ().getConfigurations ();
108+
109+ sourceSets .all (sourceSet -> {
110+ // Use this target for target-independent classpaths to make some decision
111+ configureTargetAttributes (configurations .getByName (sourceSet .getCompileClasspathConfigurationName ()), target );
112+ configureTargetAttributes (configurations .getByName (sourceSet .getRuntimeClasspathConfigurationName ()), target );
113+ // Integration for consistent resolution by 'java-module-dependencies' plugin
114+ configurations .matching (conf -> "mainRuntimeClasspath" .equals (conf .getName ())).all (conf -> configureTargetAttributes (conf , target ));
115+ });
84116
117+ return target ;
118+ }
119+
120+ public TestSuite multiTargetTestSuite (TestSuite testSuite ) {
121+ if (!(testSuite instanceof JvmTestSuite )) {
122+ return testSuite ;
123+ }
124+
125+ JvmTestSuite suite = (JvmTestSuite ) testSuite ;
126+ targets .all (target -> {
127+ suite .getTargets ().register (testSuite .getName () + capitalize (target .getName ()), testTarget -> {
128+ testTarget .getTestTask ().configure (task -> {
129+ ConfigurationContainer configurations = getProject ().getConfigurations ();
130+ task .setClasspath (configurations .getByName (target .getName () + capitalize (suite .getSources ().getRuntimeClasspathConfigurationName ())).plus (
131+ getObjects ().fileCollection ().from (getProject ().getTasks ().named (suite .getSources ().getJarTaskName ())))
132+ );
133+ });
134+ });
135+ });
136+
137+ return testSuite ;
138+ }
139+
140+ private void newTarget (Target target ) {
85141 target .getPackageTypes ().convention (target .getOperatingSystem ().map (os -> {
86142 switch (os ) {
87143 case WINDOWS :
@@ -98,30 +154,23 @@ public void target(String label, Action<? super Target> action) {
98154 SourceSetContainer sourceSets = getProject ().getExtensions ().getByType (SourceSetContainer .class );
99155
100156 sourceSets .all (sourceSet -> {
101- // Use first target for target-independent classpaths to make some decision
102- maybeConfigureTargetAttributes (configurations .getByName (sourceSet .getCompileClasspathConfigurationName ()), target );
103- maybeConfigureTargetAttributes (configurations .getByName (sourceSet .getRuntimeClasspathConfigurationName ()), target );
104- // Integration for consistent resolution by 'java-module-dependencies' plugin
105- configurations .matching (conf -> "mainRuntimeClasspath" .equals (conf .getName ())).all (conf -> maybeConfigureTargetAttributes (conf , target ));
106-
107157 Configuration internal = maybeCreateInternalConfiguration ();
108-
109- configurations .create (target .getLabel () + capitalize (sourceSet .getCompileClasspathConfigurationName ()), c -> {
158+ configurations .create (target .getName () + capitalize (sourceSet .getCompileClasspathConfigurationName ()), c -> {
110159 c .setCanBeConsumed (false );
111160 c .setVisible (false );
112161 configureJavaStandardAttributes (c , Usage .JAVA_API );
113- maybeConfigureTargetAttributes (c , target );
162+ configureTargetAttributes (c , target );
114163 c .extendsFrom (
115164 configurations .getByName (sourceSet .getImplementationConfigurationName ()),
116165 configurations .getByName (sourceSet .getCompileOnlyConfigurationName ()),
117166 internal
118167 );
119168 });
120- Configuration runtimeClasspath = configurations .create (target .getLabel () + capitalize (sourceSet .getRuntimeClasspathConfigurationName ()), c -> {
169+ Configuration runtimeClasspath = configurations .create (target .getName () + capitalize (sourceSet .getRuntimeClasspathConfigurationName ()), c -> {
121170 c .setCanBeConsumed (false );
122171 c .setVisible (false );
123172 configureJavaStandardAttributes (c , Usage .JAVA_RUNTIME );
124- maybeConfigureTargetAttributes (c , target );
173+ configureTargetAttributes (c , target );
125174 c .extendsFrom (
126175 configurations .getByName (sourceSet .getImplementationConfigurationName ()),
127176 configurations .getByName (sourceSet .getRuntimeOnlyConfigurationName ()),
@@ -133,7 +182,6 @@ public void target(String label, Action<? super Target> action) {
133182 getProject ().getPlugins ().withType (ApplicationPlugin .class , p -> registerTargetSpecificTasks (target , sourceSet .getJarTaskName (), runtimeClasspath ));
134183 }
135184 });
136-
137185 }
138186
139187 private void configureJavaStandardAttributes (Configuration resolvable , String usage ) {
@@ -146,11 +194,9 @@ private void configureJavaStandardAttributes(Configuration resolvable, String us
146194 resolvable .getAttributes ().attribute (JAVA_MODULE_ATTRIBUTE , true );
147195 }
148196
149- private void maybeConfigureTargetAttributes (Configuration resolvable , Target target ) {
150- if (!resolvable .getAttributes ().contains (OPERATING_SYSTEM_ATTRIBUTE )) {
151- resolvable .getAttributes ().attributeProvider (OPERATING_SYSTEM_ATTRIBUTE , target .getOperatingSystem ().map (name -> getObjects ().named (OperatingSystemFamily .class , name )));
152- resolvable .getAttributes ().attributeProvider (ARCHITECTURE_ATTRIBUTE , target .getArchitecture ().map (name -> getObjects ().named (MachineArchitecture .class , name )));
153- }
197+ private void configureTargetAttributes (Configuration resolvable , Target target ) {
198+ resolvable .getAttributes ().attributeProvider (OPERATING_SYSTEM_ATTRIBUTE , target .getOperatingSystem ().map (name -> getObjects ().named (OperatingSystemFamily .class , name )));
199+ resolvable .getAttributes ().attributeProvider (ARCHITECTURE_ATTRIBUTE , target .getArchitecture ().map (name -> getObjects ().named (MachineArchitecture .class , name )));
154200 }
155201
156202 private void registerTargetSpecificTasks (Target target , String applicationJarTask , Configuration runtimeClasspath ) {
@@ -159,7 +205,7 @@ private void registerTargetSpecificTasks(Target target, String applicationJarTas
159205 JavaPluginExtension java = getProject ().getExtensions ().getByType (JavaPluginExtension .class );
160206 JavaApplication application = getProject ().getExtensions ().getByType (JavaApplication .class );
161207
162- TaskProvider <Jpackage > jpackage = tasks .register ("jpackage" + capitalize (target .getLabel ()), Jpackage .class , t -> {
208+ TaskProvider <Jpackage > jpackage = tasks .register ("jpackage" + capitalize (target .getName ()), Jpackage .class , t -> {
163209 t .getJavaInstallation ().convention (getJavaToolchains ().compilerFor (java .getToolchain ()).get ().getMetadata ());
164210 t .getOperatingSystem ().convention (target .getOperatingSystem ());
165211 t .getArchitecture ().convention (target .getArchitecture ());
@@ -178,23 +224,24 @@ private void registerTargetSpecificTasks(Target target, String applicationJarTas
178224 t .getPackageTypes ().convention (target .getPackageTypes ());
179225 t .getResources ().from (getResources ());
180226
181- t .getDestination ().convention (getProject ().getLayout ().getBuildDirectory ().dir ("packages/" + target .getLabel ()));
227+ t .getDestination ().convention (getProject ().getLayout ().getBuildDirectory ().dir ("packages/" + target .getName ()));
182228 });
183229
184- tasks .register ("run" + capitalize (target .getLabel ()), JavaExec .class , t -> {
230+ tasks .register ("run" + capitalize (target .getName ()), JavaExec .class , t -> {
185231 t .setGroup (ApplicationPlugin .APPLICATION_GROUP );
186- t .setDescription ("Run this project as a JVM application on " + target .getLabel ());
232+ t .setDescription ("Run this project as a JVM application on " + target .getName ());
187233 t .getJavaLauncher ().convention (getJavaToolchains ().launcherFor (java .getToolchain ()));
188234 t .getMainModule ().convention (application .getMainModule ());
235+ t .getMainClass ().convention (application .getMainClass ());
189236 t .setJvmArgs (application .getApplicationDefaultJvmArgs ());
190237 t .classpath (tasks .named ("jar" ), runtimeClasspath );
191238 });
192239
193- String targetAssembleLifecycle = "assemble" + capitalize (target .getLabel ());
240+ String targetAssembleLifecycle = "assemble" + capitalize (target .getName ());
194241 if (!tasks .getNames ().contains (targetAssembleLifecycle )) {
195242 TaskProvider <Task > lifecycleTask = tasks .register (targetAssembleLifecycle , t -> {
196243 t .setGroup (BUILD_GROUP );
197- t .setDescription ("Builds this project for " + target .getLabel ());
244+ t .setDescription ("Builds this project for " + target .getName ());
198245 });
199246 tasks .named (ASSEMBLE_TASK_NAME , t -> t .dependsOn (lifecycleTask ));
200247 }
0 commit comments