|
1 |
| -ENV['RC_ARCHS'] = '' if RUBY_PLATFORM =~ /darwin/ |
2 |
| - |
3 |
| -# :stopdoc: |
4 |
| - |
5 | 1 | require 'mkmf'
|
6 |
| -require 'rbconfig' |
7 |
| -require_relative './extconsts' |
8 |
| - |
9 |
| -# Shamelessly copied from nokogiri |
10 |
| -# |
11 |
| - |
12 |
| -def do_help |
13 |
| - print <<HELP |
14 |
| -usage: ruby #{$0} [options] |
15 |
| - --with-freetds-dir=DIR |
16 |
| - Use the freetds library placed under DIR. |
17 |
| -HELP |
18 |
| - exit! 0 |
| 2 | +require_relative 'extconsts' |
| 3 | + |
| 4 | +if ENV['MAINTAINER_MODE'] |
| 5 | + $stderr.puts "Maintainer mode enabled." |
| 6 | + $CFLAGS << |
| 7 | + ' -Wall' << |
| 8 | + ' -ggdb' << |
| 9 | + ' -DDEBUG' << |
| 10 | + ' -pedantic' |
| 11 | + $LDFLAGS << |
| 12 | + ' -ggdb' |
19 | 13 | end
|
20 | 14 |
|
21 |
| -do_help if arg_config('--help') |
| 15 | +if gem_platform=with_config("cross-build") |
| 16 | + require 'mini_portile2' |
| 17 | + |
| 18 | + openssl_platform = with_config("openssl-platform") |
| 19 | + |
| 20 | + class BuildRecipe < MiniPortile |
| 21 | + attr_accessor :gem_platform |
| 22 | + |
| 23 | + def initialize(name, version, files) |
| 24 | + super(name, version) |
| 25 | + self.files = files |
| 26 | + rootdir = File.expand_path('../../..', __FILE__) |
| 27 | + self.target = File.join(rootdir, "ports") |
| 28 | + self.patch_files = Dir[File.join("patches", self.name, self.version, "*.patch")].sort |
| 29 | + end |
| 30 | + |
| 31 | + # this will yield all ports into the same directory, making our path configuration for the linker easier |
| 32 | + def port_path |
| 33 | + "#{@target}/#{gem_platform}" |
| 34 | + end |
| 35 | + |
| 36 | + def cook_and_activate |
| 37 | + checkpoint = File.join(self.target, "#{self.name}-#{self.version}-#{gem_platform}.installed") |
| 38 | + |
| 39 | + unless File.exist?(checkpoint) |
| 40 | + self.cook |
| 41 | + FileUtils.touch checkpoint |
| 42 | + end |
| 43 | + |
| 44 | + self.activate |
| 45 | + self |
| 46 | + end |
| 47 | + end |
22 | 48 |
|
23 |
| -# Make sure to check the ports path for the configured host |
24 |
| -architecture = RbConfig::CONFIG['arch'] |
| 49 | + openssl_recipe = BuildRecipe.new("openssl", OPENSSL_VERSION, [OPENSSL_SOURCE_URI]).tap do |recipe| |
| 50 | + class << recipe |
| 51 | + attr_accessor :openssl_platform |
| 52 | + |
| 53 | + def configure |
| 54 | + envs = [] |
| 55 | + envs << "CFLAGS=-DDSO_WIN32 -DOPENSSL_THREADS" if RUBY_PLATFORM =~ /mingw|mswin/ |
| 56 | + envs << "CFLAGS=-fPIC -DOPENSSL_THREADS" if RUBY_PLATFORM =~ /linux/ |
| 57 | + execute('configure', ['env', *envs, "./Configure", openssl_platform, "threads", "-static", "CROSS_COMPILE=#{host}-", configure_prefix, "--libdir=lib"], altlog: "config.log") |
| 58 | + end |
| 59 | + |
| 60 | + def compile |
| 61 | + execute('compile', "#{make_cmd} build_libs") |
| 62 | + end |
| 63 | + |
| 64 | + def install |
| 65 | + execute('install', "#{make_cmd} install_dev") |
| 66 | + end |
| 67 | + end |
| 68 | + |
| 69 | + recipe.gem_platform = gem_platform |
| 70 | + recipe.openssl_platform = openssl_platform |
| 71 | + recipe.cook_and_activate |
| 72 | + end |
25 | 73 |
|
26 |
| -project_dir = File.expand_path("../../..", __FILE__) |
27 |
| -freetds_ports_dir = File.join(project_dir, 'ports', architecture, 'freetds', FREETDS_VERSION) |
28 |
| -freetds_ports_dir = File.expand_path(freetds_ports_dir) |
| 74 | + libiconv_recipe = BuildRecipe.new("libiconv", ICONV_VERSION, [ICONV_SOURCE_URI]).tap do |recipe| |
| 75 | + recipe.configure_options << "CFLAGS=-fPIC" if RUBY_PLATFORM =~ /linux/ |
| 76 | + recipe.gem_platform = gem_platform |
29 | 77 |
|
30 |
| -# Add all the special path searching from the original tiny_tds build |
31 |
| -# order is important here! First in, first searched. |
32 |
| -DIRS = %w( |
33 |
| - /opt/local |
34 |
| - /usr/local |
35 |
| -) |
| 78 | + recipe.cook_and_activate |
| 79 | + end |
36 | 80 |
|
37 |
| -if RbConfig::CONFIG['host_os'] =~ /darwin/i |
38 |
| - # Ruby below 2.7 seems to label the host CPU on Apple Silicon as aarch64 |
39 |
| - # 2.7 and above print is as ARM64 |
40 |
| - target_host_cpu = Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.7') ? 'aarch64' : 'arm64' |
| 81 | + # remove the ".la" files, otherwise libtool starts to complain when linking into FreeTDS |
| 82 | + Dir.glob(File.join(libiconv_recipe.path, "lib", "**", "*.la")).each do |la_file| |
| 83 | + File.delete(la_file) |
| 84 | + end |
41 | 85 |
|
42 |
| - if RbConfig::CONFIG['host_cpu'] == target_host_cpu |
43 |
| - # Homebrew on Apple Silicon installs into /opt/hombrew |
44 |
| - # https://docs.brew.sh/Installation |
45 |
| - # On Intel Macs, it is /usr/local, so no changes necessary to DIRS |
46 |
| - DIRS.unshift("/opt/homebrew") |
| 86 | + freetds_recipe = BuildRecipe.new("freetds", FREETDS_VERSION, [FREETDS_SOURCE_URI]).tap do |recipe| |
| 87 | + class << recipe |
| 88 | + def configure_defaults |
| 89 | + [ |
| 90 | + "--host=#{@host}", |
| 91 | + "--enable-shared", |
| 92 | + "--disable-static", |
| 93 | + "--disable-odbc", |
| 94 | + "--enable-sspi", |
| 95 | + ] |
| 96 | + end |
| 97 | + end |
| 98 | + |
| 99 | + # i am not 100% what is going on behind the scenes |
| 100 | + # it seems that FreeTDS build system prefers OPENSSL_CFLAGS and OPENSSL_LIBS |
| 101 | + # but the linker still relies on LIBS and CPPFLAGS |
| 102 | + # removing one or the other leads to build failures in any case of FreeTDS |
| 103 | + recipe.configure_options << "CFLAGS=-fPIC" if RUBY_PLATFORM =~ /linux/ |
| 104 | + recipe.configure_options << "LDFLAGS=-L#{openssl_recipe.path}/lib" |
| 105 | + recipe.configure_options << "LIBS=-liconv -lssl -lcrypto -lwsock32 -lgdi32 -lws2_32 -lcrypt32" |
| 106 | + recipe.configure_options << "CPPFLAGS=-I#{openssl_recipe.path}/include" |
| 107 | + |
| 108 | + recipe.configure_options << "OPENSSL_CFLAGS=-L#{openssl_recipe.path}/lib" |
| 109 | + recipe.configure_options << "OPENSSL_LIBS=-lssl -lcrypto -lwsock32 -lgdi32 -lws2_32 -lcrypt32" |
| 110 | + |
| 111 | + recipe.configure_options << "--with-openssl=#{openssl_recipe.path}" |
| 112 | + recipe.configure_options << "--with-libiconv-prefix=#{libiconv_recipe.path}" |
| 113 | + |
| 114 | + recipe.gem_platform = gem_platform |
| 115 | + recipe.cook_and_activate |
47 | 116 | end
|
48 |
| -end |
49 | 117 |
|
50 |
| -if ENV["RI_DEVKIT"] && ENV["MINGW_PREFIX"] # RubyInstaller Support |
51 |
| - DIRS.unshift(File.join(ENV["RI_DEVKIT"], ENV["MINGW_PREFIX"])) |
52 |
| -end |
| 118 | + ENV["LDFLAGS"] = "-Wl,-rpath -Wl,#{freetds_recipe.path}/lib" |
| 119 | + dir_config('freetds', "#{freetds_recipe.path}/include", "#{freetds_recipe.path}/lib") |
| 120 | +else |
| 121 | + # Make sure to check the ports path for the configured host |
| 122 | + architecture = RbConfig::CONFIG['arch'] |
| 123 | + |
| 124 | + project_dir = File.expand_path("../../..", __FILE__) |
| 125 | + freetds_ports_dir = File.join(project_dir, 'ports', architecture, 'freetds', FREETDS_VERSION) |
| 126 | + freetds_ports_dir = File.expand_path(freetds_ports_dir) |
| 127 | + |
| 128 | + # Add all the special path searching from the original tiny_tds build |
| 129 | + # order is important here! First in, first searched. |
| 130 | + DIRS = %w( |
| 131 | + /opt/local |
| 132 | + /usr/local |
| 133 | + ) |
| 134 | + |
| 135 | + if RbConfig::CONFIG['host_os'] =~ /darwin/i |
| 136 | + # Ruby below 2.7 seems to label the host CPU on Apple Silicon as aarch64 |
| 137 | + # 2.7 and above print is as ARM64 |
| 138 | + target_host_cpu = Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.7') ? 'aarch64' : 'arm64' |
| 139 | + |
| 140 | + if RbConfig::CONFIG['host_cpu'] == target_host_cpu |
| 141 | + # Homebrew on Apple Silicon installs into /opt/hombrew |
| 142 | + # https://docs.brew.sh/Installation |
| 143 | + # On Intel Macs, it is /usr/local, so no changes necessary to DIRS |
| 144 | + DIRS.unshift("/opt/homebrew") |
| 145 | + end |
| 146 | + end |
53 | 147 |
|
54 |
| -# Add the ports directory if it exists for local developer builds |
55 |
| -DIRS.unshift(freetds_ports_dir) if File.directory?(freetds_ports_dir) |
| 148 | + if ENV["RI_DEVKIT"] && ENV["MINGW_PREFIX"] # RubyInstaller Support |
| 149 | + DIRS.unshift(File.join(ENV["RI_DEVKIT"], ENV["MINGW_PREFIX"])) |
| 150 | + end |
56 | 151 |
|
57 |
| -# Grab freetds environment variable for use by people on services like |
58 |
| -# Heroku who they can't easily use bundler config to set directories |
59 |
| -DIRS.unshift(ENV['FREETDS_DIR']) if ENV.has_key?('FREETDS_DIR') |
| 152 | + # Add the ports directory if it exists for local developer builds |
| 153 | + DIRS.unshift(freetds_ports_dir) if File.directory?(freetds_ports_dir) |
60 | 154 |
|
61 |
| -# Add the search paths for freetds configured above |
62 |
| -ldirs = DIRS.flat_map do |path| |
63 |
| - ldir = "#{path}/lib" |
64 |
| - [ldir, "#{ldir}/freetds"] |
65 |
| -end |
| 155 | + # Grab freetds environment variable for use by people on services like |
| 156 | + # Heroku who they can't easily use bundler config to set directories |
| 157 | + DIRS.unshift(ENV['FREETDS_DIR']) if ENV.has_key?('FREETDS_DIR') |
66 | 158 |
|
67 |
| -idirs = DIRS.flat_map do |path| |
68 |
| - idir = "#{path}/include" |
69 |
| - [idir, "#{idir}/freetds"] |
70 |
| -end |
| 159 | + # Add the search paths for freetds configured above |
| 160 | + ldirs = DIRS.flat_map do |path| |
| 161 | + ldir = "#{path}/lib" |
| 162 | + [ldir, "#{ldir}/freetds"] |
| 163 | + end |
71 | 164 |
|
72 |
| -puts "looking for freetds headers in the following directories:\n#{idirs.map{|a| " - #{a}\n"}.join}" |
73 |
| -puts "looking for freetds library in the following directories:\n#{ldirs.map{|a| " - #{a}\n"}.join}" |
74 |
| -dir_config('freetds', idirs, ldirs) |
75 |
| - |
76 |
| -have_dependencies = [ |
77 |
| - find_header('sybfront.h'), |
78 |
| - find_header('sybdb.h'), |
79 |
| - find_library('sybdb', 'tdsdbopen'), |
80 |
| - find_library('sybdb', 'dbanydatecrack') |
81 |
| -].inject(true) do |memo, current| |
82 |
| - memo && current |
| 165 | + idirs = DIRS.flat_map do |path| |
| 166 | + idir = "#{path}/include" |
| 167 | + [idir, "#{idir}/freetds"] |
| 168 | + end |
| 169 | + |
| 170 | + puts "looking for freetds headers in the following directories:\n#{idirs.map{|a| " - #{a}\n"}.join}" |
| 171 | + puts "looking for freetds library in the following directories:\n#{ldirs.map{|a| " - #{a}\n"}.join}" |
| 172 | + dir_config('freetds', idirs, ldirs) |
83 | 173 | end
|
84 | 174 |
|
85 |
| -unless have_dependencies |
86 |
| - abort 'Failed! Do you have FreeTDS 1.0.0 or higher installed?' |
| 175 | +if /solaris/ =~ RUBY_PLATFORM |
| 176 | + append_cppflags( '-D__EXTENSIONS__' ) |
87 | 177 | end
|
88 | 178 |
|
89 |
| -create_makefile('tiny_tds/tiny_tds') |
| 179 | +find_header('sybfront.h') or abort "Can't find the 'sybfront.h' header" |
| 180 | +find_header('sybdb.h') or abort "Can't find the 'sybdb.h' header" |
| 181 | + |
| 182 | +unless find_library('sybdb', 'dbanydatecrack') |
| 183 | + abort "Failed! Do you have FreeTDS 1.0.0 or higher installed?" |
| 184 | +end |
90 | 185 |
|
91 |
| -# :startdoc: |
| 186 | +create_makefile("tiny_tds/tiny_tds") |
0 commit comments