Skip to content

Commit

Permalink
Initial support for mill 0.12 (#421)
Browse files Browse the repository at this point in the history
  • Loading branch information
WojciechMazur authored Oct 25, 2024
1 parent aef59b3 commit 6b85609
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 55 deletions.
12 changes: 9 additions & 3 deletions project-builder/build-revision.sh
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,9 @@ function detectSourceVersion() {
echo "Using configured source version: $sourceVersion"
sourceVersionSetting="REQUIRE:-source:$sourceVersion"
fi
else
elif [[ -z "$sourceVersion" ]]; then
echo "No configured source version" > /dev/null
else
echo "Configured version `$sourceVersion` is invalid, it would be ignored"
fi
if [[ -z "$sourceVersionSetting" ]]; then
Expand Down Expand Up @@ -114,11 +116,14 @@ function setupScalacOptions(){
commonAppendScalacOptions="$sourceVersionSetting,-Wconf:msg=can be rewritten automatically under:s"
commonRemoveScalacOptions="-deprecation,-feature,-Xfatal-warnings,-Werror,MATCH:.*-Wconf.*any:e,-migration,"

extraScalacOptions="$_extraScalacOptions,$commonAppendScalacOptions"
extraScalacOptions="$commonAppendScalacOptions"
disabledScalacOptions="$_disabledScalacOption,$commonRemoveScalacOptions";
if [[ $isMigrating == true ]]; then
extraScalacOptions="-rewrite,$extraScalacOptions"
disabledScalacOptions="-indent,-no-indent,-new-syntax,$disabledScalacOptions"
else
# Apply extraScalacOptions passed as input only when compiling with target Scala version
extraScalacOptions="$_extraScalacOptions,$extraScalacOptions"
fi

echo "Would try to apply common scalacOption (best-effort, sbt/mill only):"
Expand Down Expand Up @@ -160,7 +165,8 @@ function buildForScalaVersion(){
echo "Execute tests: ${executeTests}"
echo "started" > build-status.txt
# Mill
if [ -f "repo/mill" ] || [ -f "repo/build.sc" ]; then
# We check either for mill boostrap script or one of valid root build files
if [ -f "repo/mill" ] || [ -f "repo/build.mill" ] || [ -f "repo/build.mill.scala"] || [ -f "repo/build.sc"]; then
echo "Mill project found: ${isMillProject}"
echo "mill" > $buildToolFile
$scriptDir/mill/prepare-project.sh "$project" repo "$scalaVersion" "$projectConfig"
Expand Down
73 changes: 49 additions & 24 deletions project-builder/mill/prepare-project.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,34 @@ scalaVersion="$3" # e.g. 3.1.2-RC1
projectConfig="$4"

export OPENCB_PROJECT_DIR=$repoDir

scriptDir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"

MILL_0_12="0.12.0-RC2"
MILL_0_12="0.12.0"
MILL_0_11=0.11.12
MILL_0_10=0.10.15
MILL_0_9=0.9.12
RESOLVE="resolve _"
MILL_BUILD_SCALA=build.mill.scala
MILL_BUILD=build.mill

cd $repoDir
millBuildFile=
for rootBuildFile in "$MILL_BUILD" "$MILL_BUILD_SCALA" "./build.sc"; do
if [[ -f $rootBuildFile ]]; then
millBuildFile=$rootBuildFile
if [[ $rootBuildFile == "$MILL_BUILD_SCALA" ]]; then
echo "Replace $MILL_BUILD_SCALA with $MILL_BUILD"
mv $MILL_BUILD_SCALA $MILL_BUILD
millBuildFile="$MILL_BUILD"
fi
break 1
fi
done
if [[ -z "$millBuildFile" ]]; then
echo "Not found a valid mill build root file"
exit 1
fi

millVersion=
if [[ -f .mill-version ]];then
millVersion=`cat .mill-version`
Expand All @@ -43,18 +61,7 @@ else
for v in $MILL_0_12 $MILL_0_11 $MILL_0_10 $MILL_0_9; do
if `${scriptDir}/millw --mill-version $v $RESOLVE > /dev/null 2>/dev/null`; then
echo "Successfully applied build using mill $v"
buildScVersions=($MILL_0_11 $MILL_0_10 $MILL_0_9)
if [[ " ${buildScVersions[*]} " =~ " ${v} " && -f ./build.sc ]]; then
echo "Found build.sc file and matching Mill version"
millVersion=$v
break
elif [[ -f ./build.mill ]]; then
echo "Found build.mill file"
millVersion=$v
break
else
echo "Able to resolve build, but not found matching build files"
fi
millVersion=$v
else
echo "Failed to apply build using mill $v"
fi
Expand Down Expand Up @@ -109,17 +116,30 @@ fi

# Rename build.sc to build.scala - Scalafix does ignore .sc files
# Use scala 3 dialect to allow for top level defs
millBuildExt="mill"
if [[ "$millBinaryVersionMajor" -eq "0" && "$millBinaryVersionMinor" -le "11" ]]; then
millBuildExt=sc
adaptedFiles=( $millBuildFile )
millBuildDirectory=
# if [[ -d "./mill-build" ]]; then
# millBuildDirectory="./mill-build"
if [[ -d "./project" ]]; then
millBuildDirectory="./project"
fi
adaptedFiles=( $PWD/build.${millBuildExt} )
if [[ -d ./project ]]; then
adaptedFiles+=(`find ./project -type f -name "*.$millBuildExt"`)
if [[ -z "$millBuildDirectory" ]]; then
echo "No mill build directory found"
else
for file in `find $millBuildDirectory -type f -name "*.mill.scala"`; do
echo "Strip .scala suffix from $file"
mv $file "${file%.scala}"
done
adaptedFiles+=(`find $millBuildDirectory -type f -name "*.mill"`)
adaptedFiles+=(`find $millBuildDirectory -type f -name "*.sc"`)
fi
for buildFile in "${adaptedFiles[@]}"; do
isMainBuildFile=false
if [[ "$buildFile" == "$millBuildFile" ]]; then
isMainBuildFile=true
fi
echo "Apply scalafix rules to $buildFile"
scalaFile="${buildFile%.$millBuildExt}.scala"
scalaFile="${buildFile}.scala"
cp $buildFile $scalaFile
scalafix \
--rules file:${scriptDir}/scalafix/rules/src/main/scala/fix/Scala3CommunityBuildMillAdapter.scala \
Expand All @@ -128,12 +148,17 @@ for buildFile in "${adaptedFiles[@]}"; do
--syntactic \
--settings.Scala3CommunityBuildMillAdapter.targetScalaVersion "$scalaVersion" \
--settings.Scala3CommunityBuildMillAdapter.millBinaryVersion "$millBinaryVersion" \
--settings.Scala3CommunityBuildMillAdapter.isMainBuildFile "$isMainBuildFile" \
--scala-version 3.1.0 > ${buildFile}.adapted \
&& mv ${buildFile}.adapted $buildFile \
|| (echo "Failed to adapt $buildFile, ignoring changes"; cat ${buildFile}.adapted; rm -f ${buildFile}.adapted)
rm $scalaFile
done

millBuildExt="mill"
if [[ "$millBinaryVersionMajor" -eq "0" && "$millBinaryVersionMinor" -le "11" ]]; then
millBuildExt=sc
fi
for f in "${adaptedFiles[@]}"; do
dir="$(dirname $(realpath "$f"))"
cp $scriptDir/MillCommunityBuild.sc ${dir}/MillCommunityBuild.$millBuildExt
Expand All @@ -146,9 +171,9 @@ for f in "${adaptedFiles[@]}"; do
# Compat for Mill 0.11+ sources
cp $scriptDir/../shared/CommunityBuildCore.scala ${dir}/CommunityBuildCore.$millBuildExt
for fileCopy in ${dir}/CommunityBuildCore.$millBuildExt ${dir}/MillCommunityBuild.$millBuildExt ${dir}/MillVersionCompat.$millBuildExt; do
scala-cli $scriptDir/../shared/searchAndReplace.scala -- $fileCopy "package build\n" ""
scala-cli $scriptDir/../shared/searchAndReplace.scala -- $fileCopy "import CommunityBuildCore." "import \$file.CommunityBuildCore, CommunityBuildCore."
scala-cli $scriptDir/../shared/searchAndReplace.scala -- $fileCopy "import MillVersionCompat." "import \$file.MillVersionCompat, MillVersionCompat."
scala-cli $scriptDir/../shared/searchAndReplace.scala -- $fileCopy "package build\n" "" 2> /dev/null
scala-cli $scriptDir/../shared/searchAndReplace.scala -- $fileCopy "import CommunityBuildCore." "import \$file.CommunityBuildCore, CommunityBuildCore." 2> /dev/null
scala-cli $scriptDir/../shared/searchAndReplace.scala -- $fileCopy "import MillVersionCompat." "import \$file.MillVersionCompat, MillVersionCompat." 2> /dev/null
done
fi

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import metaconfig._

case class Scala3CommunityBuildMillAdapterConfig(
targetScalaVersion: Option[String] = None,
millBinaryVersion: Option[String] = None
millBinaryVersion: Option[String] = None,
isMainBuildFile: Option[Boolean] = None
)
object Scala3CommunityBuildMillAdapterConfig {
def default = Scala3CommunityBuildMillAdapterConfig()
Expand Down Expand Up @@ -53,26 +54,36 @@ class Scala3CommunityBuildMillAdapter(
"scala3Version",
"Scala_3",
"scala_3",
"scala",
"scala"
// "Scala" - explicitly ignored
)

val Scala3Literal = raw""""3.\d+.\d+(?:-RC\d+)?"""".r
val useLegacyMillCross =
config.millBinaryVersion.exists(_.split('.').toList match {
case "0" :: minor :: _ =>
try minor.toInt <= 10
catch { case ex: Throwable => false }
case _ => false
})
val millVersionSegments = config.millBinaryVersion.map(_.split('.').toList)
def toIntOption(value: String) =
try Some(value.toInt)
catch { case ex: Throwable => None }
val useLegacyMillCross = millVersionSegments.exists {
case "0" :: minor :: _ => toIntOption(minor).exists(_ < 11)
case _ => false
}
val useLegacyTasks = millVersionSegments.exists {
case "0" :: minor :: _ => toIntOption(minor).exists(_ < 12)
case _ => false
}

object Transform {
val RootMill = Term.Select(Term.Name("_root_"), Term.Name("mill"))
val TaskType = Term.Select(RootMill, if (useLegacyTasks) Term.Name("T") else Term.Name("Task"))
// val TaskTerm =
val TaskCommandType =
Term.Select(TaskType, if (useLegacyTasks) Term.Name("command") else Term.Name("Command"))

def shouldWrapInTarget(body: Term, tpe: Option[Type]) = {
val isLiteral = body.isInstanceOf[Lit.String]
def hasTargetType = tpe match {
case Some(Type.Apply(Type.Name("T"), _)) => true
case _ => false
case Some(Type.Apply(Type.Name("T" | "Task"), _)) => true
case _ => false
}
!isLiteral || hasTargetType
}
Expand Down Expand Up @@ -158,7 +169,7 @@ class Scala3CommunityBuildMillAdapter(
decltpe = None,
body =
Term.Apply(
Term.Select(Term.Select(Term.Select(Term.Name("_root_"), Term.Name("mill")), Term.Name("T")), Term.Name("command")),
TaskCommandType,
List(
Term.Block(List(
Defn.Def(
Expand Down Expand Up @@ -197,7 +208,9 @@ class Scala3CommunityBuildMillAdapter(
if (hasScalacOptions || !canHaveScalacOptions || noInjects) Nil
else injectScalacOptionsMapping
} ++ traits.collectFirst {
case Init(WithTypeName("RootModule"), _, _) if !noInjects => injectRootModuleRunCommand
case Init(WithTypeName("RootModule" | "MillBuildRootModule"), _, _)
if !noInjects && config.isMainBuildFile.forall(_ == true) =>
injectRootModuleRunCommand
}
)

Expand Down Expand Up @@ -267,12 +280,14 @@ class Scala3CommunityBuildMillAdapter(
val headerInject = {
if (noInjects) Patch.empty
else {
val lastSpecialImport = doc.tree.collect {
val insertAfter = doc.tree.collect {
case tree: Import if Seq("$file", "$ivy").exists(tree.syntax.contains) => tree
case pkg: Pkg => pkg
}.lastOption
lastSpecialImport match {
case Some(lastImport) => Patch.addRight(lastImport, Replacment.injects)
case None => Patch.addLeft(doc.tree, Replacment.injects)
insertAfter match {
case Some(Pkg(_, firstStat :: _)) => Patch.addLeft(firstStat, Replacment.injects)
case Some(insertAfter) => Patch.addRight(insertAfter, Replacment.injects)
case None => Patch.addLeft(doc.tree, Replacment.injects)
}
}
}
Expand Down Expand Up @@ -353,11 +368,10 @@ class Scala3CommunityBuildMillAdapter(
quote + stripQutoes + quote
}

val MillCommunityBuildInject = """
|import $file.MillCommunityBuild
|import $file.MillVersionCompat, MillVersionCompat.compat.{Task => MillCompatTask}
val MillCommunityBuildInject = s"""
|// Main entry point for community build
|def runCommunityBuild(_evaluator: _root_.mill.eval.Evaluator, scalaVersion: _root_.scala.Predef.String, configJson: _root_.scala.Predef.String, projectDir: _root_.scala.Predef.String, targets: _root_.scala.Predef.String*) = _root_.mill.T.command {
|def runCommunityBuild(_evaluator: _root_.mill.eval.Evaluator, scalaVersion: _root_.scala.Predef.String, configJson: _root_.scala.Predef.String, projectDir: _root_.scala.Predef.String, targets: _root_.scala.Predef.String*) = ${Transform.TaskCommandType
.toString()} {
| implicit val ctx = MillCommunityBuild.Ctx(this, scalaVersion, _evaluator, _root_.mill.T.log)
| MillCommunityBuild.runBuild(configJson, projectDir, targets)
|}
Expand Down Expand Up @@ -399,13 +413,22 @@ class Scala3CommunityBuildMillAdapter(
|""".stripMargin

val injects = {
List(
MillCommunityBuildInject,
MapScalacOptionsOps
) ++
Seq(
if (useLegacyMillCross) Some(MillCommunityBuildCrossInject) else None
).flatten ++
Seq(
Some(
if (useLegacyTasks) """
|import $file.MillCommunityBuild
|import $file.MillVersionCompat, MillVersionCompat.compat.{Task => MillCompatTask}""".stripMargin
else
"\nimport MillVersionCompat.compat.{Task => MillCompatTask}"
),
if (useLegacyTasks) None else Some("private object _OpenCommunityBuildOps {"),
if (useLegacyTasks && config.isMainBuildFile.forall(_ == true))
Some(MillCommunityBuildInject)
else None,
Some(MapScalacOptionsOps),
if (useLegacyMillCross) Some(MillCommunityBuildCrossInject) else None,
if (useLegacyTasks) None else Some("}\nimport _OpenCommunityBuildOps._")
).flatten ++
Seq("// End of OpenCB code injects\n")
}.mkString("\n")

Expand Down

0 comments on commit 6b85609

Please sign in to comment.