How create osgi manifest for bundle built in task? - scala

I have to create osgi manifest for bundle created by task that uses proguard.
For osgi part I'm using sbtosgi plugin (ver 0.6)
Currently I tried something like this:
object BuilderKeys {
val pkg = TaskKey[File]("package")
val bld = TaskKey[File]("build")
val targetFile = TaskKey[File]("targetFile")
...
}
lazy val settings = ... + BuilderSettings.default(bundle) + BuilderSettings.osgi(bundle)
object BuilderSettings {
def default(configuration: Configuration) // initializes bld (task that creates one uber-jar using proguard)
def osgi(configuration: Configuration) = inConfig(configuration)(SbtOsgi.defaultOsgiSettings ++ Seq(
fullClasspath in Compile := Seq(Attributed.blank((targetFile in configuration).value)),
pkg <<= (OsgiKeys.bundle dependsOn bld) map { f: File =>
f
}
))
}
Running bundle:package creates jar with manifest but not based on jar created by proguard. Is it possible to force it in some way?

Related

Calling a task from a plug-in that may be not present

Depending on a setting I need to call either package or assembly but obviously the assembly task is from sbt-assembly plugin that may not be added. My task looks something like this
lazy val useAssembly = settingKey[Boolean]("Use assembly")
lazy val myTask = Def.task {
val file = if (useAssembly.value) {
// somehow call assembly here
} else {
(`package` in Compile).value
}
// Do other stuff
}
PluginsDebug.autoPluginMap may be used to get available auto plugins. Create project/AssemblyIsAvailable.scala like so
package sbt.internal
/** If sbt-assembly is loaded, then it should be listed as sbtassembly.AssemblyPlugin **/
object AssemblyIsAvailable {
def apply(state: sbt.State): Boolean = {
PluginsDebug
.autoPluginMap(state)
.values
.toList
.map(_.label)
.exists(_.contains("ssembly"))
}
}
then define dynamic task assemblyOrDefaultPackage to be able to use conditional task evaluation within a task:
lazy val assemblyOrDefaultPackage = Def.taskDyn {
if (AssemblyIsAvailable(state.value))
Def.task { assembly.value }
else
Def.task { (Compile / Keys.`package`).value }
}
Now assemblyOrDefaultPackage can be evaluated within another task like so
lazy val myTask = Def.task {
val file = assemblyOrDefaultPackage.value
// Do other stuff
}
Alternatively, define custom command assemblyOrDefaultPackage in build.sbt like so
commands += Command.command("assemblyOrDefaultPackage") { state =>
(if (AssemblyIsAvailable(state)) "assembly" else "package") :: state
}
Now executing sbt assemblyOrDefaultPackage should package with sbt-assembly if available, otherwise fallback to default packaging.

SBT 0.13 Build.scala References to undefined settings

I am new to SBT and I have been trying to build a custom task for this build.
I have a simple build project:
import sbt._
import Keys._
object JsonBuild extends Build{
lazy val barTask = taskKey[Unit]("some simple task")
val afterTestTask1 = barTask := { println("tests ran!") }
val afterTestTask2 = barTask <<= barTask.dependsOn(test in Test)
lazy val myBarTask = taskKey[Unit]("some simple task")
//val afterMyBarTask1 = myBarTask := { println("tests ran!") }
lazy val afterMyBarTask2 = myBarTask <<= (myBarTask).dependsOn(test in Test) map { _ => println("tests ran!") }
//settings ++ Seq(afterMyBarTask2)
override lazy val settings = super.settings ++ Seq(afterMyBarTask2)
}
I keep getting the error:
References to undefined settings:
{.}/*:myBarTask from {.}/*:myBarTask (C:\Users\haques\Documents\workspace\SBT\jsonParser\project\Build.scala:13)
{.}/test:test from {.}/*:myBarTask (C:\Users\haques\Documents\workspace\SBT\jsonParser\project\Build.scala:13)
Did you mean test:test ?
I have googled around and I cannot find a solution.
Can you explain why it is not working?
lazy val myBarTask = taskKey[Unit]("some simple task")
override lazy val settings = super.settings ++ Seq(myBarTask := { (test in Test).value; println("tests ran!") } )
myBarTask is undefined when you call dependsOn. you should define it before using dependsOn. also value call on key (task/setting) is now preferred way to depend on other keys. you can still use your version, but define myBarTask
This has been bothering.
I did a bit more reading.
I think I know why the above code does not work.
lazy val afterMyBarTask2 = myBarTask <<= (myBarTask).dependsOn(test in Test) map { _ => println("tests ran!") }
When I write (myBarTask).dependsOn(test in Test), the project scope for test is chosen by SBT as ThisBuild.
{.}/test:test from {.}/*:myBarTask (C:\Users\haques\Documents\workspace\SBT\jsonParser\project\Build.scala:13)
ThisBuild project scope does not have the setting test in configuration Test.
Only projects have the setting test.
The key I think that setting is added by some default SBT plugin to the projects settings.
You check what scopes settings exist in SBT by using the inspect command.
If you type in the SBT REPL:
{.}/test:test
The output is:
inspect {.}/test:test
[info] No entry for key.
SBT correctly suggests:
test:test which is:
{file:/C:/Users/haques/Documents/workspace/SBT/jsonParser/}jsonparser/test:test
If the project is not specified in the project scope axis, SBT chooses the current project by default.
Every SBT project if not specified has its own project settings.

Getting an SBT task to depend on the OneJar task

I'm having trouble getting my new SBT task 'install' to depend on the OneJar task. Here's my Build.scala file:
import sbt._
import Keys._
import com.github.retronym.SbtOneJar._
object BuildBroBuild extends Build {
val install = TaskKey[Unit]("install", "Installs the JAR and a launcher script into your homedir")
private def installTask = task {
println("Hello world!")
}
override lazy val settings = super.settings ++
Seq(install <<= (oneJar in Global)(installTask dependsOn(_)))
lazy val root = Project(id = "buildbro",
base = file("."),
settings = Project.defaultSettings)
}
And here's the error I'm getting:
[error] Reference to undefined setting:
[error]
[error] */*:one-jar from {.}/*:install
[error] Did you mean *:one-jar ?
[error]
Does anybody know what this means? I believe I have to scope the oneJar TaskKey in a different way. Thanks for any help you can offer.
I think something like this should work:
object BuildBroBuild extends Build {
val install = TaskKey[Unit]("install", "Installs the JAR and a launcher script into your homedir")
private lazy val installTask = install <<= (oneJar, streams) map { case (a, s) => {
// 'a' is the output from the onejar task (ie, the artifact)
println("Hello world!")
}
override lazy val settings = super.settings ++
Seq(installTask)
lazy val root = Project(id = "buildbro",
base = file("."),
settings = Project.defaultSettings)
}
Here, we are taking the output of the oneJar task (as well as streams, which allows for logging, etc) as input for our new task.

sbt Task classpath

I'm working on a sbt Task and I would like to have access to some of the application classes and dependencies.
(Specifically, I'd like to generate the Database DDL using scalaquery)
Is there any way to add those dependencies to the task or maybe I need to create a plugin for this?
object ApplicationBuild extends Build {
val appName = "test"
val appVersion = "1.0-SNAPSHOT"
val appDependencies = Seq(
"org.scalaquery" % "scalaquery_2.9.0-1" % "0.9.5")
val ddl = TaskKey[Unit]("ddl", "Generates the ddl in the evolutions folder")
val ddlTask = ddl <<= (baseDirectory, fullClasspath in Runtime) map { (bs, cp) =>
val f = bs / "conf/evolutions/default"
// Figures out the last sql number used
def nextFileNumber = { ... }
//writes to file
def printToFile(f: java.io.File)(op: java.io.PrintWriter => Unit) { ...}
def createDdl = {
import org.scalaquery.session._
import org.scalaquery.ql._
import org.scalaquery.ql.TypeMapper._
import org.scalaquery.ql.extended.H2Driver.Implicit._
import org.scalaquery.ql.extended.{ ExtendedTable => Table }
import models._
printToFile(new java.io.File(nextFileNumber, f))(p => {
models.Table.ddl.createStatements.foreach(p.println)
});
}
createDdl
None
}
val main = PlayProject(appName, appVersion, appDependencies, mainLang = SCALA).settings(
ddlTask)
}
The error I get is
[test] $ reload
[info] Loading global plugins from /home/asal/.sbt/plugins
[info] Loading project definition from /home/asal/myapps/test/project
[error] /home/asal/myapps/test/project/Build.scala:36: object scalaquery is not a member of package org
[error] import org.scalaquery.session._
[error] ^
[error] one error found
Thanks in advance
You have to add ScalaQuery and everything else your build depends on as a build dependency. That means that basically, you have to add it "as an sbt plugin".
This is described in some detail in the Using Plugins section of the sbt wiki. It all boils down to a very simple thing, though - just add a line defining your dependency under project/plugins.sbt like this:
libraryDependencies += "org.scalaquery" % "scalaquery_2.9.0-1" % "0.9.5"
Now, the problem with using application classes in the build is that you can't really add build products as build dependencies. - So, you would probably have to create a separate project that builds your DDL module, and add that as dependency to the build of this project.

sbt 0.11 run task examples needed

My projects are still using sbt 0.7.7 and I find it very convenient to have utility classes that I can run from the sbt prompt. I can also combine this with properties that are separately maintained - typically for environment related values that changes from hosts to hosts. This is an example of my project definition under the project/build directory:
class MyProject(info: ProjectInfo) extends DefaultProject(info) {
//...
lazy val extraProps = new BasicEnvironment {
// use the project's Logger for any properties-related logging
def log = MyProject.this.log
def envBackingPath = path("paths.properties")
// define some properties that will go in paths.properties
lazy val inputFile = property[String]
}
lazy val myTask = task { args =>
runTask(Some("foo.bar.MyTask"),
runClasspath, extraProps.inputFile.value :: args.toList).dependsOn(compile)
describedAs "my-task [options]"
}
}
I can then use my task as my-task option1 option2 under the sbt shell.
I've read the new sbt 0.11 documentation at https://github.com/harrah/xsbt/wiki including the sections on Tasks and TaskInputs and frankly I'm still struggling on how to accomplish what I did on 0.7.7.
It seems the extra properties could simply be replaced a separate environment.sbt, that tasks have to be defined in project/build.scala before being set in build.sbt. It also looks like there is completion support, which looks very interesting.
Beyond that I'm somewhat overwhelmed. How do I accomplish what I did with the new sbt?
You can define a task like this :
val myTask = InputKey[Unit]("my-task")
And your setting :
val inputFile = SettingKey[String]("input-file", "input file description")
You can also define a new configuration like :
lazy val ExtraProps = config("extra-props") extend(Compile)
add this config to your project and use it to set settings for this configuration :
lazy val root = Project("root", file(".")).config( ExtraProps ).settings(
inputFile in ExtraProps := ...
...
myTask in ExtraPops <<= inputTask { (argTask:TaskKey[Seq[String]]) =>
(argTask, inputFile) map { (args:Seq[String], iFile[String]) =>
...
}
}
).dependsOn(compile)
then launch your task with extra-props:my-task