57a1915b10
Implements: - BattleResult type and JSON-lines parser (#127) - TR server lifecycle manager (#128) - Bot compiler using nim c (#129) - runBattle() orchestrator (#130) - Example test in OscillatorBot_garage (#131) - Framework usage guide (#132) - TestBattleRunner.java for external server (#133) - BattleRunner process lifecycle (#134) Fix: runner_process.nim was redefining TimeoutError locally; now uses std/net.TimeoutError consistently with server_manager.nim.
49 lines
2.0 KiB
Nim
49 lines
2.0 KiB
Nim
## Compiles Nim bots before battle tests.
|
|
## config.nims in each bot dir already sets --path and --outdir, so we just
|
|
## run `nim c src/BotName.nim` from the bot dir and let config.nims do the rest.
|
|
|
|
import std/[os, osproc, streams, strformat, strutils, sequtils]
|
|
|
|
proc compileBots*(botDirs: seq[string]): seq[string] =
|
|
## Compiles each bot dir, returns absolute paths to compiled binaries.
|
|
## Raises on first compilation failure, message includes compiler output.
|
|
for dir in botDirs:
|
|
let absDir = absolutePath(dir)
|
|
# Infer main source: src/<stem>.nim where stem = last path component
|
|
# minus optional _garage suffix (e.g. OscillatorBot_garage → OscillatorBot)
|
|
var stem = lastPathPart(absDir)
|
|
if stem.endsWith("_garage"): stem = stem[0 ..< stem.len - "_garage".len]
|
|
|
|
let srcFile = absDir / "src" / stem & ".nim"
|
|
if not fileExists(srcFile):
|
|
# Fall back: pick the first .nim in src/
|
|
let candidates = toSeq(walkFiles(absDir / "src" / "*.nim"))
|
|
if candidates.len == 0:
|
|
raise newException(IOError, fmt"No .nim source found in {absDir}/src/")
|
|
stem = splitFile(candidates[0]).name
|
|
|
|
# ponytail: startProcess+streams for timeout; execCmdEx has no timeout param
|
|
let p = startProcess("nim", workingDir = absDir,
|
|
args = ["c", fmt"src/{stem}.nim"],
|
|
options = {poUsePath, poStdErrToStdOut})
|
|
let exitCode = waitForExit(p, timeout = 30_000)
|
|
let output = p.outputStream.readAll()
|
|
p.close()
|
|
if exitCode != 0:
|
|
raise newException(OSError,
|
|
fmt"Compilation failed for {absDir}:{'\n'}{output}")
|
|
|
|
result.add absDir / "out" / stem
|
|
|
|
when isMainModule:
|
|
let botDir = currentSourcePath().parentDir().parentDir().parentDir() /
|
|
"OscillatorBot_garage"
|
|
echo "Compiling OscillatorBot from: ", botDir
|
|
try:
|
|
let bins = compileBots(@[botDir])
|
|
echo "OK — binary: ", bins[0]
|
|
doAssert fileExists(bins[0]), "binary not found after compile"
|
|
except CatchableError as e:
|
|
echo "FAIL: ", e.msg
|
|
quit(1)
|