Skip to content

Commit

Permalink
Don't allow transitive scala_library dependencies onto the classpath
Browse files Browse the repository at this point in the history
Without this patch, scala and java "deps of deps" end up on the
classpath. This isn't the way java_library rules work:

    A rule X can access the code in Y if there exists a dependency
    path between them that begins with a deps edge followed by zero
    or more exports edges.

I verified my understanding of this behavior with a small test repo,
copying one of the tests from this repo and changing 'scala_' to
'java_':
https://gist.github.com/colinmarc/c683652ef9a7d817c5e7ce9ca1236a6d

This patch fixes that, and all the tests that were incorrectly
depending on the behavior. It also adds some negative tests for the
behavior, under `test_transitive_deps`.

Unfortunately, this is going to be majorly backwards incompatible
with existing scala repositories.
  • Loading branch information
colinmarc committed Jun 8, 2016
1 parent 5dbb873 commit ebaeff6
Show file tree
Hide file tree
Showing 23 changed files with 189 additions and 67 deletions.
2 changes: 1 addition & 1 deletion scala/scala.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ def _lib(ctx, non_macro_lib):
texp = _collect_jars(ctx.attr.exports)
scalaattr = struct(outputs = rule_outputs,
transitive_runtime_deps = rjars,
transitive_compile_exports = texp.compiletime + cjars,
transitive_compile_exports = texp.compiletime,
transitive_runtime_exports = texp.runtime
)
runfiles = ctx.runfiles(
Expand Down
2 changes: 1 addition & 1 deletion test/A.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ object A {
def main(args: Array[String]) {
println("4 8 15 16 23 42")
}
}
}
26 changes: 3 additions & 23 deletions test/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ scala_library(
deps = [
"OtherJavaLib",
"OtherLib",
"MacroTest"
"MacroTest",
"Exported"
],
)

Expand All @@ -87,31 +88,10 @@ scala_repl(
name = "HelloLibTestRepl",
deps = [":HelloLibTest"])

scala_library(
name = "a",
srcs = ["A.scala"]
)

scala_library(
name = "b",
exports = [":a"],
)

scala_library(
name = "c",
deps = [":b"],
)

scala_library(
name = "d",
deps = [":c"],
srcs = ["D.scala"],
)

scala_library(
name = "OtherLib",
srcs = ["OtherLib.scala"],
exports = ["ExportOnly"], # test of exported target
deps = ["ExportOnly"],
)

# Test of library without src
Expand Down
2 changes: 1 addition & 1 deletion test/D.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ object D {
def main(args: Array[String]) {
A.main(args)
}
}
}
2 changes: 1 addition & 1 deletion test/HelloLibTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ object TestUtil {

class ScalaSuite extends FlatSpec {
"HelloLib" should "call scala" in {
assert(HelloLib.getOtherLibMessage("hello").equals("hello scala!"))
assert(HelloLib.getOtherLibMessage("hello").equals("hello you all, everybody. I am Runtime"))
}
}

Expand Down
6 changes: 1 addition & 5 deletions test/OtherLib.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,5 @@ package scala.test

// It is just to show how a Scala library can depend on another Scala library.
object OtherLib {
def getMessage(): String = {
// This won't compile because Exported is exported, not a dep:
// Exported.message
"scala!"
}
def getMessage(): String = Exported.message
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
package scala.test

object ClassProvider {
def dissappearingClassMethod: String = "testContents"
}


object BackgroundNoise{}
6 changes: 4 additions & 2 deletions test/src/main/scala/scala/test/twitter_scrooge/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ scala_library(
name = "justscrooge1",
srcs = ["JustScrooge1.scala"],
deps = [":scrooge1"],
exports = [":scrooge1"]
)

scala_library(
Expand All @@ -68,6 +69,7 @@ scala_library(
name = "justscrooge3",
srcs = ["JustScrooge3.scala"],
deps = [":scrooge3"],
exports = [":scrooge3"],
)

scala_library(
Expand Down Expand Up @@ -107,7 +109,7 @@ scala_binary(

scala_library(
name = "allscrooges",
deps = [
exports = [
":scrooge1",
":scrooge2_a",
":scrooge2_b",
Expand All @@ -120,4 +122,4 @@ scala_binary(
srcs = ["JustScrooge1.scala"],
deps = [":allscrooges"],
main_class = "scala.test.twitter_scrooge.JustScrooge1",
)
)
8 changes: 8 additions & 0 deletions test_expect_failure/disappearing_class/ClassProvider.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package scala.test

object ClassProvider {
def dissappearingClassMethod: String = "testContents"
}


object BackgroundNoise{}
7 changes: 7 additions & 0 deletions test_expect_failure/transitive/java_to_scala/A.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package example

object A {
def foo {
println("hi")
}
}
24 changes: 24 additions & 0 deletions test_expect_failure/transitive/java_to_scala/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
load("//scala:scala.bzl", "scala_library", "scala_export_to_java")

scala_library(
name = "a",
srcs = ["A.scala"]
)

scala_export_to_java(
name = "b",
exports = [":a"],
runtime_deps = []
)

java_library(
name = "c",
srcs = ["C.java"],
deps = [":b"],
)

java_library(
name = "d",
srcs = ["D.java"],
deps = [":c"],
)
3 changes: 3 additions & 0 deletions test_expect_failure/transitive/java_to_scala/C.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package example;

public class C {}
7 changes: 7 additions & 0 deletions test_expect_failure/transitive/java_to_scala/D.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package example;

public class D {
public static void main(String[] args) {
A.foo();
}
}
7 changes: 7 additions & 0 deletions test_expect_failure/transitive/scala_to_java/A.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package example;

public class A {
public static void foo() {
System.out.println("yeah?");
}
}
22 changes: 22 additions & 0 deletions test_expect_failure/transitive/scala_to_java/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
load("//scala:scala.bzl", "scala_library")

java_library(
name = "a",
srcs = ["A.java"]
)

scala_library(
name = "b",
exports = [":a"],
)

scala_library(
name = "c",
deps = [":b"],
)

scala_library(
name = "d",
deps = [":c"],
srcs = ["D.scala"],
)
7 changes: 7 additions & 0 deletions test_expect_failure/transitive/scala_to_java/D.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package example

object D {
def main(args: Array[String]) {
A.foo
}
}
7 changes: 7 additions & 0 deletions test_expect_failure/transitive/scala_to_scala/A.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package example

object A {
def foo {
println("hi")
}
}
22 changes: 22 additions & 0 deletions test_expect_failure/transitive/scala_to_scala/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
load("//scala:scala.bzl", "scala_library")

scala_library(
name = "a",
srcs = ["A.scala"]
)

scala_library(
name = "b",
exports = [":a"],
)

scala_library(
name = "c",
deps = [":b"],
)

scala_library(
name = "d",
deps = [":c"],
srcs = ["D.scala"],
)
7 changes: 7 additions & 0 deletions test_expect_failure/transitive/scala_to_scala/D.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package example

object D {
def main(args: Array[String]) {
A.foo
}
}
40 changes: 33 additions & 7 deletions test_run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
set -e

test_disappearing_class() {
git checkout test/src/main/scala/scala/test/disappearing_class/ClassProvider.scala
bazel build test/src/main/scala/scala/test/disappearing_class:uses_class
echo -e "package scala.test\n\nobject BackgroundNoise{}" > test/src/main/scala/scala/test/disappearing_class/ClassProvider.scala
git checkout test_expect_failure/disappearing_class/ClassProvider.scala
bazel build test_expect_failure/disappearing_class:uses_class
echo -e "package scala.test\n\nobject BackgroundNoise{}" > test_expect_failure/disappearing_class/ClassProvider.scala
set +e
bazel build test/src/main/scala/scala/test/disappearing_class:uses_class
bazel build test_expect_failure/disappearing_class:uses_class
RET=$?
git checkout test/src/main/scala/scala/test/disappearing_class/ClassProvider.scala
git checkout test_expect_failure/disappearing_class/ClassProvider.scala
if [ $RET -eq 0 ]; then
echo "Class caching at play. This should fail"
exit 1
Expand All @@ -18,14 +18,39 @@ test_disappearing_class() {
}

test_build_is_identical() {
bazel build test/...
bazel build test/...
md5sum bazel-bin/test/*.jar > hash1
bazel clean
bazel build test/...
bazel build test/...
md5sum bazel-bin/test/*.jar > hash2
diff hash1 hash2
}

test_transitive_deps() {
set +e

bazel build test_expect_failure/transitive/scala_to_scala/...
if [ $? -eq 0 ]; then
echo "'bazel build test_expect_failure/transitive/scala_to_scala/...' should have failed."
exit 1
fi

bazel build test_expect_failure/transitive/java_to_scala/...
if [ $? -eq 0 ]; then
echo "'bazel build test_expect_failure/transitive/java_to_scala/...' should have failed."
exit 1
fi

bazel build test_expect_failure/transitive/scala_to_java/...
if [ $? -eq 0 ]; then
echo "'bazel build test_transitive_deps/scala_to_java/...' should have failed."
exit 1
fi

set -e
exit 0
}

test_repl() {
echo "import scala.test._; HelloLib.printMessage(\"foo\")" | bazel-bin/test/HelloLibRepl | grep "foo scala" &&
echo "import scala.test._; TestUtil.foo" | bazel-bin/test/HelloLibTestRepl | grep "bar" &&
Expand All @@ -43,5 +68,6 @@ bazel build test/... \
&& (find -L ./bazel-testlogs -iname "*.xml" | xargs -n1 xmllint > /dev/null) \
&& test_disappearing_class \
&& test_build_is_identical \
&& test_transitive_deps \
&& test_repl \
&& echo "all good"
44 changes: 23 additions & 21 deletions twitter_scrooge/twitter_scrooge.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ def _assert_set_is_subset(left, right):
missing += [l]
if len(missing) > 0:
fail('scrooge_srcjar target must depend on scrooge_srcjar targets sufficient to ' +
'cover the transitive graph of thrift files. Uncovered sources: ' + missing)
'cover the transitive graph of thrift files. Uncovered sources: ' + str(missing))

def _path_newline(data):
return '\n'.join([f.path for f in data])
Expand Down Expand Up @@ -201,23 +201,25 @@ scrooge_scala_srcjar = rule(
)

def scrooge_scala_library(name, deps=[], remote_jars=[], jvm_flags=[], visibility=None):
scrooge_scala_srcjar(
name = name + '_srcjar',
deps = deps,
remote_jars = remote_jars,
visibility = visibility,
)
scala_library(
name = name,
deps = remote_jars + [
name + '_srcjar',
"@libthrift//jar",
"@scrooge_core//jar",
],
exports = [
"@libthrift//jar",
"@scrooge_core//jar",
],
jvm_flags = jvm_flags,
visibility = visibility,
)
srcjar = name + '_srcjar'
scrooge_scala_srcjar(
name = srcjar,
deps = deps,
remote_jars = remote_jars,
visibility = visibility,
)

scala_library(
name = name,
deps = deps + remote_jars + [
srcjar,
"@libthrift//jar",
"@scrooge_core//jar"
],
exports = deps + remote_jars + [
"@libthrift//jar",
"@scrooge_core//jar",
],
jvm_flags = jvm_flags,
visibility = visibility,
)

0 comments on commit ebaeff6

Please sign in to comment.