Skip to content

Add precompiled binary gem support and modernize build system#2

Open
wesleyjellis wants to merge 4 commits into
masterfrom
claude/precompile-jq-gem-0g9x67
Open

Add precompiled binary gem support and modernize build system#2
wesleyjellis wants to merge 4 commits into
masterfrom
claude/precompile-jq-gem-0g9x67

Conversation

@wesleyjellis

Copy link
Copy Markdown

Summary

This PR modernizes the ruby-jq gem's build and release infrastructure by adding support for precompiled platform-specific binaries, updating to use OpsLevel's jq fork, and migrating from Travis CI to GitHub Actions with cibuildgem.

Key Changes

  • Precompiled binaries: Added GitHub Actions workflow (.github/workflows/cibuildgem.yaml) to build and release platform-specific gems for x86_64-linux and arm64-darwin across multiple Ruby versions (3.3, 3.4, 4.0)
  • Updated jq source: Switched from upstream jq 1.6 to OpsLevel's fork where env/$ENV always return an empty object
  • Onigmo integration: Added static compilation of Onigmo 6.2.0 for regex support instead of relying on system libraries
  • Build system updates:
    • Updated Rakefile to output compiled extensions to lib/jq/ and exclude mini_portile2 from platform gem dependencies
    • Modified lib/jq.rb to load precompiled binaries matching the Ruby version, with fallback to source-compiled extension
    • Updated extconf.rb to compile both Onigmo and jq statically with proper configuration options
  • CI/CD migration: Removed .travis.yml in favor of GitHub Actions workflow
  • Documentation: Updated README.md to document precompiled binary availability and build requirements
  • Modernization:
    • Bumped minimum Ruby version to 3.3 in gemspec
    • Updated RuboCop configuration (target Ruby 3.3, renamed Metrics/LineLength to Layout/LineLength)
    • Version bump to 0.3.0
    • Minor code style improvements (string interpolation, typo fixes)

Notable Implementation Details

  • The gem now supports two installation modes: precompiled binaries on supported platforms (no build tools needed) and source compilation on others (requires autoconf, automake, libtool)
  • Precompiled binaries are loaded via version-specific require paths (e.g., jq/3.3/jq_core) with graceful fallback
  • The build process uses cibuildgem for cross-platform compilation and automated RubyGems release
  • Added test coverage for regex support and the OpsLevel jq fork's env behavior

https://claude.ai/code/session_01PpxfE1fTm5fFQYBqWTzg4y

claude and others added 4 commits July 7, 2026 14:05
- Build a static, self-contained extension: vendor OpsLevel's jq fork
  (env/$ENV always return {}) plus Onigmo 6.2.0 for regex support,
  compiled with --disable-shared --enable-static --with-pic
- Move the binary to lib/jq/jq_core.so and load a per-Ruby-minor
  precompiled binary when present, falling back to the source build
- Add .github/workflows/cibuildgem.yaml to compile, test, verify, and
  release fat platform gems (x86_64-linux, arm64-darwin) for Ruby
  3.3/3.4/4.0 via Shopify's cibuildgem
- Declare required_ruby_version >= 3.3; drop mini_portile2 from
  platform gems
- Add specs guarding regex support and the fork's empty env behavior
- Bump version to 0.3.0; update README; remove stale .travis.yml

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PpxfE1fTm5fFQYBqWTzg4y
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
libruby exports its own onig_* functions and ELF's flat namespace lets
calls bind across copies of Onigmo; today both are 6.2.0 so it works by
coincidence, but a version skew would cause crashes. Keep the vendored
jq/Onigmo symbols local to the extension.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@wesleyjellis wesleyjellis left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://github.com/flavorjones/mini_portile mentions that "gem "mini_portile2", "~> 2.0.0" # NECESSARY if used in extconf.rb. see below." which seems missing

Comment thread ext/extconf.rb
recipe = MiniPortile.new('jq', '1.6')
recipe.files = ['https://github.com/stedolan/jq/archive/jq-1.6.tar.gz']
onigmo = MiniPortile.new('onigmo', '6.2.0')
onigmo.files = ['https://github.com/k-takata/Onigmo/releases/download/Onigmo-6.2.0/onigmo-6.2.0.tar.gz']

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should add the expected sha256

Comment thread ext/extconf.rb
require 'mkmf'

def using_system_libraries?
arg_config('--use-system-libraries', ENV.key?('RUBYJQ_USE_SYSTEM_LIBRARIES'))

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we set this in Opslevel, might have to remove it

Comment thread lib/jq.rb
begin
# Load the precompiled binary matching the current Ruby, if this is a
# platform-specific gem packaged by cibuildgem.
require "jq/#{RUBY_VERSION[/\d+\.\d+/]}/jq_core"

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand how this magic works

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread Rakefile

Rake::ExtensionTask.new('jq_core') do |ext|
ext.ext_dir = 'ext'
ext.lib_dir = 'lib/jq'

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or what this does

Comment thread ext/extconf.rb

# OpsLevel fork of jq: `env`/`$ENV` always return an empty object.
recipe = MiniPortile.new('jq', '1.6.opslevel')
recipe.files = ['https://github.com/OpsLevel/jq/archive/845f4206dd8a82355325bafffbb54a5155cf67ec.tar.gz']

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here as well

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants