Zinc is a standalone version of sbt's incremental compiler meant to be run in nailgun.
—
Comprehensive utility functions for file operations, timing, property management, and debugging support.
Functions for measuring and formatting execution time and durations.
object Util {
/**
* Format elapsed time from start timestamp
* @param start Start time in milliseconds (from System.currentTimeMillis)
* @return Formatted elapsed time string
*/
def timing(start: Long): String
/**
* Format duration in milliseconds as human-readable string
* @param millis Duration in milliseconds
* @return Formatted duration string (e.g., "2.5s", "1m 30s")
*/
def duration(millis: Long): String
/**
* Format timestamp as human-readable date/time string
* @param time Timestamp in milliseconds
* @return Formatted date/time string
*/
def dateTime(time: Long): String
}File system operations and path manipulation functions.
/**
* Normalize file paths relative to working directory
* @param cwd Optional working directory for relative path resolution
* @return Function to normalize File instances
*/
def normalise(cwd: Option[File])(file: File): File
/**
* Check if file or directory is writable
* @param file File or directory to check
* @return True if file is writable
*/
def checkWritable(file: File): Boolean
/**
* Clean all class files from directory recursively
* @param dir Directory to clean (.class files removed)
*/
def cleanAllClasses(dir: File): Unit
/**
* Generate hash string from file path
* @param file File to hash
* @return Hash string based on file path
*/
def pathHash(file: File): StringSystem property management and resource property extraction.
/**
* Get integer system property with default value
* @param name Property name
* @param default Default value if property not set or invalid
* @return Property value as integer
*/
def intProperty(name: String, default: Int): Int
/**
* Set multiple system properties from string sequence
* @param props Property strings in "key=value" format
*/
def setProperties(props: Seq[String]): Unit
/**
* Extract property value from resource file
* @param resource Resource file path
* @param property Property key to extract
* @param classLoader ClassLoader for resource loading
* @return Optional property value
*/
def propertyFromResource(resource: String, property: String,
classLoader: ClassLoader): Option[String]Timer and alarm functionality for delayed operations and timeouts.
/**
* Create resettable timer for delayed operations
* @param delay Delay in milliseconds
* @param body Code block to execute after delay
* @return Alarm instance for timer control
*/
def timer(delay: Long)(body: => Unit): Alarm
/**
* Parse duration string with units (s, m, h) to milliseconds
* @param arg Duration string (e.g., "30s", "5m", "1h")
* @param default Default value if parsing fails
* @return Duration in milliseconds
*/
def duration(arg: String, default: Long): Longimport org.pantsbuild.zinc.Util
import System.currentTimeMillis
// Measure compilation time
val start = currentTimeMillis()
// ... perform compilation ...
val elapsed = Util.timing(start)
println(s"Compilation completed in $elapsed")
// Format arbitrary durations
val buildTime = 125000L // 2 minutes, 5 seconds
println(s"Build took: ${Util.duration(buildTime)}")
// Format timestamps
val now = currentTimeMillis()
println(s"Build finished at: ${Util.dateTime(now)}")import org.pantsbuild.zinc.Util
import java.io.File
// Normalize paths relative to project directory
val projectDir = Some(new File("/home/user/project"))
val normalizer = Util.normalise(projectDir)
val sourceFile = new File("src/main/scala/Example.scala")
val normalizedFile = normalizer(sourceFile)
// Result: /home/user/project/src/main/scala/Example.scala
// Check directory writability
val outputDir = new File("/tmp/output")
if (Util.checkWritable(outputDir)) {
println("Output directory is writable")
} else {
println("Cannot write to output directory")
}
// Clean compiled classes
val classesDir = new File("target/classes")
Util.cleanAllClasses(classesDir)
println("Cleaned all .class files")
// Generate path hash for caching
val cacheKey = Util.pathHash(sourceFile)
println(s"Cache key for $sourceFile: $cacheKey")import org.pantsbuild.zinc.Util
// Get system properties with defaults
val maxHeapSize = Util.intProperty("zinc.max.heap.mb", 1024)
val debugMode = System.getProperty("zinc.debug", "false").toBoolean
// Set multiple properties
val props = Seq(
"zinc.incremental=true",
"zinc.analysis.cache.limit=100",
"scala.usejavacp=true"
)
Util.setProperties(props)
// Extract build information from resources
val classLoader = getClass.getClassLoader
val version = Util.propertyFromResource(
"zinc-version.properties",
"version",
classLoader
)
println(s"Zinc version: ${version.getOrElse("unknown")}")import org.pantsbuild.zinc.Util
// Create heartbeat timer
val heartbeat = Util.timer(30000) { // 30 second intervals
println(s"Compilation still running... ${java.time.LocalTime.now}")
}
// Start long-running compilation
startCompilation()
// Timer will fire every 30 seconds until reset or cancelled
// Reset timer to prevent next execution
heartbeat.cancel()
// Parse duration strings
val timeoutMs = Util.duration("5m", 300000L) // 5 minutes or default
val heartbeatMs = Util.duration("30s", 30000L) // 30 seconds or default
println(s"Timeout: ${timeoutMs}ms, Heartbeat: ${heartbeatMs}ms")import org.pantsbuild.zinc._
import java.io.File
// Normalize all input files
val settings = Settings.parse(args.toSeq).get
val normalizer = Util.normalise(Some(new File(".")))
val normalizedSources = settings.sources.map(normalizer)
// Check output directory writability
if (!Util.checkWritable(settings.classesDirectory)) {
throw new IllegalArgumentException(
s"Cannot write to output directory: ${settings.classesDirectory}"
)
}
// Set up timing and properties
val compilationStart = System.currentTimeMillis()
Util.setProperties(settings.properties)
// Execute compilation with timing
val compiler = Compiler(Setup(settings), log)
compiler.compile(inputs, Some(new File(".")), reporter, progress)(log)
// Report results
val totalTime = Util.timing(compilationStart)
log.info(s"Total compilation time: $totalTime")
// Clean up if requested
if (settings.scalacOptions.contains("-Ycompiler-debug")) {
Util.cleanAllClasses(settings.classesDirectory)
}The normalise function handles various path formats:
. and .. path componentsThe duration parser supports multiple time units:
s or sec for secondsm or min for minutesh or hour for hoursResource property loading supports:
Timer utilities provide:
Install with Tessl CLI
npx tessl i tessl/maven-org-pantsbuild--zinc