Skip to content

Commit 5e76791

Browse files
committed
Merge pull request #5 from bazelbuild/johnynek/support_empty_srcs
Support empty srcs
2 parents 3871e90 + ee2cb16 commit 5e76791

File tree

6 files changed

+93
-16
lines changed

6 files changed

+93
-16
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
bazel-*

scala/scala.bzl

Lines changed: 58 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,40 @@ def _adjust_resources_path(path):
2626
return dir_1 + dir_2, rel_path
2727
return "", path
2828

29+
def _build_nosrc_jar(ctx, buildijar):
30+
res_cmd = ""
31+
for f in ctx.files.resources:
32+
c_dir, res_path = _adjust_resources_path(f.path)
33+
change_dir = "-C " + c_dir if c_dir else ""
34+
res_cmd = "\n{jar} uf {out} " + change_dir + " " + res_path
35+
ijar_cmd = ""
36+
if buildijar:
37+
ijar_cmd = "\ncp {out} {ijar_out}".format(
38+
out=ctx.outputs.jar.path,
39+
ijar_out=ctx.outputs.ijar.path)
40+
cmd = """
41+
set -e
42+
# Make jar file deterministic by setting the timestamp of files
43+
touch -t 198001010000 {manifest}
44+
{jar} cmf {manifest} {out}
45+
""" + ijar_cmd + res_cmd
46+
cmd = cmd.format(
47+
out=ctx.outputs.jar.path,
48+
manifest=ctx.outputs.manifest.path,
49+
jar=ctx.file._jar.path)
50+
outs = [ctx.outputs.jar]
51+
if buildijar:
52+
outs.extend([ctx.outputs.ijar])
53+
ctx.action(
54+
inputs=
55+
ctx.files.resources +
56+
ctx.files._jdk +
57+
[ctx.outputs.manifest, ctx.file._jar],
58+
outputs=outs,
59+
command=cmd,
60+
progress_message="scala %s" % ctx.label,
61+
arguments=[])
62+
2963
def _compile(ctx, jars, buildijar):
3064
res_cmd = ""
3165
for f in ctx.files.resources:
@@ -71,6 +105,21 @@ touch -t 198001010000 {manifest}
71105
progress_message="scala %s" % ctx.label,
72106
arguments=[f.path for f in ctx.files.srcs])
73107

108+
def _compile_or_empty(ctx, jars, buildijar):
109+
if len(ctx.files.srcs) == 0:
110+
_build_nosrc_jar(ctx, buildijar)
111+
# no need to build ijar when empty
112+
return struct(ijar=ctx.outputs.jar, class_jar=ctx.outputs.jar)
113+
else:
114+
_compile(ctx, jars, buildijar)
115+
ijar = None
116+
if buildijar:
117+
ijar = ctx.outputs.ijar
118+
else:
119+
# macro code needs to be available at compile-time, so set ijar == jar
120+
ijar = ctx.outputs.jar
121+
return struct(ijar=ijar, class_jar=ctx.outputs.jar)
122+
74123
def _write_manifest(ctx):
75124
# TODO(bazel-team): I don't think this classpath is what you want
76125
manifest = "Class-Path: %s\n" % ctx.file._scalalib.path
@@ -142,24 +191,22 @@ def _collect_jars(targets):
142191
compile_jars += target.files
143192
return struct(compiletime = compile_jars, runtime = runtime_jars)
144193

145-
def _lib(ctx, use_ijar):
194+
def _lib(ctx, non_macro_lib):
146195
jars = _collect_jars(ctx.attr.deps)
147196
(cjars, rjars) = (jars.compiletime, jars.runtime)
148197
_write_manifest(ctx)
149-
_compile(ctx, cjars, use_ijar)
198+
outputs = _compile_or_empty(ctx, cjars, non_macro_lib)
150199

151200
rjars += [ctx.outputs.jar]
152201
rjars += _collect_jars(ctx.attr.runtime_deps).runtime
153202

154-
ijar = None
155-
if use_ijar:
156-
ijar = ctx.outputs.ijar
157-
else:
158-
# macro code needs to be available at compile-time, so set ijar == jar
159-
ijar = ctx.outputs.jar
203+
if not non_macro_lib:
204+
# macros need the scala reflect jar
205+
cjars += [ctx.file._scalareflect]
206+
rjars += [ctx.file._scalareflect]
160207

161208
texp = _collect_jars(ctx.attr.exports)
162-
scalaattr = struct(outputs = struct(ijar=ijar, class_jar=ctx.outputs.jar),
209+
scalaattr = struct(outputs = outputs,
163210
transitive_runtime_deps = rjars,
164211
transitive_compile_exports = texp.compiletime,
165212
transitive_runtime_exports = texp.runtime
@@ -180,7 +227,7 @@ def _scala_macro_library_impl(ctx):
180227
# Common code shared by all scala binary implementations.
181228
def _scala_binary_common(ctx, cjars, rjars):
182229
_write_manifest(ctx)
183-
_compile(ctx, cjars, False) # no need to build an ijar for an executable
230+
_compile_or_empty(ctx, cjars, False) # no need to build an ijar for an executable
184231

185232
runfiles = ctx.runfiles(
186233
files = list(rjars) + [ctx.outputs.executable] + [ctx.file._java] + ctx.files._jdk,
@@ -221,8 +268,7 @@ _implicit_deps = {
221268
# Common attributes reused across multiple rules.
222269
_common_attrs = {
223270
"srcs": attr.label_list(
224-
allow_files=_scala_filetype,
225-
non_empty=True),
271+
allow_files=_scala_filetype),
226272
"deps": attr.label_list(),
227273
"runtime_deps": attr.label_list(),
228274
"data": attr.label_list(allow_files=True, cfg=DATA_CFG),
@@ -249,7 +295,6 @@ scala_macro_library = rule(
249295
attrs={
250296
"main_class": attr.string(),
251297
"exports": attr.label_list(allow_files=False),
252-
"_scala-reflect": attr.label(default=Label("@scala//:lib/scala-reflect.jar"), single_file=True, allow_files=True),
253298
} + _implicit_deps + _common_attrs,
254299
outputs={
255300
"jar": "%{name}_deploy.jar",

test/BUILD

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
load("//scala:scala.bzl", "scala_binary", "scala_library", "scala_test")
1+
load("//scala:scala.bzl", "scala_binary", "scala_library", "scala_test", "scala_macro_library")
22

33
# The examples below show how to combine Scala and Java rules.
44
# ScalaBinary is the Scala equivalent of JavaBinary.
@@ -21,7 +21,7 @@ scala_binary(
2121
name = "ScalaBinary",
2222
srcs = ["ScalaBinary.scala"],
2323
main_class = "scala.test.ScalaBinary",
24-
deps = [":HelloLib"],
24+
deps = [":HelloLib", ":MacroTest"],
2525
)
2626

2727
scala_library(
@@ -30,6 +30,7 @@ scala_library(
3030
deps = [
3131
"OtherJavaLib",
3232
"OtherLib",
33+
"MacroTest"
3334
],
3435
)
3536

@@ -49,7 +50,13 @@ scala_test(
4950
scala_library(
5051
name = "OtherLib",
5152
srcs = ["OtherLib.scala"],
52-
exports = ["Exported"], # test of exported target
53+
exports = ["ExportOnly"], # test of exported target
54+
)
55+
56+
# Test of library without src
57+
scala_library(
58+
name = "ExportOnly",
59+
exports = [ "Exported" ],
5360
)
5461

5562
scala_library(
@@ -58,6 +65,11 @@ scala_library(
5865
runtime_deps = ["Runtime"],
5966
)
6067

68+
scala_macro_library(
69+
name = "MacroTest",
70+
srcs = ["MacroTest.scala"]
71+
)
72+
6173
scala_library(
6274
name = "Runtime",
6375
srcs = ["Runtime.scala"],

test/HelloLib.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ package scala.test
1616

1717
object HelloLib {
1818
def printMessage(arg: String) {
19+
MacroTest.hello(arg == "yo")
1920
println(getOtherLibMessage(arg))
2021
println(getOtherJavaLibMessage(arg))
2122
println(Exported.message)

test/MacroTest.scala

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package scala.test
2+
3+
import language.experimental.macros
4+
5+
import reflect.macros.Context
6+
7+
object MacroTest {
8+
def hello(param: Any): Unit = macro hello_impl
9+
10+
def hello_impl(c: Context)(param: c.Expr[Any]): c.Expr[Unit] = {
11+
import c.universe._
12+
val paramRep = show(param.tree)
13+
val paramRepTree = Literal(Constant(paramRep))
14+
val paramRepExpr = c.Expr[String](paramRepTree)
15+
reify { println(paramRepExpr.splice + " = " + param.splice) }
16+
}
17+
}

test/ScalaBinary.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ package scala.test
1616

1717
object ScalaBinary {
1818
def main(args: Array[String]) {
19+
println(MacroTest.hello(1 + 2))
1920
HelloLib.printMessage("Hello");
2021
}
2122
}

0 commit comments

Comments
 (0)