blob: 193a6836f1fc31806e28208e4c8e03d6fd1a7b58 [file] [log] [blame]
# Copyright 2015 Google Inc. 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.
"""Rules for supporting the Scala language."""
_scala_filetype = FileType([".scala"])
# TODO(bazel-team): Add local_repository to properly declare the dependency.
_scala_library_path = "/usr/share/java/scala-library.jar"
_scalac_path = "/usr/bin/scalac"
def _compile(ctx, jars):
cmd = """
set -e
mkdir -p {out}_tmp
{scalac} {scala_opts} {jvm_flags} -classpath "{jars}" $@ -d {out}_tmp
# Make jar file deterministic by setting the timestamp of files
touch -t 198001010000 $(find .)
jar cmf {manifest} {out} -C {out}_tmp .
"""
cmd = cmd.format(
scalac=_scalac_path,
scala_opts=" ".join(ctx.attr.scalacopts),
jvm_flags=" ".join(["-J" + flag for flag in ctx.attr.jvm_flags]),
out=ctx.outputs.jar.path,
manifest=ctx.outputs.manifest.path,
jars=":".join([j.path for j in jars]))
ctx.action(
inputs=list(jars) + ctx.files.srcs + [ctx.outputs.manifest],
outputs=[ctx.outputs.jar],
command=cmd,
progress_message="scala %s" % ctx.label,
arguments=[f.path for f in ctx.files.srcs])
def _write_manifest(ctx):
cp = "/usr/share/java/scala-library.jar"
manifest = "Class-Path: %s\n" % cp
if getattr(ctx.attr, "main_class", ""):
manifest += "Main-Class: %s\n" % ctx.attr.main_class
ctx.file_action(
output = ctx.outputs.manifest,
content = manifest)
def _write_launcher(ctx, jars):
content = """#!/bin/bash
cd $0.runfiles
java -cp {cp} {name} "$@"
"""
content = content.format(
name=ctx.attr.main_class,
deploy_jar=ctx.outputs.jar.path,
cp=":".join([j.short_path for j in jars]))
ctx.file_action(
output=ctx.outputs.executable,
content=content)
def _collect_jars(ctx):
jars = set()
for target in ctx.attr.deps:
if hasattr(target, "jar_files"):
jars += target.jar_files
elif hasattr(target, "java"):
jars += target.java.transitive_runtime_deps
return jars
def _scala_library_impl(ctx):
jars = _collect_jars(ctx)
_write_manifest(ctx)
_compile(ctx, jars)
jars += [ctx.outputs.jar]
runfiles = ctx.runfiles(
files = list(jars),
collect_data = True)
return struct(
files=jars,
jar_files=jars,
runfiles=runfiles)
def _scala_binary_impl(ctx):
jars = _collect_jars(ctx)
_write_manifest(ctx)
_compile(ctx, jars)
jars += [ctx.outputs.jar]
_write_launcher(ctx, jars)
runfiles = ctx.runfiles(
files = list(jars) + [ctx.outputs.executable],
collect_data = True)
return struct(
files=set([ctx.outputs.executable]),
runfiles=runfiles)
scala_library = rule(
implementation=_scala_library_impl,
attrs={
"main_class": attr.string(),
"srcs": attr.label_list(
allow_files=_scala_filetype,
non_empty=True),
"deps": attr.label_list(),
"data": attr.label_list(allow_files=True, cfg=DATA_CFG),
"scalacopts": attr.string_list(),
"jvm_flags": attr.string_list(),
},
outputs={
"jar": "%{name}_deploy.jar",
"manifest": "%{name}_MANIFEST.MF",
},
)
scala_binary = rule(
implementation=_scala_binary_impl,
attrs={
"main_class": attr.string(mandatory=True),
"srcs": attr.label_list(
allow_files=_scala_filetype,
non_empty=True),
"deps": attr.label_list(),
"data": attr.label_list(allow_files=True, cfg=DATA_CFG),
"scalacopts":attr.string_list(),
"jvm_flags": attr.string_list(),
},
outputs={
"jar": "%{name}_deploy.jar",
"manifest": "%{name}_MANIFEST.MF",
},
executable=True,
)