Conversation
Establishes the libBeresta org-wide mandatory baseline for the Ruby member of the brst-binding-<lang> family: a top-level README plus a CMakeLists.txt that builds libBeresta into a shared library the FFI loader can dlopen. On top of that baseline we drop in the Ruby gem skeleton (gemspec, Gemfile, Rakefile, LICENSE under zlib/libpng, CHANGELOG, .rspec, .gitignore, ext/extconf.rb stub, top-level entrypoint module, and a Library loader that resolves libbrst across vendored / in-tree / system locations). Per agreement with @dmitrys99 (libBeresta Issue #19, danbako 399): the gem name matches the repo name (brst-binding-ruby), license matches upstream (zlib/libpng), and the high-level idiomatic API stays out of this gem — v0.1.0 is intentionally a faithful low-level FFI surface.
The generator parses libBeresta's canonical S-expression definitions
directly (gen/json/*.json is treated as a derived artifact only, used for
cross-checking — see spec/cross_check_spec.rb). Pipeline:
gen/data/*.lsp
| SexpParser (StringScanner; UTF-8; tolerant of upstream quirks
| like Cyrillic-letter keywords `:ру` in doc_font.lsp
| and a stray trailing `)` in encrypt.lsp)
v
parsed Ruby Hash/Array tree
| SymbolTable (consolidates :types / :pointers / :definitions /
| :enums / :structs / :consts / :sizes; synthesises
| a :PageSizes enum from page_sizes.lsp ISO 216 entries
| since the .lsp data never declares that enum
| explicitly even though base.lsp / page_routines.lsp
| reference it)
v
Renderer -> lib/brst/binding/ruby/types.rb (consolidated)
lib/brst/binding/ruby/<file>.rb (per-file FFI module)
Implements the four design improvements from danbako 366:
#1 Consolidated :types renderer (typedef'd from inner->outer mapping).
#2 Enums emitted as FFI enums (effectively :int-backed typedefs).
#3 Structs registered with FFI::Struct.by_value aliases.
#4 Every typedef lives in types.rb so per-file modules have no
load-order dependency.
Generated from libBeresta master @ HEAD (post-#26 merge, gen/data layout):
- 56 .lsp files processed
- lib/brst/binding/ruby/types.rb consolidates 39 enums, 22 pointers,
8 definitions, 3 structs, 6 constants, plus the synthesised
:PageSizes enum (ISO 216 build).
- 36 per-file modules, 246 attached_function bindings; 22 captions are
skipped with a recorded MISSING_SYMBOLS entry (mostly Asian font
captions whose .lsp caption drifted from the C symbol, plus PNG
image loaders compiled out of the default macOS build, plus the
`Image` opaque type which upstream never declared in .lsp data).
Smoke specs port demo/minimal.c to RSpec and add a "Hello, Beresta from
Ruby!" text-write test using the built-in Helvetica path. Both produce
a real %PDF-marked file on disk via libbrst.dylib.
Cross-check spec asserts that our parser's per-file counts of
functions / enums / pointers / definitions / structs / consts / sizes
match libBeresta's auto-generated gen/json/*.json view of the same
data — a structural sanity net that doesn't make us depend on JSON.
CI runs on macos-14 across Ruby 3.2 / 3.3 / 3.4: clones libBeresta,
builds the dylib, regenerates bindings, fails if the regeneration
diff is non-empty (drift guard), runs rspec, then `gem build`.
Per dmitrys99's guidance (libBeresta/libBeresta#19), all brst-binding-<lang> repositories should expose three standard CMake targets for cross-language CI/CD: - binding: regenerate FFI bindings from gen/data/*.lsp - check: run rspec to verify the bindings work - bundle: build the .gem archive These are implemented as custom targets that shell out to the Ruby toolchain (ruby, bundle, gem).
|
@dmitrys99 PR opened, would love your review when you have a moment 👀✨ |
|
Thank you so much for the kind words and for the review, @dmitrys99! 😊 Good catch on the ISO 216 restriction — that was not intentional. The generator currently filters I'll push a fix to include all page sizes before merging. Thanks for pointing this out! |
Per review feedback from @dmitrys99: the generator was filtering page_sizes.lsp entries to ISO 216 only, but should include all origins (US Letter, US Arch, JIS B, etc.) to match the full set available in the C headers.
|
One thing I noticed: since the default CMake build uses |
|
The intent of First, there are plans to make library configurable as much as possible (make it modular through configuration). Second, I had external requirement outside library (in other project) to have only ISO 216 paper sizes included. I implemented this option and managed it to work. But after I made it and use it, I think it was incorrect decision. The more valuable solution will be to have all paper sizes available and To reduce library size I can propose CMake option, which will drop But from interface point of view it'll be the same amount of page sizes despite of CMake option(s). So, short answer for your question, you made right decision. |
|
Thank you for the detailed explanation, @dmitrys99 — that context really helps. The direction of keeping all page sizes available at the interface level and removing |
|
One small housekeeping request, @dmitrys99: could you switch the default branch of |
Initial v0.1.0 scaffold: S-expression generator, FFI bindings, smoke tests, and CI
This PR bootstraps the
brst-binding-rubygem as agreed with @dmitrys99 in libBeresta/libBeresta#19.What's included
S-expression generator (
generator/)gen/data/*.lspdirectly — the canonical S-expression definitions remain the source of truth (JSON/YAML are used only for cross-checking, not as a dependency).SexpParser→SymbolTable→Renderer.:typesrenderer, FFI enums,Struct.by_valuealiases, and load-order-independenttypes.rb.:руtypo — fix submitted as Fix Cyrillic keyword typo and stray closing paren in gen/data libBeresta#47; stray)inencrypt.lsp).Generated FFI bindings (
lib/brst/binding/ruby/).lspfiles processed → 36 per-file FFI modules.MISSING_SYMBOLS(caption–symbol drift and build-flag-gated features like Asian fonts and PNG loaders).types.rbwith 39 enums, 22 opaque pointers, 8 type aliases, 3 structs, 6 constants, plus a synthesised:PageSizesenum from ISO 216 entries.Smoke tests (
spec/smoke/)demo/minimal.c: creates Doc → adds Page → sets A4 landscape → saves PDF → verifies%PDFheader.libbrst.dylib.Structural cross-check (
spec/cross_check_spec.rb)gen/json/*.json— a sanity net without making JSON a dependency.CI (
.github/workflows/ci.yml)libbrst.dylib, regenerates bindings (fails on drift), runs rspec, thengem build.Mandatory baseline
README.md+CMakeLists.txtper thebrst-binding-<lang>family convention.binding(regenerate FFI fromgen/data/*.lsp),check(run rspec),bundle(build.gem).Not included (intentional)
gem push/ rubygems release (coordinated with libBeresta 1.0.0 per the agreed roadmap).Related