Skip to content

Commit

Permalink
Provide precompiled gem for Linux
Browse files Browse the repository at this point in the history
  • Loading branch information
andyundso committed Jan 3, 2025
1 parent f5cd106 commit b6ce459
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 83 deletions.
79 changes: 45 additions & 34 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ jobs:
platform:
- "x64-mingw32"
- "x64-mingw-ucrt"
name: cross-compile-windows
- "x86_64-linux-gnu"

name: cross-compile
runs-on: ubuntu-22.04
container:
image: "ghcr.io/rake-compiler/rake-compiler-dock-image:1.7.0-mri-${{ matrix.platform }}"
Expand Down Expand Up @@ -336,36 +338,38 @@ jobs:
ruby -e "require 'tiny_tds'; puts TinyTds::Gem.root_path"
exit $LASTEXITCODE
compile-native-ports:
install-linux:
needs:
- cross-compile
strategy:
fail-fast: false
matrix:
platform:
- "x86_64-linux-gnu"

ruby-version:
- "2.7"
- "3.0"
- "3.1"
- "3.2"
- "3.3"
- "3.4"

runs-on: ubuntu-22.04
name: cross-compile-linux
steps:
- uses: actions/checkout@v4

- uses: ruby/setup-ruby@v1
- uses: actions/download-artifact@v4
with:
ruby-version: 3.4
bundler-cache: true

- name: Write used versions into file
run: bundle exec rake ports:version_file

- name: Cache ports
uses: actions/cache@v4
with:
path: ports
key: native-v3-${{ hashFiles('**/.ports_versions') }}
restore-keys: |
native-v3-${{ hashFiles('* */.ports_versions') }}
native-v3-
- name: Build required libraries
run: |
bundle exec rake ports
name: gem-${{ matrix.platform }}
path: precompiled

- run: |
docker run --rm -v $PWD/precompiled:/precompiled -w /precompiled ${{ matrix.docker-platform }} ruby:${{ matrix.ruby-version }}${{ matrix.docker-tag }} sh -c "ls -lstar && gem update --system && gem install --no-document $(ls *.gem | head -n1) && ruby -e \"require 'tiny_tds'; puts TinyTds::Gem.root_path\""
test-linux:
needs:
- compile-native-ports
- cross-compile
name: test-linux
strategy:
fail-fast: false
Expand All @@ -391,20 +395,27 @@ jobs:
ruby-version: ${{ matrix.ruby-version }}
bundler-cache: true

- name: Write used versions into file
run: |
bundle exec rake ports:version_file
- name: Cache ports
uses: actions/cache@v4
- name: Download precompiled gem
uses: actions/download-artifact@v4
with:
path: ports
key: native-v3-${{ hashFiles('**/.ports_versions') }}
fail-on-cache-miss: true
name: gem-x86_64-linux-gnu

- name: Build gem
- name: Install native gem and restore cross-compiled code from it
shell: pwsh
run: |
bundle exec rake build
$gemVersion = (Get-Content VERSION).Trim()
$gemToUnpack = "./tiny_tds-$gemVersion-x86_64-linux-gnu.gem"
Write-Host "Looking to unpack $gemToUnpack"
gem unpack --target ./tmp "$gemToUnpack"
# Restore precompiled code
$source = (Resolve-Path ".\tmp\tiny_tds-$gemVersion-x86_64-linux-gnu\lib\tiny_tds").Path
$destination = (Resolve-Path ".\lib\tiny_tds").Path
Get-ChildItem $source -Recurse -Exclude "*.rb" | Copy-Item -Destination {Join-Path $destination $_.FullName.Substring($source.length)}
# Restore ports
Copy-Item -Path ".\tmp\tiny_tds-$gemVersion-x86_64-linux-gnu\ports" -Destination "." -Recurse
- name: Setup MSSQL
uses: rails-sqlserver/setup-mssql@v1
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## (unreleased)

* Provide precompiled gem for Linux

## 3.1.0

* Add Ruby 3.4 to the cross compile list
Expand Down
10 changes: 10 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ SPEC = Gem::Specification.load(File.expand_path('../tiny_tds.gemspec', __FILE__)

ruby_cc_ucrt_versions = "3.4.0:3.3.5:3.2.0:3.1.0".freeze
ruby_cc_mingw32_versions = "3.0.0:2.7.0".freeze
ruby_cc_all_supported_versions = "#{ruby_cc_ucrt_versions}:#{ruby_cc_mingw32_versions}"

GEM_PLATFORM_HOSTS = {
'x64-mingw32' => {
Expand All @@ -19,6 +20,10 @@ GEM_PLATFORM_HOSTS = {
host: 'x86_64-w64-mingw32',
ruby_versions: ruby_cc_ucrt_versions
},
'x86_64-linux-gnu' => {
host: 'x86_64-linux-gnu',
ruby_versions: ruby_cc_all_supported_versions
},
}

# Add our project specific files to clean for a rebuild
Expand Down Expand Up @@ -51,6 +56,11 @@ Rake::ExtensionTask.new('tiny_tds', SPEC) do |ext|
end

spec.files += Dir.glob('exe/*')

if spec.platform.os == "linux"
# with this release, "-gnu" refers to glibc-based Linux and "-musl" for musl
spec.required_rubygems_version.concat([">= 3.3.22"])
end
end
end

Expand Down
61 changes: 12 additions & 49 deletions lib/tiny_tds.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,53 +9,16 @@
require 'tiny_tds/result'
require 'tiny_tds/gem'

# Support multiple ruby versions, fat binaries under Windows.
if RUBY_PLATFORM =~ /mingw|mswin/ && RUBY_VERSION =~ /(\d+.\d+)/
ver = Regexp.last_match(1)

add_dll_path = proc do |path, &block|
begin
require 'ruby_installer/runtime'
RubyInstaller::Runtime.add_dll_directory(path, &block)
rescue LoadError
old_path = ENV['PATH']
ENV['PATH'] = "#{path};#{old_path}"
begin
block.call
ensure
ENV['PATH'] = old_path
end
end
end

add_dll_paths = proc do |paths, &block|
if path=paths.shift
add_dll_path.call(path) do
add_dll_paths.call(paths, &block)
end
else
block.call
end
end

# Temporary add bin directories for DLL search, so that freetds DLLs can be found.
add_dll_paths.call( TinyTds::Gem.ports_bin_paths ) do
begin
require "tiny_tds/#{ver}/tiny_tds"
rescue LoadError
require 'tiny_tds/tiny_tds'
end
end
else
# Load dependent shared libraries into the process, so that they are already present,
# when tiny_tds.so is loaded. This ensures, that shared libraries are loaded even when
# the path is different between build and run time (e.g. Heroku).
ports_libs = File.join(TinyTds::Gem.ports_root_path,
"#{RbConfig::CONFIG['host']}/lib/*.so")
Dir[ports_libs].each do |lib|
require 'fiddle'
Fiddle.dlopen(lib)
end

require 'tiny_tds/tiny_tds'
begin
# load the precompiled extension file
ruby_version = /(\d+\.\d+)/.match(::RUBY_VERSION)
puts "tiny_tds/#{ruby_version}/tiny_tds"
require_relative "tiny_tds/#{ruby_version}/tiny_tds"
rescue LoadError
# fall back to the extension compiled upon installation.
# use "require" instead of "require_relative" because non-native gems will place C extension files
# in Gem::BasicSpecification#extension_dir after compilation (during normal installation), which
# is in $LOAD_PATH but not necessarily relative to this file
# (see https://github.com/sparklemotion/nokogiri/issues/2300 for more)
require "tiny_tds/tiny_tds"
end

0 comments on commit b6ce459

Please sign in to comment.