diff options
| author | Huang Rui | 2023-02-23 15:20:50 +0800 |
|---|---|---|
| committer | GitHub | 2023-02-23 07:20:50 +0000 |
| commit | 6a999e306c81bb6a3276311022349523a576b552 (patch) | |
| tree | 392d497213832e7686c47a6035f3d8bcb24e9b1d | |
| parent | 94d425f0f48e84bbae1be9d44d64615a37d960d8 (diff) | |
build.sc: fix NoSuchElementException: empty.head (#2605)
- Use regular expressions to get version strings more rigorously
- Add version discriminant function, you can compare version size
- Correct the version comparison of antlr under special conditions
- Improve the version comparison of protoc
Signed-off-by: Huang Rui <vowstar@gmail.com>
| -rw-r--r-- | build.sc | 63 |
1 files changed, 55 insertions, 8 deletions
@@ -9,6 +9,7 @@ import $ivy.`com.lihaoyi::mill-contrib-buildinfo:$MILL_VERSION` import mill.contrib.buildinfo.BuildInfo import java.io.IOException +import scala.util.matching.Regex object firrtl extends mill.Cross[firrtlCrossModule]("2.12.17", "2.13.10") @@ -91,6 +92,18 @@ class firrtlCrossModule(val crossScalaVersion: String) generatedAntlr4Source() ++ generatedProtoSources() :+ generatedBuildInfo()._2 } + // compare version, 1 for (a > b), 0 for (a == b), -1 for (a < b) + def versionCompare(a: String, b: String) = { + def nums(s: String) = s.split("\\.").map(_.toInt) + val pairs = nums(a).zipAll(nums(b), 0, 0).toList + def go(ps: List[(Int, Int)]): Int = ps match { + case Nil => 0 + case (a, b) :: t => + if (a > b) 1 else if (a < b) -1 else go(t) + } + go(pairs) + } + /* antlr4 */ def antlr4Version = "4.9.3" @@ -105,11 +118,28 @@ class firrtlCrossModule(val crossScalaVersion: String) // Linux distro package antlr4 as antlr4, while brew package as antlr PathRef(Seq("antlr4", "antlr").flatMap { f => try { - val systemAntlr4Version = os.proc(f).call(check = false).out.lines.head.split(" ").last - if (systemAntlr4Version == antlr4Version || !checkSystemAntlr4Version) - Some(os.Path(os.proc("bash", "-c", s"command -v $f").call().out.lines.head)) + // pattern to extract version from antlr4/antlr version output + val versionPattern: Regex = """(?s).*(\d+\.\d+\.\d+).*""".r + // get version from antlr4/antlr version output + val systemAntlr4Version = os.proc(f).call(check = false).out.text().trim match { + case versionPattern(v) => v + case _ => "0.0.0" + } + val systemAntlr4Path = os.Path(os.proc("bash", "-c", s"command -v $f").call().out.text().trim) + if (checkSystemAntlr4Version) + // Perform strict version checking + // check if system antlr4 version is the same as the one we want + if (versionCompare(systemAntlr4Version, antlr4Version) == 0) + Some(systemAntlr4Path) + else + None else - None + // Perform a cursory version check, avoid using antlr2 + // check if system antlr4 version is greater than 4.0.0 + if (versionCompare(systemAntlr4Version, "4.0.0") >= 0) + Some(systemAntlr4Path) + else + None } catch { case _: IOException => None @@ -186,11 +216,28 @@ class firrtlCrossModule(val crossScalaVersion: String) def protocPath = T.persistent { PathRef({ try { - val systemProtocVersion = os.proc("protoc", "--version").call(check = false).out.lines.head.split(" ").last - if (systemProtocVersion == protocVersion || !checkSystemProtocVersion) - Some(os.Path(os.proc("bash", "-c", "command -v protoc").call().out.lines.head)) + // pattern to extract version from protoc version output + val versionPattern: Regex = """(?s).*(\d+\.\d+\.\d+).*""".r + // get version from protoc version output + val systemProtocVersion = os.proc("protoc", "--version").call(check = false).out.text().trim match { + case versionPattern(v) => v + case _ => "0.0.0" + } + val systemProtocPath = os.Path(os.proc("bash", "-c", "command -v protoc").call().out.text().trim) + if (checkSystemProtocVersion) + // Perform strict version checking + // check if system protoc version is the same as the one we want + if (versionCompare(systemProtocVersion, protocVersion) == 0) + Some(systemProtocPath) + else + None else - None + // Perform a cursory version check + // check if system protoc version is greater than 3.0.0 + if (versionCompare(systemProtocVersion, "3.0.0") >= 0) + Some(systemProtocPath) + else + None } catch { case _: IOException => None |
