I've created Java annotations (since I need run time retention) under $PROJECT/src/main/java and my scala codewhich uses these java annotations us under $PROJECT/src/main/scala. The Java annotation thus created also makes use of a Java ENUM as it's value.
If I compile the project then sbt doesn't seem to compile the Java annotations first and errors out on each usage of the enum in annotations. If I comment out all usages of the Java enum in annotations in scala code and do a compile, uncomment enum usage and compile again it all works fine.
How do I ensure that sbt compiles my java annotations and enum (i.e. $PROJECT/src/main/java) before attempting to compile scala code when doing a clean build?
EDIT: I have a bare bones build.sbt and am using sbt 0.11.2
Some good news: This is a known issue and has been resolved.
Some bad news: It's resolved in 2.10 and the fix may not be backported to 2.9.3 (quoting Paul Phillips in the issue thread):
I've tagged this for backporting, which is not a guarantee; I don't
have time to do it right now but I expect to in the near future.
Some good news: If you're stuck on pre-2.10 and your Java sources don't depend on your Scala sources, you can just add the following to your build.sbt and all is well:
compileOrder := CompileOrder.JavaThenScala
Some bad news: If you're stuck on pre-2.10 and your Java sources do depend on your Scala sources, I'm pretty sure you're out of luck, and the comment-compile-uncomment trick is probably your best bet.
I'll bet you're facing SI-2764. This has been fixed in Scala 2.10.
In the meantime, create a separate sub-project for your Java annotations, and depend on this from the project containing the Scala code.. Then the Scala compiler will only process the .class files, rather the .java files.
Related
I would like to cross-build some of my Bazel targets to Scala 2.12 and 2.13. As a further point of complexity, I need to be able to express cross-target dependencies (eg. some 2.13 target may have a Bazel dependency on a 2.12 target).
Note: this isn't a regular library dependency (eg. with the dependency 2.12-built JAR showing up on the class path when compiling the 2.13 JAR), as that would almost surely result in issues due to having two incompatible versions of the Scala standard library on the class path. Rather, this is just a case where I need the dependency JAR built so I can use it in some integration tests in the 2.13 target.
What I've found online so far...
This issue from rules_scala seems it doesn't support baking the Scala version into the target and instead you have to pick the Scala version globally.
This Databricks post has a cross-building section that is exactly what I think I would like (eg. one target generated per library per supported Scala version), but the snippets in that post don't seem to be backed by any runnable Bazel code.
This later post by Databricks also hints at a cross_scala_lib rule, but also doesn't have any accompanying code.
https://docs.scala-lang.org/overviews/compiler-options/index.html says
Scala compiler scalac offers various compiler options, also referred to as compiler flags, to change how to compile your program.
Nowadays, most people are not running scalac from the command line. Instead, they use sbt, an IDE, and other tools as their interface to the compiler. Therefore they may not even have scalac installed, and won’t think to do man scalac.
Does "the compiler" refer to scalac?
If yes, is "they use sbt, an IDE, and other tools as their interface to the compiler" contrary to "therefore they may not even have scalac installed"?
Does sbt rely on scalac?
Thanks.
Scala compiler can be accessed programmatically via an API packaged by scala-compiler.jar dependency, hence tools such as IDEs and SBT can implement their own client frontends over this API to drive compiler functionality. scalac is just a bash script that executes scala.tools.nsc.MainClass class from scala-compiler.jar.
Does sbt rely on scalac?
No, sbt uses compiler API directly. One of the key concepts to understand regarding sbt is that the build definition is itself Scala code, either vanilla or DSL, but Scala nevertheless. The version of Scala used to compile the build definition is separate from the version of Scala used to compile project proper. The build definition source code in build.sbt and project/*.scala will be compiled using Scala version specified indirectly via sbt.version=1.2.8 setting in project/build.properties, whilst project source code proper in src/main/scala/* will be compiled using Scala version specified directly via scalaVersion := "2.13.1" setting in build.sbt. Note how they can indeed differ. Think of the build definition as simply another Scala app which uses sbt API for its implementation.
We use sbt-clojure in Scala project (https://github.com/Geal/sbt-clojure).
In one subproject there are Scala-code, which are imported in Clojure code.
In this case, Clojure doesn't see Scala-code (by "sbt compile", by default Clojure compiles earlier than Scala).
How can sbt compile Scala-code before Clojure-code?
I've faced the same issue and simply forked and modified the plugin: https://github.com/tomaszym/sbt-clojure Might be just enough also for you, if you don't mind firing clojurec instead of compile.
I would use Maven that supports both Scala and Clojure.
Maven has clojure-maven-plugin for Cloture and the maven-scala-plugin for Scala. You can arrange order of compilation of the both language source code.
I've got a Scala project that is built with Gradle. The Scala code is source compatible with scala 2.9 and 2.10 and I'd like to cross build it to both major Scala versions. Does Gradle support this?
For example, my gradle project will have a single module:
build.gradle
src/main/scala/foo.scala
and I'd like the resulting published jars to be:
org-foo_2.9-0.1.jar (with dependency on scala-library 2.9)
org-foo_2.10-0.1.jar (with dependency on scala-library 2.10)
Gradle's Scala plugin doesn't currently support cross-building. It's possible to implement it yourself, though. In my Polyglot Gradle talk, I presented a proof-of-concept.
I am searching for a good example of this. The Gradle manual doesn't mention how to specify Scala version but looking at the source code for the Scala plugin it seems to infer it from the Scala library jar that you specify.
The best example I could find is the Apache Kafka build system. It specifies the Scala version and then uses some additional logic to resolve the correct version of the Scala libraries. It also uses some logic to attach the correct label to the jars its builds to correspond to the correct Scala version.
This feels like a lot of work and something that the build system should do for you like in SBT.
I've just generated a fresh Play! application, version 2.1-RC1.
This one includes two Scala compiler/library couple:
Scala 2.9.2
Scala 2.10.0-RC1
The whole well compiles within IntelliJ IDEA 12 but a warning occurs as the image shows it:
It would seem so that another compiler is used instead 2.10.0-RC1.
However, my Scala facet is configured as this:
What might be the warning cause?
I precise that I've got also a Scala variable environment (used for shell Scala commands) configured to point to scala-2.10.0-RC2, but I well imagine that IntelliJ is based on library that user indicates in Scala Facet.
You can remove that .jar from the libraries, it's not used because it's redundantly generated by IntelliJ SBT plubin.