Class: Beni::Builder
- Inherits:
-
Object
- Object
- Beni::Builder
- Defined in:
- lib/beni/builder.rb,
sig/beni/builder.rbs
Overview
Drives the vendored mruby tree's build to produce the per-target
libmruby.a archives, by running mruby's own Rakefile — the
documented build entry point (doc/guides/compile.md). With no
build_config, mruby falls back to its own
build_config/default.rb; an explicit config is wired in via the
MRUBY_CONFIG env var, which mruby resolves as an absolute path.
Constant Summary collapse
- DEFAULT_TARGETS =
mruby's anonymous
MRuby::Build.newnames its target "host" (lib/mruby/build.rb), so the upstream default config producesbuild/host/lib/libmruby.a. A custom build config with different target names supplies its own list viaBeni::Tasks. %w[host].freeze
Instance Attribute Summary collapse
-
#build_config ⇒ String?
readonly
Returns the value of attribute build_config.
-
#targets ⇒ Array[String]
readonly
Returns the value of attribute targets.
-
#vendor_dir ⇒ String
readonly
Returns the value of attribute vendor_dir.
Instance Method Summary collapse
-
#artifact_paths ⇒ Array[String]
Every artifact the build must leave behind: the per-target archive and its flags.mak sidecar.
-
#build ⇒ void
Run mruby's rake and raise unless every target's
libmruby.aexists afterwards. -
#built? ⇒ Boolean
True when every target's artifacts —
libmruby.aplus thelibmruby.flags.maksidecarbeni-sysparses for ABI alignment — are already present, letting callers skip the build without spawning a subprocess. -
#check_build_config! ⇒ void
The declared config belongs to the consumer; a path that does not exist is a configuration error named before anything spawns.
-
#clean ⇒ void
Remove each target's build tree (keeps the vendored mruby source).
-
#ensure_built ⇒ void
Idempotent build entry point for
rake beni:build: skip with a note when every artifact is already present, otherwise build and report readiness. -
#env ⇒ Hash[String, String]
Environment for the mruby build subprocess.
-
#flags_mak_paths ⇒ Array[String]
Per-target
libmruby.flags.makfile-task paths, matching the task names mruby defines in tasks/libmruby.rake (absolute, anchored on the defaultbuild/<target>layout). -
#initialize(vendor_dir:, build_config: nil, targets: DEFAULT_TARGETS) ⇒ Builder
constructor
A new instance of Builder.
- #libmruby_path(target) ⇒ String
- #libmruby_paths ⇒ Array[String]
- #mruby_dir ⇒ String
-
#run_mruby_rake(env, cmd) ⇒ void
Spawn mruby's rake with the parent environment plus the
envoverlay. -
#verify_artifacts! ⇒ void
Report every missing artifact at once, so a multi-target build failure shows the whole gap instead of one path per run.
Constructor Details
#initialize(vendor_dir:, build_config: nil, targets: DEFAULT_TARGETS) ⇒ Builder
Returns a new instance of Builder.
22 23 24 25 26 |
# File 'lib/beni/builder.rb', line 22 def initialize(vendor_dir:, build_config: nil, targets: DEFAULT_TARGETS) @vendor_dir = vendor_dir @build_config = build_config @targets = targets end |
Instance Attribute Details
#build_config ⇒ String? (readonly)
Returns the value of attribute build_config.
20 21 22 |
# File 'lib/beni/builder.rb', line 20 def build_config @build_config end |
#targets ⇒ Array[String] (readonly)
Returns the value of attribute targets.
20 21 22 |
# File 'lib/beni/builder.rb', line 20 def targets @targets end |
#vendor_dir ⇒ String (readonly)
Returns the value of attribute vendor_dir.
20 21 22 |
# File 'lib/beni/builder.rb', line 20 def vendor_dir @vendor_dir end |
Instance Method Details
#artifact_paths ⇒ Array[String]
Every artifact the build must leave behind: the per-target archive and its flags.mak sidecar.
94 95 96 |
# File 'lib/beni/builder.rb', line 94 def artifact_paths libmruby_paths + flags_mak_paths end |
#build ⇒ void
This method returns an undefined value.
Run mruby's rake and raise unless every target's libmruby.a
exists afterwards. Alongside the default task, each target's
libmruby.flags.mak file task is requested explicitly — mruby's
embedder interface recording the exact compile flags, which
+beni-sys+'s build script parses to keep bindgen's view of the
ABI aligned with the archive. (The file task is defined per
target but not part of mruby's default products.) The underlying
build is make-style incremental, so re-running on a partially
built tree only compiles what is missing.
73 74 75 76 77 78 79 |
# File 'lib/beni/builder.rb', line 73 def build check_build_config! cmd = [RbConfig.ruby, "-S", "rake", "default", *flags_mak_paths] puts "[beni] cd #{mruby_dir} && #{env.map { |k, v| "#{k}=#{v}" }.join(" ")} #{cmd.join(" ")}" run_mruby_rake(env, cmd) verify_artifacts! end |
#built? ⇒ Boolean
True when every target's artifacts — libmruby.a plus the
libmruby.flags.mak sidecar beni-sys parses for ABI alignment
— are already present, letting callers skip the build without
spawning a subprocess. An archive without its sidecar triggers
a rebuild, which is incremental and only emits the missing file.
45 46 47 |
# File 'lib/beni/builder.rb', line 45 def built? artifact_paths.all? { |path| File.exist?(path) } end |
#check_build_config! ⇒ void
This method returns an undefined value.
The declared config belongs to the consumer; a path that does not exist is a configuration error named before anything spawns.
125 126 127 128 129 |
# File 'lib/beni/builder.rb', line 125 def check_build_config! return if build_config.nil? || File.exist?(build_config) raise Error, "[beni] build config #{build_config} does not exist" end |
#clean ⇒ void
This method returns an undefined value.
Remove each target's build tree (keeps the vendored mruby source).
82 83 84 85 86 87 88 |
# File 'lib/beni/builder.rb', line 82 def clean targets.each do |target| dir = File.join(mruby_dir, "build", target) FileUtils.rm_rf(dir) puts "[beni] removed #{dir}" end end |
#ensure_built ⇒ void
This method returns an undefined value.
Idempotent build entry point for rake beni:build: skip with a
note when every artifact is already present, otherwise build and
report readiness. A declared config that does not exist aborts
before the skip check — stale artifacts must not mask it.
53 54 55 56 57 58 59 60 61 62 |
# File 'lib/beni/builder.rb', line 53 def ensure_built check_build_config! if built? puts "[beni] libmruby.a already present for #{targets.join(" + ")} — skipping" return end build puts "[beni] libmruby.a ready for #{targets.join(" + ")}" end |
#env ⇒ Hash[String, String]
Environment for the mruby build subprocess. BENI_VENDOR_DIR
lets build configs resolve the vendor tree without knowing where
the consuming project lives on disk. MRUBY_CONFIG is only set
for an explicit config — absent, mruby falls back to its own
build_config/default.rb (lib/mruby/build.rb#mruby_config_path).
110 111 112 113 114 |
# File 'lib/beni/builder.rb', line 110 def env env = { "BENI_VENDOR_DIR" => vendor_dir } env["MRUBY_CONFIG"] = build_config if build_config env end |
#flags_mak_paths ⇒ Array[String]
Per-target libmruby.flags.mak file-task paths, matching the
task names mruby defines in tasks/libmruby.rake (absolute,
anchored on the default build/<target> layout).
119 120 121 |
# File 'lib/beni/builder.rb', line 119 def flags_mak_paths targets.map { |target| File.join(mruby_dir, "build", target, "lib", "libmruby.flags.mak") } end |
#libmruby_path(target) ⇒ String
32 33 34 |
# File 'lib/beni/builder.rb', line 32 def libmruby_path(target) File.join(mruby_dir, "build", target, "lib", "libmruby.a") end |
#libmruby_paths ⇒ Array[String]
36 37 38 |
# File 'lib/beni/builder.rb', line 36 def libmruby_paths targets.map { |target| libmruby_path(target) } end |
#mruby_dir ⇒ String
28 29 30 |
# File 'lib/beni/builder.rb', line 28 def mruby_dir File.join(vendor_dir, "mruby") end |
#run_mruby_rake(env, cmd) ⇒ void
This method returns an undefined value.
Spawn mruby's rake with the parent environment plus the env
overlay. Extracted as a seam so tests can fake the subprocess
while observing the full env + cmd contract.
101 102 103 |
# File 'lib/beni/builder.rb', line 101 def run_mruby_rake(env, cmd) system(env, *cmd, chdir: mruby_dir, exception: true) end |
#verify_artifacts! ⇒ void
This method returns an undefined value.
Report every missing artifact at once, so a multi-target build failure shows the whole gap instead of one path per run.
133 134 135 136 137 138 |
# File 'lib/beni/builder.rb', line 133 def verify_artifacts! missing = artifact_paths.reject { |path| File.exist?(path) } return if missing.empty? raise Error, "[beni] build completed but artifacts are missing:\n #{missing.join("\n ")}" end |