/* * Copyright 2016-present Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. You may obtain * a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. */ package com.facebook.buck.jvm.kotlin; import com.facebook.buck.cli.BuckConfig; import com.facebook.buck.io.ExecutableFinder; import com.facebook.buck.model.Either; import com.facebook.buck.rules.HashedFileTool; import com.facebook.buck.rules.SourcePath; import com.facebook.buck.rules.Tool; import com.facebook.buck.util.HumanReadableException; import com.google.common.base.Supplier; import com.google.common.base.Suppliers; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Optional; import javax.annotation.Nullable; public class KotlinBuckConfig { private static final String SECTION = "kotlin"; private static final Path DEFAULT_KOTLIN_COMPILER = Paths.get("kotlinc"); private final BuckConfig delegate; private @Nullable Path kotlinHome; public KotlinBuckConfig(BuckConfig delegate) { this.delegate = delegate; } /** * Get the Tool instance for the Kotlin compiler. * * @return the Kotlin compiler Tool */ public Supplier<Tool> getKotlinCompiler() { Path compilerPath = getKotlinHome().resolve("kotlinc"); if (!Files.isExecutable(compilerPath)) { compilerPath = getKotlinHome().resolve(Paths.get("bin", "kotlinc")); if (!Files.isExecutable(compilerPath)) { throw new HumanReadableException("Could not resolve kotlinc location."); } } Path compiler = new ExecutableFinder().getExecutable(compilerPath, delegate.getEnvironment()); return Suppliers.ofInstance(new HashedFileTool(compiler)); } /** * Get the path to the Kotlin runtime jar. * * @return the Kotlin runtime jar path */ public Either<SourcePath, Path> getPathToRuntimeJar() { Optional<String> value = delegate.getValue(SECTION, "runtime_jar"); if (value.isPresent()) { boolean isAbsolute = Paths.get(value.get()).isAbsolute(); if (isAbsolute) { return Either.ofRight(delegate.getPath(SECTION, "runtime_jar", false).get().normalize()); } else { return Either.ofLeft(delegate.getSourcePath(SECTION, "runtime_jar").get()); } } Path runtime = getKotlinHome().resolve("kotlin-runtime.jar"); if (Files.isRegularFile(runtime)) { return Either.ofRight(runtime.toAbsolutePath().normalize()); } runtime = getKotlinHome().resolve(Paths.get("lib", "kotlin-runtime.jar")); if (Files.isRegularFile(runtime)) { return Either.ofRight(runtime.toAbsolutePath().normalize()); } throw new HumanReadableException("Could not resolve kotlin runtime JAR location."); } private Path getKotlinHome() { if (kotlinHome != null) { return kotlinHome; } try { // Check the buck configuration for a specified kotlin compliler Optional<String> value = delegate.getValue(SECTION, "compiler"); boolean isAbsolute = (value.isPresent() && Paths.get(value.get()).isAbsolute()); Optional<Path> compilerPath = delegate.getPath(SECTION, "compiler", !isAbsolute); if (compilerPath.isPresent()) { if (Files.isExecutable(compilerPath.get())) { kotlinHome = compilerPath.get().toRealPath().getParent().normalize(); if (kotlinHome != null && kotlinHome.endsWith(Paths.get("bin"))) { kotlinHome = kotlinHome.getParent().normalize(); } return kotlinHome; } else { throw new HumanReadableException( "Could not deduce kotlin home directory from path " + compilerPath.toString()); } } else { // If the KOTLIN_HOME environment variable is specified we trust it String home = delegate.getEnvironment().get("KOTLIN_HOME"); if (home != null) { kotlinHome = Paths.get(home).normalize(); return kotlinHome; } else { // Lastly, we try to resolve from the system PATH Optional<Path> compiler = new ExecutableFinder() .getOptionalExecutable(DEFAULT_KOTLIN_COMPILER, delegate.getEnvironment()); if (compiler.isPresent()) { kotlinHome = compiler.get().toRealPath().getParent().normalize(); if (kotlinHome != null && kotlinHome.endsWith(Paths.get("bin"))) { kotlinHome = kotlinHome.getParent().normalize(); } return kotlinHome; } else { throw new HumanReadableException( "Could not resolve kotlin home directory, Consider setting KOTLIN_HOME."); } } } } catch (IOException io) { throw new HumanReadableException( "Could not resolve kotlin home directory, Consider setting KOTLIN_HOME.", io); } } }