how to compile single file in sbt - scala

I'm doing some refactoring that made compiler temporally give errors in several files. I'd like to work with them one by one (starting with common dependencies) and need some tool to check if modification is correct.
sbt compile is inconvenient because it gives too many errors and spends much time for compiling things that have no good.
I'm searching for a way to compile single file with sbt or a method for extracting sbt side libraries definition to pass them to a normal scalac compiler
There was a similar topic: How to compile just some files with sbt? that turned out to be source code error discussion rather that sbt functionality disclosure.

You could add the following line to build.sbt:
sources in Compile <<= (sources in Compile).map(_ filter(_.name == "Particular.scala"))
Then fix Particular.scala, then edit build.sbt and put the name of the next source file. If you keep the sbt console open, reload will re-read the .sbt file after you modify it.

I just wanted to mention here that I came across sbt-compile-quick-plugin (https://github.com/etsy/sbt-compile-quick-plugin). It does what it says on the tin, just add addSbtPlugin("com.etsy" % "sbt-compile-quick-plugin" % "1.3.0") to your project/plugins.sbt, then you can just start up sbt and run compileQuick /path/to/your/file

Related

Scala "not found: object com" - should i really add entry in build.sbt if there are no other dependencies?

I have created basic Scala Play application with https://www.playframework.com/getting-started play-scala-seed. This project compiles and runs with sbt run. But I have another Scala project that compiles and runs and which I have submitted to my local Ivy repository with command sbt publishLocal. This other project was saved at C:\Users\tomr\.ivy2\local\com.agiintelligence\scala-isabelle_2.13\master-SNAPSHOT as a result of this command.
Then I imported (exactly so - imported, no just opened) my Play project in IntelliJ and I used Project - Open Module Settings - Project Settings - Libraries to add com.agiintelligence jar from my ivy2 location. After such operations IntelliJ editor recognizes com.agiintelligence classes. That is fine.
But when I am trying to run my Play application with sbt run, I experience the error message not found: object com that is exactly when compiling import com.agiintelligence line in my Scala controller file of Play application.
Of course - such error has been reported and resolved with, e.g. object play not found in scala application
But that solution suggests to append build.sbt file. My build.sbt file is pretty bare:
name := """agiintelligence"""
organization := "com.agiintelligence"
version := "1.0-SNAPSHOT"
lazy val root = (project in file(".")).enablePlugins(PlayScala)
scalaVersion := "2.13.5"
libraryDependencies += guice
libraryDependencies += "org.scalatestplus.play" %% "scalatestplus-play" % "5.0.0" % Test
// Adds additional packages into Twirl
//TwirlKeys.templateImports += "com.skaraintelligence.controllers._"
// Adds additional packages into conf/routes
// play.sbt.routes.RoutesKeys.routesImport += "com.skaraintelligence.binders._"
My Play application contains (as can bee seen from the IntelliJ project pane) some tens of 'external libraries' (it shows my com.agiintelligence jar as well), but why should I add my own ivy2 library in build.sbt file if no other libraries are listed here? What is different with my library? It is on my computer, in the repository as expected already?
Of course, I can try to add it build.sbt and issue sbt update and see what happens, but I can not understand this logic? Can someone explain it and provide some clue to intelligible solution of my error message?
My Play application contains (as can bee seen from the IntelliJ project pane) some tens of 'external libraries'
Those are probably just transitive dependencies of your Play dependency, that is why sbt downloaded all of them and put them in your classpath so you could use them without you needing to tell it about them; because the pom of Play already did.
It is not that the build tool or the IDE magically added all those dependencies for you because they read your mind and magically understood you wanted them. And that for some reason the magic stopped working for your own library.
Why it is not sufficient to list it Project-Setting--External Libraries in IntelliJ only?
That is sufficient for the IDE to work, but not for the build tool. The build tool is independent of the IDE; it doesn't know about it. sbt just knows about the dependencies you configured in your definition file.
Even more, you should always configure your dependencies on your build tool and then import that in the IDE; rather than the opposite. IDEs are graphical tools, so their state can not be committed, can not be shared, can not keep track of changes, can not be used in CI / CD environments; additionally, different teammates may want to use different IDEs.
I resolved the error message by adding line in build.sbt file
libraryDependencies += "de.unruh" %% "scala-isabelle" % "master-SNAPSHOT"
and by subsequent run of sbt update.
Error is solved, but the main question still stand - why I had to do this? Why there are tens of dependencies that are not listed in build.sbt and why should I list my dependency in build.sbt and why it is not sufficient to list it Project-Setting--External Libraries in IntelliJ only?
OK, comment by #Luis_Miguel_Mejía_Suárez gave the explanation, that comment is the actual and expected answer to my question.

How to use SBT's externalPom() command

I have a Maven POM file that the deployment engineers need to deploy the system in the enterprise. I have developers using SBT for a Scala project. They use SBT targets that just aren't supported in Maven. We'd like to use the Maven POM file to define the dependencies, slurp in those dependencies in SBT, and define SBT development targets there.
According to the SBT documentation, the externalPom() command is the way to do that. But even with the simplest POM file (two developers have tried this with two different simple POM files that defined different dependencies), the externalPom() command seems to half work. The SBT targets clearly recognize the dependency defined in the POM, but can't resolve it. This error arises:
Cannot add dependency 'commons-collections#commons-collections;3.2.2'
to configuration 'default' of module
default#maven-sbt$sources_javadoc;0.1-SNAPSHOT because this
configuration doesn't exist!
When the externalPom() command is commented out and the equivalent dependency added directly in the build.sbt file everything goes swimmingly. The dependency comes directly from Maven Central in both cases; one from copying the dependency from the Maven tab and one from copying the dependency from the SBT tab. Once again, two developers are seeing exactly the same thing, from two different dependencies. The thing that's common is that both developers have reduced the build.sbt file down to a single statement. In the "slurp from POM" case, that statement is externalPom(). In the "plain old SBT" case, that statement is the dependency copied from Maven Central. The POM file is a dependency list with a single dependency (as simple as we can make it and still test externalPom()).
We suspect that we need something else in the build.sbt to make the externalPom() command work but we don't know what it is. Any help with that would be greatly appreciated.
I did some experimentation with this, and was able to replicate your error in my experiments.
I'm still a bit of a Scala / SBT newbie, but I created a build.sbt file that looks like so:
val Default = config("default")
lazy val root = (project in file(".")).
configs(Default).
settings(
externalPom()
)
This did compile for me!
One non-obvious catch: I had to make sure to include the scala-library in my POM file as a dependency

How to synchronize Intellij and sbt builds for a scala project

I have an sbt project that I have imported into Intellij. Sometimes I build the project at the command line using sbt, and then when I need to debug I build it from within Intellij. However, each time I alternate it requires a full rebuild when there is no need. Both build procedures output to the same class folder, namely .../target/scala-2.11/classes, so I don't understand why a full rebuild keeps happening?
As stated by CrazyCoder, intellij and sbt build have each their own tracking of changed files for incremental build. Thus each time one re-compile a file, the other treats it as a changed file and recompile it too.
While CrazyCoder's answer describes how to make them work on separated directory, by changing the sbt compiled classes dir. This answer explain how you can configure Intellij to use sbt for all build, thus only sbt does the compilation. This is a relatively new feature.
Just check the option:
file
> Settings
> Build, Execution, Deployment
> Build Tools
> SBT
> Use SBT shell for build and import
It works at least since intellij version 2017.2.3, and most probably it is an option from the SBT plugin.
For details about this feature, see jetbrains ticket: https://youtrack.jetbrains.com/issue/SCL-10984
IntelliJ IDEA cannot reuse the classes produced by the other build systems because it has its own incremental compiler which tracks the dependencies and builds the caches during the compilation so that it can compile only modified and dependent files when you make a change in the code. When you built with SBT/Maven/Gradle or command line javac, IntelliJ IDEA compiler cache doesn't know about what has changed and which files it should compile, therefore it performs the full rebuild.
A solution would be to use different output directories for IDE and SBT, this way IntelliJ IDEA will rebuild only files modified since the last build in the IDE and your command line SBT build will not trigger a rebuild in the IDE.
This configuration is performed using the sbt-ide-settings plug-in.
Add the following into plugins.sbt (or whatever files you configure the plugins in):
resolvers += Resolver.url("jetbrains-bintray",url("http://dl.bintray.com/jetbrains/sbt-plugins/"))(Resolver.ivyStylePatterns)
addSbtPlugin("org.jetbrains" % "sbt-ide-settings" % "0.1.2")
And here is how to customize the IDE output directory in build.sbt:
ideOutputDirectory in Compile := Some(new File("target/idea/classes"))
ideOutputDirectory in Test := Some(new File("target/idea/test-classes"))
Feel free to change the paths according to your needs.

sbt ignoring library dependency

I have a library dependency
libraryDependencies += "mygroup" % "myartifact" % "myversion"
This is properly retrieved, and found in lib_managed. It contains some XML files (resources), and using jar tf I can see that the jar file is complete.
Ok. But—although this had always been working before—it is not ending up on my classpath any more. When I do show full-classpath, I see all libraries but this one. Consequently the program fails because it cannot read these resources. This also effects bundling the program as a standalone.
This library has no dependencies itself, nor does any other library of the project depend on it. What could cause this problem, and how to fix it? sbt version is 0.12.4.
This is a variant of this problem. Although other than in the linked question the .jar file does end up in lib_managed, it still isn't somehow "considered important" by sbt.
The solution is the same.
$ rm -r ~/.ivy2/cache/mygroup/myartifact

How to build a jar file out of github project in sbt to be used in a scala program

I am trying to use scala to access Amazon's DynamoDB and found this great package on github https://github.com/piotrga/async-dynamo
so I downloaded the code as a zip file , unzipped it and then did "sbt clean test" and getting the following error
error sbt.ResolveException: unresolved dependency: asyncdynamo#async-dynamo;1.6.0: not found
Questions : is this the correct way to generate a jar file that I can include in my Scala program or is there a better way?
thanks in advance.
EDIT:
just for the benefit of others, the SCALA SBT documentation provides lots of information regarding the build process.
Instead of generating a jar file, you can just run 'sbt publish-local' and then include the lines for the managed dependency in the other project.
Sbt/ivy will see you have the artifact that way you don't need to add the jar to the other project which is much cleaner.
Then for example if you need to update the other project you don't need to replace the jar again - just publish-local again and clean and run your other project!
You are not the only one to have problems with this it seems, see github issues page:
https://github.com/piotrga/async-dynamo/issues
The command 'sbt clean test' will run the tests sbt detects. If you want a .jar file you could use 'sbt clean package', which produces a .jar in the target/ folder.
I cloned the repo and was able to run sbt package after changing release.sbt a bit. I had to change the 'publishTo'-variable as it seemed to depend on the repository creators local environment variable, so I just commented it away.
I did not get the dependency problem, so I suppose it is correctly declared. The tests it tries to run do fail though, but sbt package compiles produces the .jar just fine.
EDIT: As Matthias Schlaipfer pointed out in the comments, the more elegant way(and much easier) would just be to add this as an depency in your build.sbt. From the readme, this is what you need to add:
resolvers += "piotrga" at
"https://github.com/piotrga/piotrga.github.com/tree/master/maven-repo"
libraryDependencies += "asyncdynamo" % "async-dynamo" % "1.6"