Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error compiling code that is source compatible, but binary incompatible, across library boundaries #4596

Closed
bhmiller opened this issue May 16, 2017 · 16 comments
Assignees
Labels
Milestone

Comments

@bhmiller
Copy link

Repro

pants.ini:

[GLOBAL]
pants_version: 1.3.0rc1

BUILD:

scala_library(
    name='MyLibrary',
    sources=['MyClass.scala'],
)

scala_library(
    name='MyApp',
    sources=['MyApp.scala'],
    dependencies=[':MyLibrary'],
)

jvm_binary(
    name='MyApp-bin',
    main='bar.MyApp',
    dependencies=[':MyApp'],
)

MyClass.scala:

package bar

object MyClass {
  def print(str1: String, str2: Option[String] = None) = {
    println(s"$str1 $str2")
  }
}

MyApp.scala:

package bar

object MyApp extends App {
  MyClass.print("hello")
}

Run ./pants run :MyApp-bin:

...
                   [1/2] Compiling 1 zinc source in 1 target (//:MyLibrary).
19:46:32 00:11       [compile]
...
19:47:35 01:14         [zinc]
                       [info] Compiling 1 Scala source to /<dir>/.pants.d/compile/zinc/c95338cea9cc/.MyLibrary/current/classes...
                       [info] Compile success at May 15, 2017 7:47:40 PM [4.662s]
                        
                   [2/2] Compiling 1 zinc source in 1 target (//:MyApp).
19:47:40 01:19       [compile]
                     
19:47:40 01:19         [zinc]
                       [info] Compiling 1 Scala source to /<dir>/.pants.d/compile/zinc/c95338cea9cc/.MyApp/current/classes...
                       [info] Compile success at May 15, 2017 7:47:41 PM [1.013s]
                       
19:47:41 01:20     [jvm-dep-check]
19:47:41 01:20   [run]
19:47:41 01:20     [py]
19:47:41 01:20     [jvm]
19:47:41 01:20       [run]
hello None

               Waiting for background workers to finish.
19:47:41 01:20   [complete]
               SUCCESS

Now edit MyClass.scala to add an optional 3rd argument to the method:

package bar

object MyClass {
  def print(str1: String, str2: Option[String] = None, str3: Option[String] = Some("foo")) = {
    println(s"$str1 $str2 $str3")
  }
}

And re-run ./pants run :MyApp-bin:

...
                   [1/2] Compiling 1 zinc source in 1 target (//:MyLibrary).
19:48:19 00:01       [compile]
                     
19:48:19 00:01         [zinc]
                       [info] Compiling 1 Scala source to /<dir>/.pants.d/compile/zinc/c95338cea9cc/.MyLibrary/current/classes...
                       [info] Compile success at May 15, 2017 7:48:19 PM [0.723s]
                        
                   [2/2] Compiling 1 zinc source in 1 target (//:MyApp).
19:48:19 00:01       [compile]
                     
19:48:19 00:01         [zinc]
                       [info] Compile success at May 15, 2017 7:48:19 PM [0.013s]
                       
19:48:19 00:01     [jvm-dep-check]
19:48:19 00:01   [run]
19:48:19 00:01     [py]
19:48:19 00:01     [jvm]
19:48:19 00:01       [run]
Exception in thread "main" java.lang.NoSuchMethodError: bar.MyClass$.print(Ljava/lang/String;Lscala/Option;)V
	at bar.MyApp$.delayedEndpoint$bar$MyApp$1(MyApp.scala:4)
	at bar.MyApp$delayedInit$body.apply(MyApp.scala:3)
	at scala.Function0.apply$mcV$sp(Function0.scala:34)
	at scala.Function0.apply$mcV$sp$(Function0.scala:34)
	at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
	at scala.App.$anonfun$main$1$adapted(App.scala:76)
	at scala.collection.immutable.List.foreach(List.scala:389)
	at scala.App.main(App.scala:76)
	at scala.App.main$(App.scala:74)
	at bar.MyApp$.main(MyApp.scala:3)
	at bar.MyApp.main(MyApp.scala)

FAILURE: java bar.MyApp ... exited non-zero (1)


19:48:20 00:02   [complete]

Interestingly, in futzing around with this repro, when I got a shared cache server involved, after the 2nd run's NoSuchMethodError, running ./pants clean-all, and then running again, the cache server had both compilations and then I could freely flip back and forth between versions of MyClass.scala and have run work fine in both cases without a clean-all. Context here is this error put all my build agents out of commission and so thus I was exploring to what extent the shared cache server helped or hindered here.

@stuhood
Copy link
Member

stuhood commented May 16, 2017

In your second run, you'll notice that the compile of //:MyApp did not compile any sources (the "Compiling X Scala sources to DIR" message is not reported by zinc). So this is almost certainly an incremental compile bug in zinc. We're hoping to update zinc during the 1.4.0.dev series (see #4477), which might address this issue and others.

Pants does not write incremental compiles to the buildcache by default (--no-compile-zinc-incremental-caching is set by default), for precisely this reason. So unless you enabled that option, the results of a incremental compile should never end up in any cache.

But you should always either 1) run ./pants clean-all between CI builds, or 2) set --no-compile-zinc-incremental (note: different option). If you disable incremental compile entirely, you rule out these issues.

zinc incremental compiles are a deal with the devil which is really only safe to make on developer machines. Whether we should invert the default and disable it by default is an open question.

@bhmiller
Copy link
Author

Hm, we've got [compile.zinc] incremental: False in our CI builds. Will play around to see if I can get a repro with that on.

@bhmiller
Copy link
Author

No difference. pants.ini:

[GLOBAL]
pants_version: 1.3.0rc1

[compile.zinc]
incremental: False

First run:

...
21:05:01 00:02   [compile]
21:05:01 00:02     [compile-jvm-prep-command]
21:05:01 00:02       [jvm_prep_command]
21:05:01 00:02     [compile-prep-command]
21:05:01 00:02     [compile]
21:05:01 00:02     [zinc]
21:05:01 00:02       [cache]  
                   No cached artifacts for 2 targets.
                   Invalidated 2 targets.
21:05:01 00:02       [isolation-zinc-pool-bootstrap] 
                   [1/2] Compiling 1 zinc source in 1 target (//:MyLibrary).
21:05:01 00:02       [compile]
                     
21:05:01 00:02         [cache] 
                     No cached artifacts for 1 target.
                     Invalidated 1 target.
21:05:01 00:02         [cache] 
21:05:01 00:02         [bootstrap-compiler-interface]
21:05:01 00:02         [cache] 
21:05:01 00:02         [bootstrap-jar-tool]
21:05:02 00:03         [cache] 
21:05:02 00:03         [bootstrap-jarjar]
21:05:03 00:04         [shade-compiler-interface]
21:05:04 00:05         [cache] 
21:05:04 00:05         [bootstrap-compiler-bridge]
21:05:04 00:05         [cache] 
                     No cached artifacts for 1 target.
                     Invalidated 1 target.
21:05:04 00:05         [cache] 
21:05:04 00:05         [bootstrap-zinc]
21:05:08 00:09         [shade-zinc]
21:05:56 00:57         [cache] 
21:05:56 00:57         [bootstrap-scalac_2_12]
21:05:57 00:58         [zinc]
                       [info] Compiling 1 Scala source to /<dir>/.pants.d/compile/zinc/c95338cea9cc/.MyLibrary/current/classes...
                       [info] Compile success at May 15, 2017 9:06:02 PM [4.817s]
                        
                   [2/2] Compiling 1 zinc source in 1 target (//:MyApp).
21:06:02 01:03       [compile]
                     
21:06:02 01:03         [zinc]
                       [info] Compiling 1 Scala source to /<dir>/.pants.d/compile/zinc/c95338cea9cc/.MyApp/current/classes...
                       [info] Compile success at May 15, 2017 9:06:03 PM [1.042s]
                       
21:06:03 01:04     [jvm-dep-check]
21:06:03 01:04   [pyprep]
21:06:03 01:04     [interpreter]
21:06:13 01:14     [requirements]
21:06:13 01:14     [sources]
21:06:14 01:15   [resources]
21:06:14 01:15     [prepare]
21:06:14 01:15     [services]
21:06:14 01:15   [run]
21:06:14 01:15     [py]
21:06:14 01:15     [jvm]
21:06:14 01:15       [run]
hello None

               Waiting for background workers to finish.
21:06:14 01:15   [complete]
               SUCCESS

Update MyClass and then run:

21:06:46 00:01   [compile]
21:06:46 00:01     [compile-jvm-prep-command]
21:06:46 00:01       [jvm_prep_command]
21:06:46 00:01     [compile-prep-command]
21:06:46 00:01     [compile]
21:06:46 00:01     [zinc]
21:06:46 00:01       [cache]  
                   No cached artifacts for 2 targets.
                   Invalidated 2 targets.
21:06:46 00:01       [isolation-zinc-pool-bootstrap] 
                   [1/2] Compiling 1 zinc source in 1 target (//:MyLibrary).
21:06:46 00:01       [compile]
                     
21:06:46 00:01         [zinc]
                       [info] Compiling 1 Scala source to /<dir>/.pants.d/compile/zinc/c95338cea9cc/.MyLibrary/current/classes...
                       [info] Compile success at May 15, 2017 9:06:46 PM [0.786s]
                        
                   [2/2] Compiling 1 zinc source in 1 target (//:MyApp).
21:06:46 00:01       [compile]
                     
21:06:46 00:01         [zinc]
                       [info] Compiling 1 Scala source to /<dir>/.pants.d/compile/zinc/c95338cea9cc/.MyApp/current/classes...
                       [info] Compile success at May 15, 2017 9:06:47 PM [0.701s]
                       
21:06:47 00:02     [jvm-dep-check]
21:06:47 00:02   [run]
21:06:47 00:02     [py]
21:06:47 00:02     [jvm]
21:06:47 00:02       [run]
Exception in thread "main" java.lang.NoSuchMethodError: bar.MyClass$.print(Ljava/lang/String;Lscala/Option;)V
	at bar.MyApp$.delayedEndpoint$bar$MyApp$1(MyApp.scala:4)
	at bar.MyApp$delayedInit$body.apply(MyApp.scala:3)
	at scala.Function0.apply$mcV$sp(Function0.scala:34)
	at scala.Function0.apply$mcV$sp$(Function0.scala:34)
	at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
	at scala.App.$anonfun$main$1$adapted(App.scala:76)
	at scala.collection.immutable.List.foreach(List.scala:389)
	at scala.App.main(App.scala:76)
	at scala.App.main$(App.scala:74)
	at bar.MyApp$.main(MyApp.scala:3)
	at bar.MyApp.main(MyApp.scala)

FAILURE: java bar.MyApp ... exited non-zero (1)


               Waiting for background workers to finish.
21:06:48 00:03   [complete]

So, am seeing the Compiling X Scala sources to DIR call you mentioned was previously missing, but still seeing the error.

@bhmiller
Copy link
Author

Interestingly, with incremental compilation off, ./pants clean-all no longer fixes the problem. I have to manually delete the .pants.d and .cache directories to get run to work again.

@stuhood
Copy link
Member

stuhood commented May 16, 2017

Yikes.

@stuhood stuhood added this to the 1.3.0 milestone May 16, 2017
@baroquebobcat baroquebobcat self-assigned this May 16, 2017
@baroquebobcat
Copy link
Contributor

I'm going to pull this into an integration test to see if I can check it against other pants versions.

@baroquebobcat
Copy link
Contributor

baroquebobcat commented May 18, 2017

got a reproduction working. Or, to be more precise, not working.

@baroquebobcat
Copy link
Contributor

testing on pants 1.2.1

@baroquebobcat
Copy link
Contributor

Testing on pants 1.2.1. It looks like 1.2.1 doesn't exhibit the behavior.

@baroquebobcat
Copy link
Contributor

now trying 1.3.0.dev4

@baroquebobcat
Copy link
Contributor

I've narrowed it down to a change between 1.3.0.dev16 and .dev19

@baroquebobcat
Copy link
Contributor

Between .dev18 and .dev19

@baroquebobcat
Copy link
Contributor

It's this one 94775d9

baroquebobcat added a commit to baroquebobcat/pants that referenced this issue May 18, 2017
stuhood pushed a commit that referenced this issue May 19, 2017
### Problem

With the 1.0.0-X5 version of sbt, there's a case where having use-classpath-jars enabled causes runtime failures because zinc/sbt incorrectly detect interface changes. (See #4596).

### Solution

Revert the commit making use-classpath-jars the default: 94775d9.

### Result

#4596 is fixed.
@stuhood
Copy link
Member

stuhood commented May 19, 2017

Fixed by #4607

@stuhood stuhood closed this as completed May 19, 2017
stuhood pushed a commit that referenced this issue May 19, 2017
### Problem

With the 1.0.0-X5 version of sbt, there's a case where having use-classpath-jars enabled causes runtime failures because zinc/sbt incorrectly detect interface changes. (See #4596).

### Solution

Revert the commit making use-classpath-jars the default: 94775d9.

### Result

#4596 is fixed.
@mateor
Copy link
Member

mateor commented May 26, 2017

Arg...too bad. Is the hope that the 1.4.0 zinc upgrade could make this a possibility again?

@stuhood
Copy link
Member

stuhood commented May 26, 2017

Yea, hopefully. See #4477. Also, there is some movement on this upstream.

stuhood pushed a commit that referenced this issue May 17, 2018
### Problem

We didn't have test coverage for source compatible, binary incompatible incremental changes for compiles with zinc.

### Solution

Add a test case that covers it.

### Result

If #4596 comes up again, it should be caught in the tests.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants