Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for pure Java subprojects #14

Closed
Kreinoee opened this issue May 22, 2019 · 1 comment · Fixed by #21

Comments

@Kreinoee
Copy link

@Kreinoee Kreinoee commented May 22, 2019

There is currently no good way to have a project, with a mix of scala and java sub projects. Consider the following build file:

val baseName = "util-inmemdbtest"

val ScalaVersion = new AnyRef {
  val `2.10` = "2.10.7"
  val `2.11` = "2.11.12"
  val `2.12` = "2.12.8"

  val all = List(this.`2.10`, this.`2.11`, this.`2.12`)
}

val sharedSettings = Defaults.coreDefaultSettings ++ Seq(
  version := "2.13.6_beta12",
  organization := "dk.cirque.util",

  organizationName := "Cirque A/S",
  organizationHomepage := Some(url("http://www.cirque.dk")),

  externalResolvers := {
    externalResolvers.value.filter(_.name == "local") ++ Seq(
      "Cirque repo" at "https://nexus.cirque-udv.dk/repository/cirque.default/")
  },

  credentials += {
    Option(System.getenv("SBT_CIRQUE_NEXUS_USER")) map { envUserName =>
      Option(System.getenv("SBT_CIRQUE_NEXUS_PASSWORD"))
          .map(Credentials("Sonatype Nexus Repository Manager", "repo.cirque.dk",
            envUserName, _))
          .getOrElse(throw new IllegalStateException(
            "There is a SBT_CIRQUE_NEXUS_USER env variable, but no SBT_CIRQUE_NEXUS_PASSWORD"))
    } getOrElse {
      val f = Path.userHome / ".sbt" / "credentials"
      if (!f.exists())
        throw new IllegalStateException(
          s"Credentials for our nexus repo, is not available, either as env variables, or from file: ${f.getAbsolutePath}")
      Credentials(f)
    }
  },

  //-package nessesary for javadoc to insert javadoc from the package private base classes to the documentation of the implementation classes.
  //-target 1.7 is nessesary as there is scala_2.10 project that use this project, and scala 2.10 can only be compiled up to jvm 1.7 bytecode.
  javacOptions in doc += "-package",
  javacOptions in(Compile, compile) ++= Seq("-target", "1.7", "-source", "1.7"),

  // Make test run compilation of documentation, as this often fails, and therefore should be part of the test suite.
  (test in Test) := {
    val docResult = (doc in Compile).value
    (test in Test).value
  },

  publishMavenStyle := true,
  publishTo := {
    if (version.value.toUpperCase.contains("SNAPSHOT"))
      Some("snapshots" at "https://nexus.cirque-udv.dk/repository/internal.snapshots/")
    else
      Some("internal" at "https://nexus.cirque-udv.dk/repository/internal/")
  }

)

val scalaSharedSettings = sharedSettings ++ Seq(
  scalacOptions ++= Seq("-unchecked", "-deprecation", "-feature")
)

lazy val shared = (projectMatrix in file("shared"))
    .settings(sharedSettings ++ Seq(
      name := s"$baseName-shared",
      libraryDependencies ++= Seq(
        "org.postgresql" % "postgresql" % "9.4-1201-jdbc41" % "test",
        "org.slf4j" % "slf4j-api" % "1.7.14",
        "commons-io" % "commons-io" % "2.4"
      ),
      crossPaths := false,
      autoScalaLibrary := false
    )).jvmPlatform(ScalaVersion.all)

lazy val hikariCP = (projectMatrix in file("hikariCP"))
    .settings(sharedSettings ++ Seq(
      name := s"$baseName-hikariCP",
      libraryDependencies ++= Seq(
        "com.zaxxer" % "HikariCP" % "2.5.0" % "provided"
      ),
      crossPaths := false,
      autoScalaLibrary := false
    ))
    .jvmPlatform(ScalaVersion.all.take(1))
    .dependsOn(shared)

lazy val jpa = (projectMatrix in file("jpa"))
    .settings(scalaSharedSettings ++ Seq(
      name := s"$baseName-jpa",
      libraryDependencies ++= Seq(
        "dk.cirque.util" %% "util-db" % "1.2.3",
        "org.eclipse.persistence" % "javax.persistence" % "2.1.1",
        "org.eclipse.persistence" % "eclipselink" % "2.6.3" % "test",
        "com.h2database" % "h2" % "1.4.185" % "test",
        "dk.cirque.util" % "billing" % "6.2.13" % "test",
        "org.scalatest" %% "scalatest" % "3.0.1" % "test"
      )
    ))
    .dependsOn(shared)
    .jvmPlatform(ScalaVersion.all)

val slickSettings = scalaSharedSettings ++ Seq(
  unmanagedSourceDirectories in Compile += baseDirectory.value.getParentFile / "slick-shared-source" / "main",
  // For some reason, adding an extra test dir, makes idea unable to load the project.
  // See https://youtrack.jetbrains.com/issue/SCL-12012 for IDEA bug
  // We currently have no test that can be used for all versions of slick anyway, so
  // just outcommenting the line for now.
  //	unmanagedSourceDirectories in Test += baseDirectory.value.getParentFile / "slick-shared-source" / "test"
)

lazy val slick31 = (projectMatrix in file("slick-3_1"))
    .settings(slickSettings ++ Seq(
      name := s"$baseName-slick-3_1",
      libraryDependencies ++= Seq(
        "com.typesafe.slick" %% "slick" % "3.1.1",
        "org.postgresql" % "postgresql" % "9.4-1201-jdbc41" % "test",
        "dk.cirque.billing" %% "billing-slick" % "1.2.9" % "test",
        "org.scalatest" %% "scalatest" % "2.2.4" % "test",
        "com.h2database" % "h2" % "1.4.191" % "test",
        "org.slf4j" % "slf4j-simple" % "1.7.15" % "test"
      )
    ))
    .jvmPlatform(Seq(ScalaVersion.`2.10`, ScalaVersion.`2.11`))
    .dependsOn(shared)

lazy val slick32 = (projectMatrix in file("slick-3_2"))
    .settings(slickSettings ++ Seq(
      name := s"$baseName-slick-3_2",
      libraryDependencies ++= Seq(
        "com.typesafe.slick"                          %% "slick"                   % "3.2.0",
        "dk.cirque.billing"                           %% "billing-slick"           % "3.2.1.3"     % "test",
        "org.postgresql"                              %  "postgresql"              % "9.4-1201-jdbc41"  % "test",
        "org.scalatest"                               %% "scalatest"               % "3.0.1"            % "test",
        "com.h2database"                              %  "h2"                      % "1.4.191"          % "test",
        "org.slf4j"                                   %  "slf4j-simple"            % "1.7.15"           % "test"
      )
    ))
    .dependsOn(shared)
    .jvmPlatform(Seq(ScalaVersion.`2.11`, ScalaVersion.`2.12`))

// It should be able to crossbuild the same project for slick 3.2 and 3.3, but it then cannot found the
// correct version of shared to depen on, due to the problem described here: https://github.com/sbt/sbt-projectmatrix/issues/13
lazy val slick33 = (projectMatrix in file("slick-3_2"))
    .settings(slickSettings ++ Seq(
      name := s"$baseName-slick-3_3",
      libraryDependencies ++= Seq(
        "com.typesafe.slick"                          %% "slick"                   % "3.3.0",
        "dk.cirque.billing"                           %% "billing-slick-3_3"       % "4.0.0"      % "test",
        "org.postgresql"                              %  "postgresql"              % "9.4-1201-jdbc41"  % "test",
        "org.scalatest"                               %% "scalatest"               % "3.0.1"            % "test",
        "com.h2database"                              %  "h2"                      % "1.4.191"          % "test",
        "org.slf4j"                                   %  "slf4j-simple"            % "1.7.15"           % "test"
      )
    ))
    .dependsOn(shared)
    .jvmPlatform(Seq(ScalaVersion.`2.11`, ScalaVersion.`2.12`))

This file have two pure java sub project, one called shared, and one called hikariCP. However, if I do not specify .jvmPlatform(...) on the java projects, they are simply ignored in the build, and the only allowed input to jvmPlatform(...) is a Seq of scala versions.

For the hikariCP project, it can be solved pretty easy, by just picking a single scala version by random, and then make sure to set the autoScalaLibrary and crossPaths settings to false.

However, this workaround is not working for the shared project, because some of the scala sub projects (jpa, and the slick ones), depends on the shared project, and if the shared project does not have the same scalaversions defined in jvmPlatform(...) as the projects depending on it has, the build script will fail, and say that it cannot find the correct sharedJVM2.X project to depend on.

I can get it to work, by cross building the shared java sub project, for every scala version used by the projects that depend on it. However this is far from optimal by several reasons:

  1. The shared project gets build multiply times without no reason (ones for each defined scala version).
  2. When publishing, it does gets published, but with a lot of errors in the output, as it tries to publish the same library multiples times, and therefore is trying to override an already published artifact.
@eed3si9n

This comment has been minimized.

Copy link
Member

@eed3si9n eed3si9n commented May 22, 2019

Thanks for the report. I agree there should be support for pure Java subprojects.

eed3si9n added a commit that referenced this issue Nov 4, 2019
Fixes #13
Fixes #14

This adds the notion of VirutalAxis that allows the matrix to define strong or weak axis.
@eed3si9n eed3si9n closed this in #21 Nov 4, 2019
@eed3si9n eed3si9n changed the title Support for pure Java sub projects. Support for pure Java subprojects Nov 4, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.