Skip to content

Commit

Permalink
Merge pull request #10 from hsyed/mix-mode
Browse files Browse the repository at this point in the history
#3 broad rework of mix-mode compilation and fixes.
  • Loading branch information
hsyed committed Feb 2, 2018
2 parents 18a7c5c + aa732ea commit 78ee448
Show file tree
Hide file tree
Showing 28 changed files with 917 additions and 323 deletions.
9 changes: 6 additions & 3 deletions kotlin/rules/compile.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,12 @@ def _kotlin_do_compile_action(ctx, output_jar, compile_jars, opts):
by the caller -- kotlin-reflect could be optional.
opts: struct containing Kotlin compilation options.
"""
compiler_output_base=ctx.actions.declare_directory(ctx.label.name + "." + "kotlinc")

args = [
"--label", ctx.label,
"--output_classjar", output_jar.path,
"--target_label", ctx.label,
"--compiler_output_base", compiler_output_base.path,
"--output", output_jar.path,
"--output_jdeps", ctx.outputs.jdeps.path,
"--classpath", ":".join([f.path for f in compile_jars.to_list()]),
"--sources", ":".join([f.path for f in ctx.files.srcs]),
Expand Down Expand Up @@ -79,7 +82,7 @@ def _kotlin_do_compile_action(ctx, output_jar, compile_jars, opts):
ctx.action(
mnemonic = "KotlinCompile",
inputs = compile_inputs,
outputs = [output_jar, ctx.outputs.jdeps],
outputs = [output_jar, ctx.outputs.jdeps, compiler_output_base],
executable = ctx.executable._kotlinw,
execution_requirements = {"supports-workers": "1"},
arguments = ["@" + args_file.path],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@


import com.google.devtools.build.lib.worker.WorkerProtocol;
import io.bazel.ruleskotlin.workers.compilers.jvm.utils.Utils;
import io.bazel.ruleskotlin.workers.utils.IOUtils;

import java.io.*;
import java.nio.file.Files;
Expand Down Expand Up @@ -135,7 +135,7 @@ private List<String> loadArguments(List<String> args, boolean isWorker) {
}

private boolean wasInterrupted(Throwable e) {
Throwable cause = Utils.getRootCause(e);
Throwable cause = IOUtils.getRootCause(e);
if (cause instanceof InterruptedException
|| cause instanceof InterruptedIOException) {
output.println("Terminating worker due to interrupt signal");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.bazel.ruleskotlin.workers.compilers.jvm.actions;
package io.bazel.ruleskotlin.workers;

import io.bazel.ruleskotlin.workers.compilers.jvm.Context;

import java.util.function.Function;

Expand Down
120 changes: 120 additions & 0 deletions kotlin/workers/src/io/bazel/ruleskotlin/workers/CompileResult.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/*
* Copyright 2018 The Bazel Authors. All rights reserved.
*
* 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 io.bazel.ruleskotlin.workers;

import java.util.Optional;
import java.util.function.Function;
import java.util.function.Supplier;

@FunctionalInterface
public interface CompileResult {
/**
* The status of this operation.
*/
default int status() {
return 0;
}

default Optional<Exception> error() {
return Optional.empty();
}

default void propogateError(String message) throws RuntimeException {
error().ifPresent(e -> {
throw new RuntimeException(message, e);
});
}

static CompileResult just(final int status) {
return new CompileResult() {
@Override
public int status() {
return status;
}

@Override
public Integer render(Context ctx) {
return status;
}
};
}

static CompileResult error(final Exception error) {
return new CompileResult() {
@Override
public int status() {
return -1;
}

@Override
public Optional<Exception> error() {
return Optional.of(error);
}

@Override
public Integer render(Context ctx) {
throw new RuntimeException(error);
}
};
}

static CompileResult deferred(final int status, Function<Context, Integer> renderer) {
return new CompileResult() {
@Override
public int status() {
return status;
}

@Override
public Integer render(Context ctx) {
return renderer.apply(ctx);
}
};
}

final class Meta extends io.bazel.ruleskotlin.workers.Meta<CompileResult> {
public Meta(String id) {
super(id);
}

public CompileResult run(final Context ctx, Function<Context, Integer> op) {
CompileResult result;
try {
result = CompileResult.just(op.apply(ctx));
} catch (Exception e) {
result = CompileResult.error(e);
}
return result;
}

public CompileResult runAndBind(final Context ctx, Function<Context, Integer> op) {
CompileResult res = run(ctx, op);
bind(ctx, res);
return res;
}

public CompileResult runAndBind(final Context ctx, Supplier<Integer> op) {
return runAndBind(ctx, (c) -> op.get());
}
}

/**
* Materialise the output of the compile result.
*
* @return the new status of the compile operation, this shouldn't make a failing status pass, but it could fail a compile operation.
*/
Integer render(Context ctx);
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.bazel.ruleskotlin.workers.compilers.jvm;
package io.bazel.ruleskotlin.workers;

import java.util.*;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Context {
private final EnumMap<Flag, String> args = new EnumMap<>(Flag.class);
private final EnumMap<Flags, String> args = new EnumMap<>(Flags.class);
private final Map<Meta<?>, Object> meta = new HashMap<>();

private static final Map<String, Flag> ALL_FIELDS_MAP = Arrays.stream(Flag.values()).collect(Collectors.toMap(x -> x.name, x -> x));
private static final Flag[] MANDATORY_FIELDS = Arrays.stream(Flag.values()).filter(x -> x.mandatory).toArray(Flag[]::new);
private static final Map<String, Flags> ALL_FIELDS_MAP = Arrays.stream(Flags.values()).collect(Collectors.toMap(x -> x.name, x -> x));
private static final Flags[] MANDATORY_FIELDS = Arrays.stream(Flags.values()).filter(x -> x.mandatory).toArray(Flags[]::new);

private Context(List<String> args) {
if (args.size() % 2 != 0) {
Expand All @@ -33,27 +35,27 @@ private Context(List<String> args) {
for (int i = 0; i < args.size() / 2; i++) {
String flag = args.get(i * 2);
String value = args.get((i * 2) + 1);
Flag field = ALL_FIELDS_MAP.get(flag);
Flags field = ALL_FIELDS_MAP.get(flag);
if (field == null) {
throw new RuntimeException("unrecognised arg: " + flag);
}
this.args.put(field, value);
}

for (Flag mandatoryField : MANDATORY_FIELDS) {
for (Flags mandatoryField : MANDATORY_FIELDS) {
if (!this.args.containsKey(mandatoryField)) {
throw new RuntimeException("mandatory arg missing: " + mandatoryField.name);
}
}
}

static Context from(List<String> args) {
public static Context from(List<String> args) {
return new Context(args);
}

public EnumMap<Flag, String> copyOfArgsContaining(Flag... fields) {
EnumMap<Flag, String> result = new EnumMap<>(Flag.class);
for (Flag field : fields) {
public EnumMap<Flags, String> of(Flags... fields) {
EnumMap<Flags, String> result = new EnumMap<>(Flags.class);
for (Flags field : fields) {
String value = args.get(field);
if (value != null) {
result.put(field, value);
Expand All @@ -62,14 +64,23 @@ public EnumMap<Flag, String> copyOfArgsContaining(Flag... fields) {
return result;
}

String get(Flag field) {
public interface Action extends Consumer<Context> {
}

public void apply(Action... consumers) {
Stream.of(consumers).forEach(c -> c.accept(this));
}


String get(Flags field) {
return args.get(field);
}

@SuppressWarnings("unchecked")
<T> T get(Meta<T> key) {
return (T) meta.get(key);
}

@SuppressWarnings("unchecked")
<T> T putIfAbsent(Meta<T> key, T value) {
return (T) meta.putIfAbsent(key, value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,21 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.bazel.ruleskotlin.workers.compilers.jvm;
package io.bazel.ruleskotlin.workers;

public enum Flag {
LABEL("--label", null, true),
OUTPUT_CLASSJAR("--output_classjar", "-d", true),

public enum Flags {
// flags that line up with the java builder.
LABEL(JavaBuilderFlags.TARGET_LABEL.flag, null, true),
OUTPUT_CLASSJAR(JavaBuilderFlags.OUTPUT.flag, null, true),
SOURCES(JavaBuilderFlags.SOURCES.flag, null, true),
CLASSPATH(JavaBuilderFlags.CLASSPATH.flag, "-cp", true),

// flags that could be aligned with the java builder.
OUTPUT_JDEPS("--output_jdeps", null, true),
CLASSPATH("--classpath", "-cp", true),
SOURCES("--sources", null, true),
COMPILER_OUTPUT_BASE("--compiler_output_base", null, true),

// flags for kotlin.
KOTLIN_API_VERSION("--kotlin_api_version", "-api-version", false),
KOTLIN_LANGUAGE_VERSION("--kotlin_language_version", "-language-version", false),
KOTLIN_JVM_TARGET("--kotlin_jvm_target", "-jvm-target", false);
Expand All @@ -29,7 +36,7 @@ public enum Flag {
public final String kotlinFlag;
final boolean mandatory;

Flag(String name, String kotlinName, boolean mandatory) {
Flags(String name, String kotlinName, boolean mandatory) {
this.name = name;
this.kotlinFlag = kotlinName;
this.mandatory = mandatory;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright 2018 The Bazel Authors. All rights reserved.
*
* 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 io.bazel.ruleskotlin.workers;

/**
* Flags used by the java builder.
*/
@SuppressWarnings("unused")
public enum JavaBuilderFlags {
TARGET_LABEL("--target_label"),
CLASSPATH("--classpath"),
JAVAC_OPTS("--javacopts"),
DEPENDENCIES("--dependencies"),
DIRECT_DEPENDENCIES("--direct_dependencies"),
DIRECT_DEPENDENCY("--direct_dependency"),
INDIRECT_DEPENDENCY("--indirect_dependency"),
STRICT_JAVA_DEPS("--strict_java_deps"),
OUTPUT_DEPS_PROTO("--output_deps_proto"),
DEPS_ARTIFACTS("--deps_artifacts"),
REDUCE_CLASSPATH("--reduce_classpath"),
SOURCEGEN_DIR("--sourcegendir"),
GENERATED_SOURCES_OUTPUT("--generated_sources_output"),
OUTPUT_MANIFEST_PROTO("--output_manifest_proto"),
SOURCES("--sources"),
SOURCE_ROOTS("--source_roots"),
SOURCE_JARS("--source_jars"),
SOURCE_PATH("--sourcepath"),
BOOT_CLASSPATH("--bootclasspath"),
PROCESS_PATH("--processorpath"),
PROCESSORS("--processors"),
EXT_CLASSPATH("--extclasspath"),
EXT_DIR("--extdir"),
OUTPUT("--output"),
NATIVE_HEADER_OUTPUT("--native_header_output"),
CLASSDIR("--classdir"),
TEMPDIR("--tempdir"),
GENDIR("--gendir"),
POST_PROCESSOR("--post_processor"),
COMPRESS_JAR("--compress_jar"),
RULE_KIND("--rule_kind"),
TEST_ONLY("--testonly");

public final String flag;

JavaBuilderFlags(String flag) {
this.flag = flag;
}
}
Loading

0 comments on commit 78ee448

Please sign in to comment.