From c15f002cac89fe9a73230d3d3e64e30e987fb412 Mon Sep 17 00:00:00 2001 From: Andy Pfister Date: Wed, 8 Jan 2025 17:14:38 +0100 Subject: [PATCH] Fix FreeTDS utility wrappers --- .github/workflows/ci.yml | 46 ++++++++++++++++++++++--- CHANGELOG.md | 1 + Rakefile | 12 +++++-- ext/tiny_tds/extconf.rb | 5 +-- lib/tiny_tds/bin.rb | 15 +-------- lib/tiny_tds/gem.rb | 8 ++--- test/gem_test.rb | 73 ---------------------------------------- 7 files changed, 59 insertions(+), 101 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cb29f398..97609a7e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -39,10 +39,10 @@ jobs: uses: actions/cache@v4 with: path: ports - key: cross-compiled-v8-${{ matrix.platform }}-${{ hashFiles('**/.ports_versions') }} + key: cross-compiled-v9-${{ matrix.platform }}-${{ hashFiles('**/.ports_versions') }} restore-keys: | - cross-compiled-v8-${{ matrix.platform }}-${{ hashFiles('**/.ports_versions') }} - cross-compiled-v8-${{ matrix.platform }}- + cross-compiled-v9-${{ matrix.platform }}-${{ hashFiles('**/.ports_versions') }} + cross-compiled-v9-${{ matrix.platform }}- - name: Build gem shell: bash @@ -94,6 +94,18 @@ jobs: ruby -e "require 'tiny_tds'; puts TinyTds::Gem.root_path" exit $LASTEXITCODE + - name: Test if tsql wrapper works + shell: pwsh + run: | + tsql-ttds -C + exit $LASTEXITCODE + + - name: Test if defncopy wrapper works + shell: pwsh + run: | + defncopy-ttds -v + exit $LASTEXITCODE + test-windows-mingw: needs: - cross-compile @@ -207,6 +219,18 @@ jobs: ruby -e "require 'tiny_tds'; puts TinyTds::Gem.root_path" exit $LASTEXITCODE + - name: Test if tsql wrapper works + shell: pwsh + run: | + tsql-ttds -C + exit $LASTEXITCODE + + - name: Test if defncopy wrapper works + shell: pwsh + run: | + defncopy-ttds -v + exit $LASTEXITCODE + test-windows-ucrt: needs: - cross-compile @@ -317,6 +341,18 @@ jobs: ruby -e "require 'tiny_tds'; puts TinyTds::Gem.root_path" exit $LASTEXITCODE + - name: Test if tsql wrapper works + shell: pwsh + run: | + tsql-ttds -C + exit $LASTEXITCODE + + - name: Test if defncopy wrapper works + shell: pwsh + run: | + defncopy-ttds -v + exit $LASTEXITCODE + install-linux: needs: - cross-compile @@ -372,7 +408,9 @@ jobs: gem update --system 3.3.22 && ${{ matrix.bootstrap }} gem install --no-document ./gems/tiny_tds-$(cat VERSION)-${{ matrix.platform }}.gem && - ruby -e \"require 'tiny_tds'; puts TinyTds::Gem.root_path\" + ruby -e \"require 'tiny_tds'; puts TinyTds::Gem.root_path\" && + tsql-ttds -C && + defncopy-ttds -v " test-linux: diff --git a/CHANGELOG.md b/CHANGELOG.md index c79b64f8..ffe8e6b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ * Reduce number of files shipped with precompiled Windows gem * Provide precompiled gem for Linux (GNU + MUSL / 64-bit x86 + ARM) +* Fix wrappers for `tsql` and `defncopy` utility. ## 3.1.0 diff --git a/Rakefile b/Rakefile index e4bef2f7..ec6da503 100644 --- a/Rakefile +++ b/Rakefile @@ -40,9 +40,17 @@ Rake::ExtensionTask.new('tiny_tds', SPEC) do |ext| spec.metadata.delete('msys2_mingw_dependencies') if spec.platform.to_s =~ /mingw/ - spec.files << "ports/#{spec.platform.to_s}/bin/libsybdb-5.dll" + spec.files += [ + "ports/#{spec.platform.to_s}/bin/libsybdb-5.dll", + "ports/#{spec.platform.to_s}/bin/defncopy.exe", + "ports/#{spec.platform.to_s}/bin/tsql.exe" + ] elsif spec.platform.to_s =~ /linux/ - spec.files << "ports/#{spec.platform.to_s}/lib/libsybdb.so.5" + spec.files += [ + "ports/#{spec.platform.to_s}/lib/libsybdb.so.5", + "ports/#{spec.platform.to_s}/bin/defncopy", + "ports/#{spec.platform.to_s}/bin/tsql" + ] end end diff --git a/ext/tiny_tds/extconf.rb b/ext/tiny_tds/extconf.rb index 152ef052..47f6630c 100644 --- a/ext/tiny_tds/extconf.rb +++ b/ext/tiny_tds/extconf.rb @@ -105,8 +105,9 @@ def configure_defaults recipe.configure_options << "--enable-sspi" end - recipe.configure_options << "LDFLAGS=-L#{openssl_recipe.path}/lib" - recipe.configure_options << "LIBS=-liconv -lssl -lcrypto #{"-lwsock32 -lgdi32 -lws2_32 -lcrypt32" if MiniPortile.windows?} #{"-ldl -lpthread" if MiniPortile.linux?}" + # pass an additional runtime path to the linker so defncopy and tsql can find our shared sybdb + recipe.configure_options << "LDFLAGS=-L#{openssl_recipe.path}/lib #{"-Wl,-rpath='$$ORIGIN/../lib'" if MiniPortile.linux?}" + recipe.configure_options << "LIBS=-liconv -lssl -lcrypto #{"-lwsock32 -lgdi32 -lws2_32 -lcrypt32" if MiniPortile.windows?} #{"-ldl -lpthread" if MiniPortile.linux?}" recipe.configure_options << "CPPFLAGS=-I#{openssl_recipe.path}/include" recipe.configure_options << "OPENSSL_CFLAGS=-L#{openssl_recipe.path}/lib" diff --git a/lib/tiny_tds/bin.rb b/lib/tiny_tds/bin.rb index 832692a3..87cee11a 100644 --- a/lib/tiny_tds/bin.rb +++ b/lib/tiny_tds/bin.rb @@ -81,24 +81,11 @@ def which exe = File.expand_path File.join(path, "#{name}#{ext}"), @root next if exe == @binstub next unless File.executable?(exe) - next unless binary?(exe) + return exe end end nil end - - # Implementation directly copied from ptools. - # https://github.com/djberg96/ptools - # https://opensource.org/licenses/Artistic-2.0 - # - def binary?(file) - bytes = File.stat(file).blksize - return false unless bytes - bytes = 4096 if bytes > 4096 - s = (File.read(file, bytes) || '') - s = s.encode('US-ASCII', undef: :replace).split(//) - ((s.size - s.grep(' '..'~').size) / s.size.to_f) > 0.30 - end end end diff --git a/lib/tiny_tds/gem.rb b/lib/tiny_tds/gem.rb index a52f047d..55be78b4 100644 --- a/lib/tiny_tds/gem.rb +++ b/lib/tiny_tds/gem.rb @@ -12,15 +12,11 @@ def ports_root_path end def ports_bin_paths - Dir.glob(File.join(ports_root_path,ports_host,'**','bin')) + Dir.glob(File.join(ports_root_path, '**', 'bin')) end def ports_lib_paths - Dir.glob(File.join(ports_root_path,ports_host,'**','lib')) - end - - def ports_host - RbConfig::CONFIG["arch"] + Dir.glob(File.join(ports_root_path, '**', 'lib')) end end end diff --git a/test/gem_test.rb b/test/gem_test.rb index 0412a88a..eea45623 100644 --- a/test/gem_test.rb +++ b/test/gem_test.rb @@ -98,79 +98,6 @@ class GemTest < Minitest::Spec end end end - - describe '#ports_lib_paths' do - let(:ports_lib_paths) { TinyTds::Gem.ports_lib_paths } - - describe 'when the ports directories exist' do - let(:fake_lib_paths) do - ports_host_root = File.join(gem_root, 'ports', 'fake-host-with-dirs') - [ - File.join('a','lib'), - File.join('a','inner','lib'), - File.join('b','lib') - ].map do |p| - File.join(ports_host_root, p) - end - end - - before do - RbConfig::CONFIG['arch'] = 'fake-host-with-dirs' - fake_lib_paths.each do |path| - FileUtils.mkdir_p(path) - end - end - - after do - FileUtils.remove_entry_secure( - File.join(gem_root, 'ports', 'fake-host-with-dirs'), true - ) - end - - it 'should return all the lib directories' do - _(ports_lib_paths.sort).must_equal fake_lib_paths.sort - end - - it 'should return all the lib directories regardless of cwd' do - Dir.chdir '/' - _(ports_lib_paths.sort).must_equal fake_lib_paths.sort - end - end - - describe 'when the ports directories are missing' do - before do - RbConfig::CONFIG['arch'] = 'fake-host-without-dirs' - end - - - it 'should return no directories' do - _(ports_lib_paths).must_be_empty - end - - it 'should return no directories regardless of cwd' do - Dir.chdir '/' - _(ports_lib_paths).must_be_empty - end - end - end - - describe '#ports_host' do - { - 'x64-mingw-ucrt' => 'x64-mingw-ucrt', - 'x64-mingw32' => 'x64-mingw32', - 'x86_64-linux' => 'x86_64-linux', - }.each do |host,expected| - describe "on a #{host} architecture" do - before do - RbConfig::CONFIG['arch'] = host - end - - it "should return a #{expected} ports host" do - _(TinyTds::Gem.ports_host).must_equal expected - end - end - end - end end end