Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to separate task code from build.sbt

Tags:

sbt

I have written custom task for my sbt project and placed it in build.sbt. However I would like to put the task's code to separate file and import it from build.sbt. I have created mytask.sbt that contains something like this:

lazy val myTask = taskKey[Unit]("my task")

myTask := {
   //doing task
}

but I don't know how can I import this task from within build.sbt so I could use something like this:

compile <<= (compile in Compile) dependsOn myTask

I'm aware that there is plugins concept but I think this is overkill for my needs. All I want is to separate some code.

like image 422
Vistritium Avatar asked Mar 12 '23 01:03

Vistritium


1 Answers

You do not mention what sbt version your are using, so the following answer is based on version 0.13.12.

As far as I know, task has to be defined either in an sbt file, in a plugin, or inside a scala file object extending the Build trait. I don't think its possibly to define anything in one sbt file, and use it in another, so from my point of view, your have these options:

Extending the Build trait this way of doing things, has become deprecated in the later versions of sbt, so I will not go into that one.

Defining the logic of the task in an scala file. You could split the declaration and the logic of the task up, so that your declare the task in the sbt build file, but move the logic of it into a scala file. Then your build file could be like this:

import CommonBuildCode._

val myTask = taskKey[Unit]("my task")

myTask := {
    myTaskPerform()
}


compile := {
    myTask.value
    (compile in Compile).value
}

And you logic for the task could be in the file project/CommonBuildCode.scala

import sbt._

object CommonBuildCode {

    def myTaskPerform(): Unit = {
        println("-------------------------- myTask called --------------------------")
    }
}

I do not know it this would be enough for your, but it would keep the number of lines concerning the myTask task in your build.sbt file to a minimum.

Creating a simple plugin Its pretty easy to create a plugin with sbt, and this will give a result very close to what your asking for. First create the file project/MyTaskPlugin.scala like this:

import sbt._

object MyTaskPlugin extends AutoPlugin {

    object autoImport {
        val myTask = taskKey[Unit]("my task")
    }

    import autoImport._

    override def projectSettings = Seq(
        myTask := {
            println("--------------- myTask called from a plugin------------------")
        }
    )
}

When the project is enabled, anything under the autoImport project will be auto imported and available to use in your sbt build file, and all the settings set in the projectSettings method will apply. So now the only thing you need to do in you build.sbt file, is to activate the plugin:

enablePlugins(MyTaskPlugin)

compile := {
    myTask.value
    (compile in Compile).value
}

An extra bonus of using a plugin, is that it will be pretty easy to refactor the plugin into its own project, where it can publish a jar, that will be easily activated by other projects. This could be relly handy, in case myTask turns out to be a common build task among your project.

like image 168
Anders Kreinøe Avatar answered Apr 24 '23 00:04

Anders Kreinøe