Module: Toy::Core::ToyRoot

Defined in:
lib/toy/core/toy_root.rb

Class Method Summary collapse

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_rootObject

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?
    expanded = File.expand_path(env)
    return expanded if source_tree?(expanded)
  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.

Returns:

  • (Boolean)


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