vm_tiny_tds 2.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +20 -0
  3. data/.gitattributes +1 -0
  4. data/.gitignore +20 -0
  5. data/.rubocop.yml +31 -0
  6. data/.travis.yml +24 -0
  7. data/BACKERS.md +32 -0
  8. data/CHANGELOG.md +255 -0
  9. data/CODE_OF_CONDUCT.md +31 -0
  10. data/Gemfile +9 -0
  11. data/ISSUE_TEMPLATE.md +38 -0
  12. data/MIT-LICENSE +23 -0
  13. data/README.md +504 -0
  14. data/Rakefile +53 -0
  15. data/VERSION +1 -0
  16. data/appveyor.yml +51 -0
  17. data/bin/defncopy-ttds +3 -0
  18. data/bin/tsql-ttds +3 -0
  19. data/exe/.keep +0 -0
  20. data/ext/tiny_tds/client.c +451 -0
  21. data/ext/tiny_tds/client.h +51 -0
  22. data/ext/tiny_tds/extconf.rb +69 -0
  23. data/ext/tiny_tds/extconsts.rb +15 -0
  24. data/ext/tiny_tds/result.c +619 -0
  25. data/ext/tiny_tds/result.h +32 -0
  26. data/ext/tiny_tds/tiny_tds_ext.c +12 -0
  27. data/ext/tiny_tds/tiny_tds_ext.h +17 -0
  28. data/lib/tiny_tds/bin.rb +104 -0
  29. data/lib/tiny_tds/client.rb +136 -0
  30. data/lib/tiny_tds/error.rb +14 -0
  31. data/lib/tiny_tds/gem.rb +32 -0
  32. data/lib/tiny_tds/result.rb +7 -0
  33. data/lib/tiny_tds/version.rb +3 -0
  34. data/lib/tiny_tds.rb +61 -0
  35. data/patches/freetds/1.00.27/0001-mingw_missing_inet_pton.diff +34 -0
  36. data/patches/freetds/1.00.27/0002-Don-t-use-MSYS2-file-libws2_32.diff +28 -0
  37. data/patches/libiconv/1.14/1-avoid-gets-error.patch +17 -0
  38. data/tasks/native_gem.rake +14 -0
  39. data/tasks/package.rake +8 -0
  40. data/tasks/ports/freetds.rb +37 -0
  41. data/tasks/ports/libiconv.rb +43 -0
  42. data/tasks/ports/openssl.rb +78 -0
  43. data/tasks/ports/recipe.rb +52 -0
  44. data/tasks/ports.rake +87 -0
  45. data/tasks/test.rake +9 -0
  46. data/test/appveyor/dbsetup.ps1 +27 -0
  47. data/test/appveyor/dbsetup.sql +9 -0
  48. data/test/benchmark/query.rb +77 -0
  49. data/test/benchmark/query_odbc.rb +106 -0
  50. data/test/benchmark/query_tinytds.rb +126 -0
  51. data/test/bin/install-freetds.sh +20 -0
  52. data/test/bin/install-openssl.sh +18 -0
  53. data/test/bin/setup.sh +19 -0
  54. data/test/client_test.rb +230 -0
  55. data/test/gem_test.rb +179 -0
  56. data/test/result_test.rb +773 -0
  57. data/test/schema/1px.gif +0 -0
  58. data/test/schema/sqlserver_2000.sql +140 -0
  59. data/test/schema/sqlserver_2005.sql +140 -0
  60. data/test/schema/sqlserver_2008.sql +140 -0
  61. data/test/schema/sqlserver_2014.sql +140 -0
  62. data/test/schema/sqlserver_2016.sql +140 -0
  63. data/test/schema/sqlserver_azure.sql +140 -0
  64. data/test/schema/sybase_ase.sql +138 -0
  65. data/test/schema_test.rb +443 -0
  66. data/test/test_helper.rb +217 -0
  67. data/test/thread_test.rb +98 -0
  68. data/tiny_tds.gemspec +29 -0
  69. metadata +225 -0
@@ -0,0 +1,104 @@
1
+ require_relative './version'
2
+ require_relative './gem'
3
+ require 'shellwords'
4
+
5
+ module TinyTds
6
+ class Bin
7
+
8
+ attr_reader :name
9
+
10
+ class << self
11
+ def exe(name, *args)
12
+ bin = new(name)
13
+ puts bin.info unless args.any? { |x| x == '-q' }
14
+ bin.run(*args)
15
+ end
16
+ end
17
+
18
+ def initialize(name)
19
+ @root = Gem.root_path
20
+ @exts = (ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']) | ['.exe']
21
+
22
+ @name = name
23
+ @binstub = find_bin
24
+ @exefile = find_exe
25
+ end
26
+
27
+ def run(*args)
28
+ with_ports_paths do
29
+ return nil unless path
30
+ Kernel.system Shellwords.join(args.unshift(path))
31
+ $CHILD_STATUS.to_i
32
+ end
33
+ end
34
+
35
+ def path
36
+ @path ||= @exefile && File.exist?(@exefile) ? @exefile : which
37
+ end
38
+
39
+ def info
40
+ "[TinyTds][v#{TinyTds::VERSION}][#{name}]: #{path}"
41
+ end
42
+
43
+ private
44
+
45
+ def search_paths
46
+ ENV['PATH'].split File::PATH_SEPARATOR
47
+ end
48
+
49
+ def with_ports_paths
50
+ old_path = ENV['PATH']
51
+
52
+ begin
53
+ ENV['PATH'] = [
54
+ Gem.ports_bin_paths,
55
+ old_path
56
+ ].flatten.join File::PATH_SEPARATOR
57
+
58
+ yield if block_given?
59
+ ensure
60
+ ENV['PATH'] = old_path
61
+ end
62
+ end
63
+
64
+ def find_bin
65
+ File.join @root, 'bin', name
66
+ end
67
+
68
+ def find_exe
69
+ Gem.ports_bin_paths.each do |bin|
70
+ @exts.each do |ext|
71
+ f = File.join bin, "#{name}#{ext}"
72
+ return f if File.exist?(f)
73
+ end
74
+ end
75
+ nil
76
+ end
77
+
78
+ def which
79
+ search_paths.each do |path|
80
+ @exts.each do |ext|
81
+ exe = File.expand_path File.join(path, "#{name}#{ext}"), @root
82
+ next if exe == @binstub
83
+ next unless File.executable?(exe)
84
+ next unless binary?(exe)
85
+ return exe
86
+ end
87
+ end
88
+ nil
89
+ end
90
+
91
+ # Implementation directly copied from ptools.
92
+ # https://github.com/djberg96/ptools
93
+ # https://opensource.org/licenses/Artistic-2.0
94
+ #
95
+ def binary?(file)
96
+ bytes = File.stat(file).blksize
97
+ return false unless bytes
98
+ bytes = 4096 if bytes > 4096
99
+ s = (File.read(file, bytes) || '')
100
+ s = s.encode('US-ASCII', undef: :replace).split(//)
101
+ ((s.size - s.grep(' '..'~').size) / s.size.to_f) > 0.30
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,136 @@
1
+ module TinyTds
2
+ class Client
3
+
4
+ @default_query_options = {
5
+ as: :hash,
6
+ symbolize_keys: false,
7
+ cache_rows: true,
8
+ timezone: :local,
9
+ empty_sets: true
10
+ }
11
+
12
+ attr_reader :query_options
13
+ attr_reader :message_handler
14
+
15
+ class << self
16
+
17
+ attr_reader :default_query_options
18
+
19
+ # Most, if not all, iconv encoding names can be found by ruby. Just in case, you can
20
+ # overide this method to return a string name that Encoding.find would work with. Default
21
+ # is to return the passed encoding.
22
+ #
23
+ def transpose_iconv_encoding(encoding)
24
+ encoding
25
+ end
26
+
27
+ def local_offset
28
+ ::Time.local(2010).utc_offset.to_r / 86_400
29
+ end
30
+
31
+ end
32
+
33
+ # rubocop:disable Metrics/AbcSize
34
+ # rubocop:disable Metrics/MethodLength
35
+ # rubocop:disable Metrics/CyclomaticComplexity
36
+ # rubocop:disable Metrics/PerceivedComplexity
37
+ def initialize(opts = {})
38
+ if opts[:dataserver].to_s.empty? && opts[:host].to_s.empty?
39
+ raise ArgumentError, 'missing :host option if no :dataserver given'
40
+ end
41
+
42
+ @message_handler = opts[:message_handler]
43
+ if @message_handler && !@message_handler.respond_to?(:call)
44
+ raise ArgumentError, ':message_handler must implement `call` (eg, a Proc or a Method)'
45
+ end
46
+
47
+ opts[:username] = parse_username(opts)
48
+ @query_options = self.class.default_query_options.dup
49
+ opts[:password] = opts[:password].to_s if opts[:password] && opts[:password].to_s.strip != ''
50
+ opts[:appname] ||= 'TinyTds'
51
+ opts[:tds_version] = tds_versions_setter(opts)
52
+ opts[:use_utf16] = opts[:use_utf16].nil? || ["true", "1", "yes"].include?(opts[:use_utf16].to_s)
53
+ opts[:login_timeout] ||= 60
54
+ opts[:timeout] ||= 5
55
+ opts[:encoding] = opts[:encoding].nil? || opts[:encoding].casecmp('utf8').zero? ? 'UTF-8' : opts[:encoding].upcase
56
+ opts[:port] ||= 1433
57
+ opts[:dataserver] = "#{opts[:host]}:#{opts[:port]}" if opts[:dataserver].to_s.empty?
58
+ forced_integer_keys = [:login_timeout, :port, :timeout]
59
+ forced_integer_keys.each { |k| opts[k] = opts[k].to_i if opts[k] }
60
+ connect(opts)
61
+ end
62
+
63
+ def tds_73?
64
+ tds_version >= 11
65
+ end
66
+
67
+ def tds_version_info
68
+ info = TDS_VERSIONS_GETTERS[tds_version]
69
+ "#{info[:name]} - #{info[:description]}" if info
70
+ end
71
+
72
+ def active?
73
+ !closed? && !dead?
74
+ end
75
+
76
+ private
77
+
78
+ def parse_username(opts)
79
+ host = opts[:host]
80
+ username = opts[:username]
81
+ return username if username.nil? || !opts[:azure]
82
+ return username if username.include?('@') && !username.include?('database.windows.net')
83
+ user, domain = username.split('@')
84
+ domain ||= host
85
+ "#{user}@#{domain.split('.').first}"
86
+ end
87
+
88
+ def tds_versions_setter(opts = {})
89
+ v = opts[:tds_version] || ENV['TDSVER'] || '7.3'
90
+ TDS_VERSIONS_SETTERS[v.to_s]
91
+ end
92
+
93
+ # From sybdb.h comments:
94
+ # DBVERSION_xxx are used with dbsetversion()
95
+ #
96
+ TDS_VERSIONS_SETTERS = {
97
+ 'unknown' => 0,
98
+ '46' => 1,
99
+ '100' => 2,
100
+ '42' => 3,
101
+ '70' => 4,
102
+ '7.0' => 4,
103
+ '71' => 5,
104
+ '7.1' => 5,
105
+ '80' => 5,
106
+ '8.0' => 5,
107
+ '72' => 6,
108
+ '7.2' => 6,
109
+ '90' => 6,
110
+ '9.0' => 6,
111
+ '73' => 7,
112
+ '7.3' => 7
113
+ }.freeze
114
+
115
+ # From sybdb.h comments:
116
+ # DBTDS_xxx are returned by DBTDS()
117
+ # The integer values of the constants are poorly chosen.
118
+ #
119
+ TDS_VERSIONS_GETTERS = {
120
+ 0 => { name: 'DBTDS_UNKNOWN', description: 'Unknown' },
121
+ 1 => { name: 'DBTDS_2_0', description: 'Pre 4.0 SQL Server' },
122
+ 2 => { name: 'DBTDS_3_4', description: 'Microsoft SQL Server (3.0)' },
123
+ 3 => { name: 'DBTDS_4_0', description: '4.0 SQL Server' },
124
+ 4 => { name: 'DBTDS_4_2', description: '4.2 SQL Server' },
125
+ 5 => { name: 'DBTDS_4_6', description: '2.0 OpenServer and 4.6 SQL Server.' },
126
+ 6 => { name: 'DBTDS_4_9_5', description: '4.9.5 (NCR) SQL Server' },
127
+ 7 => { name: 'DBTDS_5_0', description: '5.0 SQL Server' },
128
+ 8 => { name: 'DBTDS_7_0', description: 'Microsoft SQL Server 7.0' },
129
+ 9 => { name: 'DBTDS_7_1/DBTDS_8_0', description: 'Microsoft SQL Server 2000' },
130
+ 10 => { name: 'DBTDS_7_2/DBTDS_9_0', description: 'Microsoft SQL Server 2005' },
131
+ 11 => { name: 'DBTDS_7_3', description: 'Microsoft SQL Server 2008' },
132
+ 12 => { name: 'DBTDS_7_4', description: 'Microsoft SQL Server 2012/2014' }
133
+ }.freeze
134
+
135
+ end
136
+ end
@@ -0,0 +1,14 @@
1
+ module TinyTds
2
+ class Error < StandardError
3
+
4
+ attr_accessor :source, :severity, :db_error_number, :os_error_number
5
+
6
+ def initialize(message)
7
+ super
8
+ @severity = nil
9
+ @db_error_number = nil
10
+ @os_error_number = nil
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,32 @@
1
+ require 'rbconfig'
2
+
3
+ module TinyTds
4
+ module Gem
5
+ class << self
6
+ def root_path
7
+ File.expand_path '../../..', __FILE__
8
+ end
9
+
10
+ def ports_root_path
11
+ File.join(root_path,'ports')
12
+ end
13
+
14
+ def ports_bin_paths
15
+ Dir.glob(File.join(ports_root_path,ports_host,'**','bin'))
16
+ end
17
+
18
+ def ports_lib_paths
19
+ Dir.glob(File.join(ports_root_path,ports_host,'**','lib'))
20
+ end
21
+
22
+ def ports_host
23
+ h = RbConfig::CONFIG['host']
24
+
25
+ # Our fat binary builds with a i686-w64-mingw32 toolchain
26
+ # but ruby for windows x32-mingw32 reports i686-pc-mingw32
27
+ # so correct the host here
28
+ h.gsub('i686-pc-mingw32', 'i686-w64-mingw32')
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,7 @@
1
+ module TinyTds
2
+ class Result
3
+
4
+ include Enumerable
5
+
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ module TinyTds
2
+ VERSION = File.read(File.expand_path('../../../VERSION', __FILE__)).chomp
3
+ end
data/lib/tiny_tds.rb ADDED
@@ -0,0 +1,61 @@
1
+ # encoding: UTF-8
2
+ require 'date'
3
+ require 'bigdecimal'
4
+ require 'rational'
5
+
6
+ require 'tiny_tds/version'
7
+ require 'tiny_tds/error'
8
+ require 'tiny_tds/client'
9
+ require 'tiny_tds/result'
10
+ require 'tiny_tds/gem'
11
+
12
+ # Support multiple ruby versions, fat binaries under Windows.
13
+ if RUBY_PLATFORM =~ /mingw|mswin/ && RUBY_VERSION =~ /(\d+.\d+)/
14
+ ver = Regexp.last_match(1)
15
+
16
+ add_dll_path = proc do |path, &block|
17
+ begin
18
+ require 'ruby_installer/runtime'
19
+ RubyInstaller::Runtime.add_dll_directory(path, &block)
20
+ rescue LoadError
21
+ old_path = ENV['PATH']
22
+ ENV['PATH'] = "#{path};#{old_path}"
23
+ begin
24
+ block.call
25
+ ensure
26
+ ENV['PATH'] = old_path
27
+ end
28
+ end
29
+ end
30
+
31
+ add_dll_paths = proc do |paths, &block|
32
+ if path=paths.shift
33
+ add_dll_path.call(path) do
34
+ add_dll_paths.call(paths, &block)
35
+ end
36
+ else
37
+ block.call
38
+ end
39
+ end
40
+
41
+ # Temporary add bin directories for DLL search, so that freetds DLLs can be found.
42
+ add_dll_paths.call( TinyTds::Gem.ports_bin_paths ) do
43
+ begin
44
+ require "tiny_tds/#{ver}/tiny_tds"
45
+ rescue LoadError
46
+ require 'tiny_tds/tiny_tds'
47
+ end
48
+ end
49
+ else
50
+ # Load dependent shared libraries into the process, so that they are already present,
51
+ # when tiny_tds.so is loaded. This ensures, that shared libraries are loaded even when
52
+ # the path is different between build and run time (e.g. Heroku).
53
+ ports_libs = File.join(TinyTds::Gem.ports_root_path,
54
+ "#{RbConfig::CONFIG['host']}/lib/*.so")
55
+ Dir[ports_libs].each do |lib|
56
+ require 'fiddle'
57
+ Fiddle.dlopen(lib)
58
+ end
59
+
60
+ require 'tiny_tds/tiny_tds'
61
+ end
@@ -0,0 +1,34 @@
1
+ diff --git a/src/tds/tls.c b/src/tds/tls.c
2
+ index 09e7fa0..1da18f6 100644
3
+ --- a/src/tds/tls.c
4
+ +++ b/src/tds/tls.c
5
+ @@ -101,6 +101,29 @@
6
+ #define SSL_PTR BIO_get_data(bio)
7
+ #endif
8
+
9
+ +/*
10
+ + * Add a workaround for older Mingw versions without inet_pton().
11
+ + * This means RubyInstallers DevKit-4.7.2 in particular.
12
+ + */
13
+ +#if defined(__MINGW32__) && !defined(InetPtonA)
14
+ + #include <windows.h>
15
+ +
16
+ + static HMODULE ws2_32 = NULL;
17
+ + typedef INT (WINAPI * __inet_pton)(INT Family, LPCWSTR pStringBuf, PVOID pAddr);
18
+ + static __inet_pton _inet_pton = NULL;
19
+ +
20
+ + INT WINAPI inet_pton(INT Family, LPCWSTR pStringBuf, PVOID pAddr)
21
+ + {
22
+ + if (_inet_pton == NULL) {
23
+ + ws2_32 = LoadLibraryEx("Ws2_32.dll", NULL, 0);
24
+ +
25
+ + _inet_pton = (__inet_pton)GetProcAddress(ws2_32, "inet_pton");
26
+ + }
27
+ +
28
+ + return (_inet_pton)(Family, pStringBuf, pAddr);
29
+ + }
30
+ +#endif
31
+ +
32
+ static SSL_RET
33
+ tds_pull_func_login(SSL_PULL_ARGS)
34
+ {
@@ -0,0 +1,28 @@
1
+ From 56e8972f66c3e948e2ad6885595c58fd23dcdb37 Mon Sep 17 00:00:00 2001
2
+ From: Lars Kanis <kanis@comcard.de>
3
+ Date: Thu, 6 Jul 2017 17:09:40 +0200
4
+ Subject: [PATCH] Don't use MSYS2 file libws2_32.a for MINGW build
5
+
6
+ This file is intended for MSYS2/cygwin builds and blocks OpenSSL
7
+ detection of freetds on i686.
8
+ ---
9
+ configure | 2 --
10
+ configure.ac | 2 --
11
+ 2 files changed, 4 deletions(-)
12
+
13
+ diff --git a/configure b/configure
14
+ index 9495a49..31eb01d 100644
15
+ --- a/configure
16
+ +++ b/configure
17
+ @@ -15915,8 +15915,6 @@ case $host in
18
+ tds_mingw=yes
19
+ if test "$host_cpu" = "x86_64"; then
20
+ LIBS="-lws2_32"
21
+ - elif test -r /usr/lib/w32api/libws2_32.a; then
22
+ - LIBS="-L/usr/lib/w32api -lws2_32"
23
+ else
24
+ LIBS="-lws2_32"
25
+ fi
26
+ --
27
+ 2.6.2.windows.1
28
+
@@ -0,0 +1,17 @@
1
+ --- a/srclib/stdio.in.h 2017-01-22 01:23:00.000000000 -0400
2
+ +++ b/srclib/stdio.in.h 2017-01-22 01:24:00.000000000 -0400
3
+ @@ -695,8 +695,14 @@
4
+ /* It is very rare that the developer ever has full control of stdin,
5
+ so any use of gets warrants an unconditional warning. Assume it is
6
+ always declared, since it is required by C89. */
7
+ +#if defined(__GLIBC__) && !defined(__UCLIBC__)
8
+ +# ifdef __GLIBC_PREREQ
9
+ +# if !__GLIBC_PREREQ(2, 16)
10
+ _GL_WARN_ON_USE (gets, "gets is a security hole - use fgets instead");
11
+ +# endif
12
+ +# endif
13
+ +#endif
14
+ #endif
15
+
16
+
17
+ #if @GNULIB_OBSTACK_PRINTF@ || @GNULIB_OBSTACK_PRINTF_POSIX@
@@ -0,0 +1,14 @@
1
+ # encoding: UTF-8
2
+
3
+ desc 'Build the windows binary gems per rake-compiler-dock'
4
+ task 'gem:windows' => ['ports:cross'] do
5
+ require 'rake_compiler_dock'
6
+
7
+ # make sure to install our bundle
8
+ build = ['bundle']
9
+
10
+ # and finally build the native gem
11
+ build << 'rake cross native gem RUBY_CC_VERSION=2.5.0:2.4.0:2.3.0:2.2.2:2.1.6:2.0.0 CFLAGS="-Wall" MAKE="make -j`nproc`"'
12
+
13
+ RakeCompilerDock.sh build.join(' && ')
14
+ end
@@ -0,0 +1,8 @@
1
+ # encoding: UTF-8
2
+ require 'rubygems/package_task'
3
+
4
+ Gem::PackageTask.new(SPEC) do |pkg|
5
+ pkg.need_tar = false
6
+ pkg.need_zip = false
7
+ end
8
+
@@ -0,0 +1,37 @@
1
+ require_relative './recipe'
2
+
3
+ module Ports
4
+ class Freetds < Recipe
5
+ def initialize(version)
6
+ super('freetds', version)
7
+
8
+ set_patches
9
+ end
10
+
11
+ private
12
+
13
+ def configure_defaults
14
+ opts = super
15
+
16
+ opts << '--with-pic'
17
+ opts << '--disable-odbc'
18
+
19
+ if version =~ /0\.91/
20
+ opts << '--with-tdsver=7.1'
21
+ else
22
+ opts << '--with-tdsver=7.3'
23
+ end
24
+
25
+ if windows?
26
+ opts << '--sysconfdir=C:/Sites'
27
+ opts << '--enable-sspi'
28
+ end
29
+
30
+ opts
31
+ end
32
+
33
+ def set_patches
34
+ self.patch_files.concat get_patches(name, version)
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,43 @@
1
+ require_relative './recipe'
2
+
3
+ module Ports
4
+ class Libiconv < Recipe
5
+ def initialize(version)
6
+ super('libiconv', version)
7
+
8
+ set_patches
9
+ end
10
+
11
+ def cook
12
+ chdir_for_build do
13
+ super
14
+ end
15
+ self
16
+ end
17
+
18
+ private
19
+
20
+ # When using rake-compiler-dock on Windows, the underlying Virtualbox shared
21
+ # folders don't support symlinks, but libiconv expects it for a build on
22
+ # Linux. We work around this limitation by using the temp dir for cooking.
23
+ def chdir_for_build
24
+ build_dir = ENV['RCD_HOST_RUBY_PLATFORM'].to_s =~ /mingw|mswin|cygwin/ ? '/tmp' : '.'
25
+ Dir.chdir(build_dir) do
26
+ yield
27
+ end
28
+ end
29
+
30
+ def configure_defaults
31
+ [
32
+ "--host=#{@host}",
33
+ '--disable-static',
34
+ '--enable-shared',
35
+ 'CFLAGS=-fPIC -O2'
36
+ ]
37
+ end
38
+
39
+ def set_patches
40
+ self.patch_files.concat get_patches(name, version)
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,78 @@
1
+ require_relative './recipe'
2
+
3
+ module Ports
4
+ class Openssl < Recipe
5
+ def initialize(version)
6
+ super('openssl', version)
7
+
8
+ set_patches
9
+ end
10
+
11
+ def configure
12
+ return if configured?
13
+
14
+ md5_file = File.join(tmp_path, 'configure.md5')
15
+ digest = Digest::MD5.hexdigest(computed_options.to_s)
16
+ File.open(md5_file, "w") { |f| f.write digest }
17
+
18
+ # Windows doesn't recognize the shebang so always explicitly use sh
19
+ execute('configure', "sh -c \"./Configure #{computed_options.join(' ')}\"")
20
+ end
21
+
22
+ def install
23
+ unless installed?
24
+ execute('install', %Q(#{make_cmd} install_sw install_ssldirs))
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def execute(action, command, options={})
31
+ # OpenSSL Requires Perl >= 5.10, while the Ruby devkit uses MSYS1 with Perl 5.8.8.
32
+ # To overcome this, prepend Git's usr/bin to the PATH.
33
+ # It has MSYS2 with a recent version of perl.
34
+ prev_path = ENV['PATH']
35
+ if host =~ /mingw/ && IO.popen(["perl", "-e", "print($])"], &:read).to_f < 5.010
36
+ git_perl = 'C:/Program Files/Git/usr/bin'
37
+ if File.directory?(git_perl)
38
+ ENV['PATH'] = "#{git_perl}#{File::PATH_SEPARATOR}#{ENV['PATH']}"
39
+ ENV['PERL'] = 'perl'
40
+ end
41
+ end
42
+
43
+ super
44
+ ENV['PATH'] = prev_path
45
+ end
46
+
47
+ def configure_defaults
48
+ opts = [
49
+ 'shared',
50
+ target_arch
51
+ ]
52
+
53
+ if cross_build?
54
+ opts << "--cross-compile-prefix=#{host}-"
55
+ end
56
+
57
+ opts
58
+ end
59
+
60
+ def target_arch
61
+ if windows?
62
+ arch = ''
63
+ arch = '64' if host=~ /x86_64/
64
+
65
+ "mingw#{arch}"
66
+ else
67
+ arch = 'x32'
68
+ arch = 'x86_64' if host=~ /x86_64/
69
+
70
+ "linux-#{arch}"
71
+ end
72
+ end
73
+
74
+ def set_patches
75
+ self.patch_files.concat get_patches(name, version)
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,52 @@
1
+ # encoding: UTF-8
2
+ require 'mini_portile2'
3
+ require 'fileutils'
4
+ require 'rbconfig'
5
+
6
+ module Ports
7
+ class Recipe < MiniPortile
8
+ def cook
9
+ checkpoint = "ports/#{name}-#{version}-#{host}.installed"
10
+
11
+ unless File.exist? checkpoint
12
+ super
13
+ FileUtils.touch checkpoint
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def configure_defaults
20
+ [
21
+ "--host=#{@host}",
22
+ '--disable-static',
23
+ '--enable-shared'
24
+ ]
25
+ end
26
+
27
+ def windows?
28
+ host =~ /mswin|mingw32/
29
+ end
30
+
31
+ def system_host
32
+ RbConfig::CONFIG['host']
33
+ end
34
+
35
+ def cross_build?
36
+ host != system_host
37
+ end
38
+
39
+ def get_patches(libname, version)
40
+ patches = []
41
+
42
+ patch_path = File.expand_path(
43
+ File.join('..','..','..','patches',libname,version),
44
+ __FILE__
45
+ )
46
+
47
+ patches.concat(Dir[File.join(patch_path, '*.patch')].sort)
48
+ patches.concat(Dir[File.join(patch_path, '*.diff')].sort)
49
+ end
50
+ end
51
+ end
52
+