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

universal script generation for assembly, launcher, and release that run on linux and windows #264

Merged
merged 8 commits into from
Mar 30, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 63 additions & 63 deletions build.sc
Original file line number Diff line number Diff line change
Expand Up @@ -205,35 +205,57 @@ object integration extends MillModule{
def forkArgs = testArgs()
}

def launcherScript(isWin: Boolean,
jvmArgs: Seq[String],
classPath: Agg[String]) = {
private def universalScript(shellCommands: String,
cmdCommands: String,
shebang: Boolean = false): String = {
Seq(
if (shebang) "#!/usr/bin/env sh" else "",
"@ 2>/dev/null # 2>nul & echo off & goto BOF\r",
":",
shellCommands.replaceAll("\r\n|\n", "\n"),
"exit",
Seq(
"",
":BOF",
"@echo off",
cmdCommands.replaceAll("\r\n|\n", "\r\n"),
"exit /B %errorlevel%",
""
).mkString("\r\n")
).filterNot(_.isEmpty).mkString("\n")
}

def launcherScript(jvmArgs: Seq[String],
shellClassPath: Agg[String],
cmdClassPath: Agg[String]) = {
val jvmArgsStr = jvmArgs.mkString(" ")
val classPathStr = if (isWin) classPath.mkString(";") else classPath.mkString(":")
if (isWin)
s"""::#!
|@echo off
|if "%1" == "-i" set _I_=true
|if "%1" == "--interactive" set _I_=true
|if defined _I_ (
| java $jvmArgsStr %JAVA_OPTS% -cp "$classPathStr" mill.Main %*
|) else (
| java $jvmArgsStr %JAVA_OPTS% -cp "$classPathStr" mill.clientserver.Client %*
|)
|EXIT /B %errorlevel%
""".stripMargin.split('\n').mkString("\r\n")
else
s"""#!/usr/bin/env sh
|
|case "$$1" in
| -i | --interactive )
| exec java $jvmArgsStr $$JAVA_OPTS -cp "$classPathStr" mill.Main "$$@"
| ;;
| *)
| exec java $jvmArgsStr $$JAVA_OPTS -cp "$classPathStr" mill.clientserver.Client "$$@"
| ;;
|esac
""".stripMargin
universalScript(
shellCommands = {
def java(mainClass: String) =
s"""exec java $jvmArgsStr $$JAVA_OPTS -cp "${shellClassPath.mkString(":")}" mill.Main "$$@""""

s"""case "$$1" in
| -i | --interactive )
| ${java("mill.Main")}
| ;;
| *)
| ${java("mill.clientserver.Client")}
| ;;
|esac""".stripMargin
},
cmdCommands = {
def java(mainClass: String) =
s"""java $jvmArgsStr %JAVA_OPTS% -cp "${cmdClassPath.mkString(";")}" $mainClass %*"""

s"""if "%1" == "-i" set _I_=true
|if "%1" == "--interactive" set _I_=true
|if defined _I_ (
| ${java("mill.Main")}
|) else (
| ${java("mill.clientserver.Client")}
|)""".stripMargin
}
)
}

object dev extends MillModule{
Expand All @@ -243,7 +265,7 @@ object dev extends MillModule{
}
def launcher = T{
val isWin = scala.util.Properties.isWin
val outputPath = T.ctx().dest / (if (isWin) "run.bat" else "run")
val outputPath = T.ctx().dest / "run"

write(outputPath, prependShellScript())

Expand All @@ -258,12 +280,15 @@ object dev extends MillModule{
}

def assembly = T{
val filename = if (scala.util.Properties.isWin) "mill.bat" else "mill"
val filename = "mill"
mv(super.assembly().path, T.ctx().dest / filename)
PathRef(T.ctx().dest / filename)
}

def prependShellScript = launcherScript(scala.util.Properties.isWin, forkArgs(), runClasspath().map(_.path.toString))
def prependShellScript = T{
val classpath = runClasspath().map(_.path.toString)
launcherScript(forkArgs(), classpath, classpath)
}

def run(args: String*) = T.command{
args match{
Expand All @@ -282,51 +307,29 @@ object dev extends MillModule{
}
}


private def releaseHelper(dest: Path,
cp: Agg[Path],
ver: String,
isWin: Boolean)
ver: String)
(implicit ctx: mill.util.Ctx.Dest): PathRef = {
val (filename, arg) =
if (isWin) ("mill.bat", "%~dp0%~nx0")
else ("mill", "$0")
mv(
createAssembly(
cp,
prependShellScript = launcherScript(
isWin,
Seq("-DMILL_VERSION=" + ver),
Agg(arg)
Agg("$0"),
Agg("%~dpnx0")
)
).path,
dest / filename
dest / "mill"
)
PathRef(dest / filename)
PathRef(dest / "mill")
}

def release = T{
releaseHelper(
T.ctx().dest,
dev.runClasspath().map(_.path),
publishVersion()._2,
false)
}

def releaseBatch = T{
releaseHelper(
T.ctx().dest,
dev.runClasspath().map(_.path),
publishVersion()._2,
true)
}

def releaseAll = T{
val dest = T.ctx().dest
val cp = dev.runClasspath().map(_.path)
val ver = publishVersion()._2
for (isWin <- Seq(false, true))
yield (isWin, releaseHelper(dest, cp, ver, isWin))
publishVersion()._2)
}

val isMasterCommit = {
Expand Down Expand Up @@ -377,8 +380,5 @@ def uploadToGithub(authKey: String) = T.command{
.asString
}

for ((isWin, pr) <- releaseAll())
upload.apply(pr.path, releaseTag,
if (isWin) s"mill-$label.bat" // so browser downloads it as mill-<version>.bat (?)
else label, authKey)
upload.apply(release().path, releaseTag, label, authKey)
}
52 changes: 34 additions & 18 deletions main/src/mill/modules/Jvm.scala
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ object Jvm {
// Prepend shell script and make it executable
if (prependShellScript.isEmpty) mv(tmp, output)
else{
val lineSep = if (isWin) "\r\n" else "\n"
val lineSep = if (!prependShellScript.endsWith("\n")) "\n\r\n" else ""
val outputStream = newOutputStream(output.toNIO)
IO.stream(new ByteArrayInputStream((prependShellScript + lineSep).getBytes()), outputStream)
IO.stream(read.getInputStream(tmp), outputStream)
Expand Down Expand Up @@ -319,30 +319,46 @@ object Jvm {

}

def launcherShellScript(isWin: Boolean,
mainClass: String,
classPath: Agg[String],
jvmArgs: Seq[String]) = {
val cp = classPath.mkString(File.pathSeparator)
if (isWin)
s"""@echo off
|
|java ${jvmArgs.mkString(" ")} %JAVA_OPTS% -cp "$cp" $mainClass %*
""".stripMargin.split('\n').mkString("\r\n")
else
s"""#!/usr/bin/env sh
|
|exec java ${jvmArgs.mkString(" ")} $$JAVA_OPTS -cp "$cp" $mainClass "$$@"
""".stripMargin
def universalScript(shellCommands: String,
cmdCommands: String,
shebang: Boolean = false): String = {
Seq(
if (shebang) "#!/usr/bin/env sh" else "",
"@ 2>/dev/null # 2>nul & echo off & goto BOF\r",
":",
shellCommands.replaceAll("\r\n|\n", "\n"),
"exit",
Seq(
"",
":BOF",
"@echo off",
cmdCommands.replaceAll("\r\n|\n", "\r\n"),
"exit /B %errorlevel%",
""
).mkString("\r\n")
).filterNot(_.isEmpty).mkString("\n")
}

def launcherUniversalScript(mainClass: String,
shellClassPath: Agg[String],
cmdClassPath: Agg[String],
jvmArgs: Seq[String]) = {
universalScript(
shellCommands =
s"""exec java ${jvmArgs.mkString(" ")} $$JAVA_OPTS -cp "${shellClassPath.mkString(":")}" $mainClass "$$@"""",
cmdCommands =
s"""java ${jvmArgs.mkString(" ")} %JAVA_OPTS% -cp "${cmdClassPath.mkString(";")}" $mainClass %*""",
)
}
def createLauncher(mainClass: String,
classPath: Agg[Path],
jvmArgs: Seq[String])
(implicit ctx: Ctx.Dest)= {
val isWin = scala.util.Properties.isWin
val outputPath = ctx.dest / (if (isWin) "run.bat" else "run")
val outputPath = ctx.dest / "run"
val classPathStrs = classPath.map(_.toString)

write(outputPath, launcherShellScript(isWin, mainClass, classPath.map(_.toString), jvmArgs))
write(outputPath, launcherUniversalScript(mainClass, classPathStrs, classPathStrs, jvmArgs))

if (!isWin) {
val perms = Files.getPosixFilePermissions(outputPath.toNIO)
Expand Down
5 changes: 2 additions & 3 deletions scalalib/src/mill/scalalib/ScalaModule.scala
Original file line number Diff line number Diff line change
Expand Up @@ -136,10 +136,9 @@ trait ScalaModule extends mill.Module with TaskModule { outer =>
case None => ""
case Some(cls) =>
val isWin = scala.util.Properties.isWin
mill.modules.Jvm.launcherShellScript(
isWin,
mill.modules.Jvm.launcherUniversalScript(
cls,
Agg(if (isWin) "%~dp0%~nx0" else "$0"),
Agg("$0"), Agg("%~dpnx0"),
forkArgs()
)
}
Expand Down