1
1
package mill
2
2
package scalalib
3
3
4
- import scala .util .chaining .scalaUtilChainingOps
5
- import scala .util .matching .Regex
6
-
7
- import coursier .Repository
8
- import coursier .Type
9
- import coursier .core as cs
10
- import coursier .core .BomDependency
11
- import coursier .core .Configuration
12
- import coursier .core .DependencyManagement
13
- import coursier .core .Resolution
4
+ import coursier .{Repository , Type , core as cs }
5
+ import coursier .core .{BomDependency , Configuration , DependencyManagement , Resolution }
14
6
import coursier .params .ResolutionParams
15
- import coursier .parse .JavaOrScalaModule
16
- import coursier .parse .ModuleParser
17
- import coursier .util .EitherT
18
- import coursier .util .ModuleMatcher
19
- import coursier .util .Monad
7
+ import coursier .parse .{JavaOrScalaModule , ModuleParser }
8
+ import coursier .util .{EitherT , ModuleMatcher , Monad }
20
9
import mainargs .Flag
21
- import mill .api .MillException
22
- import mill .api .Result
23
- import mill .api .Segments
24
- import mill .api .internal .BspBuildTarget
25
- import mill .api .internal .BspModuleApi
26
- import mill .api .internal .BspUri
27
- import mill .api .internal .EvaluatorApi
28
- import mill .api .internal .IdeaConfigFile
29
- import mill .api .internal .JavaFacet
30
- import mill .api .internal .JavaModuleApi
31
- import mill .api .internal .JvmBuildTarget
32
- import mill .api .internal .ResolvedModule
33
- import mill .api .internal .Scoped
34
- import mill .api .internal .internal
35
- import mill .define .ModuleRef
36
- import mill .define .PathRef
37
- import mill .define .Segment
38
- import mill .define .Task
39
- import mill .define .TaskCtx
40
- import mill .define .TaskModule
10
+ import mill .api .{MillException , Result , Segments }
11
+ import mill .api .internal .{
12
+ BspBuildTarget ,
13
+ BspClientType ,
14
+ BspModuleApi ,
15
+ BspUri ,
16
+ EvaluatorApi ,
17
+ IdeaConfigFile ,
18
+ JavaFacet ,
19
+ JavaModuleApi ,
20
+ JvmBuildTarget ,
21
+ ResolvedModule ,
22
+ Scoped ,
23
+ internal
24
+ }
25
+ import mill .define .{ModuleRef , PathRef , Segment , Task , TaskCtx , TaskModule }
41
26
import mill .scalalib .api .CompilationResult
42
27
import mill .scalalib .bsp .BspModule
43
28
import mill .scalalib .internal .ModuleUtils
44
29
import mill .scalalib .publish .Artifact
45
- import mill .util .JarManifest
46
- import mill .util .Jvm
30
+ import mill .util .{JarManifest , Jvm }
47
31
import os .Path
48
32
33
+ import scala .util .chaining .scalaUtilChainingOps
34
+ import scala .util .matching .Regex
35
+
49
36
/**
50
37
* Core configuration required to compile a single Java compilation target
51
38
*/
@@ -695,17 +682,6 @@ trait JavaModule
695
682
Task .traverse(transitiveModuleCompileModuleDeps)(_.jar)()
696
683
}
697
684
698
- /**
699
- * Same as [[transitiveLocalClasspath ]], but with all dependencies on [[compile ]]
700
- * replaced by their non-compiling [[bspCompileClassesPath ]] variants.
701
- *
702
- * Keep in sync with [[transitiveLocalClasspath ]]
703
- */
704
- @ internal
705
- private [mill] def bspTransitiveLocalClasspath : T [Seq [UnresolvedPath ]] = Task {
706
- Task .traverse(transitiveModuleCompileModuleDeps)(_.bspLocalClasspath)().flatten
707
- }
708
-
709
685
/**
710
686
* The transitive version of `compileClasspath`
711
687
*/
@@ -722,11 +698,14 @@ trait JavaModule
722
698
* Keep in sync with [[transitiveCompileClasspath ]]
723
699
*/
724
700
@ internal
725
- private [mill] def bspTransitiveCompileClasspath : T [Seq [UnresolvedPath ]] = Task {
701
+ private [mill] def bspTransitiveCompileClasspath (clientType : BspClientType )
702
+ : Task [Seq [UnresolvedPath ]] = Task .Anon {
726
703
Task .traverse(transitiveModuleCompileModuleDeps)(m =>
727
704
Task .Anon {
728
- m.localCompileClasspath().map(p => UnresolvedPath .ResolvedPath (p.path)) ++
729
- Seq (m.bspCompileClassesPath())
705
+ val localCompileClasspath =
706
+ m.localCompileClasspath().map(p => UnresolvedPath .ResolvedPath (p.path))
707
+ val compileClassesPath = m.bspCompileClassesPath(clientType)()
708
+ localCompileClasspath :+ compileClassesPath
730
709
}
731
710
)()
732
711
.flatten
@@ -820,29 +799,32 @@ trait JavaModule
820
799
)
821
800
}
822
801
802
+ /** Resolves paths relative to the `out` folder. */
803
+ @ internal
804
+ private [mill] def resolveRelativeToOut (
805
+ task : Task .Named [? ],
806
+ mkPath : os.SubPath => os.SubPath = identity
807
+ ): UnresolvedPath .DestPath =
808
+ UnresolvedPath .DestPath (mkPath(os.sub), task.ctx.segments)
809
+
810
+ /** The path where the compiled classes produced by [[compile ]] are stored. */
811
+ @ internal
812
+ private [mill] def compileClassesPath : UnresolvedPath .DestPath =
813
+ resolveRelativeToOut(compile, _ / " classes" )
814
+
823
815
/**
824
816
* The path to the compiled classes by [[compile ]] without forcing to actually run the compilation.
825
817
* This is safe in an BSP context, as the compilation done later will use the
826
818
* exact same compilation settings, so we can safely use the same path.
827
819
*
828
- * Keep in sync with [[compile ]]
820
+ * Keep in sync with [[compile ]] and [[ bspBuildTargetCompile ]].
829
821
*/
830
822
@ internal
831
- private [mill] def bspCompileClassesPath : T [UnresolvedPath ] =
832
- if (compile.ctx.enclosing == s " ${classOf [JavaModule ].getName}#compile " ) {
833
- Task {
834
- Task .log.debug(
835
- s " compile target was not overridden, assuming hard-coded classes directory for target ${compile}"
836
- )
837
- UnresolvedPath .DestPath (os.sub / " classes" , compile.ctx.segments)
838
- }
839
- } else {
840
- Task {
841
- Task .log.debug(
842
- s " compile target was overridden, need to actually execute compilation to get the compiled classes directory for target ${compile}"
843
- )
844
- UnresolvedPath .ResolvedPath (compile().classes.path)
845
- }
823
+ private [mill] def bspCompileClassesPath (clientType : BspClientType ): Task [UnresolvedPath ] =
824
+ Task .Anon {
825
+ if (clientType.needsToMergeResourcesIntoCompileDest)
826
+ resolveRelativeToOut(bspBuildTargetCompileMerged)
827
+ else compileClassesPath
846
828
}
847
829
848
830
/**
@@ -851,20 +833,20 @@ trait JavaModule
851
833
* Keep in sync with [[bspLocalRunClasspath ]]
852
834
*/
853
835
override def localRunClasspath : T [Seq [PathRef ]] = Task {
854
- super .localRunClasspath() ++ resources() ++
855
- Seq (compile().classes)
836
+ super .localRunClasspath() ++ resources() ++ Seq (compile().classes)
856
837
}
857
838
858
839
/**
859
840
* Same as [[localRunClasspath ]] but for use in BSP server.
860
841
*
861
842
* Keep in sync with [[localRunClasspath ]]
862
843
*/
863
- private [mill] def bspLocalRunClasspath : T [Seq [UnresolvedPath ]] = Task {
864
- Seq .from(super .localRunClasspath() ++ resources())
865
- .map(p => UnresolvedPath .ResolvedPath (p.path)) ++
866
- Seq (bspCompileClassesPath())
867
- }
844
+ private [mill] def bspLocalRunClasspath (clientType : BspClientType ): Task [Seq [UnresolvedPath ]] =
845
+ Task .Anon {
846
+ Seq .from(super .localRunClasspath() ++ resources())
847
+ .map(p => UnresolvedPath .ResolvedPath (p.path)) ++
848
+ Seq (bspCompileClassesPath(clientType)())
849
+ }
868
850
869
851
/**
870
852
* The *output* classfiles/resources from this module, used for execution,
@@ -886,10 +868,11 @@ trait JavaModule
886
868
* Keep in sync with [[localClasspath ]]
887
869
*/
888
870
@ internal
889
- private [mill] def bspLocalClasspath : T [Seq [UnresolvedPath ]] = Task {
890
- (localCompileClasspath()).map(p => UnresolvedPath .ResolvedPath (p.path)) ++
891
- bspLocalRunClasspath()
892
- }
871
+ private [mill] def bspLocalClasspath (clientType : BspClientType ): Task [Seq [UnresolvedPath ]] =
872
+ Task .Anon {
873
+ localCompileClasspath().map(p => UnresolvedPath .ResolvedPath (p.path)) ++
874
+ bspLocalRunClasspath(clientType)()
875
+ }
893
876
894
877
/**
895
878
* All classfiles and resources from upstream modules and dependencies
@@ -907,10 +890,11 @@ trait JavaModule
907
890
* Keep in sync with [[compileClasspath ]]
908
891
*/
909
892
@ internal
910
- private [mill] def bspCompileClasspath : Task [EvaluatorApi => Seq [String ]] = Task .Anon {
893
+ private [mill] def bspCompileClasspath (clientType : BspClientType )
894
+ : Task [EvaluatorApi => Seq [String ]] = Task .Anon {
911
895
(ev : EvaluatorApi ) =>
912
896
(resolvedMvnDeps().map(p => UnresolvedPath .ResolvedPath (p.path)) ++
913
- bspTransitiveCompileClasspath() ++
897
+ bspTransitiveCompileClasspath(clientType)( ) ++
914
898
localCompileClasspath().map(p => UnresolvedPath .ResolvedPath (p.path))).map(_.resolve(
915
899
os.Path (ev.outPathJava)
916
900
)).map(sanitizeUri)
@@ -1345,6 +1329,7 @@ trait JavaModule
1345
1329
}
1346
1330
1347
1331
private [mill] def bspBuildTargetScalacOptions (
1332
+ clientType : BspClientType ,
1348
1333
enableJvmCompileClasspathProvider : Boolean ,
1349
1334
clientWantsSemanticDb : Boolean
1350
1335
) = {
@@ -1359,10 +1344,10 @@ trait JavaModule
1359
1344
if (enableJvmCompileClasspathProvider) {
1360
1345
// We have a dedicated request for it
1361
1346
Task .Anon {
1362
- (e : EvaluatorApi ) => Seq .empty[String ]
1347
+ (_ : EvaluatorApi ) => Seq .empty[String ]
1363
1348
}
1364
1349
} else {
1365
- bspCompileClasspath
1350
+ bspCompileClasspath(clientType)
1366
1351
}
1367
1352
1368
1353
val classesPathTask =
@@ -1372,7 +1357,7 @@ trait JavaModule
1372
1357
)
1373
1358
} else {
1374
1359
Task .Anon ((e : EvaluatorApi ) =>
1375
- bspCompileClassesPath().resolve(os.Path (e.outPathJava)).toNIO
1360
+ bspCompileClassesPath(clientType)( ).resolve(os.Path (e.outPathJava)).toNIO
1376
1361
)
1377
1362
}
1378
1363
@@ -1381,17 +1366,20 @@ trait JavaModule
1381
1366
}
1382
1367
}
1383
1368
1384
- private [mill] def bspBuildTargetJavacOptions (clientWantsSemanticDb : Boolean ) = {
1369
+ private [mill] def bspBuildTargetJavacOptions (
1370
+ clientType : BspClientType ,
1371
+ clientWantsSemanticDb : Boolean
1372
+ ) = {
1385
1373
val classesPathTask = this match {
1386
1374
case sem : SemanticDbJavaModule if clientWantsSemanticDb =>
1387
1375
sem.bspCompiledClassesAndSemanticDbFiles
1388
- case _ => bspCompileClassesPath
1376
+ case _ => bspCompileClassesPath(clientType)
1389
1377
}
1390
1378
Task .Anon { (ev : EvaluatorApi ) =>
1391
1379
(
1392
1380
classesPathTask().resolve(os.Path (ev.outPathJava)).toNIO,
1393
1381
javacOptions() ++ mandatoryJavacOptions(),
1394
- bspCompileClasspath.apply().apply(ev)
1382
+ bspCompileClasspath(clientType) .apply().apply(ev)
1395
1383
)
1396
1384
}
1397
1385
}
@@ -1452,7 +1440,34 @@ trait JavaModule
1452
1440
1453
1441
private [mill] def bspBuildTargetResources = Task .Anon { resources().map(_.path.toNIO) }
1454
1442
1455
- private [mill] def bspBuildTargetCompile = Task .Anon { compile().classes.path.toNIO }
1443
+ /**
1444
+ * Performs the compilation (via [[compile ]]) and merging of [[resources ]] needed by
1445
+ * [[BspClientType.needsToMergeResourcesIntoCompileDest ]].
1446
+ */
1447
+ private [mill] def bspBuildTargetCompileMerged : T [PathRef ] = Task {
1448
+
1449
+ /**
1450
+ * Make sure to invoke the [[bspBuildTargetCompileMerged ]] of the transitive dependencies. For example, tests
1451
+ * should be able to read resources of the module that they are testing.
1452
+ */
1453
+ val _ = Task .traverse(transitiveModuleCompileModuleDeps)(m =>
1454
+ Task .Anon (m.bspBuildTargetCompileMerged())
1455
+ )()
1456
+
1457
+ // Merge the compile and resources classpaths.
1458
+ os.copy(compile().classes.path, Task .dest, mergeFolders = true )
1459
+ resources().foreach { resource =>
1460
+ os.copy(resource.path, Task .dest, mergeFolders = true )
1461
+ }
1462
+
1463
+ PathRef (Task .dest)
1464
+ }
1465
+
1466
+ private [mill] def bspBuildTargetCompile (clientType : BspClientType ): Task [java.nio.file.Path ] = {
1467
+ if (clientType.needsToMergeResourcesIntoCompileDest)
1468
+ Task .Anon { bspBuildTargetCompileMerged().path.toNIO }
1469
+ else Task .Anon { compile().classes.path.toNIO }
1470
+ }
1456
1471
1457
1472
private [mill] def bspLoggingTest = Task .Anon {
1458
1473
System .out.println(" bspLoggingTest from System.out" )
0 commit comments