Module: Bundler::Spinel::Scaffold
- Defined in:
- lib/bundler/spinel/engine_installer.rb
Overview
Scaffolds a minimal Spinel project so onboarding is ‘bundle install && spinel-compat init && bin/build` (spinelgems#9, stretch). Writes a Gemfile with the engine marker + a framework gem, a hello entrypoint, and a bin/build that provisions the engine, vendors deps, and compiles.
Class Method Summary collapse
- .app_rb ⇒ Object
- .build_sh ⇒ Object
- .gemfile ⇒ Object
- .gitignore ⇒ Object
- .init(dir, out: $stdout, rev: nil) ⇒ Object
- .write(out, path, body) ⇒ Object
Class Method Details
.app_rb ⇒ Object
218 219 220 221 222 223 224 225 226 |
# File 'lib/bundler/spinel/engine_installer.rb', line 218 def app_rb <<~RUBY require "tep" get "/" do "hello from a Spinel-compiled Tep app\\n" end RUBY end |
.build_sh ⇒ Object
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 |
# File 'lib/bundler/spinel/engine_installer.rb', line 228 def build_sh <<~SH #!/usr/bin/env bash # From a fresh checkout to a native binary. The Gemfile's `engine: spinel` # marker makes `bundle install` refuse to run under CRuby, so we resolve # with `bundle lock` and place deps with `spinel-compat vendor` instead. set -e command -v tep >/dev/null 2>&1 || gem install tep # the tep build CLI (a compile-time tool) [ -f Gemfile.lock ] || bundle lock # resolve deps (NOT `bundle install`) spinel-compat install-engine # fetch+build the pinned engine (cached) export SPINEL="${SPINEL:-$HOME/.cache/spinel/current/spinel}" # tell tep where the engine is spinel-compat vendor # place deps where Spinel follows them tep build app.rb -o app # compile -> ./app echo "built ./app — run it with: ./app -p 4567" SH end |
.gemfile ⇒ Object
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 |
# File 'lib/bundler/spinel/engine_installer.rb', line 201 def gemfile <<~RUBY source "https://rubygems.org" # Spinel is the engine: code here is compiled ahead-of-time to a native # binary, not run on CRuby. `engine_version` is advisory and must be a # version literal (bundler parses it as a Gem requirement); the actual # engine revision install-engine builds is pinned in ./SPINEL_PIN. ruby "3.3.0", engine: "spinel", engine_version: "0.0.0" # The web framework — Sinatra-style, compiles via Spinel. >= 0.11.1 builds # its C helpers on demand (needed for `gem install tep` without `make`). # (For an unreleased sibling instead: gem "tep", git: "https://github.com/OriPekelman/tep.git") gem "tep", ">= 0.11.1" RUBY end |
.gitignore ⇒ Object
245 246 247 248 249 250 251 252 |
# File 'lib/bundler/spinel/engine_installer.rb', line 245 def gitignore <<~TXT /app /vendor *.o *.bin TXT end |
.init(dir, out: $stdout, rev: nil) ⇒ Object
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
# File 'lib/bundler/spinel/engine_installer.rb', line 160 def init(dir, out: $stdout, rev: nil) FileUtils.mkdir_p(dir) engine_rev = rev || EngineInstaller::DEFAULT_REV write(out, File.join(dir, "Gemfile"), gemfile) # The engine revision is a git SHA — NOT a valid `engine_version:` (bundler # parses that as a Gem version requirement and `bundle lock` errors on a # SHA). So the rev lives in a SPINEL_PIN file, which `install-engine` # reads; the Gemfile keeps a version-literal advisory marker. write(out, File.join(dir, "SPINEL_PIN"), "#{engine_rev}\n") write(out, File.join(dir, "app.rb"), app_rb) bin = File.join(dir, "bin", "build") FileUtils.mkdir_p(File.dirname(bin)) write(out, bin, build_sh) File.chmod(0o755, bin) write(out, File.join(dir, ".gitignore"), gitignore) # Pin the *real* CRuby (the one running this, which has spinel-compat) so # version managers don't misread the Gemfile's `engine: "spinel"` marker. # mise/asdf parse that as `ruby@spinel-0.0.0`, fail to find it, and fall # back to a Ruby without bundler-spinel — `bin/build` then can't find # `spinel-compat`. A config-tier .tool-versions overrides that parse. write(out, File.join(dir, ".tool-versions"), "ruby #{RUBY_VERSION}\n") out.puts "" out.puts "Scaffolded a Spinel + Tep project in #{dir}/" out.puts "Next:" out.puts " cd #{dir}" unless File.(dir) == Dir.pwd out.puts " ./bin/build # ensures tep, resolves + vendors deps, provisions Spinel, compiles" out.puts " ./app -p 4567 # run the native binary" out.puts "" out.puts "(The `engine: spinel` Gemfile marker makes `bundle install` refuse to run" out.puts " under CRuby by design — bin/build uses `bundle lock` + `spinel-compat vendor`.)" end |
.write(out, path, body) ⇒ Object
192 193 194 195 196 197 198 199 |
# File 'lib/bundler/spinel/engine_installer.rb', line 192 def write(out, path, body) if File.exist?(path) out.puts " skip (exists): #{path}" else File.write(path, body) out.puts " create: #{path}" end end |