-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbuild.mill
More file actions
164 lines (139 loc) · 6.41 KB
/
build.mill
File metadata and controls
164 lines (139 loc) · 6.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
package build
import mill.*
import mill.scalalib.*
import mill.scalalib.Assembly.*
object flix extends ScalaModule {
def scalaVersion = "2.13.18"
// moduleDir resolves to <root>/flix/ (module name appended).
// Our sources live at <root>/main/src, so navigate up one level.
val root = moduleDir / os.up
def sources = Task.Sources(root / "main" / "src")
def mainClass = Some("ca.uwaterloo.flix.Main")
def mvnDeps = Seq(
mvn"org.java-websocket:Java-WebSocket:1.6.0",
mvn"org.jline:jline:3.30.9",
mvn"org.json4s::json4s-native:4.0.7",
mvn"org.ow2.asm:asm:9.9.1",
mvn"com.github.rjeschke:txtmark:0.13",
mvn"com.github.scopt::scopt:4.1.0",
mvn"org.apache.commons:commons-lang3:3.20.0",
mvn"io.get-coursier::coursier:2.1.24",
mvn"org.tomlj:tomlj:1.1.1", // determines antlr version
mvn"org.antlr:antlr4-runtime:4.11.1",
mvn"org.slf4j:slf4j-nop:2.0.17", // silence JLine logger
mvn"org.eclipse.lsp4j:org.eclipse.lsp4j:1.0.0"
)
def scalacOptions = Seq(
"-Xfatal-warnings",
"-Ypatmat-exhaust-depth", "400",
"-release", "21",
"-opt:inline:ca.uwaterloo.**",
"-Xmixin-force-forwarders:false",
"-Xsource:3",
"-Ytasty-reader"
)
def javacOptions = Seq("--release", "21")
// Manifest: Main-Class is set by mainClass; add Enable-Native-Access
def manifest = Task {
super.manifest().add("Enable-Native-Access" -> "ALL-UNNAMED")
}
// Fat JAR: create a proper non-executable JAR
override def prependShellScript: T[String] = ""
// Fat JAR: exclude META-INF signatures, first-wins for duplicates
def assemblyRules = Seq(
Rule.ExcludePattern("META-INF/.*\\.(RSA|SF|DSA)"),
// ── Test files (saves ~5 MB) ────────────────────────────
// The resources directive includes main/ which brings in main/test/.
// These .flix and .scala test files are not needed at runtime.
Rule.ExcludePattern("test/.*"),
// ── Scala source files (saves ~4 MB) ────────────────────
// The resources directive includes main/src/ for .flix library files,
// but also pulls in .scala compiler sources. Only ClassList.txt and
// .flix files are needed at runtime; the compiled .class files are
// already in the JAR.
Rule.ExcludePattern("src/ca/.*\\.scala"),
// ── zstd-jni native libraries (saves ~15 MB) ────────────
// Coursier bundles zstd-jni native binaries for every OS/arch.
// These are optional: coursier falls back to a Java implementation.
// The v0.66.1 release JAR never included them.
Rule.ExcludePattern("linux/.*"),
Rule.ExcludePattern("win/.*"),
Rule.ExcludePattern("darwin/.*"),
Rule.ExcludePattern("freebsd/.*"),
// ── Coursier transitive dependencies (saves ~4 MB) ──────
// Coursier pulls in Maven build infrastructure (Plexus) and
// compression libraries that are not needed at runtime.
// Plexus: Maven dependency injection / archiver framework.
Rule.ExcludePattern("org/codehaus/plexus/.*"),
// commons-compress/io/codec: used by plexus-archiver, not by coursier itself.
Rule.ExcludePattern("org/apache/commons/compress/.*"),
Rule.ExcludePattern("org/apache/commons/io/.*"),
Rule.ExcludePattern("org/apache/commons/codec/.*"),
// aircompressor: Java zstd/lz4 implementation, optional for coursier.
Rule.ExcludePattern("io/airlift/compress/.*"),
// xbean-reflect: dependency injection helper for Plexus.
Rule.ExcludePattern("org/apache/xbean/.*")
) ++ super.assemblyRules
// Include .flix, .json, .zip, ClassList.txt from main/ in the JAR.
// Gradle does: from('main') { include '**/*.flix' ... }
// We add main/ as an extra resource root so these files land in the assembly.
override def resources = Task.Sources(
root / "main" / "src" / "resources",
root / "main"
)
// ── Test Module ─────────────────────────────────────────
object test extends ScalaTests with TestModule.ScalaTest {
def sources = Task.Sources(flix.root / "main" / "test")
def mvnDeps = Seq(
mvn"org.scalatest::scalatest:3.2.20",
mvn"org.scala-lang.modules::scala-xml:2.4.0",
)
def forkArgs = Seq("-Xmx3g")
def forkWorkingDir = root
def testSandboxWorkingDir = false
def testParallelism = false
def forkEnv = super.forkEnv() ++ Task.env
}
// ── Custom Tasks ────────────────────────────────────────
/** Run: ./mill flix.testFuzzerSuite */
def testFuzzerSuite = Task {
os.proc("java", "-Xmx3g",
"-cp", test.runClasspath().map(_.path).mkString(java.io.File.pathSeparator),
"org.scalatest.tools.Runner",
"-s", "flix.fuzzers.FuzzerSuite", "-o"
).call(stdout = os.Inherit, stderr = os.Inherit, stdin = os.Inherit, cwd = root, env = Task.env)
}
/** Run: ./mill flix.testIDECompletion */
def testIDECompletion = Task {
os.proc("java", "-Xmx3g",
"-cp", test.runClasspath().map(_.path).mkString(java.io.File.pathSeparator),
"org.scalatest.tools.Runner",
"-s", "ca.uwaterloo.flix.api.lsp.TestCompletionProvider", "-o"
).call(stdout = os.Inherit, stderr = os.Inherit, stdin = os.Inherit, cwd = root, env = Task.env)
}
/** Run: ./mill flix.testPackageManager */
def testPackageManager = Task {
os.proc("java", "-Xmx3g",
"-cp", test.runClasspath().map(_.path).mkString(java.io.File.pathSeparator),
"org.scalatest.tools.Runner",
"-s", "ca.uwaterloo.flix.tools.pkg.PackageManagerSuite", "-o"
).call(stdout = os.Inherit, stderr = os.Inherit, stdin = os.Inherit, cwd = root, env = Task.env)
}
/** Run: ./mill flix.vscode */
def vscode() = Task.Command {
val envFile = root / ".env"
if (!os.exists(envFile)) {
throw new Exception("Create .env in the project root with:\n VSCODE_PATH=/path/to/vscode/project")
}
val targetDir = os.read.lines(envFile)
.map(_.trim)
.filter(_.nonEmpty)
.filterNot(_.startsWith("#"))
.collectFirst { case s if s.startsWith("VSCODE_PATH=") =>
s.stripPrefix("VSCODE_PATH=").trim
}
.getOrElse(throw new Exception(".env must contain: VSCODE_PATH=/path/to/vscode/project"))
val jar = assembly().path
os.copy.over(jar, os.Path(targetDir) / "flix.jar")
}
}