Top Level Namespace

Defined Under Namespace

Modules: TinyTds Classes: BuildRecipe

Constant Summary collapse

ICONV_VERSION =
ENV['TINYTDS_ICONV_VERSION'] || "1.14"
ICONV_SOURCE_URI =
"http://ftp.gnu.org/pub/gnu/libiconv/libiconv-#{ICONV_VERSION}.tar.gz"
OPENSSL_VERSION =
ENV['TINYTDS_OPENSSL_VERSION'] || '1.0.2g'
OPENSSL_SOURCE_URI =
"https://www.openssl.org/source/openssl-#{OPENSSL_VERSION}.tar.gz"
FREETDS_VERSION =
ENV['TINYTDS_FREETDS_VERSION'] || "1.0rc3"
FREETDS_VERSION_INFO =
Hash.new { |h,k|
  h[k] = {files: "ftp://ftp.freetds.org/pub/freetds/stable/freetds-#{k}.tar.bz2"}
}
FREETDS_SOURCE_URI =
FREETDS_VERSION_INFO[FREETDS_VERSION][:files]
FREETDSDIR =
ENV['FREETDS_DIR']
LIBDIR =
"#{FREETDSDIR}/lib"
INCLUDEDIR =
"#{FREETDSDIR}/include"
SEARCHABLE_PATHS =
begin
  eop_regexp = /#{File::SEPARATOR}bin$/
  paths = ENV['PATH']
  paths = paths.gsub(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR
  paths = paths.split(File::PATH_SEPARATOR)
  bin_paths = paths.select{ |p| p =~ eop_regexp }
  bin_paths.map{ |p| p.sub(eop_regexp,'') }.compact.reject{ |p| p.empty? }.uniq
end
HEADER_DIRS =

There's no default include/lib dir on Windows. Let's just add the Ruby ones and resort on the search path specified by INCLUDE and LIB environment variables

[
  # First search /opt/local for macports
  '/opt/local/include',
  # Then search /usr/local for people that installed from source
  '/usr/local/include',
  # Check the ruby install locations
  INCLUDEDIR,
  # Finally fall back to /usr
  '/usr/include'
].reject{ |dir| !File.directory?(dir) }
LIB_DIRS =
[
  # First search /opt/local for macports
  '/opt/local/lib',
  # Then search /usr/local for people that installed from source
  '/usr/local/lib',
  # Check the ruby install locations
  LIBDIR,
  # Finally fall back to /usr
  '/usr/lib',
].reject{ |dir| !File.directory?(dir) }
FREETDS_HEADER_DIRS =
(searchable_paths_with_directories(['include'],['include','freetds']) + HEADER_DIRS).uniq
FREETDS_LIB_DIRS =
(searchable_paths_with_directories(['lib'],['lib','freetds']) + LIB_DIRS).uniq

Instance Method Summary collapse

Instance Method Details

#asplode(lib) ⇒ Object


294
295
296
# File 'ext/tiny_tds/extconf.rb', line 294

def asplode(lib)
  abort "-----\n#{lib} is missing.\n-----"
end

#define_freetds_recipe(host, libiconv, libssl, gnutls) ⇒ Object


200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
# File 'ext/tiny_tds/extconf.rb', line 200

def define_freetds_recipe(host, libiconv, libssl, gnutls)
  BuildRecipe.new("freetds", FREETDS_VERSION, [FREETDS_SOURCE_URI]).tap do |recipe|
    with_tdsver = FREETDS_VERSION =~ /0\.91/ ? "--with-tdsver=7.1" : "--with-tdsver=7.3"
    for_windows = recipe.host =~ /mswin|mingw/i
    recipe.configure_options << '--with-pic'
    recipe.configure_options << "--with-libiconv-prefix=#{libiconv.path}" if libiconv
    if true == libssl
      recipe.configure_options << "--with-openssl"
    elsif libssl
      recipe.configure_options << "--with-openssl=#{libssl.path}"
    end
    recipe.configure_options << "--with-gnutls" if gnutls
    recipe.configure_options << '--sysconfdir=C:\Sites' if for_windows
    recipe.configure_options << '--enable-sspi' if for_windows
    recipe.configure_options << "--disable-odbc"
    recipe.configure_options << with_tdsver
    if libiconv      # For some reason freetds doesn't honor --with-libiconv-prefix
      # so we have do add it by hand:

      recipe.configure_options << "CFLAGS=-I#{libiconv.path}/include"
      recipe.configure_options << "LDFLAGS=-L#{libiconv.path}/lib -liconv"
    end

    class << recipe

      def install
        super_value = super        # Install binstub target binaries.

        if super_value
          bin_path = File.expand_path File.join(path, 'bin')
          exe_path = File.expand_path File.join(target, '..', 'exe')
          return unless File.directory?(bin_path)
          ['tsql', 'defncopy'].each do |bin|
            ['.exe', ''].each do |ext|
              exe = File.join bin_path, "#{bin}#{ext}"
              next unless File.exists?(exe)
              next unless File.executable?(exe)
              FileUtils.cp exe, exe_path
            end
          end
        end
        super_value
      end

    end

  end
end

#define_libiconv_recipe(host) ⇒ Object


193
194
195
196
197
198
# File 'ext/tiny_tds/extconf.rb', line 193

def define_libiconv_recipe(host)
  BuildRecipe.new("libiconv", ICONV_VERSION, [ICONV_SOURCE_URI]).tap do |recipe|
    # always produce position independent code
    recipe.configure_options << "CFLAGS=-fPIC"
  end
end

#define_libssl_recipe(host) ⇒ Object


137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# File 'ext/tiny_tds/extconf.rb', line 137

def define_libssl_recipe(host)
  BuildRecipe.new("openssl", OPENSSL_VERSION, [OPENSSL_SOURCE_URI]).tap do |recipe|
    class << recipe
      def extract_file(file, target)
        filename = File.basename(file)
        FileUtils.mkdir_p target

        message "Extracting #{filename} into #{target}... "
        result = `#{tar_exe} #{tar_compression_switch(filename)}xf "#{file}" -C "#{target}" 2>&1`
        if $?.success?
          output "OK"
        else
          # tar on windows returns error exit code, because it can not extract symlinks
          output "ERROR (ignored)"
        end
      end

      def configure
        config = if host=~/mingw/
          host=~/x86_64/ ? 'mingw64' : 'mingw'
        end
        args = [ "CFLAGS=-DDSO_WIN32",
            "./Configure",
            "no-shared",
            configure_prefix,
            config,
          ]
        args.unshift("CROSS_COMPILE=#{host}-") if enable_config("cross-build")

        execute "configure", "sh -c \"#{args.join(" ")}\""
      end

      def compile
        super        # OpenSSL DLLs are called "libeay32.dll" and "ssleay32.dll" per default,
        # regardless to the version. This is best suited to meet the Windows DLL hell.
        # To avoid any conflicts we do a static build and build DLLs afterwards,
        # with our own naming scheme.

        execute "mkdef-libeay32", "(perl util/mkdef.pl 32 libeay >libeay32.def)"
        execute "mkdef-ssleay32", "(perl util/mkdef.pl 32 ssleay >ssleay32.def)"
        dllwrap = consolidated_host(RbConfig::CONFIG["DLLWRAP"])
        execute "dllwrap-libeay32", "#{dllwrap} --dllname libeay32-#{version}-#{host}.dll --output-lib libcrypto.dll.a --def libeay32.def libcrypto.a -lwsock32 -lgdi32 -lcrypt32"
        execute "dllwrap-ssleay32", "#{dllwrap} --dllname ssleay32-#{version}-#{host}.dll --output-lib libssl.dll.a --def ssleay32.def libssl.a libcrypto.dll.a"
      end

      def install
        super
        FileUtils.cp "#{work_path}/libeay32-#{version}-#{host}.dll", "#{path}/bin/"
        FileUtils.cp "#{work_path}/ssleay32-#{version}-#{host}.dll", "#{path}/bin/"
        FileUtils.cp "#{work_path}/libcrypto.dll.a", "#{path}/lib/"
        FileUtils.cp "#{work_path}/libssl.dll.a", "#{path}/lib/"
      end
    end
  end
end

#do_helpObject

Shamelessly copied from nokogiri


19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'ext/tiny_tds/extconf.rb', line 19

def do_help
  print <<HELP
usage: ruby #{$0} [options]

    --enable-system-freetds / --disable-system-freetds
    --enable-system-iconv   / --disable-system-iconv
    --enable-system-openssl / --disable-system-openssl
      Force use of system or builtin freetds/iconv/openssl library.
      Default is to prefer system libraries and fallback to builtin.

    --with-freetds-dir=DIR
      Use the freetds library placed under DIR.

    --enable-lookup
      Search for freetds through all paths in the PATH environment variable.

    --disable-openssl
      Disable OpenSSL for freetds build. No effect on system-freetds.

    --enable-gnutls
      Use GnuTLS instead of OpenSSL for freetds build.

    --enable-cross-build
      Do cross-build.
HELP
  exit! 0
end

#freetds_usable?(lib_prefix) ⇒ Boolean


298
299
300
301
302
# File 'ext/tiny_tds/extconf.rb', line 298

def freetds_usable?(lib_prefix)
  have_header('sybfront.h') && have_header('sybdb.h') &&
    find_library("#{lib_prefix}sybdb", 'tdsdbopen') &&
    find_library("#{lib_prefix}ct",    'ct_bind')
end

#searchable_paths_with_directories(*directories) ⇒ Object


73
74
75
76
77
78
79
80
# File 'ext/tiny_tds/extconf.rb', line 73

def searchable_paths_with_directories(*directories)
  SEARCHABLE_PATHS.map do |path|
    directories.map do |paths|
      dir = File.join path, *paths
      File.directory?(dir) ? dir : nil
    end.flatten.compact
  end.flatten.compact
end