I am new to sbt (using sbt.version=0.13.5) created multiproject build definition as following (build.sbt):
name := "hello-app"
version in ThisBuild := "1.0.0"
organization in ThisBuild := "com.jaksky.hello"
scalaVersion := "2.10.4"
ideaExcludeFolders ++= Seq (
".idea",
".idea_modules"
)
lazy val common = (
Project("common",file("common"))
)
lazy val be_services = (
Project("be-services",file("be-services"))
dependsOn(common)
)
My expectation was that sbt will generate directory layout for the projects (based on the documentation). What happened was that just only top directories were generated (common and be-services) with target folder in it.
I tried it in batch mode sbt compile or in interactive mode - none has generated expected folder structures e.g. /src/{main, test}/{scala, java, resources}.
So either my expectations are wrong or there is some problem in my definition or some speciall setting, plugin etc.
Could some more experienced user clarify that, please?
Thanks
As #vptheron correctly points out, sbt does not generate any project directories, with the exception of the target directory when it produces compiled class files.
You might find that functionality in plugins, e.g. np. Also if you use an IDE such as IntelliJ IDEA, creating a new sbt-based project will initialize a couple of directories (such as src).
Related
Following the hints of the post explaining the basics of migrating to scalajs and this page about cross-compilations, I decided to add cross compilation to my standalone dependency-free scala library by doing the following changes:
I added a file project/plugins.sbt with the content
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.16")
I added scalaVersion in ThisBuild := "2.11.8" in build.sbt because else just scalaVersion was using 2.10
I also added in the build.sbt the following content to ensure that I can keep the same directory structure, since I don't have any particular files for the JVM or for Javascript:
lazy val root = project.in(file(".")).
aggregate(fooJS, fooJVM).
settings(
publish := {},
publishLocal := {}
)
lazy val foo = crossProject.crossType(CrossType.Pure).in(file(".")).
settings(version := "0.1").
jvmSettings(
// Add JVM-specific settings here
).
jsSettings(
// Add JS-specific settings here
)
lazy val fooJVM = foo.jvm
lazy val fooJS = foo.js
But now, after I published the project locally using sbt publish-local the projects depending on this library do not work anymore, i.e. they don't see the classes that this library was offering and raise errors.
I looked into .ivy2/local/.../foo/0.1/jars and the JAR went from 1MB to 1KB, so the errors make sense.
However, how can I make sure the JVM jar file is compiled correctly?
Further informations
The jar time does not change anymore, it looks like there had been some miscompilation. I deleted the .ivy2 cache, but now sbt publish-local always finishes with success but does not regenerate the files.
Ok I found the solution myself.
I needed to remove the publishLocal := {} from the build, and now all the projects depending on my library work fine.
can a sbt sub project have its own project directory? or only the root project can project directory with .scala helper files for the build?. Below is my current build scructure. The /my-project/sub-projects/sub-project-1/build.sbt is not able to access objects defined in /my-project/sub-projects/sub-project-1/SubProjectHelper.scala.
/my-project
build.sbt
/projects
Helper.scala
sub-projects
sub-project-1
build.sbt
/projects
SubProjectHelper.scala
Update:
The below sbt definition in sub-project-1/build.sbt
lazy val localhost = (project in file(".")).settings (
name := """localhost""",
version := Common.version,
scalaVersion := Common.scalaVersion,
libraryDependencies ++= Common.dependencies,
libraryDependencies ++= Localhost.dependencies
)
is failing with the below error
libraryDependencies ++= Localhost.dependencies
^
sbt.compiler.EvalException: Type error in expression
at sbt.compiler.Eval.checkError(Eval.scala:384)
at sbt.compiler.Eval.compileAndLoad(Eval.scala:183)
at sbt.compiler.Eval.evalCommon(Eval.scala:152)
at sbt.compiler.Eval.evalDefinitions(Eval.scala:122)
at sbt.EvaluateConfigurations$.evaluateDefinitions(EvaluateConfigurations.scala:271)
at sbt.EvaluateConfigurations$.evaluateSbtFile(EvaluateConfigurations.scala:109)
at sbt.Load$.sbt$Load$$loadSettingsFile$1(Load.scala:712)
Common is defined in /my-project/projects/Common.scala and has no issues. But Localhost is defined in /my-project/sub-projects/sub-project-1/projects/SubProjectHelper.scala is not properly resolved in the sub-project-1 build.sbt
Yes, they can, and you even don't need to have sub-projects dir, just place sub-project-1 in my-project dir.
Usually (at least this is what scala/scala-seed.g8 ends up with) project subdirectory doesn't ends with an extra s like your directory structure.
You should rename projects to project.
The answer is no, unfortunately. As seen here
You cannot have a project subdirectory or project/*.scala files in the sub-projects. foo/project/Build.scala would be ignored.
I'd like to know how to convert a regular scala project into an sbt project. I've tried manually creating an sbt file on the root directory, correctly implemented, but Intellij still doesn't recognize this as a sbt project, i.e, it won't show me in the "View -> Tool Windows" the "SBT" option.
How should I go about this? What I'm actually attempting to do is to create an empty project with multiple (independent) modules.
From what I've gathered there seems to be no way to add a module directly with sbt support, am I right?
Thanks
Here is an example of a multi-project build. The root project "aggregates" them all in case you want to compile them all together or package them all together, etc. The "coreLibrary" project depends on the code of "coreA" and "coreB".
import sbt.Keys._
import sbt._
name := "MultiProject"
lazy val root = project.in(file(".")).aggregate(coreA, coreB, coreLibrary)
lazy val coreA = Project("CoreA", file("core-a")).settings(
organization := "org.me",
version := "0.1-SNAPSHOT"
)
lazy val coreB = Project("CoreB", file("core-b")).settings(
organization := "org.me",
libraryDependencies += "org.apache.kafka" %% "kafka" % "0.8.2-beta",
version := "0.3-SNAPSHOT"
)
lazy val coreLibrary = Project("UberCore", file("core-main")).dependsOn(coreA, coreB).settings(
organization := "org.me",
version := "0.2-SNAPSHOT"
)
You can (for example) compile each project from the command line:
>sbt CoreB/compile
Or you can do this interactively:
>sbt
>project CoreB
>compile
I recommend you to use a single multiple-module SBT project. sbt is a great build tool for scala, you can do a lot of things with sbt, including checking out from the repository one module and built it.
sbt
projects
project <helloProject>
Actually, this feature allows multiple people to work on the same project in parallel. Please take a look at this: http://www.scala-sbt.org/0.13.5/docs/Getting-Started/Multi-Project.html.
I've been tasked with rewriting an old ant build script to SBT. As it happens, our suite is built up of 3 modules:
A Play 2.3 front-end webserver;
A back-end for retrieving data from various other systems;
A middle module containing some shared classes for database access and business logic.
Below an excerpt of my Build.scala file can be found:
val sharedSettings = Seq(
organization := <organization here>,
version := "1.2.5",
scalaVersion := "2.11.1",
libraryDependencies ++= libraries,
unmanagedJars in Compile ++= baseDirectory.value / "lib",
unmanagedJars in Compile ++= baseDirectory.value / "src",
unmanagedJars in Compile ++= baseDirectory.value / "test"
)
lazy val middle = project.settings(sharedSettings: _*)
lazy val back = project.settings(sharedSettings: _*).dependsOn(middle)
However, when I try to compile the source, I get the following error:
bad symbolic reference to scala.reflect.runtime encountered in class file 'ValueConverter.class'. Cannot access term runtime in package scala.reflect. The current classpath may be missing a definition for scala.reflect.runtime, or ValueConverter.class may have been compiled against a version that's incompatible with the one found on the current classpath.
The source code is organized in the following structure:
back
src
test
lib
middle
src
test
lib
front
src
test
lib
Here each lib folder contains some manually maintained libraries (which is why we want to move to sbt).
Any ideas on how to solve this?
In the end, I gave up on trying to get the compiler to understand the additional libraries. Eventually, I added those dependencies that were available using sbt, to the sbt managed libraries. This apparently works well.
When using oneJar to package a multi project sbt build, project dependencies are not bundled into the jar. My setting is the following:
foo/build.sbt (top-level build.sbt)
foo/src/ (sources of the root project)
foo/gui/build.sbt (project 'build' definition)
foo/gui/src (sources of the 'gui' project)
The build definitions are:
// foo/build.sbt
name := "foo"
version := "0.0.1"
scalaVersion := "2.10.4"
lazy val root = project.in( file(".") )
lazy val gui = project.in( file("gui") ).dependsOn( root )
[...]
//foo/gui/build.sbt
name := "foo-gui"
seq(com.github.retronym.SbtOneJar.oneJarSettings: _*)
[...]
When calling oneJar on the gui project everything seems to run fine, but the classes of the root project are not included in the jar (although the library dependencies are). Is there any fix ?
I never tried a light configuration as you but shouldn't you put the oneJar settings in the root sbt file? You want to package the root and include guy right?
I tried something similar for the first time today and started with oneJar but when using a full sbt configuration the compiler complained that settings were a Seq(_) and sbt expected a single setting or something like that. I switched to sbt-assembly and it worked.
sbt-oneJar has not been updated for 2 years while sbt-assembly was recently updated. I'm not sure which one is preferred but I'd rather use an active tool.