build.sbt (669 lines of code) (raw):
Global / onChangedBuildSource := ReloadOnSourceChanges
Global / excludeLintKeys += scalacOptions // might be actually unused in util-doc module but not sure
// All Twitter library releases are date versioned as YY.MM.patch
val releaseVersion = "24.8.0-SNAPSHOT"
val slf4jVersion = "1.7.30"
val jacksonVersion = "2.14.3"
val json4sVersion = "4.0.3"
val mockitoVersion = "3.3.3"
val mockitoScalaVersion = "1.14.8"
val zkVersion = "3.5.6"
val zkClientVersion = "0.0.81"
val zkGroupVersion = "0.0.92"
val zkDependency = "org.apache.zookeeper" % "zookeeper" % zkVersion excludeAll (
ExclusionRule("com.sun.jdmk", "jmxtools"),
ExclusionRule("com.sun.jmx", "jmxri"),
ExclusionRule("javax.jms", "jms")
)
val guavaLib = "com.google.guava" % "guava" % "25.1-jre"
val caffeineLib = "com.github.ben-manes.caffeine" % "caffeine" % "2.9.3"
val jsr305Lib = "com.google.code.findbugs" % "jsr305" % "2.0.1"
val scalacheckLib = "org.scalacheck" %% "scalacheck" % "1.15.4" % "test"
val slf4jApi = "org.slf4j" % "slf4j-api" % slf4jVersion
val snakeyaml = "org.yaml" % "snakeyaml" % "1.28"
def travisTestJavaOptions: Seq[String] = {
// We have some custom configuration for the Travis environment
// https://docs.travis-ci.com/user/environment-variables/#default-environment-variables
val travisBuild = sys.env.getOrElse("TRAVIS", "false").toBoolean
if (travisBuild) {
Seq(
"-DSKIP_FLAKY=true",
"-DSKIP_FLAKY_TRAVIS=true"
)
} else {
Seq(
"-DSKIP_FLAKY=true"
)
}
}
def gcJavaOptions: Seq[String] = {
val javaVersion = System.getProperty("java.version")
if (javaVersion.startsWith("1.8")) {
jdk8GcJavaOptions
} else {
jdk11GcJavaOptions
}
}
def jdk8GcJavaOptions: Seq[String] = {
Seq(
"-XX:+UseParNewGC",
"-XX:+UseConcMarkSweepGC",
"-XX:+CMSParallelRemarkEnabled",
"-XX:+CMSClassUnloadingEnabled",
"-XX:ReservedCodeCacheSize=128m",
"-XX:SurvivorRatio=128",
"-XX:MaxTenuringThreshold=0",
"-Xss8M",
"-Xms512M",
"-Xmx2G"
)
}
def jdk11GcJavaOptions: Seq[String] = {
Seq(
"-XX:+UseConcMarkSweepGC",
"-XX:+CMSParallelRemarkEnabled",
"-XX:+CMSClassUnloadingEnabled",
"-XX:ReservedCodeCacheSize=128m",
"-XX:SurvivorRatio=128",
"-XX:MaxTenuringThreshold=0",
"-Xss8M",
"-Xms512M",
"-Xmx2G"
)
}
val _scalaVersion = "2.13.6"
val _crossScalaVersions = Seq("2.12.12", "2.13.6")
val defaultScalaSettings = Seq(
scalaVersion := _scalaVersion,
crossScalaVersions := _crossScalaVersions
)
val defaultScala3EnabledSettings = Seq(
scalaVersion := _scalaVersion,
crossScalaVersions := _crossScalaVersions ++ Seq("3.0.2")
)
// Our dependencies or compiler options may differ for both Scala 2 and 3. We branch here
// to account for there differences but should merge these artifacts as they are updated.
val scalaDependencies = Seq("org.scala-lang.modules" %% "scala-collection-compat" % "2.4.4")
val scala2cOptions = Seq(
"-target:jvm-1.8",
// Needs -missing-interpolator due to https://issues.scala-lang.org/browse/SI-8761
"-Xlint:-missing-interpolator",
"-Yrangepos"
)
val scala3cOptions = Seq(
"-Xtarget:8"
)
val scala3Dependencies = scalaDependencies ++ Seq(
"org.scalatest" %% "scalatest" % "3.2.9" % "test",
"org.scalatestplus" %% "junit-4-13" % "3.2.9.0" % "test"
)
val scala2Dependencies = scalaDependencies ++ Seq(
"org.scalatest" %% "scalatest" % "3.1.2" % "test",
"org.scalatestplus" %% "junit-4-12" % "3.1.2.0" % "test"
)
val baseSettings = Seq(
version := releaseVersion,
organization := "com.twitter",
// Workaround for a scaladoc bug which causes it to choke on empty classpaths.
Compile / unmanagedClasspath += Attributed.blank(new java.io.File("doesnotexist")),
libraryDependencies ++= Seq(
// See https://www.scala-sbt.org/0.13/docs/Testing.html#JUnit
"com.novocode" % "junit-interface" % "0.11" % "test",
),
Test / fork := true, // We have to fork to get the JavaOptions
// Workaround for cross building HealthyQueue.scala, which is not compatible between
// 2.12-, 2.13+, and scala 3.
Compile / unmanagedSourceDirectories += {
val sourceDir = (Compile / sourceDirectory).value
CrossVersion.partialVersion(scalaVersion.value) match {
case Some((2, n)) if n < 13 => sourceDir / "scala-2.12-"
case _ => sourceDir / "scala-2.13+"
}
},
// Let's skip compiling docs for Scala 3 due a Dotty Scaladoc bug where generating the docs
// requires network access. See https://github.com/lampepfl/dotty/issues/13272 or CSL-11251.
Compile / doc / sources := {
if (scalaVersion.value.startsWith("3")) Seq.empty
else (Compile / doc / sources).value
},
resolvers +=
"Sonatype OSS Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots",
scalacOptions := Seq(
"-unchecked",
"-deprecation",
"-feature",
"-encoding",
"utf8",
) ++ {
if (scalaVersion.value.startsWith("2")) scala2cOptions
else scala3cOptions
},
// Note: Use -Xlint rather than -Xlint:unchecked when TestThriftStructure
// warnings are resolved
javacOptions ++= Seq("-Xlint:unchecked", "-source", "1.8", "-target", "1.8"),
doc / javacOptions := Seq("-source", "1.8"),
javaOptions ++= Seq(
"-Djava.net.preferIPv4Stack=true",
"-XX:+AggressiveOpts",
"-server"
),
javaOptions ++= gcJavaOptions,
Test / javaOptions ++= travisTestJavaOptions,
// -a: print stack traces for failing asserts
testOptions += Tests.Argument(TestFrameworks.JUnit, "-a"),
// This is bad news for things like com.twitter.util.Time
Test / parallelExecution := false,
// Sonatype publishing
Test / publishArtifact := false,
pomIncludeRepository := { _ => false },
publishMavenStyle := true,
publishConfiguration := publishConfiguration.value.withOverwrite(true),
publishLocalConfiguration := publishLocalConfiguration.value.withOverwrite(true),
autoAPIMappings := true,
apiURL := Some(url("https://twitter.github.io/util/docs/")),
pomExtra :=
<url>https://github.com/twitter/util</url>
<licenses>
<license>
<name>Apache License, Version 2.0</name>
<url>https://www.apache.org/licenses/LICENSE-2.0</url>
</license>
</licenses>
<scm>
<url>git@github.com:twitter/util.git</url>
<connection>scm:git:git@github.com:twitter/util.git</connection>
</scm>
<developers>
<developer>
<id>twitter</id>
<name>Twitter Inc.</name>
<url>https://www.twitter.com/</url>
</developer>
</developers>,
publishTo := {
val nexus = "https://oss.sonatype.org/"
if (version.value.trim.endsWith("SNAPSHOT"))
Some("snapshots" at nexus + "content/repositories/snapshots")
else
Some("releases" at nexus + "service/local/staging/deploy/maven2")
}
)
val sharedSettings =
baseSettings ++
defaultScalaSettings ++
Seq(libraryDependencies ++= scala2Dependencies)
val sharedScala3EnabledSettings =
baseSettings ++
defaultScala3EnabledSettings ++
Seq(libraryDependencies ++= scala3Dependencies) ++
Seq(excludeDependencies ++= Seq("org.scala-lang.modules" % "scala-collection-compat_3"))
// settings for projects that are cross compiled with scala 2.10
val settingsCrossCompiledWithTwoTen =
baseSettings ++
Seq(
crossScalaVersions := Seq("2.10.7") ++ _crossScalaVersions,
scalaVersion := _scalaVersion,
javacOptions ++= Seq("-source", "1.8", "-target", "1.8", "-Xlint:unchecked"),
doc / javacOptions := Seq("-source", "1.8"),
libraryDependencies ++= Seq(
"org.scalacheck" %% "scalacheck" % "1.14.3" % "test"
)
)
lazy val noPublishSettings = Seq(
publish / skip := true
)
def scalatestMockitoVersionedDep(scalaVersion: String) = {
if (scalaVersion.startsWith("2")) {
Seq(
"org.scalatestplus" %% "mockito-3-3" % "3.1.2.0" % "test"
)
} else {
Seq(
"org.scalatestplus" %% "mockito-3-4" % "3.2.9.0" % "test"
)
}
}
def scalatestScalacheckVersionedDep(scalaVersion: String) = {
if (scalaVersion.startsWith("2")) {
Seq(
"org.scalatestplus" %% "scalacheck-1-14" % "3.1.2.0" % "test"
)
} else {
Seq(
"org.scalatestplus" %% "scalacheck-1-15" % "3.2.9.0" % "test"
)
}
}
lazy val util = Project(
id = "util",
base = file(".")
).enablePlugins(
ScalaUnidocPlugin
).settings(
sharedSettings ++
noPublishSettings ++
Seq(
ScalaUnidoc / unidoc / unidocProjectFilter := inAnyProject -- inProjects(utilBenchmark)
)
).aggregate(
utilApp,
utilAppLifecycle,
utilBenchmark,
utilCache,
utilCacheGuava,
utilClassPreloader,
utilCodec,
utilCore,
utilDoc,
utilFunction,
utilHashing,
utilJacksonAnnotations,
utilJackson,
utilJvm,
utilLint,
utilLogging,
utilMock,
utilReflect,
utilRegistry,
utilRouting,
utilSecurity,
utilSecurityTestCerts,
utilSlf4jApi,
utilSlf4jJulBridge,
utilStats,
utilTest,
utilThrift,
utilTunable,
utilValidator,
utilValidatorConstraint,
utilZk,
utilZkTest
)
lazy val utilApp = Project(
id = "util-app",
base = file("util-app")
).settings(
sharedScala3EnabledSettings
).settings(
name := "util-app",
libraryDependencies ++= Seq(
"org.mockito" % "mockito-core" % mockitoVersion % "test",
) ++ scalatestMockitoVersionedDep(scalaVersion.value)
).dependsOn(utilAppLifecycle, utilCore, utilRegistry)
lazy val utilAppLifecycle = Project(
id = "util-app-lifecycle",
base = file("util-app-lifecycle")
).settings(
sharedScala3EnabledSettings
).settings(
name := "util-app-lifecycle"
).dependsOn(utilCore)
lazy val utilBenchmark = Project(
id = "util-benchmark",
base = file("util-benchmark")
).settings(
sharedSettings
).enablePlugins(
JmhPlugin
).settings(
name := "util-benchmark"
).dependsOn(
utilCore,
utilHashing,
utilJackson,
utilJvm,
utilReflect,
utilStats,
utilValidator
)
lazy val utilCache = Project(
id = "util-cache",
base = file("util-cache")
).settings(
sharedScala3EnabledSettings
).settings(
name := "util-cache",
libraryDependencies ++= Seq(
caffeineLib,
jsr305Lib,
"org.mockito" % "mockito-core" % mockitoVersion % "test",
) ++ scalatestMockitoVersionedDep(scalaVersion.value)
).dependsOn(utilCore)
lazy val utilCacheGuava = Project(
id = "util-cache-guava",
base = file("util-cache-guava")
).settings(
sharedScala3EnabledSettings
).settings(
name := "util-cache-guava",
libraryDependencies ++= Seq(guavaLib, jsr305Lib)
).dependsOn(utilCache % "compile->compile;test->test", utilCore)
lazy val utilClassPreloader = Project(
id = "util-class-preloader",
base = file("util-class-preloader")
).settings(
sharedSettings
).settings(
name := "util-class-preloader"
).dependsOn(utilCore)
lazy val utilCodec = Project(
id = "util-codec",
base = file("util-codec")
).settings(
sharedScala3EnabledSettings
).settings(
name := "util-codec"
).dependsOn(utilCore)
lazy val utilCore = Project(
id = "util-core",
base = file("util-core")
).settings(
sharedScala3EnabledSettings
).settings(
name := "util-core",
// Moved some code to 'concurrent-extra' to conform to Pants' 1:1:1 principle (https://www.pantsbuild.org/build_files.html#target-granularity)
// so that util-core would work better for Pants projects in IntelliJ.
Compile / unmanagedSourceDirectories += baseDirectory.value / "concurrent-extra",
libraryDependencies ++= Seq(
caffeineLib % "test",
scalacheckLib,
"org.mockito" % "mockito-core" % mockitoVersion % "test",
) ++
scalatestMockitoVersionedDep(scalaVersion.value) ++
scalatestScalacheckVersionedDep(scalaVersion.value) ++ {
if (scalaVersion.value.startsWith("2")) {
Seq(
"org.scala-lang" % "scala-reflect" % scalaVersion.value,
"org.scala-lang.modules" %% "scala-parser-combinators" % "1.1.2"
)
} else {
Seq(
"org.scala-lang.modules" %% "scala-parser-combinators" % "2.0.0"
)
}
},
Compile / resourceGenerators += Def.task {
val projectName = name.value
val file = resourceManaged.value / "com" / "twitter" / projectName / "build.properties"
val buildRev = scala.sys.process.Process("git" :: "rev-parse" :: "HEAD" :: Nil).!!.trim
val buildName = new java.text.SimpleDateFormat("yyyyMMdd-HHmmss").format(new java.util.Date)
val contents =
s"name=$projectName\nversion=${version.value}\nbuild_revision=$buildRev\nbuild_name=$buildName"
IO.write(file, contents)
Seq(file)
}.taskValue,
Compile / doc / sources := {
// Monitors.java causes "not found: type Monitor$" (CSL-5034)
// so exclude it from the sources used for scaladoc
val previous = (Compile / doc / sources).value
previous.filterNot(file => file.getName() == "Monitors.java")
}
).dependsOn(utilFunction)
lazy val utilDoc = Project(
id = "util-doc",
base = file("doc")
).enablePlugins(
SphinxPlugin
).settings(
sharedSettings ++
noPublishSettings ++ Seq(
doc / scalacOptions ++= Seq("-doc-title", "Util", "-doc-version", version.value),
Sphinx / includeFilter := ("*.html" | "*.png" | "*.svg" | "*.js" | "*.css" | "*.gif" | "*.txt")
))
lazy val utilFunction = Project(
id = "util-function",
base = file("util-function")
).settings(
sharedSettings
).settings(
name := "util-function"
)
lazy val utilReflect = Project(
id = "util-reflect",
base = file("util-reflect")
).settings(
sharedSettings
).settings(
name := "util-reflect"
).dependsOn(utilCore)
lazy val utilHashing = Project(
id = "util-hashing",
base = file("util-hashing")
).settings(
sharedScala3EnabledSettings
).settings(
name := "util-hashing",
libraryDependencies ++= Seq(
scalacheckLib
) ++ scalatestScalacheckVersionedDep(scalaVersion.value)
).dependsOn(utilCore % "test")
lazy val utilJacksonAnnotations = Project(
id = "util-jackson-annotations",
base = file("util-jackson-annotations")
).settings(
sharedSettings
).settings(
name := "util-jackson-annotations"
)
lazy val utilJackson = Project(
id = "util-jackson",
base = file("util-jackson")
).settings(
sharedSettings
).settings(
name := "util-jackson",
libraryDependencies ++= Seq(
"com.fasterxml.jackson.core" % "jackson-core" % jacksonVersion,
"com.fasterxml.jackson.core" % "jackson-databind" % jacksonVersion,
"com.fasterxml.jackson.dataformat" % "jackson-dataformat-yaml" % jacksonVersion,
"com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % jacksonVersion,
"com.fasterxml.jackson.module" %% "jackson-module-scala" % jacksonVersion exclude ("com.google.guava", "guava"),
"jakarta.validation" % "jakarta.validation-api" % "3.0.0",
"org.json4s" %% "json4s-core" % json4sVersion,
"com.fasterxml.jackson.core" % "jackson-annotations" % jacksonVersion % "test",
scalacheckLib,
"org.scalatestplus" %% "scalacheck-1-14" % "3.1.2.0" % "test",
"org.slf4j" % "slf4j-simple" % slf4jVersion % "test"
)
).dependsOn(
utilCore,
utilJacksonAnnotations,
utilMock % Test,
utilReflect,
utilSlf4jApi,
utilValidator)
lazy val utilJvm = Project(
id = "util-jvm",
base = file("util-jvm")
).settings(
sharedScala3EnabledSettings
).settings(
name := "util-jvm",
libraryDependencies ++= Seq(
"org.mockito" % "mockito-core" % mockitoVersion % "test",
) ++ scalatestMockitoVersionedDep(scalaVersion.value)
).dependsOn(utilApp, utilCore, utilStats)
lazy val utilLint = Project(
id = "util-lint",
base = file("util-lint")
).settings(
sharedScala3EnabledSettings
).settings(
name := "util-lint"
).dependsOn(utilCore)
lazy val utilLogging = Project(
id = "util-logging",
base = file("util-logging")
).settings(
sharedScala3EnabledSettings
).settings(
name := "util-logging"
).dependsOn(utilCore, utilApp, utilStats)
lazy val utilMock = Project(
id = "util-mock",
base = file("util-mock")
).settings(
sharedSettings
).settings(
name := "util-mock",
libraryDependencies ++= Seq(
// only depend on mockito-scala; it will pull in the correct corresponding version of mockito.
"org.mockito" %% "mockito-scala" % mockitoScalaVersion,
"org.mockito" %% "mockito-scala-scalatest" % mockitoScalaVersion % "test"
)
).dependsOn(utilCore % "test")
lazy val utilRegistry = Project(
id = "util-registry",
base = file("util-registry")
).settings(
sharedScala3EnabledSettings
).settings(
name := "util-registry",
libraryDependencies ++= Seq(
"org.mockito" % "mockito-core" % mockitoVersion % "test",
) ++ scalatestMockitoVersionedDep(scalaVersion.value)
).dependsOn(utilCore)
lazy val utilRouting = Project(
id = "util-routing",
base = file("util-routing")
).settings(
sharedScala3EnabledSettings
).settings(
name := "util-routing"
).dependsOn(utilCore, utilSlf4jApi)
lazy val utilSlf4jApi = Project(
id = "util-slf4j-api",
base = file("util-slf4j-api")
).settings(
sharedScala3EnabledSettings
).settings(
name := "util-slf4j-api",
libraryDependencies ++= Seq(
slf4jApi,
"org.mockito" % "mockito-core" % mockitoVersion % "test",
"org.slf4j" % "slf4j-simple" % slf4jVersion % "test",
) ++ scalatestMockitoVersionedDep(scalaVersion.value)
).dependsOn(utilCore % "test")
lazy val utilSlf4jJulBridge = Project(
id = "util-slf4j-jul-bridge",
base = file("util-slf4j-jul-bridge")
).settings(
sharedScala3EnabledSettings
).settings(
name := "util-slf4j-jul-bridge",
libraryDependencies ++= Seq(slf4jApi, "org.slf4j" % "jul-to-slf4j" % slf4jVersion)
).dependsOn(utilCore, utilApp, utilSlf4jApi)
lazy val utilSecurity = Project(
id = "util-security",
base = file("util-security")
).settings(
sharedScala3EnabledSettings
).settings(
name := "util-security",
libraryDependencies ++= Seq(
scalacheckLib,
snakeyaml
) ++ scalatestScalacheckVersionedDep(scalaVersion.value)
).dependsOn(utilCore, utilLogging, utilSecurityTestCerts % "test")
lazy val utilSecurityTestCerts = Project(
id = "util-security-test-certs",
base = file("util-security-test-certs")
).settings(
sharedSettings
).settings(
name := "util-security-test-certs"
)
lazy val utilStats = Project(
id = "util-stats",
base = file("util-stats")
).settings(
sharedScala3EnabledSettings
).settings(
name := "util-stats",
libraryDependencies ++= Seq(
caffeineLib,
jsr305Lib,
scalacheckLib,
"com.fasterxml.jackson.core" % "jackson-core" % jacksonVersion,
"com.fasterxml.jackson.core" % "jackson-databind" % jacksonVersion,
("com.fasterxml.jackson.module" %% "jackson-module-scala" % jacksonVersion exclude ("com.google.guava", "guava"))
.cross(CrossVersion.for3Use2_13),
"org.mockito" % "mockito-core" % mockitoVersion % "test"
) ++ scalatestMockitoVersionedDep(scalaVersion.value)
++ scalatestScalacheckVersionedDep(scalaVersion.value)
++ {
CrossVersion.partialVersion(scalaVersion.value) match {
case Some((2, major)) if major <= 12 =>
Seq()
case _ =>
Seq("org.scala-lang.modules" %% "scala-parallel-collections" % "1.0.3" % "test")
}
}
).dependsOn(utilApp, utilCore, utilLint)
lazy val utilTest = Project(
id = "util-test",
base = file("util-test")
).settings(
sharedSettings
).settings(
name := "util-test",
libraryDependencies ++= Seq(
"org.mockito" % "mockito-all" % "1.10.19",
"org.scalatestplus" %% "mockito-1-10" % "3.1.0.0"
)
).dependsOn(utilCore, utilLogging, utilStats)
lazy val utilThrift = Project(
id = "util-thrift",
base = file("util-thrift")
).settings(
sharedScala3EnabledSettings
).settings(
name := "util-thrift",
libraryDependencies ++= Seq(
"org.apache.thrift" % "libthrift" % "0.10.0",
slf4jApi % "provided",
"com.fasterxml.jackson.core" % "jackson-core" % jacksonVersion,
"com.fasterxml.jackson.core" % "jackson-databind" % jacksonVersion
)
).dependsOn(utilCodec)
lazy val utilTunable = Project(
id = "util-tunable",
base = file("util-tunable")
).settings(
sharedSettings
).settings(
name := "util-tunable",
libraryDependencies ++= Seq(
"com.fasterxml.jackson.core" % "jackson-core" % jacksonVersion,
"com.fasterxml.jackson.core" % "jackson-databind" % jacksonVersion,
"com.fasterxml.jackson.module" %% "jackson-module-scala" % jacksonVersion exclude ("com.google.guava", "guava")
)
).dependsOn(utilApp, utilCore)
lazy val utilValidator = Project(
id = "util-validator",
base = file("util-validator")
).settings(
sharedSettings
).settings(
name := "util-validator",
libraryDependencies ++= Seq(
caffeineLib,
scalacheckLib,
"jakarta.validation" % "jakarta.validation-api" % "3.0.0",
"org.hibernate.validator" % "hibernate-validator" % "7.0.1.Final",
"org.glassfish" % "jakarta.el" % "4.0.0",
"org.json4s" %% "json4s-core" % json4sVersion,
"com.fasterxml.jackson.core" % "jackson-annotations" % jacksonVersion % "test",
"org.scalatestplus" %% "scalacheck-1-14" % "3.1.2.0" % "test",
"org.slf4j" % "slf4j-simple" % slf4jVersion % "test"
)
).dependsOn(utilCore, utilReflect, utilSlf4jApi, utilValidatorConstraint)
lazy val utilValidatorConstraint = Project(
id = "util-validator-constraints",
base = file("util-validator-constraints")
).settings(
settingsCrossCompiledWithTwoTen
).settings(
libraryDependencies ++= Seq(
"jakarta.validation" % "jakarta.validation-api" % "3.0.0"
)
)
lazy val utilZk = Project(
id = "util-zk",
base = file("util-zk")
).settings(
sharedSettings
).settings(
name := "util-zk",
libraryDependencies ++= Seq(
zkDependency,
"org.mockito" % "mockito-core" % mockitoVersion % "test",
"org.scalatestplus" %% "mockito-3-3" % "3.1.2.0" % "test"
)
).dependsOn(utilCore, utilLogging)
lazy val utilZkTest = Project(
id = "util-zk-test",
base = file("util-zk-test")
).settings(
sharedScala3EnabledSettings
).settings(
name := "util-zk-test",
libraryDependencies += zkDependency
).dependsOn(utilCore % "test")