Module: Toy::Core::ToyRoot
- Defined in:
- lib/toy/core/toy_root.rb
Class Method Summary collapse
-
.ensure_built(root, target, quiet: false) ⇒ Object
Build ‘target` (a Makefile target, e.g. “libexec/toy-infer”) in `root` via `make`.
-
.locate_root ⇒ Object
Priority: TOY_HOME → dev-checkout walk-up → gem dir.
-
.source_tree?(dir) ⇒ Boolean
Sentinel test: does ‘dir` look like a toy source tree we can run `make` in? Requires the Makefile plus a source-only marker (tinynn_ggml.c) that is always shipped and is never a build artifact.
Class Method Details
.ensure_built(root, target, quiet: false) ⇒ Object
Build ‘target` (a Makefile target, e.g. “libexec/toy-infer”) in `root` via `make`. Idempotent — make no-ops when the target is up-to-date, so callers may invoke this unconditionally rather than reimplement mtime staleness. The first build on a fresh tree can take minutes (the target deps pull the full lib inference stack), so echo a notice unless `quiet`.
Build progress (the notice + make’s own output) goes to $stderr so that callers which parse the runner’s $stdout (e.g. ‘toy infer`) get a clean compute stream uncontaminated by build chatter. Returns
- true, nil
-
on success, or [false, message] with a clean one-line
failure (last 20 lines of make output) — never raises, so callers can fail loud with their own command prefix.
82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/toy/core/toy_root.rb', line 82 def ensure_built(root, target, quiet: false) $stderr.puts "building #{target} in #{root} (this may take a few minutes)..." unless quiet out, status = Open3.capture2e("make", "-C", root, target) if status.success? $stderr.print out unless quiet [true, nil] else tail = out.lines.last(20).join [false, "`make #{target}` failed in #{root}:\n#{tail}"] end end |
.locate_root ⇒ Object
Priority: TOY_HOME → dev-checkout walk-up → gem dir. All three are validated with the same #source_tree? sentinel so they stay in sync — a stale TOY_HOME or empty gem dir fails the same way as a non-toy walk-up hit instead of silently returning garbage. Returns the absolute root path, or nil if none resolves.
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/toy/core/toy_root.rb', line 37 def locate_root env = ENV["TOY_HOME"] if env && !env.empty? = File.(env) return if source_tree?() end dir = __dir__ 20.times do return dir if source_tree?(dir) parent = File.dirname(dir) break if parent == dir dir = parent end if defined?(Gem) && Gem.loaded_specs["toy"] gd = Gem.loaded_specs["toy"].gem_dir return gd if gd && source_tree?(gd) end nil end |
.source_tree?(dir) ⇒ Boolean
Sentinel test: does ‘dir` look like a toy source tree we can run `make` in? Requires the Makefile plus a source-only marker (tinynn_ggml.c) that is always shipped and is never a build artifact. vendor/ggml/ is NOT a valid sentinel — setup CREATES it, so a bone-fresh clone fails it.
64 65 66 67 |
# File 'lib/toy/core/toy_root.rb', line 64 def source_tree?(dir) File.file?(File.join(dir, "Makefile")) && File.file?(File.join(dir, "tinynn", "tinynn_ggml.c")) end |