I'd like to create conditional library dependency in build.sbt file.
I'm looking for similar behavior to maven profiles where I can enter a profile / system variable in the command line and have SBT define libraryDependencies according to it.
i.e. if system variable was supplied - add HBase client dependency else don't.
Any help would be appreciated.
Thanks,
Ido
Does this help?
val my_version = System.getProperty("my_version", "")
libraryDependencies ++= (
if (my_version != "" )
("org.example.code" %% "my_library" % my_version) :: Nil
else
Nil
)
Only adds to library dependency, if a version is specified
Related
I would like to have a different version of library in test scope.
I was hoping the simplified version of project descriptor could look like that.
Please mind it's a simplified view, in my real project it's more convoluted. I need to use dependencyOverrides to enforce certain library version.
import sbt._, Keys._
organization := "me"
name := "test"
version := "0.1"
libraryDependencies := Seq("ch.qos.logback" % "logback-classic" % "1.2.3")
dependencyOverrides := Seq(
"ch.qos.logback" % "logback-classic" % "1.2.2"
)
dependencyOverrides in Test := Seq(
"ch.qos.logback" % "logback-classic" % "1.2.1"
)
I'd be hoping to see logback-classic version 1.2.1 when I run:
show test:managedClasspath.
Instead I get logback-classic version 1.2.2 as if dependencyOverrides in Test was ignored.
At the same time when I run show Test/dependencyOverrides I get the expected result which is:
ch.qos.logback:logback-classic:1.2.1
Does anyone has a clue what am I missing in the relation between dependencyOverrides in Test scope and managedClasspath?
It appears the problem cannot be solve the way I imagined. The main reason is libraryDependencies and update are not scoped to configuration.
I think the best solution is in case I need a different version of library in some tests to extract those tests to a separate module with independent set of libraryDependencies.
I'm trying to monitor my akka-http Rest web-service with NewRelic
The application has only one GET url (defined with akka-http)
I have the following configuration in the plugins.sbt
logLevel := Level.Warn
addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.0.4")
addSbtPlugin("com.gilt.sbt" % "sbt-newrelic" % "0.1.4")
I have the following configuration in the build.sbt
scalaVersion := "2.11.7"
name := "recommender-api"
...blablabla...
libraryDependencies += "com.typesafe.akka" % "akka-actor_2.11" % "2.4.2"
libraryDependencies += "com.typesafe.akka" % "akka-http-experimental_2.11" % "2.4.2"
libraryDependencies += "com.typesafe.akka" % "akka-http-spray-json-experimental_2.11" % "2.4.2"
libraryDependencies += "com.typesafe.akka" % "akka-slf4j_2.11" % "2.4.2"
newrelicIncludeApi := true
newrelicAppName := name.toString
enablePlugins(JavaServerAppPackaging, UniversalDeployPlugin, NewRelic)
I compile (and deploy) the code with sbt universal:publish, it creates a .zip, inside the .zip there is an executable file.
I pass the newRelic licenceKey by enviroment (NEW_RELIC_LICENSE_KEY)
The program starts and all works fine, the newRelic key is found (because the log dosen't say that it didn't find the key)
The aplication apears in the newRelic monitor system with the correct name
BUT NewRelic dosen't show any metrics
what I have to do to see some metrics on NewRelic?
When you specify the value of newrelicAppName as name.toString, you are not doing what you expect.
name is a value of type sbt.SettingKey, this contains details of a setting's name, type, and a short description of what the key is used for.
The type that actually contains a value is an sbt.Setting. You can get a Setting from a SettingKey (in the current project and configuration) by calling the .value method.
So when you set the value like this:
newrelicAppName := name.toString
the value looks something like this:
$ show newrelicAppName
[info] sbt.SettingKey$$anon$4#54ec2887
Yes, that is actually a string containing lots of strange characters.
On the other hand, if you used the .value call:
newrelicAppName := name.value
the value then looks like:
$ show newrelicAppName
[info] my-project
My best guess is that New Relic doesn't like application names with strange characters (like dollar signs and ampersands). By setting a more normal string, you made it more likely that New Relic would accept such a name as input.
Note: the default value for newrelicAppName is the name for the containing project, so not setting the value at all in the first example would probably have "just worked" as you would have liked.
I realy don't know what I did to make it work, the changes I made were:
In the build.sbt
newrelicVersion := "3.26.1"
newrelicAppName := "recommenders-jobs-api-monitor"
In the plugin.sbt
addSbtPlugin("com.gilt.sbt" % "sbt-newrelic" % "0.1.5")
(I updated de sbt-newrelic version)
(I harcoded the name of the new relic app)
(I specified the version of the Java Agent)
I am looking for a way to control what library dependency exported, and what not. Something along those lines:
"org.slf4j" % "slf4j-api" % "1.7.6" doNotExport
or perhaps at the point where the project is imported, like this:
lazy val main = Project(appName, file("."), settings = buildSettings)
.dependsOn(ProjectRef(uri("../Utils"), "Utils").exceptLibraryDependency(organization="org.slf4j"))
Is there anything like this in SBT?
Well, it all depends on configurations. Default configurations expose dependencies again. So similar behavior can be achieved like this:
val compileOnly = config("compileOnly").hide
ivyConfigurations += compileOnly
unmanagedClasspath in Compile ++=
update.value.select(configurationFilter(compileOnly.name))
"org.slf4j" % "slf4j-api" % "1.7.6" % compileOnly
Note that this technique was descibed in an answer to Add a compile time only dependency in sbt.
This question should be closed as a duplicate, but the bounty prevents this.
After many struggles I finally got a large project converted over from Maven to SBT. One of the remaining issues, however, is that some of the unit tests in the project use jMockit which can be a bit high-maintenance when it comes to configuring the environment.
Specifically the jmockit dependency/jar has two difficult requirements:
The jmockit jar must appear in the classpath before the junit jar
On many JVM's, such as the OpenJDK one I'm using, the JVM argument -javaagent:<path/to/jmockit.jar> is required
If both of these conditions are not met, I'm faced with the error:
[error] Test <mytestclass>.initializationError failed: java.lang.Exception: Method <mytestmethod> should have no parameters
[error] at mockit.integration.junit4.JMockit.<init>(JMockit.java:32)
I think I eventually managed to take care of #1 with SBT but I'm still having trouble with the second one. The debug SBT logs do not show enough detail about the forked process invocation to tell me if my settings are working or not. But the test output consistently indicates that it's not working. I have what I think are all the relevant settings:
lazy val myproj = Project(
...
settings = otherSettings ++ Seq(
libraryDependencies ++= Seq(
"com.googlecode.jmockit" % "jmockit" % "1.7" % "test",
"junit" % "junit" % "4.8.1" % "test"
),
fork in Test := true,
javaOptions in test += "-javaagent:<hardcode-path-to-jmockit.jar>"
)
I think the classpath is OK based on the output of the test:dependencyClasspath:
sbt> project <myproject>
sbt> show test:dependencyClasspath
[info] List(...., Attributed(/var/build/ivy2/cache/junit/junit/jars/junit-4.8.1.jar), ...
..., Attributed(/var/build/ivy2/cache/com.googlecode.jmockit/jmockit/jars/jmockit-1.7.jar), ...)
So I'm thinking that my javaagent setting is not having the intended result.
If I do happen to get this to work, my next question is how to get the hard-coded jmockit.jar path out of there but for now I'll settle for a passing test case.
So, how do I set the JVM options used for testing? How do I view/verify what options are actually used when the tests are launched?
You need to change your javaOptions to javaOptions in Test (note the T in Test is capitalized).
You can check your options by executing show test:javaOptions
> show test:javaOptions
[info] List(-javaagent:/home/lpiepiora/.ivy2/cache/com.googlecode.jmockit/jmockit/jars/jmockit-1.7.jar)
Additionally if you want to use dynamic path to the jmockit jar, you can set your javaOptions like this:
def jmockitPath(f: Seq[File]) = f.filter(_.name.endsWith("jmockit-1.7.jar")).head
javaOptions in Test += s"-javaagent:${jmockitPath((dependencyClasspath in Test).value.files)}"
build.sbt for reference
libraryDependencies += "com.novocode" % "junit-interface" % "0.9" % "test"
libraryDependencies ++= Seq(
"com.googlecode.jmockit" % "jmockit" % "1.7" % "test",
"junit" % "junit" % "4.8.1" % "test"
)
fork in Test := true
def jmockitPath(f: Seq[File]) = f.filter(_.name.endsWith("jmockit-1.7.jar")).head
javaOptions in Test += s"-javaagent:${jmockitPath((dependencyClasspath in Test).value.files)}"
I am trying to import akka.dispatch.Future in my class but the compiler is unable to find that particular package. The one that it's able to find is akka.dispatch.Futures.
Can somebody point out what I might be doing wrong? My build.sbt is as follows:
name := "SomeApp"
version := "0.1"
scalaVersion := "2.10.1"
libraryDependencies ++= Seq("com.typesafe.akka" %% "akka-actor" % "2.1.2")
It's all in the docs: http://doc.akka.io/docs/akka/2.1.2/project/migration-guide-2.0.x-2.1.x.html
See the "Pieces Moved to Scala Standard Library" section.