1717package org .jetbrains .kotlin .maven ;
1818
1919import org .apache .maven .artifact .Artifact ;
20- import org .apache .maven .artifact .resolver .ArtifactResolutionException ;
2120import org .apache .maven .plugin .MojoExecutionException ;
2221import org .apache .maven .plugin .MojoFailureException ;
2322import org .apache .maven .plugins .annotations .*;
2423import org .jetbrains .annotations .NotNull ;
2524import org .jetbrains .annotations .Nullable ;
2625import org .jetbrains .kotlin .build .SourcesUtilsKt ;
2726import org .jetbrains .kotlin .buildtools .api .*;
28- import org .jetbrains .kotlin .buildtools .api .jvm .ClasspathSnapshotBasedIncrementalCompilationApproachParameters ;
29- import org .jetbrains .kotlin .buildtools .api .jvm .ClasspathSnapshotBasedIncrementalJvmCompilationConfiguration ;
30- import org .jetbrains .kotlin .buildtools .api .jvm .JvmCompilationConfiguration ;
27+ import org .jetbrains .kotlin .buildtools .api .jvm .*;
28+ import org .jetbrains .kotlin .buildtools .api .jvm .operations .JvmCompilationOperation ;
3129import org .jetbrains .kotlin .cli .common .CLICompiler ;
3230import org .jetbrains .kotlin .cli .common .ExitCode ;
3331import org .jetbrains .kotlin .cli .common .arguments .K2JVMCompilerArguments ;
4745import java .net .URLClassLoader ;
4846import java .nio .file .Files ;
4947import java .nio .file .Path ;
48+ import java .nio .file .Paths ;
5049import java .time .Duration ;
5150import java .util .*;
5251import java .util .function .Consumer ;
@@ -123,8 +122,13 @@ public class K2JVMCompileMojo extends KotlinCompileMojoBase<K2JVMCompilerArgumen
123122 private static final String MAVEN_DAEMON_PROPERTY_NAME = "mvnd.home" ;
124123
125124 @ NotNull
126- private File getCachesDir () {
127- return new File (incrementalCachesRoot , getSourceSetName ());
125+ private Path getCachesDir () {
126+ return Paths .get (incrementalCachesRoot , getSourceSetName ());
127+ }
128+
129+ @ NotNull
130+ private Path getKotlinClassesCacheDir () {
131+ return Paths .get (incrementalCachesRoot , "classes" );
128132 }
129133
130134 protected boolean isIncremental () {
@@ -249,7 +253,7 @@ public void execute() throws MojoExecutionException, MojoFailureException {
249253 @ Inject
250254 private KotlinArtifactResolver kotlinArtifactResolver ;
251255
252- private CompilationService getCompilationService () throws MojoExecutionException {
256+ private KotlinToolchains getKotlinToolchains () throws MojoExecutionException {
253257 try {
254258 Set <Artifact > artifacts =
255259 Stream .concat (
@@ -266,14 +270,14 @@ private CompilationService getCompilationService() throws MojoExecutionException
266270 }
267271 }).toArray (URL []::new );
268272 ClassLoader btaClassLoader = new URLClassLoader (urls , SharedApiClassesClassLoader .newInstance ());
269- return CompilationService .loadImplementation (btaClassLoader );
273+ return KotlinToolchains .loadImplementation (btaClassLoader );
270274 } catch (Exception e ) {
271275 throw new MojoExecutionException ("Failed to load Kotlin Build Tools API implementation" , e );
272276 }
273277 }
274278
275- private static String getFileExtension (File file ) {
276- String fileName = file .getName ();
279+ private static String getFileExtension (Path file ) {
280+ String fileName = file .getFileName (). toString ();
277281 int lastDotIndex = fileName .lastIndexOf ('.' );
278282 if (lastDotIndex == -1 ) {
279283 return "" ;
@@ -290,9 +294,8 @@ protected ExitCode execCompiler(
290294 List <File > sourceRoots
291295 ) throws MojoExecutionException {
292296 try {
293- ProjectId projectId = ProjectId .Companion .RandomProjectUUID ();
294- CompilationService compilationService = getCompilationService ();
295- CompilerExecutionStrategyConfiguration strategyConfig = compilationService .makeCompilerExecutionStrategyConfiguration ();
297+ KotlinToolchains kotlinToolchains = getKotlinToolchains ();
298+ ExecutionPolicy executionPolicy ;
296299 if (useDaemon ) {
297300 boolean inMavenDaemon = System .getProperty (MAVEN_DAEMON_PROPERTY_NAME ) != null ;
298301 Duration usedDaemonShutdownDelay ;
@@ -305,75 +308,87 @@ protected ExitCode execCompiler(
305308 usedDaemonShutdownDelay = DEFAULT_NON_MAVEN_DAEMON_SHUTDOWN_DELAY ;
306309 }
307310 getLog ().debug ("Using Kotlin compiler daemon with shutdown delay " + usedDaemonShutdownDelay + " ms" + (inMavenDaemon ? " (in Maven daemon)" : " (outside Maven daemon)" ));
308- strategyConfig .useDaemonStrategy (kotlinDaemonJvmArgs , usedDaemonShutdownDelay );
311+ ExecutionPolicy .WithDaemon daemonPolicy = kotlinToolchains .createDaemonExecutionPolicy ();
312+ daemonPolicy .set (ExecutionPolicy .WithDaemon .JVM_ARGUMENTS , kotlinDaemonJvmArgs );
313+ daemonPolicy .set (ExecutionPolicy .WithDaemon .SHUTDOWN_DELAY_MILLIS , usedDaemonShutdownDelay .toMillis ());
314+ executionPolicy = daemonPolicy ;
309315 } else {
310316 getLog ().debug ("Using in-process Kotlin compiler" );
311- strategyConfig .useInProcessStrategy ();
312- }
313-
314- JvmCompilationConfiguration compileConfig = compilationService .makeJvmCompilationConfiguration ();
315-
316- LegacyKotlinMavenLogger kotlinMavenLogger = new LegacyKotlinMavenLogger (messageCollector , getLog ());
317- compileConfig .useLogger (kotlinMavenLogger );
318-
319- Set <Consumer <CompilationResult >> resultHandlers = new HashSet <>();
320- if (isIncremental ()) {
321- resultHandlers .add (configureIncrementalCompilation (compileConfig , arguments ));
317+ executionPolicy = kotlinToolchains .createInProcessExecutionPolicy ();
322318 }
323319
320+ JvmPlatformToolchain jvmToolchain = JvmPlatformToolchain .get (kotlinToolchains );
324321 Set <String > kotlinExtensions = SourcesUtilsKt .getDEFAULT_KOTLIN_SOURCE_FILES_EXTENSIONS ();
325322 Set <String > allExtensions = new HashSet <>(kotlinExtensions );
326323 allExtensions .add ("java" );
327324
328- List <File > allSources = new ArrayList <>();
325+ List <Path > allSources = new ArrayList <>();
329326 for (File sourceRoot : sourceRoots ) {
330327 try (Stream <Path > files = Files .walk (sourceRoot .toPath ())) {
331328 allSources .addAll (
332329 files
333- .map (Path ::toFile )
334330 .filter (file -> allExtensions .contains (getFileExtension (file ).toLowerCase (Locale .ROOT )))
335- .filter (File :: isFile )
331+ .filter (Files :: isRegularFile )
336332 .collect (Collectors .toList ())
337333 );
338334 }
339335 }
340336 List <String > myArguments = ArgumentUtils .convertArgumentsToStringList (arguments );
341337
342- CompilationResult result = compilationService .compileJvm (projectId , strategyConfig , compileConfig , allSources , myArguments );
343- compilationService .finishProjectCompilation (projectId );
344- resultHandlers .forEach (handler -> handler .accept (result ));
345- switch (result ) {
346- case COMPILATION_SUCCESS :
347- return ExitCode .OK ;
348- case COMPILATION_ERROR :
349- return ExitCode .COMPILATION_ERROR ;
350- case COMPILATION_OOM_ERROR :
351- return ExitCode .OOM_ERROR ;
352- default :
353- return ExitCode .INTERNAL_ERROR ;
338+ Set <Consumer <CompilationResult >> resultHandlers = new HashSet <>();
339+
340+ Path destination = getEffectiveDestinationDirectory (arguments );
341+ JvmCompilationOperation compilationOperation = jvmToolchain .createJvmCompilationOperation (allSources , destination );
342+
343+ if (isIncremental ()) {
344+ resultHandlers .add (configureIncrementalCompilation (compilationOperation , arguments ));
345+ }
346+
347+ LegacyKotlinMavenLogger kotlinMavenLogger = new LegacyKotlinMavenLogger (messageCollector , getLog ());
348+ try (KotlinToolchains .BuildSession buildSession = kotlinToolchains .createBuildSession ()) {
349+ compilationOperation .getCompilerArguments ().applyArgumentStrings (myArguments );
350+ CompilationResult result = buildSession .executeOperation (compilationOperation , executionPolicy , kotlinMavenLogger );
351+ resultHandlers .forEach (handler -> handler .accept (result ));
352+ switch (result ) {
353+ case COMPILATION_SUCCESS :
354+ return ExitCode .OK ;
355+ case COMPILATION_ERROR :
356+ return ExitCode .COMPILATION_ERROR ;
357+ case COMPILATION_OOM_ERROR :
358+ return ExitCode .OOM_ERROR ;
359+ default :
360+ return ExitCode .INTERNAL_ERROR ;
361+ }
354362 }
355363 } catch (Throwable t ) {
356364 getLog ().error ("Internal Kotlin compilation error" , t );
357365 return ExitCode .INTERNAL_ERROR ;
358366 }
359367 }
360368
369+ private Path getEffectiveDestinationDirectory (K2JVMCompilerArguments arguments ) {
370+ if (isIncremental ()) {
371+ return getKotlinClassesCacheDir ();
372+ } else {
373+ String destination = Objects .requireNonNull (arguments .getDestination ());
374+ return Paths .get (destination );
375+ }
376+ }
377+
361378 private Consumer <CompilationResult > configureIncrementalCompilation (
362- JvmCompilationConfiguration compileConfig ,
379+ JvmCompilationOperation compileOperation ,
363380 K2JVMCompilerArguments arguments
364- ) {
381+ ) throws IOException {
365382 getLog ().warn ("Using experimental Kotlin incremental compilation" );
366- File cachesDir = getCachesDir ();
367- //noinspection ResultOfMethodCallIgnored
368- cachesDir .mkdirs ();
383+ Path cachesDir = getCachesDir ();
384+ Files .createDirectories (cachesDir );
369385 String originalDestination = arguments .getDestination ();
370386 assert originalDestination != null : "output is not specified!" ;
371387 File classesDir = new File (originalDestination );
372- File kotlinClassesDir = new File ( cachesDir , "classes" );
373- File snapshotsFile = new File (cachesDir , "snapshots.bin" );
388+ File kotlinClassesDir = getKotlinClassesCacheDir (). toFile ( );
389+ File snapshotsFile = new File (cachesDir . toFile () , "snapshots.bin" );
374390 String originalClasspath = arguments .getClasspath ();
375391
376- arguments .setDestination (kotlinClassesDir .getAbsolutePath ());
377392 if (originalClasspath != null ) {
378393 List <String > filteredClasspath = new ArrayList <>();
379394 for (String path : originalClasspath .split (File .pathSeparator )) {
@@ -384,18 +399,19 @@ private Consumer<CompilationResult> configureIncrementalCompilation(
384399 arguments .setClasspath (StringUtil .join (filteredClasspath , File .pathSeparator ));
385400 }
386401
387- ClasspathSnapshotBasedIncrementalJvmCompilationConfiguration icConf =
388- compileConfig .makeClasspathSnapshotBasedIncrementalCompilationConfiguration ();
389- ClasspathSnapshotBasedIncrementalCompilationApproachParameters classpathSnapshotParams =
390- new ClasspathSnapshotBasedIncrementalCompilationApproachParameters (Collections .EMPTY_LIST ,
391- new File (cachesDir , "shrunk-classpath-snapshot.bin" ));
392- compileConfig .useIncrementalCompilation (cachesDir , SourcesChanges .ToBeCalculated .INSTANCE , classpathSnapshotParams , icConf );
402+ JvmSnapshotBasedIncrementalCompilationOptions classpathSnapshotsOptions = compileOperation .createSnapshotBasedIcOptions ();
403+ compileOperation .set (JvmCompilationOperation .INCREMENTAL_COMPILATION , new JvmSnapshotBasedIncrementalCompilationConfiguration (
404+ cachesDir ,
405+ SourcesChanges .ToBeCalculated .INSTANCE ,
406+ Collections .EMPTY_LIST ,
407+ cachesDir .resolve ("shrunk-classpath-snapshot.bin" ),
408+ classpathSnapshotsOptions
409+ ));
393410
394411 return compilationResult -> {
395412 if (compilationResult == CompilationResult .COMPILATION_SUCCESS ) {
396413 (new FileCopier (getLog ())).syncDirs (kotlinClassesDir , classesDir , snapshotsFile );
397414 }
398- arguments .setDestination (originalDestination );
399415 arguments .setClasspath (originalClasspath );
400416 };
401417 }
0 commit comments