├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── examples
├── common-cross
│ ├── bar
│ │ └── src
│ │ │ └── main
│ │ │ └── scala
│ │ │ └── Bar.scala
│ ├── build.sbt
│ ├── common
│ │ └── src
│ │ │ └── main
│ │ │ └── scala
│ │ │ └── Common.scala
│ ├── foo
│ │ └── src
│ │ │ └── main
│ │ │ └── scala
│ │ │ └── Foo.scala
│ └── project
│ │ ├── build.properties
│ │ └── plugins.sbt
├── dependency-configurations
│ ├── build.sbt
│ └── project
│ │ └── build.sbt
└── simple
│ ├── build.sbt
│ └── project
│ ├── build.properties
│ └── plugins.sbt
└── sbt-cross
├── RELEASE.md
├── build.sbt
├── project
├── build.properties
└── plugins.sbt
├── src
└── main
│ └── scala
│ └── com
│ └── lucidchart
│ └── sbtcross
│ ├── AggregateArgument.scala
│ ├── Axis.scala
│ ├── CrossedProject.scala
│ ├── DefaultAxis.scala
│ ├── LibraryVersionAxis.scala
│ ├── LocalProjectDependency.scala
│ ├── SbtCrossPlugin.scala
│ └── ScalaAxis.scala
└── version
/.gitignore:
--------------------------------------------------------------------------------
1 | *.log
2 | *.swp
3 |
4 | .idea/
5 | target*/
6 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | after_success: |
2 | if [ "$TRAVIS_SECURE_ENV_VARS" == true ]; then
3 | echo "$PGP_SECRET" | base64 --decode | gpg --import
4 | if [ -z "$TRAVIS_TAG" ]; then
5 | (cd sbt-cross && exec sbt publishSigned)
6 | else
7 | (cd sbt-cross && exec sbt "; publishSigned; sonatypeBundleRelease")
8 | fi
9 | fi
10 | cache:
11 | directories:
12 | - $HOME/.ivy2
13 | - $HOME/.sbt
14 | deploy:
15 | provider: releases
16 | api_key:
17 | secure: gtGkk0o5BwJyhdob+0PlL7zQHO1ACpO22cIYQyfoMvpcnTrrAHqa7Pxx7DUHstE0wIWCPrgKnzUbjqCvxpSZ2mrfg9K0CRLVBQv/BC45szXeKvAIwjij8kJY30QQD9G2xoom6vqi5OajS440jEmD0E4VgegQNaYY5HK0OKYizfU=
18 | file: '*/target/**/*.jar'
19 | file_glob: true
20 | on:
21 | tags: true
22 | repo: lucidsoftware/sbt-cross
23 | skip_cleanup: true
24 | git:
25 | depth: 1
26 | jdk: openjdk8
27 | language: scala
28 | script:
29 | - '[ "$TRAVIS_PULL_REQUEST" != false ] || export SBT_OPTS=-Dbuild.version=${TRAVIS_TAG:-$TRAVIS_BRANCH-SNAPSHOT}'
30 | - (cd sbt-cross && exec sbt checkFormat package test)
31 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2015 Lucid Software, Inc.
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this project except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0.txt
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | #sbt-cross
2 |
3 | [](https://travis-ci.com/lucidsoftware/sbt-cross)
4 | 
5 |
6 | A better solution for building multiple Scala versions (cross compiling) in SBT.
7 |
8 | ## Purpose
9 |
10 | SBT's `crossScalaVersions` allows projects to compile with multiple versions of Scala.
11 |
12 | However, `crossScalaVersions` is a hack that reuses projects by mutates settings. This causes problems:
13 |
14 | 1. Performance - Each Scala version is handled sequentially (not in parallel).
15 | 1. Subprojects - Project classpath dependencies can be tricky.
16 | 1. Aggregation - Aggregation doesn't take into account `crossScalaVersions` of subprojects, hence
17 | [sbt-doge](https://github.com/sbt/sbt-doge).
18 | 1. Cross paths - Very many tasks don't play nicely. E.g. if you use
19 | [sbt-native-packager](http://www.scala-sbt.org/sbt-native-packager/) and `+debian:packageBin`, you'll build
20 | two debs on top of each other.
21 | 1. General funniness - For example, [sbt-sonatype](https://github.com/xerial/sbt-sonatype#using-with-sbt-release-plugin)
22 | requires extra wrangling to work with `crossScalaVersions`.
23 |
24 | sbt-cross solves all by simply splitting projects: one for each version of Scala. This works with SBT's core
25 | project/task system, rather than fighting it.
26 |
27 | ## Install
28 |
29 | Requires SBT 1.3+.
30 |
31 | In project/plugins.sbt, add
32 |
33 | ```scala
34 | addSbtPlugin("com.lucidchart" % "sbt-cross" % "4.0")
35 | ```
36 |
37 | For the latest development version,
38 |
39 | ```scala
40 | resolvers += Resolver.sonatypeRepo("snapshots")
41 |
42 | addSbtPlugin("com.lucidchart" % "sbt-cross" % "master-SNAPSHOT")
43 | ```
44 |
45 | ## Example
46 |
47 | Suppose there is a project `pipers` that uses Scala 2.11, a project `drummers` that uses Scala 2.12, and they depend on a
48 | project `instruments`, which compiles with both Scala versions.
49 |
50 | This cannot be done with `crossScalaVersions`, but it can with sbt-cross.
51 |
52 | ```scala
53 | lazy val pipers = project.dependsOn(instruments_2_11).settings(scalaVersion := "2.11.8")
54 | lazy val drummers = project.dependsOn(instruments_2_12).settings(scalaVersion := "2.12.1")
55 |
56 | lazy val instruments = project.cross
57 | lazy val instruments_2_11 = instruments("2.11.8")
58 | lazy val instruments_2_12 = instruments("2.12.1")
59 | ```
60 |
61 | This defines four projects: `pipers`, `drummers`, `instruments-2_11`, and `instruments-2_12`.
62 |
63 | SBT will concurrently compile the right ones in the right order.
64 |
65 | * `sbt pipers/compile` will compile `instruments_2_11` then `pipers`.
66 |
67 | * `sbt drummers/compile` will compile `instruments_2_12` then `drummers`.
68 |
69 | * `sbt compile` will compile `instruments_2_11` then `pipers` and, *in parallel*, `instruments_2_12` then `drummers`.
70 |
71 | See [examples](examples) for more.
72 |
73 | ### Additional crossing
74 |
75 | sbt-cross generalizes this approach to other any cross-compilation-like use. You can even chain cross versions. There is
76 | currently no documentation for this, but `LibraryVersionAxis` is an example.
77 |
78 | ## Contributions
79 |
80 | We welcome issues, questions, and contributions on our GitHub project
81 | ([https://github.com/lucidsoftware/sbt-cross](github.com/lucidsoftware/sbt-cross)).
82 |
--------------------------------------------------------------------------------
/examples/common-cross/bar/src/main/scala/Bar.scala:
--------------------------------------------------------------------------------
1 | case class Bar(a: C, b: C, c: C, d: C, e: C, f: C, g: C,
2 | h: C, i: C, j: C, k: C, l: C, m: C, n: C, o: C, p: C,
3 | q: C, r: C, s: C, t: C, u: C, v: C, w: C, x: C, y: C,
4 | z: C)
5 |
6 |
--------------------------------------------------------------------------------
/examples/common-cross/build.sbt:
--------------------------------------------------------------------------------
1 | lazy val foo = (project in file("foo")).dependsOn(common_2_11).settings(
2 | scalaVersion := "2.11.12"
3 | )
4 |
5 | lazy val bar = (project in file("bar")).dependsOn(common_2_12).settings(
6 | scalaVersion := "2.12.10"
7 | )
8 |
9 | // unfortunately, pattern matching doesn't work in val assignment,
10 | // see: https://github.com/sbt/sbt/issues/2290
11 | lazy val common = (project in file("common")).cross
12 |
13 | lazy val common_2_11 = common("2.11.12")
14 |
15 | lazy val common_2_12 = common("2.12.10")
16 |
17 |
--------------------------------------------------------------------------------
/examples/common-cross/common/src/main/scala/Common.scala:
--------------------------------------------------------------------------------
1 | class C {}
2 |
3 |
--------------------------------------------------------------------------------
/examples/common-cross/foo/src/main/scala/Foo.scala:
--------------------------------------------------------------------------------
1 | object Foo {
2 | {new C}
3 | }
4 |
5 |
--------------------------------------------------------------------------------
/examples/common-cross/project/build.properties:
--------------------------------------------------------------------------------
1 | sbt.version=1.3.3
2 |
3 |
--------------------------------------------------------------------------------
/examples/common-cross/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | addSbtPlugin("com.lucidchart" % "sbt-cross" % "0-SNAPSHOT")
2 |
--------------------------------------------------------------------------------
/examples/dependency-configurations/build.sbt:
--------------------------------------------------------------------------------
1 | lazy val mainCross = Project("main", file("main")).cross
2 | .dependsOn(testCross % "test")
3 |
4 | lazy val mainCross_2_10 = mainCross("2.10.5")
5 |
6 | lazy val mainCross_2_11 = mainCross("2.11.6")
7 |
8 | lazy val testCross = Project("common", file("common")).cross
9 |
10 | lazy val testCross_2_10 = testCross("2.10.5")
11 |
12 | lazy val testCross_2_11 = testCross("2.11.6")
13 |
--------------------------------------------------------------------------------
/examples/dependency-configurations/project/build.sbt:
--------------------------------------------------------------------------------
1 | addSbtPlugin("com.lucidchart" % "sbt-cross" % "0-SNAPSHOT")
2 |
--------------------------------------------------------------------------------
/examples/simple/build.sbt:
--------------------------------------------------------------------------------
1 | lazy val base = Project("foo", file(".")).cross
2 |
3 | lazy val project_2_10 = base("2.10.4")
4 |
5 | lazy val project_2_11 = base("2.11.5")
6 |
7 | lazy val all = base.empty.aggregate(project_2_10, project_2_11)
8 |
--------------------------------------------------------------------------------
/examples/simple/project/build.properties:
--------------------------------------------------------------------------------
1 | sbt.version=1.3.3
2 |
3 |
--------------------------------------------------------------------------------
/examples/simple/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | addSbtPlugin("com.lucidchart" % "sbt-cross" % "0-SNAPSHOT")
2 |
--------------------------------------------------------------------------------
/sbt-cross/RELEASE.md:
--------------------------------------------------------------------------------
1 | # Releases
2 |
3 | ## Versioning scheme
4 |
5 | Versions are `.`.
6 |
7 | * Each major version series has a branch, with a SNAPSHOT version published for the latest.
8 |
9 | * Each major.minor version has a tag, which triggers publishing a release version.
10 |
11 | Commits are typically developed for `master` and then cherry-picked to branches as needed.
12 |
13 | ```
14 | A - B - C - D - E - F - G - H (master)
15 | \ \
16 | C' E' - G' - H' (2)
17 | \ (2.0) (2.1)
18 | D'
19 | (1.0, 1)
20 |
21 | Published versions:
22 | 1.0
23 | 1-SNAPSHOT
24 | 2.0
25 | 2.1
26 | 2-SNAPSHOT
27 | master-SNAPSHOT
28 | ```
29 |
30 | ## Release process
31 |
32 | ### 1. Create and checkout branches
33 |
34 | New major version: create, checkout, and push a new branch for the major series.
35 |
36 | ```sh
37 | git checkout -b master
38 | git push -u HEAD
39 | ```
40 |
41 | New minor version: checkout major series branch
42 |
43 | ```sh
44 | git checkout
45 | ```
46 |
47 | ### 2. Tag
48 |
49 | Push a tag with the new version.
50 |
51 | ```sh
52 | git push HEAD:refs/tags/.
53 | ```
54 |
55 | This triggers a release in Github and Sonatype.
56 |
57 | ### 3. Update documentation
58 |
59 | Update documentation and examples on `master` to point to the new version, commit, and push.
60 |
--------------------------------------------------------------------------------
/sbt-cross/build.sbt:
--------------------------------------------------------------------------------
1 | import scala.sys.process._
2 |
3 | val checkFormat = TaskKey[Unit]("check-format")
4 |
5 | checkFormat := {
6 | (scalariformFormat in Compile).value
7 | val directory = baseDirectory.value.absolutePath
8 | val logger = (streams in Compile).value.log
9 | val paths = s"git diff --name-only $directory".lineStream_!
10 | if (paths.nonEmpty) {
11 | logger.error("The following files are not corrected formatted:")
12 | paths.foreach { path =>
13 | logger.error(s" $path")
14 | }
15 | logger.error("Run `sbt scalariform-format`")
16 | throw new RuntimeException(s"${paths.size} files need formatting")
17 | }
18 | }
19 |
20 | credentials += Credentials(
21 | "Sonatype Nexus Repository Manager",
22 | "oss.sonatype.org",
23 | sys.env.getOrElse("SONATYPE_USERNAME", ""),
24 | sys.env.getOrElse("SONATYPE_PASSWORD", "")
25 | )
26 |
27 | developers := List(
28 | Developer("lucidsoftware", "Lucid Software", "github@lucidchart.com", url("https://www.golucid.co/"))
29 | )
30 |
31 | description := "A better solution for cross compiling Scala versions in SBT."
32 |
33 | homepage := Some(url("https://github.com/lucidsoftware/sbt-cross"))
34 |
35 | libraryDependencies ++= Seq(
36 | "org.apache.commons" % "commons-lang3" % "3.5"
37 | )
38 |
39 | licenses += "Apache 2" -> url("http://www.apache.org/licenses/LICENSE-2.0.txt")
40 |
41 | name := "sbt-cross"
42 |
43 | organization := "com.lucidchart"
44 |
45 | organizationHomepage := Some(url("https://www.golucido.co/"))
46 |
47 | organizationName := "Lucid Software"
48 |
49 | sbtPlugin := true
50 |
51 | scalacOptions ++= Seq("-deprecation")
52 |
53 | publishTo := sonatypePublishToBundle.value
54 |
55 | scmInfo := Some(ScmInfo(url("https://github.com/lucidsoftware/sbt-cross"), "scm:git:git@github.com:lucidsoftware/sbt-cross", None))
56 |
57 | startYear := Some(2017)
58 |
59 | version := sys.props.getOrElse("build.version", "0-SNAPSHOT")
60 |
--------------------------------------------------------------------------------
/sbt-cross/project/build.properties:
--------------------------------------------------------------------------------
1 | sbt.version=1.3.3
2 |
--------------------------------------------------------------------------------
/sbt-cross/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | addSbtPlugin("com.jsuereth" % "sbt-pgp" % "2.0.0")
2 |
3 | addSbtPlugin("org.scalariform" % "sbt-scalariform" % "1.8.3")
4 |
5 | addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.8")
6 |
--------------------------------------------------------------------------------
/sbt-cross/src/main/scala/com/lucidchart/sbtcross/AggregateArgument.scala:
--------------------------------------------------------------------------------
1 | package com.lucidchart.sbtcross
2 |
3 | import scala.language.implicitConversions
4 | import sbt._
5 |
6 | sealed trait AggregateArgument
7 |
8 | final case class ProjectAggregateArgument(project: Project) extends AggregateArgument
9 |
10 | object ProjectAggregateArgument {
11 | implicit def toArgument(project: Project): ProjectAggregateArgument = apply(project)
12 | }
13 |
14 | final case class VersionAggregateArgument(version: String) extends AggregateArgument
15 |
16 | object VersionAggregateArgument {
17 | implicit def toArgument(version: String): VersionAggregateArgument = apply(version)
18 | }
19 |
--------------------------------------------------------------------------------
/sbt-cross/src/main/scala/com/lucidchart/sbtcross/Axis.scala:
--------------------------------------------------------------------------------
1 | package com.lucidchart.sbtcross
2 |
3 | import sbt.LocalProject
4 |
5 | trait Axis {
6 | def apply[A <: CrossableProject[A]](delegate: A, version: String): A
7 | def apply(project: LocalProject, version: String): LocalProject
8 | }
9 |
--------------------------------------------------------------------------------
/sbt-cross/src/main/scala/com/lucidchart/sbtcross/CrossedProject.scala:
--------------------------------------------------------------------------------
1 | package com.lucidchart.sbtcross
2 |
3 | import sbt._
4 | import scala.language.implicitConversions
5 |
6 | sealed trait CrossableProject[A <: CrossableProject[A]] {
7 | self: A =>
8 | protected[this] type P
9 | final def %(configurations: String) = (this: LocalProjectDependency).copy(configurations = Some(configurations))
10 | final def cross(axis: Axis) = new CrossedProject(axis, this)
11 | final def empty = Project(project.id, file(".cross") / project.id)
12 | final def localProject = LocalProject(project.id)
13 | def dependsOn(dependencies: LocalProjectDependency*): A
14 | def resolve: P
15 | def project: Project
16 | def withProject(project: Project): A
17 | }
18 |
19 | object CrossableProject {
20 | implicit def toDependency(project: CrossableProject[_]): LocalProjectDependency = LocalProjectDependency(project.localProject)
21 | }
22 |
23 | final case class BaseProject(project: Project) extends CrossableProject[BaseProject] {
24 | protected[this] type P = Project
25 | def cross: CrossedProject[BaseProject] = cross(ScalaAxis)
26 | def dependsOn(dependencies: LocalProjectDependency*) = copy(project.dependsOn(dependencies.map(_.classpathDependency): _*))
27 | def resolve = project
28 | def withProject(project: Project) = copy(project)
29 | }
30 |
31 | final case class CrossedProject[A <: CrossableProject[A]](axis: Axis, delegate: A, dependencies: Seq[LocalProjectDependency] = Nil) extends CrossableProject[CrossedProject[A]] {
32 | protected[this] type P = this.type
33 | def aggregate(aggregates: AggregateArgument*) = empty.aggregate(aggregates.map {
34 | case ProjectAggregateArgument(project) => project: ProjectReference
35 | case VersionAggregateArgument(version) => axis(LocalProject(delegate.project.id), version)
36 | }: _*)
37 | def apply(version: String) =
38 | axis(delegate, version)
39 | .dependsOn(dependencies.map(d => d.copy(axis(d.project, version))): _*)
40 | .resolve
41 | def dependsOn(dependencies: LocalProjectDependency*) = copy(dependencies = this.dependencies ++ dependencies)
42 | def forVersions(version1: String) = Tuple1(apply(version1))
43 | def forVersions(version1: String, version2: String) = (apply(version1), apply(version2))
44 | def forVersions(version1: String, version2: String, version3: String) = (apply(version1), apply(version2), apply(version3))
45 | def forVersions(version1: String, version2: String, version3: String, version4: String) = (apply(version1), apply(version2), apply(version3), apply(version4))
46 | def forVersions(version1: String, version2: String, version3: String, version4: String, version5: String) = (apply(version1), apply(version2), apply(version3), apply(version4), apply(version5))
47 | def project = delegate.project
48 | def resolve = this
49 | def withProject(project: Project) = copy(delegate = delegate.withProject(project))
50 | }
51 |
--------------------------------------------------------------------------------
/sbt-cross/src/main/scala/com/lucidchart/sbtcross/DefaultAxis.scala:
--------------------------------------------------------------------------------
1 | package com.lucidchart.sbtcross
2 |
3 | import sbt.Keys._
4 | import sbt._
5 | import sbt.plugins.CorePlugin
6 |
7 | trait DefaultAxis extends Axis {
8 |
9 | import DefaultAxisPlugin.autoImport._
10 |
11 | protected[this] def name: String
12 | protected[this] def major(version: String): String
13 | protected[this] def id(id: String, version: String) = s"${id}_${major(version).replace(".", "_")}"
14 | def apply[A <: CrossableProject[A]](delegate: A, version: String) = {
15 | val project: ProjectDefinition[ProjectReference] = delegate.project
16 | // https://github.com/sbt/sbt/issues/1861
17 | // this isn't a complete fix, but most things aren't
18 | val newId = id(project.id, version)
19 | val newBase =
20 | if (project.base == file(".")) file(".cross") / newId
21 | else project.base
22 | val newProject = Project(newId, newBase)
23 | .aggregate(project.aggregate: _*)
24 | .dependsOn(project.dependencies: _*)
25 | .enablePlugins(project.plugins)
26 | .configs(project.configurations: _*)
27 | .settings(project.settings)
28 | .settings(
29 | baseDirectory := project.base.getAbsoluteFile,
30 | originalName := originalName.?.value.getOrElse(project.id),
31 | target := target.value / s"$name-${major(version)}")
32 | delegate.withProject(newProject)
33 | }
34 | def apply(project: LocalProject, version: String) = project.copy(id(project.project, version))
35 | }
36 |
37 | object DefaultAxisPlugin extends AutoPlugin {
38 | object autoImport {
39 | val originalName = SettingKey[String]("original-name")
40 | }
41 |
42 | import autoImport._
43 |
44 | override val trigger = allRequirements
45 |
46 | override val requires = CorePlugin
47 |
48 | override val projectSettings = Seq(
49 | name := originalName.?.value.getOrElse(name.value))
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/sbt-cross/src/main/scala/com/lucidchart/sbtcross/LibraryVersionAxis.scala:
--------------------------------------------------------------------------------
1 | package com.lucidchart.sbtcross
2 |
3 | import org.apache.commons.lang3.StringUtils
4 | import sbt.Keys._
5 | import sbt._
6 | import sbt.plugins.JvmPlugin
7 |
8 | class LibraryVersionAxis(protected[this] val name: String, settingKey: SettingKey[String], versionFn: String => String) extends DefaultAxis {
9 | import LibraryVersionAxis._
10 |
11 | protected[this] def major(version: String) = versionFn(version)
12 |
13 | override def apply[A <: CrossableProject[A]](delegate: A, version: String) = {
14 | val newDelegate = super.apply(delegate, version)
15 | newDelegate.withProject(newDelegate.project.settings(
16 | extraDirectories ++= (sourceDirectory.value +: extraDirectories.value).map(_ / s"$name-${major(version)}"),
17 | settingKey := version,
18 | Keys.version := {
19 | if (Keys.version.value.endsWith("-SNAPSHOT")) {
20 | s"${Keys.version.value.replace("-SNAPSHOT", "")}-${major(version)}-SNAPSHOT"
21 | } else {
22 | s"${Keys.version.value}-${major(version)}"
23 | }
24 | }))
25 | }
26 | }
27 |
28 | object LibraryVersionAxis {
29 | val majorVersion = (version: String) => version.indexOf('.') match {
30 | case StringUtils.INDEX_NOT_FOUND => version
31 | case i => version.take(i)
32 | }
33 |
34 | val minorVersion = (version: String) => StringUtils.ordinalIndexOf(version, ".", 2) match {
35 | case StringUtils.INDEX_NOT_FOUND => version
36 | case i => version.take(i)
37 | }
38 |
39 | val extraDirectories = SettingKey[Seq[File]]("extra-directories")
40 | }
41 |
42 | object LibraryVersionPlugin extends AutoPlugin {
43 | object autoImport {
44 | val extraDirectories = LibraryVersionAxis.extraDirectories
45 | }
46 | import autoImport._
47 |
48 | override val trigger = allRequirements
49 |
50 | override val requires = JvmPlugin
51 |
52 | override val globalSettings = Seq(
53 | extraDirectories := Nil)
54 |
55 | override val projectSettings = Seq(Compile, Test).flatMap { config =>
56 | Seq(
57 | unmanagedSourceDirectories in config ++= extraDirectories.value.flatMap { directory =>
58 | (unmanagedSourceDirectories in config).value.flatMap(Path.rebase(sourceDirectory.value, directory)(_))
59 | },
60 | unmanagedResourceDirectories in config ++= extraDirectories.value.flatMap { directory =>
61 | (unmanagedResourceDirectories in config).value.flatMap(Path.rebase(sourceDirectory.value, directory)(_))
62 | })
63 | }
64 | }
--------------------------------------------------------------------------------
/sbt-cross/src/main/scala/com/lucidchart/sbtcross/LocalProjectDependency.scala:
--------------------------------------------------------------------------------
1 | package com.lucidchart.sbtcross
2 |
3 | import sbt.{ ClasspathDependency, LocalProject }
4 |
5 | case class LocalProjectDependency(project: LocalProject, configurations: Option[String] = None) {
6 | def classpathDependency = ClasspathDependency(project, configurations)
7 | }
8 |
--------------------------------------------------------------------------------
/sbt-cross/src/main/scala/com/lucidchart/sbtcross/SbtCrossPlugin.scala:
--------------------------------------------------------------------------------
1 | package com.lucidchart.sbtcross
2 |
3 | import sbt._
4 | import scala.language.implicitConversions
5 |
6 | object SbtCrossPlugin extends AutoPlugin {
7 |
8 | object autoImport {
9 | implicit def toCrossable(project: Project): BaseProject = new BaseProject(project)
10 | }
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/sbt-cross/src/main/scala/com/lucidchart/sbtcross/ScalaAxis.scala:
--------------------------------------------------------------------------------
1 | package com.lucidchart.sbtcross
2 |
3 | import sbt.librarymanagement.CrossVersion
4 | import sbt.Keys._
5 |
6 | class ScalaAxis extends DefaultAxis {
7 | protected[this] val name = "scala"
8 | protected[this] def major(version: String) = CrossVersion.binaryScalaVersion(version)
9 | override def apply[A <: CrossableProject[A]](delegate: A, version: String) = {
10 | val newDelegate = super.apply(delegate, version)
11 | newDelegate.withProject(newDelegate.project.settings(
12 | crossTarget := target.value,
13 | scalaVersion := version))
14 | }
15 | }
16 |
17 | object ScalaAxis extends ScalaAxis
18 |
--------------------------------------------------------------------------------
/sbt-cross/version:
--------------------------------------------------------------------------------
1 | 4.0
2 |
--------------------------------------------------------------------------------