bonekit 0.0.4-arm-linux → 0.0.5-arm-linux

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- NjI5NDRkNjgwMzIyYWI2NTQ3ZjVmMDE5YzIzZmVhZjM4NWVhZjcyNA==
4
+ MmE3YjgyYmZiODEwZmE3MWU0NDM2MjQ1YWFmOWM1NTNiNTQ1NWEzMg==
5
5
  data.tar.gz: !binary |-
6
- YWNjMWNiMmE3N2Y4MGZlNjAzNGVjMTdmMTNiMDZlZmY2MjlkNGUwMg==
6
+ OTc4ZDMxYjI0YjU4ZDIyNGRlYjk5OTE2YTMwNTNlNjE0NWMyNTMzMA==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- NjgyOTkxNjFmZTc2Yjg2YjIyZjg2ZTE0ZDUwODFhOGFhYzczYWQ4YTM5Njgy
10
- MWQzZmRlMzUzZTRjYTI5MWI2YTExNTVmYjE2ZGU0Yzk2ODg5Njk4Y2M5ODI2
11
- NTQ2NjAwZjBkODk1OWY4ZDBjNzdjYTc2YzYwNDU5ZWUxNTNhN2Q=
9
+ MDBhMGQyMzJlYjcyY2FkMjMyNTBkNmY3ZmY0NTZmMmE4OGVlMjdiMWM4ODRl
10
+ MjE1NTM1OWE1OTI1YTE3MGI0NDEyOGQ5M2RkZjY2NTY4OGM0ODQ4ZTRiYTQ5
11
+ NzU3NTg3Yjc0NDZjZDk2ODkzZjdhNDRlNjBhNDAzOWZiODM5Yjk=
12
12
  data.tar.gz: !binary |-
13
- OGI1NGU4YWU0ZDYyNTBiNDZmODk4YmQyNTRmNjQ4OTMyNTJlOWQ1ZmRmZDYw
14
- ZGMwMDY3NGJjMTEyZWQ0OTk2MTA4OTFjZjRjOWQ4ODc0N2RhMzlkMmE5NDJl
15
- NGY1MmFjYmQyYjgyMDdkZTMxMjViYjVlNjRlMjM4ODZmZjRmZTg=
13
+ ZWQxMzI2MmNjM2Q2NzgyMTU4ZjE3ZWY4MGMzNjgxZDgzMTFlM2FiNmU5NzRm
14
+ MDY0MGJjZmZmY2RkOGU4YzA2NDAyZmZhZTQ0MTkyMDg1MTZjYjVhMjEwZTI0
15
+ ZTBmNTFmYzA1NmNjMDRhM2M4NWYxNDFjYzdiNTVkZDgwNDI1NmU=
data/.gitmodules ADDED
@@ -0,0 +1,3 @@
1
+ [submodule "deps/bonekit-c"]
2
+ path = deps/bonekit-c
3
+ url = https://github.com/laugga/bonekit-c.git
data/Rakefile CHANGED
@@ -44,3 +44,9 @@ YARD::Rake::YardocTask.new(:doc) do |t|
44
44
  t.options = ['-o docs/']
45
45
  t.options << '--debug' << '--verbose' if $trace
46
46
  end
47
+
48
+ desc "Update bonekit-c dependency"
49
+ task :deps do
50
+ system("cp -rf deps/bonekit-c/src/*.h ext/bonekit/")
51
+ system("cp -rf deps/bonekit-c/src/*.c ext/bonekit/")
52
+ end
data/bonekit.gemspec CHANGED
@@ -14,7 +14,7 @@ Gem::Specification.new do |s|
14
14
  s.email = "dev@laugga.com"
15
15
  s.homepage = "http://laugga.com/bonekit"
16
16
 
17
- s.files = `git ls-files`.split("\n")
17
+ s.files = `git ls-files`.split("\n") - %w(.gitignore deps/bonekit-c)
18
18
  s.test_files = `git ls-files -- {test,spec}/*`.split("\n")
19
19
 
20
20
  s.require_paths = ["lib"]
@@ -0,0 +1,223 @@
1
+ # Beaglebone Black with Angstrom Distribution
2
+
3
+ ## System
4
+
5
+ ```sh
6
+ opkg update
7
+ opkg upgrade
8
+ ```
9
+
10
+ ## Generating SSH Keys
11
+
12
+ Setup 'ssh-agent':
13
+
14
+ ```sh
15
+ echo 'EDITOR=/usr/bin/nano export EDITOR' > ~/.profile
16
+ echo 'eval `ssh-agent -s`' > ~/.profile
17
+ ```
18
+
19
+ Install 'ssh-keygen':
20
+
21
+ ```sh
22
+ opkg install openssh-keygen
23
+ ```
24
+
25
+ ```sh
26
+ ssh-keygen -t rsa -C "<your email here>"
27
+ ssh-add ~/.ssh/id_rsa
28
+ ```
29
+
30
+ Edit '~/.ssh/config':
31
+
32
+ ```sh
33
+ Host *
34
+ IdentityFile ~/.ssh/id_rsa
35
+ ```
36
+
37
+ ## Fix SSL certificates
38
+
39
+ For git, edit ~/.gitconfig:
40
+
41
+ ```sh
42
+ git config --global http.sslVerify true
43
+ git config --global http.sslCAinfo /etc/ssl/certs/ca-certificates.crt
44
+ ```
45
+
46
+ For curl, do:
47
+
48
+ ```sh
49
+ echo "export CURL_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt" >> ~/.profile
50
+ ```
51
+
52
+ For rubygem and other, do:
53
+
54
+ ```sh
55
+ echo "export SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt" >> ~/.profile
56
+ ```
57
+
58
+
59
+ ## Time
60
+
61
+ Automatically update the time using NTP:
62
+
63
+ http://derekmolloy.ie/automatically-setting-the-beaglebone-black-time-using-ntp/
64
+
65
+ Install ntp:
66
+
67
+ ```sh
68
+ opkg install ntp
69
+ ```
70
+
71
+ Edit '/etc/ntp.conf' file:
72
+
73
+ ```sh
74
+ # This is the most basic ntp configuration file
75
+ # The driftfile must remain in a place specific to this
76
+ # machine - it records the machine specific clock error
77
+
78
+ driftfile /etc/ntp.drift
79
+ logfile /var/log/ntpd.log
80
+
81
+ # NTP Servers for Ireland from www.pool.ntp.org
82
+ server 0.pool.ntp.org
83
+ server 1.pool.ntp.org
84
+ server 2.pool.ntp.org
85
+ server 3.pool.ntp.org
86
+
87
+ # Using local hardware clock as fallback
88
+ # Disable this when using ntpd -q -g -x as ntpdate or it will sync to itself
89
+ # server 127.127.1.0
90
+ # fudge 127.127.1.0 stratum 14
91
+
92
+ # Defining a default security setting
93
+ restrict 192.168.1.0 mask 255.255.255.0 nomodify notrap
94
+ ```
95
+
96
+ Set localtime according to time zone:
97
+
98
+ ```sh
99
+ rm localtime
100
+ ln -s /usr/share/zoneinfo/Europe/London /etc/localtime
101
+ ```
102
+
103
+ Enable the NTP services:
104
+
105
+ ```sh
106
+ systemctl enable ntpdate.service
107
+ systemctl enable ntpd.service
108
+ ```
109
+
110
+ Edit '/lib/systemd/system/ntpdate.service':
111
+
112
+ ```sh
113
+ [Unit]
114
+ Description=Network Time Service (one-shot ntpdate mode)
115
+ Before=ntpd.service
116
+
117
+ [Service]
118
+ Type=oneshot
119
+ ExecStart=/usr/bin/ntpd -q -g -x
120
+ ExecStart=/sbin/hwclock --systohc
121
+ RemainAfterExit=yes
122
+
123
+ [Install]
124
+ WantedBy=multi-user.target
125
+ ```
126
+
127
+ ## Install Ruby
128
+
129
+ You may need to install ruby. In a beaglebone with angstrom installed do:
130
+
131
+ ```sh
132
+ opkg update
133
+ opkg install ruby
134
+ ```
135
+
136
+ Fixing /usr/lib/ruby/mkmf.rb:
137
+
138
+ ```sh
139
+ INCFLAGS = -I. #$INCFLAGS -I/usr/include/
140
+ ldflags = #{$LDFLAGS} -L/lib/
141
+ ```
142
+
143
+ ## Wifi using rtl8192cu/rtl8188cus chipset
144
+
145
+ How to install a rtl8192cu/rtl8188cus on the Beaglebone Black (BBB) running Angstrom:
146
+
147
+ http://www.codealpha.net/864/how-to-set-up-a-rtl8192cu-on-the-beaglebone-black-bbb/
148
+
149
+ ```sh
150
+ opkg install kernel-dev
151
+ opkg install kernel-headers
152
+ ```
153
+
154
+ After reboot:
155
+
156
+ ```sh
157
+ cd /usr/src/kernel
158
+ make scripts
159
+ ln -s /usr/src/kernel /lib/modules/$(uname -r)/build
160
+ cd ~
161
+ git clone https://github.com/cmicali/rtl8192cu_beaglebone.git
162
+ cd rtl8192cu_beaglebone
163
+ make CROSS_COMPILE=""
164
+ ```
165
+
166
+ Install the driver:
167
+
168
+ ```sh
169
+ mv 8192cu.ko /lib/modules/$(uname -r)
170
+ depmod -a
171
+ cd /etc/modules-load.d
172
+ echo "8192cu" > rtl8192cu-vendor.conf
173
+ ```
174
+
175
+ Blacklist old rtlxxxx drivers:
176
+
177
+ ```sh
178
+ cd /etc/modprobe.d
179
+ echo "install rtl8192cu /bin/false" >wifi_blacklist.conf
180
+ echo "install rtl8192c_common /bin/false" >>wifi_blacklist.conf
181
+ echo "install rtlwifi /bin/false" >>wifi_blacklist.conf
182
+ ```
183
+
184
+ Edit '/var/lib/connman/settings':
185
+
186
+ ```sh
187
+ [global]
188
+ Timeservers=0.angstrom.pool.ntp.org;1.angstrom.pool.ntp.org;2.angstrom.pool.ntp.org;3.angstrom.pool.ntp.org
189
+ OfflineMode=false
190
+
191
+ [Wired]
192
+ Enable=true
193
+ Tethering=false
194
+
195
+ [WiFi]
196
+ Enable=true
197
+ Tethering=false
198
+ ```
199
+
200
+ Edit '/var/lib/connman/wifi.config':
201
+
202
+ ```sh
203
+ [service_home]
204
+ Type=wifi
205
+ Name="<SSID>"
206
+ ```
207
+
208
+ After reboot, connecting manually:
209
+
210
+ ```sh
211
+ pgrep wpa
212
+ wpa_supplicant -Dwext -iwlan0 -c/etc/wpa_supplicant.conf -B
213
+ wpa_cli
214
+ /sbin/udhcpc -iwlan0
215
+ ```
216
+
217
+ Or add init script:
218
+
219
+ ```
220
+ cp wifi_init.sh /etc/init.d/wifi_init
221
+ chmod 755 /etc/init.d/wifi_init
222
+ update-rc.d wifi_init defaults
223
+ ```
@@ -0,0 +1,2303 @@
1
+ # -*- indent-tabs-mode: t -*-
2
+ # module to create Makefile for extension modules
3
+ # invoke like: ruby -r mkmf extconf.rb
4
+
5
+ require 'rbconfig'
6
+ require 'fileutils'
7
+ require 'shellwords'
8
+
9
+ CONFIG = RbConfig::MAKEFILE_CONFIG
10
+ ORIG_LIBPATH = ENV['LIB']
11
+
12
+ C_EXT = %w[c m]
13
+ CXX_EXT = %w[cc mm cxx cpp]
14
+ if File::FNM_SYSCASE.zero?
15
+ CXX_EXT.concat(%w[C])
16
+ end
17
+ SRC_EXT = C_EXT + CXX_EXT
18
+ $static = nil
19
+ $config_h = '$(arch_hdrdir)/ruby/config.h'
20
+ $default_static = $static
21
+
22
+ unless defined? $configure_args
23
+ $configure_args = {}
24
+ args = CONFIG["configure_args"]
25
+ if ENV["CONFIGURE_ARGS"]
26
+ args << " " << ENV["CONFIGURE_ARGS"]
27
+ end
28
+ for arg in Shellwords::shellwords(args)
29
+ arg, val = arg.split('=', 2)
30
+ next unless arg
31
+ arg.tr!('_', '-')
32
+ if arg.sub!(/^(?!--)/, '--')
33
+ val or next
34
+ arg.downcase!
35
+ end
36
+ next if /^--(?:top|topsrc|src|cur)dir$/ =~ arg
37
+ $configure_args[arg] = val || true
38
+ end
39
+ for arg in ARGV
40
+ arg, val = arg.split('=', 2)
41
+ next unless arg
42
+ arg.tr!('_', '-')
43
+ if arg.sub!(/^(?!--)/, '--')
44
+ val or next
45
+ arg.downcase!
46
+ end
47
+ $configure_args[arg] = val || true
48
+ end
49
+ end
50
+
51
+ $libdir = CONFIG["libdir"]
52
+ $rubylibdir = CONFIG["rubylibdir"]
53
+ $archdir = CONFIG["archdir"]
54
+ $sitedir = CONFIG["sitedir"]
55
+ $sitelibdir = CONFIG["sitelibdir"]
56
+ $sitearchdir = CONFIG["sitearchdir"]
57
+ $vendordir = CONFIG["vendordir"]
58
+ $vendorlibdir = CONFIG["vendorlibdir"]
59
+ $vendorarchdir = CONFIG["vendorarchdir"]
60
+
61
+ $mswin = /mswin/ =~ RUBY_PLATFORM
62
+ $bccwin = /bccwin/ =~ RUBY_PLATFORM
63
+ $mingw = /mingw/ =~ RUBY_PLATFORM
64
+ $cygwin = /cygwin/ =~ RUBY_PLATFORM
65
+ $netbsd = /netbsd/ =~ RUBY_PLATFORM
66
+ $os2 = /os2/ =~ RUBY_PLATFORM
67
+ $beos = /beos/ =~ RUBY_PLATFORM
68
+ $haiku = /haiku/ =~ RUBY_PLATFORM
69
+ $solaris = /solaris/ =~ RUBY_PLATFORM
70
+ $universal = /universal/ =~ RUBY_PLATFORM
71
+ $dest_prefix_pattern = (File::PATH_SEPARATOR == ';' ? /\A([[:alpha:]]:)?/ : /\A/)
72
+
73
+ # :stopdoc:
74
+
75
+ def config_string(key, config = CONFIG)
76
+ s = config[key] and !s.empty? and block_given? ? yield(s) : s
77
+ end
78
+
79
+ def dir_re(dir)
80
+ Regexp.new('\$(?:\('+dir+'\)|\{'+dir+'\})(?:\$(?:\(target_prefix\)|\{target_prefix\}))?')
81
+ end
82
+
83
+ def relative_from(path, base)
84
+ dir = File.join(path, "")
85
+ if File.expand_path(dir) == File.expand_path(dir, base)
86
+ path
87
+ else
88
+ File.join(base, path)
89
+ end
90
+ end
91
+
92
+ INSTALL_DIRS = [
93
+ [dir_re('commondir'), "$(RUBYCOMMONDIR)"],
94
+ [dir_re('sitedir'), "$(RUBYCOMMONDIR)"],
95
+ [dir_re('vendordir'), "$(RUBYCOMMONDIR)"],
96
+ [dir_re('rubylibdir'), "$(RUBYLIBDIR)"],
97
+ [dir_re('archdir'), "$(RUBYARCHDIR)"],
98
+ [dir_re('sitelibdir'), "$(RUBYLIBDIR)"],
99
+ [dir_re('vendorlibdir'), "$(RUBYLIBDIR)"],
100
+ [dir_re('sitearchdir'), "$(RUBYARCHDIR)"],
101
+ [dir_re('vendorarchdir'), "$(RUBYARCHDIR)"],
102
+ [dir_re('rubyhdrdir'), "$(RUBYHDRDIR)"],
103
+ [dir_re('sitehdrdir'), "$(SITEHDRDIR)"],
104
+ [dir_re('vendorhdrdir'), "$(VENDORHDRDIR)"],
105
+ [dir_re('bindir'), "$(BINDIR)"],
106
+ ]
107
+
108
+ def install_dirs(target_prefix = nil)
109
+ if $extout
110
+ dirs = [
111
+ ['BINDIR', '$(extout)/bin'],
112
+ ['RUBYCOMMONDIR', '$(extout)/common'],
113
+ ['RUBYLIBDIR', '$(RUBYCOMMONDIR)$(target_prefix)'],
114
+ ['RUBYARCHDIR', '$(extout)/$(arch)$(target_prefix)'],
115
+ ['HDRDIR', '$(extout)/include/ruby$(target_prefix)'],
116
+ ['ARCHHDRDIR', '$(extout)/include/$(arch)/ruby$(target_prefix)'],
117
+ ['extout', "#$extout"],
118
+ ['extout_prefix', "#$extout_prefix"],
119
+ ]
120
+ elsif $extmk
121
+ dirs = [
122
+ ['BINDIR', '$(bindir)'],
123
+ ['RUBYCOMMONDIR', '$(rubylibdir)'],
124
+ ['RUBYLIBDIR', '$(rubylibdir)$(target_prefix)'],
125
+ ['RUBYARCHDIR', '$(archdir)$(target_prefix)'],
126
+ ['HDRDIR', '$(rubyhdrdir)/ruby$(target_prefix)'],
127
+ ['ARCHHDRDIR', '$(rubyhdrdir)/$(arch)/ruby$(target_prefix)'],
128
+ ]
129
+ elsif $configure_args.has_key?('--vendor')
130
+ dirs = [
131
+ ['BINDIR', '$(bindir)'],
132
+ ['RUBYCOMMONDIR', '$(vendordir)$(target_prefix)'],
133
+ ['RUBYLIBDIR', '$(vendorlibdir)$(target_prefix)'],
134
+ ['RUBYARCHDIR', '$(vendorarchdir)$(target_prefix)'],
135
+ ['HDRDIR', '$(rubyhdrdir)/ruby$(target_prefix)'],
136
+ ['ARCHHDRDIR', '$(rubyhdrdir)/$(arch)/ruby$(target_prefix)'],
137
+ ]
138
+ else
139
+ dirs = [
140
+ ['BINDIR', '$(bindir)'],
141
+ ['RUBYCOMMONDIR', '$(sitedir)$(target_prefix)'],
142
+ ['RUBYLIBDIR', '$(sitelibdir)$(target_prefix)'],
143
+ ['RUBYARCHDIR', '$(sitearchdir)$(target_prefix)'],
144
+ ['HDRDIR', '$(rubyhdrdir)/ruby$(target_prefix)'],
145
+ ['ARCHHDRDIR', '$(rubyhdrdir)/$(arch)/ruby$(target_prefix)'],
146
+ ]
147
+ end
148
+ dirs << ['target_prefix', (target_prefix ? "/#{target_prefix}" : "")]
149
+ dirs
150
+ end
151
+
152
+ def map_dir(dir, map = nil)
153
+ map ||= INSTALL_DIRS
154
+ map.inject(dir) {|d, (orig, new)| d.gsub(orig, new)}
155
+ end
156
+
157
+ topdir = File.dirname(File.dirname(__FILE__))
158
+ path = File.expand_path($0)
159
+ $extmk = path[0, topdir.size+1] == topdir+"/"
160
+ $extmk &&= %r"\A(?:ext|enc|tool|test(?:/.+)?)\z" =~ File.dirname(path[topdir.size+1..-1])
161
+ $extmk &&= true
162
+ if not $extmk and File.exist?(($hdrdir = RbConfig::CONFIG["rubyhdrdir"]) + "/ruby/ruby.h")
163
+ $topdir = $hdrdir
164
+ $top_srcdir = $hdrdir
165
+ $arch_hdrdir = $hdrdir + "/$(arch)"
166
+ elsif File.exist?(($hdrdir = ($top_srcdir ||= topdir) + "/include") + "/ruby.h")
167
+ $topdir ||= RbConfig::CONFIG["topdir"]
168
+ $arch_hdrdir = "$(extout)/include/$(arch)"
169
+ else
170
+ abort "mkmf.rb can't find header files for ruby at #{$hdrdir}/ruby.h"
171
+ end
172
+
173
+ OUTFLAG = CONFIG['OUTFLAG']
174
+ COUTFLAG = CONFIG['COUTFLAG']
175
+ CPPOUTFILE = CONFIG['CPPOUTFILE']
176
+
177
+ CONFTEST_C = "conftest.c".freeze
178
+
179
+ class String
180
+ # Wraps a string in escaped quotes if it contains whitespace.
181
+ def quote
182
+ /\s/ =~ self ? "\"#{self}\"" : "#{self}"
183
+ end
184
+
185
+ # Generates a string used as cpp macro name.
186
+ def tr_cpp
187
+ strip.upcase.tr_s("^A-Z0-9_*", "_").tr_s("*", "P")
188
+ end
189
+ end
190
+ class Array
191
+ # Wraps all strings in escaped quotes if they contain whitespace.
192
+ def quote
193
+ map {|s| s.quote}
194
+ end
195
+ end
196
+
197
+ def rm_f(*files)
198
+ opt = (Hash === files.last ? [files.pop] : [])
199
+ FileUtils.rm_f(Dir[*files.flatten], *opt)
200
+ end
201
+
202
+ def rm_rf(*files)
203
+ opt = (Hash === files.last ? [files.pop] : [])
204
+ FileUtils.rm_rf(Dir[*files.flatten], *opt)
205
+ end
206
+
207
+ # Returns time stamp of the +target+ file if it exists and is newer
208
+ # than or equal to all of +times+.
209
+ def modified?(target, times)
210
+ (t = File.mtime(target)) rescue return nil
211
+ Array === times or times = [times]
212
+ t if times.all? {|n| n <= t}
213
+ end
214
+
215
+ def merge_libs(*libs)
216
+ libs.inject([]) do |x, y|
217
+ xy = x & y
218
+ xn = yn = 0
219
+ y = y.inject([]) {|ary, e| ary.last == e ? ary : ary << e}
220
+ y.each_with_index do |v, yi|
221
+ if xy.include?(v)
222
+ xi = [x.index(v), xn].max()
223
+ x[xi, 1] = y[yn..yi]
224
+ xn, yn = xi + (yi - yn + 1), yi + 1
225
+ end
226
+ end
227
+ x.concat(y[yn..-1] || [])
228
+ end
229
+ end
230
+
231
+ # This is a custom logging module. It generates an mkmf.log file when you
232
+ # run your extconf.rb script. This can be useful for debugging unexpected
233
+ # failures.
234
+ #
235
+ # This module and its associated methods are meant for internal use only.
236
+ #
237
+ module Logging
238
+ @log = nil
239
+ @logfile = 'mkmf.log'
240
+ @orgerr = $stderr.dup
241
+ @orgout = $stdout.dup
242
+ @postpone = 0
243
+ @quiet = $extmk
244
+
245
+ def self::log_open
246
+ @log ||= File::open(@logfile, 'wb')
247
+ @log.sync = true
248
+ end
249
+
250
+ def self::open
251
+ log_open
252
+ $stderr.reopen(@log)
253
+ $stdout.reopen(@log)
254
+ yield
255
+ ensure
256
+ $stderr.reopen(@orgerr)
257
+ $stdout.reopen(@orgout)
258
+ end
259
+
260
+ def self::message(*s)
261
+ log_open
262
+ @log.printf(*s)
263
+ end
264
+
265
+ def self::logfile file
266
+ @logfile = file
267
+ log_close
268
+ end
269
+
270
+ def self::log_close
271
+ if @log and not @log.closed?
272
+ @log.flush
273
+ @log.close
274
+ @log = nil
275
+ end
276
+ end
277
+
278
+ def self::postpone
279
+ tmplog = "mkmftmp#{@postpone += 1}.log"
280
+ open do
281
+ log, *save = @log, @logfile, @orgout, @orgerr
282
+ @log, @logfile, @orgout, @orgerr = nil, tmplog, log, log
283
+ begin
284
+ log.print(open {yield @log})
285
+ ensure
286
+ @log.close if @log and not @log.closed?
287
+ File::open(tmplog) {|t| FileUtils.copy_stream(t, log)} if File.exist?(tmplog)
288
+ @log, @logfile, @orgout, @orgerr = log, *save
289
+ @postpone -= 1
290
+ rm_f tmplog
291
+ end
292
+ end
293
+ end
294
+
295
+ class << self
296
+ attr_accessor :quiet
297
+ end
298
+ end
299
+
300
+ def xsystem command, opts = nil
301
+ varpat = /\$\((\w+)\)|\$\{(\w+)\}/
302
+ if varpat =~ command
303
+ vars = Hash.new {|h, k| h[k] = ''; ENV[k]}
304
+ command = command.dup
305
+ nil while command.gsub!(varpat) {vars[$1||$2]}
306
+ end
307
+ Logging::open do
308
+ puts command.quote
309
+ if opts and opts[:werror]
310
+ result = nil
311
+ Logging.postpone do |log|
312
+ result = (system(command) and File.zero?(log.path))
313
+ ""
314
+ end
315
+ result
316
+ else
317
+ system(command)
318
+ end
319
+ end
320
+ end
321
+
322
+ def xpopen command, *mode, &block
323
+ Logging::open do
324
+ case mode[0]
325
+ when nil, /^r/
326
+ puts "#{command} |"
327
+ else
328
+ puts "| #{command}"
329
+ end
330
+ IO.popen(command, *mode, &block)
331
+ end
332
+ end
333
+
334
+ def log_src(src, heading="checked program was")
335
+ src = src.split(/^/)
336
+ fmt = "%#{src.size.to_s.size}d: %s"
337
+ Logging::message <<"EOM"
338
+ #{heading}:
339
+ /* begin */
340
+ EOM
341
+ src.each_with_index {|line, no| Logging::message fmt, no+1, line}
342
+ Logging::message <<"EOM"
343
+ /* end */
344
+
345
+ EOM
346
+ end
347
+
348
+ def create_tmpsrc(src)
349
+ src = "#{COMMON_HEADERS}\n#{src}"
350
+ src = yield(src) if block_given?
351
+ src.gsub!(/[ \t]+$/, '')
352
+ src.gsub!(/\A\n+|^\n+$/, '')
353
+ src.sub!(/[^\n]\z/, "\\&\n")
354
+ count = 0
355
+ begin
356
+ open(CONFTEST_C, "wb") do |cfile|
357
+ cfile.print src
358
+ end
359
+ rescue Errno::EACCES
360
+ if (count += 1) < 5
361
+ sleep 0.2
362
+ retry
363
+ end
364
+ end
365
+ src
366
+ end
367
+
368
+ def have_devel?
369
+ unless defined? $have_devel
370
+ $have_devel = true
371
+ $have_devel = try_link(MAIN_DOES_NOTHING)
372
+ end
373
+ $have_devel
374
+ end
375
+
376
+ def try_do(src, command, *opts, &b)
377
+ unless have_devel?
378
+ raise <<MSG
379
+ The compiler failed to generate an executable file.
380
+ You have to install development tools first.
381
+ MSG
382
+ end
383
+ begin
384
+ src = create_tmpsrc(src, &b)
385
+ xsystem(command, *opts)
386
+ ensure
387
+ log_src(src)
388
+ rm_rf 'conftest.dSYM'
389
+ end
390
+ end
391
+
392
+ def link_command(ldflags, opt="", libpath=$DEFLIBPATH|$LIBPATH)
393
+ librubyarg = $extmk ? $LIBRUBYARG_STATIC : "$(LIBRUBYARG)"
394
+ conf = RbConfig::CONFIG.merge('hdrdir' => $hdrdir.quote,
395
+ 'src' => "#{CONFTEST_C}",
396
+ 'arch_hdrdir' => $arch_hdrdir.quote,
397
+ 'top_srcdir' => $top_srcdir.quote,
398
+ 'INCFLAGS' => "#$INCFLAGS",
399
+ 'CPPFLAGS' => "#$CPPFLAGS",
400
+ 'CFLAGS' => "#$CFLAGS",
401
+ 'ARCH_FLAG' => "#$ARCH_FLAG",
402
+ 'LDFLAGS' => "#$LDFLAGS #{ldflags}",
403
+ 'LOCAL_LIBS' => "#$LOCAL_LIBS #$libs",
404
+ 'LIBS' => "#{librubyarg} #{opt} #$LIBS")
405
+ conf['LIBPATH'] = libpathflag(libpath.map {|s| RbConfig::expand(s.dup, conf)})
406
+ RbConfig::expand(TRY_LINK.dup, conf)
407
+ end
408
+
409
+ def cc_command(opt="")
410
+ conf = RbConfig::CONFIG.merge('hdrdir' => $hdrdir.quote, 'srcdir' => $srcdir.quote,
411
+ 'arch_hdrdir' => $arch_hdrdir.quote,
412
+ 'top_srcdir' => $top_srcdir.quote)
413
+ RbConfig::expand("$(CC) #$INCFLAGS #$CPPFLAGS #$CFLAGS #$ARCH_FLAG #{opt} -c #{CONFTEST_C}",
414
+ conf)
415
+ end
416
+
417
+ def cpp_command(outfile, opt="")
418
+ conf = RbConfig::CONFIG.merge('hdrdir' => $hdrdir.quote, 'srcdir' => $srcdir.quote,
419
+ 'arch_hdrdir' => $arch_hdrdir.quote,
420
+ 'top_srcdir' => $top_srcdir.quote)
421
+ RbConfig::expand("$(CPP) #$INCFLAGS #$CPPFLAGS #$CFLAGS #{opt} #{CONFTEST_C} #{outfile}",
422
+ conf)
423
+ end
424
+
425
+ def libpathflag(libpath=$DEFLIBPATH|$LIBPATH)
426
+ libpath.map{|x|
427
+ case x
428
+ when "$(topdir)", /\A\./
429
+ LIBPATHFLAG
430
+ else
431
+ LIBPATHFLAG+RPATHFLAG
432
+ end % x.quote
433
+ }.join
434
+ end
435
+
436
+ def with_werror(opt, opts = nil)
437
+ if opts
438
+ if opts[:werror] and config_string("WERRORFLAG") {|flag| opt = opt ? "#{opt} #{flag}" : flag}
439
+ (opts = opts.dup).delete(:werror)
440
+ end
441
+ yield(opt, opts)
442
+ else
443
+ yield(opt)
444
+ end
445
+ end
446
+
447
+ # :nodoc:
448
+ def try_link0(src, opt="", *opts, &b)
449
+ cmd = link_command("", opt)
450
+ if $universal
451
+ require 'tmpdir'
452
+ Dir.mktmpdir("mkmf_", oldtmpdir = ENV["TMPDIR"]) do |tmpdir|
453
+ begin
454
+ ENV["TMPDIR"] = tmpdir
455
+ try_do(src, cmd, *opts, &b)
456
+ ensure
457
+ ENV["TMPDIR"] = oldtmpdir
458
+ end
459
+ end
460
+ else
461
+ try_do(src, cmd, *opts, &b)
462
+ end
463
+ end
464
+
465
+ # Returns whether or not the +src+ can be compiled as a C source and
466
+ # linked with its depending libraries successfully.
467
+ # +opt+ is passed to the linker as options. Note that +$CFLAGS+ and +$LDFLAGS+
468
+ # are also passed to the linker.
469
+ #
470
+ # If a block given, it is called with the source before compilation. You can
471
+ # modify the source in the block.
472
+ #
473
+ # [+src+] a String which contains a C source
474
+ # [+opt+] a String which contains linker options
475
+ def try_link(src, opt="", *opts, &b)
476
+ try_link0(src, opt, *opts, &b)
477
+ ensure
478
+ rm_f "conftest*", "c0x32*"
479
+ end
480
+
481
+ # Returns whether or not the +src+ can be compiled as a C source.
482
+ # +opt+ is passed to the C compiler as options. Note that +$CFLAGS+ is
483
+ # also passed to the compiler.
484
+ #
485
+ # If a block given, it is called with the source before compilation. You can
486
+ # modify the source in the block.
487
+ #
488
+ # [+src+] a String which contains a C source
489
+ # [+opt+] a String which contains compiler options
490
+ def try_compile(src, opt="", *opts, &b)
491
+ with_werror(opt, *opts) {|_opt, *_opts| try_do(src, cc_command(_opt), *_opts, &b)}
492
+ ensure
493
+ rm_f "conftest*"
494
+ end
495
+
496
+ # Returns whether or not the +src+ can be preprocessed with the C preprocessor.
497
+ # +opt+ is passed to the preprocessor as options. Note that +$CFLAGS+ is
498
+ # also passed to the preprocessor.
499
+ #
500
+ # If a block given, it is called with the source before preprocessing. You can
501
+ # modify the source in the block.
502
+ #
503
+ # [+src+] a String which contains a C source
504
+ # [+opt+] a String which contains preprocessor options
505
+ def try_cpp(src, opt="", *opts, &b)
506
+ try_do(src, cpp_command(CPPOUTFILE, opt), *opts, &b)
507
+ ensure
508
+ rm_f "conftest*"
509
+ end
510
+
511
+ class Object
512
+ alias_method :try_header, (config_string('try_header') || :try_cpp)
513
+ end
514
+
515
+ def cpp_include(header)
516
+ if header
517
+ header = [header] unless header.kind_of? Array
518
+ header.map {|h| String === h ? "#include <#{h}>\n" : h}.join
519
+ else
520
+ ""
521
+ end
522
+ end
523
+
524
+ def with_cppflags(flags)
525
+ cppflags = $CPPFLAGS
526
+ $CPPFLAGS = flags
527
+ ret = yield
528
+ ensure
529
+ $CPPFLAGS = cppflags unless ret
530
+ end
531
+
532
+ def with_cflags(flags)
533
+ cflags = $CFLAGS
534
+ $CFLAGS = flags
535
+ ret = yield
536
+ ensure
537
+ $CFLAGS = cflags unless ret
538
+ end
539
+
540
+ def with_ldflags(flags)
541
+ ldflags = $LDFLAGS
542
+ $LDFLAGS = flags
543
+ ret = yield
544
+ ensure
545
+ $LDFLAGS = ldflags unless ret
546
+ end
547
+
548
+ def try_static_assert(expr, headers = nil, opt = "", &b)
549
+ headers = cpp_include(headers)
550
+ try_compile(<<SRC, opt, &b)
551
+ #{headers}
552
+ /*top*/
553
+ int conftest_const[(#{expr}) ? 1 : -1];
554
+ SRC
555
+ end
556
+
557
+ def try_constant(const, headers = nil, opt = "", &b)
558
+ includes = cpp_include(headers)
559
+ if CROSS_COMPILING
560
+ if try_static_assert("#{const} > 0", headers, opt)
561
+ # positive constant
562
+ elsif try_static_assert("#{const} < 0", headers, opt)
563
+ neg = true
564
+ const = "-(#{const})"
565
+ elsif try_static_assert("#{const} == 0", headers, opt)
566
+ return 0
567
+ else
568
+ # not a constant
569
+ return nil
570
+ end
571
+ upper = 1
572
+ lower = 0
573
+ until try_static_assert("#{const} <= #{upper}", headers, opt)
574
+ lower = upper
575
+ upper <<= 1
576
+ end
577
+ return nil unless lower
578
+ while upper > lower + 1
579
+ mid = (upper + lower) / 2
580
+ if try_static_assert("#{const} > #{mid}", headers, opt)
581
+ lower = mid
582
+ else
583
+ upper = mid
584
+ end
585
+ end
586
+ upper = -upper if neg
587
+ return upper
588
+ else
589
+ src = %{#{includes}
590
+ #include <stdio.h>
591
+ /*top*/
592
+ int conftest_const = (int)(#{const});
593
+ int main() {printf("%d\\n", conftest_const); return 0;}
594
+ }
595
+ if try_link0(src, opt, &b)
596
+ xpopen("./conftest") do |f|
597
+ return Integer(f.gets)
598
+ end
599
+ end
600
+ end
601
+ nil
602
+ end
603
+
604
+ # You should use +have_func+ rather than +try_func+.
605
+ #
606
+ # [+func+] a String which contains a symbol name
607
+ # [+libs+] a String which contains library names.
608
+ # [+headers+] a String or an Array of strings which contains
609
+ # names of header files.
610
+ def try_func(func, libs, headers = nil, &b)
611
+ headers = cpp_include(headers)
612
+ case func
613
+ when /^&/
614
+ decltype = proc {|x|"const volatile void *#{x}"}
615
+ else
616
+ call = true
617
+ decltype = proc {|x| "void ((*#{x})())"}
618
+ end
619
+ try_link(<<"SRC", libs, &b) or
620
+ #{headers}
621
+ /*top*/
622
+ #{MAIN_DOES_NOTHING}
623
+ int t() { #{decltype["volatile p"]}; p = (#{decltype[]})#{func}; return 0; }
624
+ SRC
625
+ call && try_link(<<"SRC", libs, &b)
626
+ #{headers}
627
+ /*top*/
628
+ #{MAIN_DOES_NOTHING}
629
+ int t() { #{func}(); return 0; }
630
+ SRC
631
+ end
632
+
633
+ # You should use +have_var+ rather than +try_var+.
634
+ def try_var(var, headers = nil, &b)
635
+ headers = cpp_include(headers)
636
+ try_compile(<<"SRC", &b)
637
+ #{headers}
638
+ /*top*/
639
+ #{MAIN_DOES_NOTHING}
640
+ int t() { const volatile void *volatile p; p = &(&#{var})[0]; return 0; }
641
+ SRC
642
+ end
643
+
644
+ # Returns whether or not the +src+ can be preprocessed with the C preprocessor and
645
+ # matches with +pat+.
646
+ #
647
+ # If a block given, it is called with the source before compilation. You can
648
+ # modify the source in the block.
649
+ #
650
+ # [+pat+] a Regexp or a String
651
+ # [+src+] a String which contains a C source
652
+ # [+opt+] a String which contains preprocessor options
653
+ #
654
+ # Note:
655
+ # When pat is a Regexp the matching will be checked in process,
656
+ # otherwise egrep(1) will be invoked to check it.
657
+ def egrep_cpp(pat, src, opt = "", &b)
658
+ src = create_tmpsrc(src, &b)
659
+ xpopen(cpp_command('', opt)) do |f|
660
+ if Regexp === pat
661
+ puts(" ruby -ne 'print if #{pat.inspect}'")
662
+ f.grep(pat) {|l|
663
+ puts "#{f.lineno}: #{l}"
664
+ return true
665
+ }
666
+ false
667
+ else
668
+ puts(" egrep '#{pat}'")
669
+ begin
670
+ stdin = $stdin.dup
671
+ $stdin.reopen(f)
672
+ system("egrep", pat)
673
+ ensure
674
+ $stdin.reopen(stdin)
675
+ end
676
+ end
677
+ end
678
+ ensure
679
+ rm_f "conftest*"
680
+ log_src(src)
681
+ end
682
+
683
+ # This is used internally by the have_macro? method.
684
+ def macro_defined?(macro, src, opt = "", &b)
685
+ src = src.sub(/[^\n]\z/, "\\&\n")
686
+ try_compile(src + <<"SRC", opt, &b)
687
+ /*top*/
688
+ #ifndef #{macro}
689
+ # error
690
+ >>>>>> #{macro} undefined <<<<<<
691
+ #endif
692
+ SRC
693
+ end
694
+
695
+ # Returns whether or not
696
+ # * the +src+ can be compiled as a C source,
697
+ # * the result object can be linked with its depending libraries successfully,
698
+ # * the linked file can be invoked as an executable
699
+ # * and the executable exits successfully
700
+ # +opt+ is passed to the linker as options. Note that +$CFLAGS+ and +$LDFLAGS+
701
+ # are also passed to the linker.
702
+ #
703
+ # If a block given, it is called with the source before compilation. You can
704
+ # modify the source in the block.
705
+ #
706
+ # [+src+] a String which contains a C source
707
+ # [+opt+] a String which contains linker options
708
+ #
709
+ # @return true when the executable exits successfully, false when it fails, or
710
+ # nil when preprocessing, compilation or link fails.
711
+ def try_run(src, opt = "", &b)
712
+ if try_link0(src, opt, &b)
713
+ xsystem("./conftest")
714
+ else
715
+ nil
716
+ end
717
+ ensure
718
+ rm_f "conftest*"
719
+ end
720
+
721
+ def install_files(mfile, ifiles, map = nil, srcprefix = nil)
722
+ ifiles or return
723
+ ifiles.empty? and return
724
+ srcprefix ||= "$(srcdir)/#{srcprefix}".chomp('/')
725
+ RbConfig::expand(srcdir = srcprefix.dup)
726
+ dirs = []
727
+ path = Hash.new {|h, i| h[i] = dirs.push([i])[-1]}
728
+ ifiles.each do |files, dir, prefix|
729
+ dir = map_dir(dir, map)
730
+ prefix &&= %r|\A#{Regexp.quote(prefix)}/?|
731
+ if /\A\.\// =~ files
732
+ # install files which are in current working directory.
733
+ files = files[2..-1]
734
+ len = nil
735
+ else
736
+ # install files which are under the $(srcdir).
737
+ files = File.join(srcdir, files)
738
+ len = srcdir.size
739
+ end
740
+ f = nil
741
+ Dir.glob(files) do |fx|
742
+ f = fx
743
+ f[0..len] = "" if len
744
+ case File.basename(f)
745
+ when *$NONINSTALLFILES
746
+ next
747
+ end
748
+ d = File.dirname(f)
749
+ d.sub!(prefix, "") if prefix
750
+ d = (d.empty? || d == ".") ? dir : File.join(dir, d)
751
+ f = File.join(srcprefix, f) if len
752
+ path[d] << f
753
+ end
754
+ unless len or f
755
+ d = File.dirname(files)
756
+ d.sub!(prefix, "") if prefix
757
+ d = (d.empty? || d == ".") ? dir : File.join(dir, d)
758
+ path[d] << files
759
+ end
760
+ end
761
+ dirs
762
+ end
763
+
764
+ def install_rb(mfile, dest, srcdir = nil)
765
+ install_files(mfile, [["lib/**/*.rb", dest, "lib"]], nil, srcdir)
766
+ end
767
+
768
+ def append_library(libs, lib) # :no-doc:
769
+ format(LIBARG, lib) + " " + libs
770
+ end
771
+
772
+ def message(*s)
773
+ unless Logging.quiet and not $VERBOSE
774
+ printf(*s)
775
+ $stdout.flush
776
+ end
777
+ end
778
+
779
+ # This emits a string to stdout that allows users to see the results of the
780
+ # various have* and find* methods as they are tested.
781
+ #
782
+ # Internal use only.
783
+ #
784
+ def checking_for(m, fmt = nil)
785
+ f = caller[0][/in `([^<].*)'$/, 1] and f << ": " #` for vim #'
786
+ m = "checking #{/\Acheck/ =~ f ? '' : 'for '}#{m}... "
787
+ message "%s", m
788
+ a = r = nil
789
+ Logging::postpone do
790
+ r = yield
791
+ a = (fmt ? fmt % r : r ? "yes" : "no") << "\n"
792
+ "#{f}#{m}-------------------- #{a}\n"
793
+ end
794
+ message(a)
795
+ Logging::message "--------------------\n\n"
796
+ r
797
+ end
798
+
799
+ def checking_message(target, place = nil, opt = nil)
800
+ [["in", place], ["with", opt]].inject("#{target}") do |msg, (pre, noun)|
801
+ if noun
802
+ [[:to_str], [:join, ","], [:to_s]].each do |meth, *args|
803
+ if noun.respond_to?(meth)
804
+ break noun = noun.send(meth, *args)
805
+ end
806
+ end
807
+ msg << " #{pre} #{noun}" unless noun.empty?
808
+ end
809
+ msg
810
+ end
811
+ end
812
+
813
+ # :startdoc:
814
+
815
+ # Returns whether or not +macro+ is defined either in the common header
816
+ # files or within any +headers+ you provide.
817
+ #
818
+ # Any options you pass to +opt+ are passed along to the compiler.
819
+ #
820
+ def have_macro(macro, headers = nil, opt = "", &b)
821
+ checking_for checking_message(macro, headers, opt) do
822
+ macro_defined?(macro, cpp_include(headers), opt, &b)
823
+ end
824
+ end
825
+
826
+ # Returns whether or not the given entry point +func+ can be found within
827
+ # +lib+. If +func+ is nil, the 'main()' entry point is used by default.
828
+ # If found, it adds the library to list of libraries to be used when linking
829
+ # your extension.
830
+ #
831
+ # If +headers+ are provided, it will include those header files as the
832
+ # header files it looks in when searching for +func+.
833
+ #
834
+ # The real name of the library to be linked can be altered by
835
+ # '--with-FOOlib' configuration option.
836
+ #
837
+ def have_library(lib, func = nil, headers = nil, &b)
838
+ func = "main" if !func or func.empty?
839
+ lib = with_config(lib+'lib', lib)
840
+ checking_for checking_message("#{func}()", LIBARG%lib) do
841
+ if COMMON_LIBS.include?(lib)
842
+ true
843
+ else
844
+ libs = append_library($libs, lib)
845
+ if try_func(func, libs, headers, &b)
846
+ $libs = libs
847
+ true
848
+ else
849
+ false
850
+ end
851
+ end
852
+ end
853
+ end
854
+
855
+ # Returns whether or not the entry point +func+ can be found within the library
856
+ # +lib+ in one of the +paths+ specified, where +paths+ is an array of strings.
857
+ # If +func+ is nil , then the main() function is used as the entry point.
858
+ #
859
+ # If +lib+ is found, then the path it was found on is added to the list of
860
+ # library paths searched and linked against.
861
+ #
862
+ def find_library(lib, func, *paths, &b)
863
+ func = "main" if !func or func.empty?
864
+ lib = with_config(lib+'lib', lib)
865
+ paths = paths.collect {|path| path.split(File::PATH_SEPARATOR)}.flatten
866
+ checking_for "#{func}() in #{LIBARG%lib}" do
867
+ libpath = $LIBPATH
868
+ libs = append_library($libs, lib)
869
+ begin
870
+ until r = try_func(func, libs, &b) or paths.empty?
871
+ $LIBPATH = libpath | [paths.shift]
872
+ end
873
+ if r
874
+ $libs = libs
875
+ libpath = nil
876
+ end
877
+ ensure
878
+ $LIBPATH = libpath if libpath
879
+ end
880
+ r
881
+ end
882
+ end
883
+
884
+ # Returns whether or not the function +func+ can be found in the common
885
+ # header files, or within any +headers+ that you provide. If found, a
886
+ # macro is passed as a preprocessor constant to the compiler using the
887
+ # function name, in uppercase, prepended with 'HAVE_'.
888
+ #
889
+ # For example, if have_func('foo') returned true, then the HAVE_FOO
890
+ # preprocessor macro would be passed to the compiler.
891
+ #
892
+ def have_func(func, headers = nil, &b)
893
+ checking_for checking_message("#{func}()", headers) do
894
+ if try_func(func, $libs, headers, &b)
895
+ $defs.push(format("-DHAVE_%s", func.tr_cpp))
896
+ true
897
+ else
898
+ false
899
+ end
900
+ end
901
+ end
902
+
903
+ # Returns whether or not the variable +var+ can be found in the common
904
+ # header files, or within any +headers+ that you provide. If found, a
905
+ # macro is passed as a preprocessor constant to the compiler using the
906
+ # variable name, in uppercase, prepended with 'HAVE_'.
907
+ #
908
+ # For example, if have_var('foo') returned true, then the HAVE_FOO
909
+ # preprocessor macro would be passed to the compiler.
910
+ #
911
+ def have_var(var, headers = nil, &b)
912
+ checking_for checking_message(var, headers) do
913
+ if try_var(var, headers, &b)
914
+ $defs.push(format("-DHAVE_%s", var.tr_cpp))
915
+ true
916
+ else
917
+ false
918
+ end
919
+ end
920
+ end
921
+
922
+ # Returns whether or not the given +header+ file can be found on your system.
923
+ # If found, a macro is passed as a preprocessor constant to the compiler using
924
+ # the header file name, in uppercase, prepended with 'HAVE_'.
925
+ #
926
+ # For example, if have_header('foo.h') returned true, then the HAVE_FOO_H
927
+ # preprocessor macro would be passed to the compiler.
928
+ #
929
+ def have_header(header, preheaders = nil, &b)
930
+ checking_for header do
931
+ if try_header(cpp_include(preheaders)+cpp_include(header), &b)
932
+ $defs.push(format("-DHAVE_%s", header.tr_cpp))
933
+ true
934
+ else
935
+ false
936
+ end
937
+ end
938
+ end
939
+
940
+ # Returns whether or not the given +framework+ can be found on your system.
941
+ # If found, a macro is passed as a preprocessor constant to the compiler using
942
+ # the framework name, in uppercase, prepended with 'HAVE_FRAMEWORK_'.
943
+ #
944
+ # For example, if have_framework('Ruby') returned true, then the HAVE_FRAMEWORK_RUBY
945
+ # preprocessor macro would be passed to the compiler.
946
+ #
947
+ def have_framework(fw, &b)
948
+ checking_for fw do
949
+ src = cpp_include("#{fw}/#{fw}.h") << "\n" "int main(void){return 0;}"
950
+ if try_link(src, opt = "-framework #{fw}", &b)
951
+ $defs.push(format("-DHAVE_FRAMEWORK_%s", fw.tr_cpp))
952
+ $LDFLAGS << " " << opt
953
+ true
954
+ else
955
+ false
956
+ end
957
+ end
958
+ end
959
+
960
+ # Instructs mkmf to search for the given +header+ in any of the +paths+
961
+ # provided, and returns whether or not it was found in those paths.
962
+ #
963
+ # If the header is found then the path it was found on is added to the list
964
+ # of included directories that are sent to the compiler (via the -I switch).
965
+ #
966
+ def find_header(header, *paths)
967
+ message = checking_message(header, paths)
968
+ header = cpp_include(header)
969
+ checking_for message do
970
+ if try_header(header)
971
+ true
972
+ else
973
+ found = false
974
+ paths.each do |dir|
975
+ opt = "-I#{dir}".quote
976
+ if try_header(header, opt)
977
+ $INCFLAGS << " " << opt
978
+ found = true
979
+ break
980
+ end
981
+ end
982
+ found
983
+ end
984
+ end
985
+ end
986
+
987
+ # Returns whether or not the struct of type +type+ contains +member+. If
988
+ # it does not, or the struct type can't be found, then false is returned. You
989
+ # may optionally specify additional +headers+ in which to look for the struct
990
+ # (in addition to the common header files).
991
+ #
992
+ # If found, a macro is passed as a preprocessor constant to the compiler using
993
+ # the type name and the member name, in uppercase, prepended with 'HAVE_'.
994
+ #
995
+ # For example, if have_struct_member('struct foo', 'bar') returned true, then the
996
+ # HAVE_STRUCT_FOO_BAR preprocessor macro would be passed to the compiler.
997
+ #
998
+ # HAVE_ST_BAR is also defined for backward compatibility.
999
+ #
1000
+ def have_struct_member(type, member, headers = nil, &b)
1001
+ checking_for checking_message("#{type}.#{member}", headers) do
1002
+ if try_compile(<<"SRC", &b)
1003
+ #{cpp_include(headers)}
1004
+ /*top*/
1005
+ #{MAIN_DOES_NOTHING}
1006
+ int s = (char *)&((#{type}*)0)->#{member} - (char *)0;
1007
+ SRC
1008
+ $defs.push(format("-DHAVE_%s_%s", type.tr_cpp, member.tr_cpp))
1009
+ $defs.push(format("-DHAVE_ST_%s", member.tr_cpp)) # backward compatibility
1010
+ true
1011
+ else
1012
+ false
1013
+ end
1014
+ end
1015
+ end
1016
+
1017
+ # Returns whether or not the static type +type+ is defined.
1018
+ #
1019
+ # See also +have_type+
1020
+ #
1021
+ def try_type(type, headers = nil, opt = "", &b)
1022
+ if try_compile(<<"SRC", opt, &b)
1023
+ #{cpp_include(headers)}
1024
+ /*top*/
1025
+ typedef #{type} conftest_type;
1026
+ int conftestval[sizeof(conftest_type)?1:-1];
1027
+ SRC
1028
+ $defs.push(format("-DHAVE_TYPE_%s", type.tr_cpp))
1029
+ true
1030
+ else
1031
+ false
1032
+ end
1033
+ end
1034
+
1035
+ # Returns whether or not the static type +type+ is defined. You may
1036
+ # optionally pass additional +headers+ to check against in addition to the
1037
+ # common header files.
1038
+ #
1039
+ # You may also pass additional flags to +opt+ which are then passed along to
1040
+ # the compiler.
1041
+ #
1042
+ # If found, a macro is passed as a preprocessor constant to the compiler using
1043
+ # the type name, in uppercase, prepended with 'HAVE_TYPE_'.
1044
+ #
1045
+ # For example, if have_type('foo') returned true, then the HAVE_TYPE_FOO
1046
+ # preprocessor macro would be passed to the compiler.
1047
+ #
1048
+ def have_type(type, headers = nil, opt = "", &b)
1049
+ checking_for checking_message(type, headers, opt) do
1050
+ try_type(type, headers, opt, &b)
1051
+ end
1052
+ end
1053
+
1054
+ # Returns where the static type +type+ is defined.
1055
+ #
1056
+ # You may also pass additional flags to +opt+ which are then passed along to
1057
+ # the compiler.
1058
+ #
1059
+ # See also +have_type+.
1060
+ #
1061
+ def find_type(type, opt, *headers, &b)
1062
+ opt ||= ""
1063
+ fmt = "not found"
1064
+ def fmt.%(x)
1065
+ x ? x.respond_to?(:join) ? x.join(",") : x : self
1066
+ end
1067
+ checking_for checking_message(type, nil, opt), fmt do
1068
+ headers.find do |h|
1069
+ try_type(type, h, opt, &b)
1070
+ end
1071
+ end
1072
+ end
1073
+
1074
+ # Returns whether or not the Constant +const+ is defined.
1075
+ #
1076
+ # See also +have_const+
1077
+ #
1078
+ def try_const(const, headers = nil, opt = "", &b)
1079
+ const, type = *const
1080
+ if try_compile(<<"SRC", opt, &b)
1081
+ #{cpp_include(headers)}
1082
+ /*top*/
1083
+ typedef #{type || 'int'} conftest_type;
1084
+ conftest_type conftestval = #{type ? '' : '(int)'}#{const};
1085
+ SRC
1086
+ $defs.push(format("-DHAVE_CONST_%s", const.tr_cpp))
1087
+ true
1088
+ else
1089
+ false
1090
+ end
1091
+ end
1092
+
1093
+ # Returns whether or not the constant +const+ is defined. You may
1094
+ # optionally pass the +type+ of +const+ as <code>[const, type]</code>,
1095
+ # like as:
1096
+ #
1097
+ # have_const(%w[PTHREAD_MUTEX_INITIALIZER pthread_mutex_t], "pthread.h")
1098
+ #
1099
+ # You may also pass additional +headers+ to check against in addition
1100
+ # to the common header files, and additional flags to +opt+ which are
1101
+ # then passed along to the compiler.
1102
+ #
1103
+ # If found, a macro is passed as a preprocessor constant to the compiler using
1104
+ # the type name, in uppercase, prepended with 'HAVE_CONST_'.
1105
+ #
1106
+ # For example, if have_const('foo') returned true, then the HAVE_CONST_FOO
1107
+ # preprocessor macro would be passed to the compiler.
1108
+ #
1109
+ def have_const(const, headers = nil, opt = "", &b)
1110
+ checking_for checking_message([*const].compact.join(' '), headers, opt) do
1111
+ try_const(const, headers, opt, &b)
1112
+ end
1113
+ end
1114
+
1115
+ STRING_OR_FAILED_FORMAT = "%s"
1116
+ # :stopdoc:
1117
+ def STRING_OR_FAILED_FORMAT.%(x)
1118
+ x ? super : "failed"
1119
+ end
1120
+
1121
+ def typedef_expr(type, headers)
1122
+ typename, member = type.split('.', 2)
1123
+ prelude = cpp_include(headers).split(/$/)
1124
+ prelude << "typedef #{typename} rbcv_typedef_;\n"
1125
+ return "rbcv_typedef_", member, prelude
1126
+ end
1127
+
1128
+ def try_signedness(type, member, headers = nil, opts = nil, &b)
1129
+ raise ArgumentError, "don't know how to tell signedness of members" if member
1130
+ if try_static_assert("(#{type})-1 < 0", headers, opts)
1131
+ return -1
1132
+ elsif try_static_assert("(#{type})-1 > 0", headers, opts)
1133
+ return +1
1134
+ end
1135
+ end
1136
+
1137
+ # :startdoc:
1138
+
1139
+ # Returns the size of the given +type+. You may optionally specify additional
1140
+ # +headers+ to search in for the +type+.
1141
+ #
1142
+ # If found, a macro is passed as a preprocessor constant to the compiler using
1143
+ # the type name, in uppercase, prepended with 'SIZEOF_', followed by the type
1144
+ # name, followed by '=X' where 'X' is the actual size.
1145
+ #
1146
+ # For example, if check_sizeof('mystruct') returned 12, then the
1147
+ # SIZEOF_MYSTRUCT=12 preprocessor macro would be passed to the compiler.
1148
+ #
1149
+ def check_sizeof(type, headers = nil, opts = "", &b)
1150
+ typedef, member, prelude = typedef_expr(type, headers)
1151
+ prelude << "static #{typedef} *rbcv_ptr_;\n"
1152
+ prelude = [prelude]
1153
+ expr = "sizeof((*rbcv_ptr_)#{"." << member if member})"
1154
+ fmt = STRING_OR_FAILED_FORMAT
1155
+ checking_for checking_message("size of #{type}", headers), fmt do
1156
+ if size = try_constant(expr, prelude, opts, &b)
1157
+ $defs.push(format("-DSIZEOF_%s=%s", type.tr_cpp, size))
1158
+ size
1159
+ end
1160
+ end
1161
+ end
1162
+
1163
+ # Returns the signedness of the given +type+. You may optionally
1164
+ # specify additional +headers+ to search in for the +type+.
1165
+ #
1166
+ # If the +type+ is found and is a numeric type, a macro is passed as a
1167
+ # preprocessor constant to the compiler using the +type+ name, in
1168
+ # uppercase, prepended with 'SIGNEDNESS_OF_', followed by the +type+
1169
+ # name, followed by '=X' where 'X' is positive integer if the +type+ is
1170
+ # unsigned, or negative integer if the +type+ is signed.
1171
+ #
1172
+ # For example, if size_t is defined as unsigned, then
1173
+ # check_signedness('size_t') would returned +1 and the
1174
+ # SIGNEDNESS_OF_SIZE_T=+1 preprocessor macro would be passed to the
1175
+ # compiler, and SIGNEDNESS_OF_INT=-1 if check_signedness('int') is
1176
+ # done.
1177
+ #
1178
+ def check_signedness(type, headers = nil, opts = nil, &b)
1179
+ typedef, member, prelude = typedef_expr(type, headers)
1180
+ signed = nil
1181
+ checking_for("signedness of #{type}", STRING_OR_FAILED_FORMAT) do
1182
+ signed = try_signedness(typedef, member, [prelude], opts, &b) or next nil
1183
+ $defs.push("-DSIGNEDNESS_OF_%s=%+d" % [type.tr_cpp, signed])
1184
+ signed < 0 ? "signed" : "unsigned"
1185
+ end
1186
+ signed
1187
+ end
1188
+
1189
+ # Returns the convertible integer type of the given +type+. You may
1190
+ # optionally specify additional +headers+ to search in for the +type+.
1191
+ # _Convertible_ means actually same type, or typedefed from same type.
1192
+ #
1193
+ # If the +type+ is a integer type and _convertible_ type is found,
1194
+ # following macros are passed as preprocessor constants to the
1195
+ # compiler using the +type+ name, in uppercase.
1196
+ #
1197
+ # * 'TYPEOF_', followed by the +type+ name, followed by '=X' where 'X'
1198
+ # is the found _convertible_ type name. * 'TYP2NUM' and 'NUM2TYP,
1199
+ # where 'TYP' is the +type+ name in uppercase with replacing '_t'
1200
+ # suffix with 'T', followed by '=X' where 'X' is the macro name to
1201
+ # convert +type+ to +Integer+ object, and vice versa.
1202
+ #
1203
+ # For example, if foobar_t is defined as unsigned long, then
1204
+ # convertible_int("foobar_t") would return "unsigned long", and define
1205
+ # macros:
1206
+ #
1207
+ # #define TYPEOF_FOOBAR_T unsigned long
1208
+ # #define FOOBART2NUM ULONG2NUM
1209
+ # #define NUM2FOOBART NUM2ULONG
1210
+ def convertible_int(type, headers = nil, opts = nil, &b)
1211
+ type, macname = *type
1212
+ checking_for("convertible type of #{type}", STRING_OR_FAILED_FORMAT) do
1213
+ if UNIVERSAL_INTS.include?(type)
1214
+ type
1215
+ else
1216
+ typedef, member, prelude = typedef_expr(type, headers, &b)
1217
+ next unless signed = try_signedness(typedef, member, [prelude])
1218
+ u = "unsigned " if signed > 0
1219
+ prelude << "extern rbcv_typedef_ foo();"
1220
+ compat = UNIVERSAL_INTS.find {|t|
1221
+ try_compile([prelude, "extern #{u}#{t} foo();"].join("\n"), opts, :werror=>true, &b)
1222
+ }
1223
+ if compat
1224
+ macname ||= type.sub(/_(?=t\z)/, '').tr_cpp
1225
+ conv = (compat == "long long" ? "LL" : compat.upcase)
1226
+ compat = "#{u}#{compat}"
1227
+ $defs.push(format("-DTYPEOF_%s=%s", type.tr_cpp, compat.quote))
1228
+ $defs.push(format("-DPRI_%s_PREFIX=PRI_%s_PREFIX", macname, conv))
1229
+ conv = (u ? "U" : "") + conv
1230
+ $defs.push(format("-D%s2NUM=%s2NUM", macname, conv))
1231
+ $defs.push(format("-DNUM2%s=NUM2%s", macname, conv))
1232
+ compat
1233
+ end
1234
+ end
1235
+ end
1236
+ end
1237
+ # :stopdoc:
1238
+
1239
+ # Used internally by the what_type? method to determine if +type+ is a scalar
1240
+ # pointer.
1241
+ def scalar_ptr_type?(type, member = nil, headers = nil, &b)
1242
+ try_compile(<<"SRC", &b) # pointer
1243
+ #{cpp_include(headers)}
1244
+ /*top*/
1245
+ volatile #{type} conftestval;
1246
+ #{MAIN_DOES_NOTHING}
1247
+ int t() {return (int)(1-*(conftestval#{member ? ".#{member}" : ""}));}
1248
+ SRC
1249
+ end
1250
+
1251
+ # Used internally by the what_type? method to determine if +type+ is a scalar
1252
+ # pointer.
1253
+ def scalar_type?(type, member = nil, headers = nil, &b)
1254
+ try_compile(<<"SRC", &b) # pointer
1255
+ #{cpp_include(headers)}
1256
+ /*top*/
1257
+ volatile #{type} conftestval;
1258
+ #{MAIN_DOES_NOTHING}
1259
+ int t() {return (int)(1-(conftestval#{member ? ".#{member}" : ""}));}
1260
+ SRC
1261
+ end
1262
+
1263
+ # Used internally by the what_type? method to check if _typeof_ GCC
1264
+ # extension is available.
1265
+ def have_typeof?
1266
+ return $typeof if defined?($typeof)
1267
+ $typeof = %w[__typeof__ typeof].find do |t|
1268
+ try_compile(<<SRC)
1269
+ int rbcv_foo;
1270
+ #{t}(rbcv_foo) rbcv_bar;
1271
+ SRC
1272
+ end
1273
+ end
1274
+
1275
+ def what_type?(type, member = nil, headers = nil, &b)
1276
+ m = "#{type}"
1277
+ var = val = "*rbcv_var_"
1278
+ func = "rbcv_func_(void)"
1279
+ if member
1280
+ m << "." << member
1281
+ else
1282
+ type, member = type.split('.', 2)
1283
+ end
1284
+ if member
1285
+ val = "(#{var}).#{member}"
1286
+ end
1287
+ prelude = [cpp_include(headers).split(/^/)]
1288
+ prelude << ["typedef #{type} rbcv_typedef_;\n",
1289
+ "extern rbcv_typedef_ *#{func};\n",
1290
+ "static rbcv_typedef_ #{var};\n",
1291
+ ]
1292
+ type = "rbcv_typedef_"
1293
+ fmt = member && !(typeof = have_typeof?) ? "seems %s" : "%s"
1294
+ if typeof
1295
+ var = "*rbcv_member_"
1296
+ func = "rbcv_mem_func_(void)"
1297
+ member = nil
1298
+ type = "rbcv_mem_typedef_"
1299
+ prelude[-1] << "typedef #{typeof}(#{val}) #{type};\n"
1300
+ prelude[-1] << "extern #{type} *#{func};\n"
1301
+ prelude[-1] << "static #{type} #{var};\n"
1302
+ val = var
1303
+ end
1304
+ def fmt.%(x)
1305
+ x ? super : "unknown"
1306
+ end
1307
+ checking_for checking_message(m, headers), fmt do
1308
+ if scalar_ptr_type?(type, member, prelude, &b)
1309
+ if try_static_assert("sizeof(*#{var}) == 1", prelude)
1310
+ return "string"
1311
+ end
1312
+ ptr = "*"
1313
+ elsif scalar_type?(type, member, prelude, &b)
1314
+ unless member and !typeof or try_static_assert("(#{type})-1 < 0", prelude)
1315
+ unsigned = "unsigned"
1316
+ end
1317
+ ptr = ""
1318
+ else
1319
+ next
1320
+ end
1321
+ type = UNIVERSAL_INTS.find do |t|
1322
+ pre = prelude
1323
+ unless member
1324
+ pre += [["static #{unsigned} #{t} #{ptr}#{var};\n",
1325
+ "extern #{unsigned} #{t} #{ptr}*#{func};\n"]]
1326
+ end
1327
+ try_static_assert("sizeof(#{ptr}#{val}) == sizeof(#{unsigned} #{t})", pre)
1328
+ end
1329
+ type or next
1330
+ [unsigned, type, ptr].join(" ").strip
1331
+ end
1332
+ end
1333
+
1334
+ # This method is used internally by the find_executable method.
1335
+ #
1336
+ # Internal use only.
1337
+ #
1338
+ def find_executable0(bin, path = nil)
1339
+ executable_file = proc do |name|
1340
+ begin
1341
+ stat = File.stat(name)
1342
+ rescue SystemCallError
1343
+ else
1344
+ next name if stat.file? and stat.executable?
1345
+ end
1346
+ end
1347
+
1348
+ exts = config_string('EXECUTABLE_EXTS') {|s| s.split} || config_string('EXEEXT') {|s| [s]}
1349
+ if File.expand_path(bin) == bin
1350
+ return bin if executable_file.call(bin)
1351
+ if exts
1352
+ exts.each {|ext| executable_file.call(file = bin + ext) and return file}
1353
+ end
1354
+ return nil
1355
+ end
1356
+ if path ||= ENV['PATH']
1357
+ path = path.split(File::PATH_SEPARATOR)
1358
+ else
1359
+ path = %w[/usr/local/bin /usr/ucb /usr/bin /bin]
1360
+ end
1361
+ file = nil
1362
+ path.each do |dir|
1363
+ return file if executable_file.call(file = File.join(dir, bin))
1364
+ if exts
1365
+ exts.each {|ext| executable_file.call(ext = file + ext) and return ext}
1366
+ end
1367
+ end
1368
+ nil
1369
+ end
1370
+
1371
+ # :startdoc:
1372
+
1373
+ # Searches for the executable +bin+ on +path+. The default path is your
1374
+ # PATH environment variable. If that isn't defined, it will resort to
1375
+ # searching /usr/local/bin, /usr/ucb, /usr/bin and /bin.
1376
+ #
1377
+ # If found, it will return the full path, including the executable name,
1378
+ # of where it was found.
1379
+ #
1380
+ # Note that this method does not actually affect the generated Makefile.
1381
+ #
1382
+ def find_executable(bin, path = nil)
1383
+ checking_for checking_message(bin, path) do
1384
+ find_executable0(bin, path)
1385
+ end
1386
+ end
1387
+
1388
+ # :stopdoc:
1389
+
1390
+ def arg_config(config, default=nil, &block)
1391
+ $arg_config << [config, default]
1392
+ defaults = []
1393
+ if default
1394
+ defaults << default
1395
+ elsif !block
1396
+ defaults << nil
1397
+ end
1398
+ $configure_args.fetch(config.tr('_', '-'), *defaults, &block)
1399
+ end
1400
+
1401
+ # :startdoc:
1402
+
1403
+ # Tests for the presence of a --with-<tt>config</tt> or --without-<tt>config</tt>
1404
+ # option. Returns true if the with option is given, false if the without
1405
+ # option is given, and the default value otherwise.
1406
+ #
1407
+ # This can be useful for adding custom definitions, such as debug information.
1408
+ #
1409
+ # Example:
1410
+ #
1411
+ # if with_config("debug")
1412
+ # $defs.push("-DOSSL_DEBUG") unless $defs.include? "-DOSSL_DEBUG"
1413
+ # end
1414
+ #
1415
+ def with_config(config, default=nil)
1416
+ config = config.sub(/^--with[-_]/, '')
1417
+ val = arg_config("--with-"+config) do
1418
+ if arg_config("--without-"+config)
1419
+ false
1420
+ elsif block_given?
1421
+ yield(config, default)
1422
+ else
1423
+ break default
1424
+ end
1425
+ end
1426
+ case val
1427
+ when "yes"
1428
+ true
1429
+ when "no"
1430
+ false
1431
+ else
1432
+ val
1433
+ end
1434
+ end
1435
+
1436
+ # Tests for the presence of an --enable-<tt>config</tt> or
1437
+ # --disable-<tt>config</tt> option. Returns true if the enable option is given,
1438
+ # false if the disable option is given, and the default value otherwise.
1439
+ #
1440
+ # This can be useful for adding custom definitions, such as debug information.
1441
+ #
1442
+ # Example:
1443
+ #
1444
+ # if enable_config("debug")
1445
+ # $defs.push("-DOSSL_DEBUG") unless $defs.include? "-DOSSL_DEBUG"
1446
+ # end
1447
+ #
1448
+ def enable_config(config, default=nil)
1449
+ if arg_config("--enable-"+config)
1450
+ true
1451
+ elsif arg_config("--disable-"+config)
1452
+ false
1453
+ elsif block_given?
1454
+ yield(config, default)
1455
+ else
1456
+ return default
1457
+ end
1458
+ end
1459
+
1460
+ # Generates a header file consisting of the various macro definitions generated
1461
+ # by other methods such as have_func and have_header. These are then wrapped in
1462
+ # a custom #ifndef based on the +header+ file name, which defaults to
1463
+ # 'extconf.h'.
1464
+ #
1465
+ # For example:
1466
+ #
1467
+ # # extconf.rb
1468
+ # require 'mkmf'
1469
+ # have_func('realpath')
1470
+ # have_header('sys/utime.h')
1471
+ # create_header
1472
+ # create_makefile('foo')
1473
+ #
1474
+ # The above script would generate the following extconf.h file:
1475
+ #
1476
+ # #ifndef EXTCONF_H
1477
+ # #define EXTCONF_H
1478
+ # #define HAVE_REALPATH 1
1479
+ # #define HAVE_SYS_UTIME_H 1
1480
+ # #endif
1481
+ #
1482
+ # Given that the create_header method generates a file based on definitions
1483
+ # set earlier in your extconf.rb file, you will probably want to make this
1484
+ # one of the last methods you call in your script.
1485
+ #
1486
+ def create_header(header = "extconf.h")
1487
+ message "creating %s\n", header
1488
+ sym = header.tr_cpp
1489
+ hdr = ["#ifndef #{sym}\n#define #{sym}\n"]
1490
+ for line in $defs
1491
+ case line
1492
+ when /^-D([^=]+)(?:=(.*))?/
1493
+ hdr << "#define #$1 #{$2 ? Shellwords.shellwords($2)[0].gsub(/(?=\t+)/, "\\\n") : 1}\n"
1494
+ when /^-U(.*)/
1495
+ hdr << "#undef #$1\n"
1496
+ end
1497
+ end
1498
+ hdr << "#endif\n"
1499
+ hdr = hdr.join
1500
+ log_src(hdr, "#{header} is")
1501
+ unless (IO.read(header) == hdr rescue false)
1502
+ open(header, "wb") do |hfile|
1503
+ hfile.write(hdr)
1504
+ end
1505
+ end
1506
+ $extconf_h = header
1507
+ end
1508
+
1509
+ # Sets a +target+ name that the user can then use to configure various 'with'
1510
+ # options with on the command line by using that name. For example, if the
1511
+ # target is set to "foo", then the user could use the --with-foo-dir command
1512
+ # line option.
1513
+ #
1514
+ # You may pass along additional 'include' or 'lib' defaults via the +idefault+
1515
+ # and +ldefault+ parameters, respectively.
1516
+ #
1517
+ # Note that dir_config only adds to the list of places to search for libraries
1518
+ # and include files. It does not link the libraries into your application.
1519
+ #
1520
+ def dir_config(target, idefault=nil, ldefault=nil)
1521
+ if dir = with_config(target + "-dir", (idefault unless ldefault))
1522
+ defaults = Array === dir ? dir : dir.split(File::PATH_SEPARATOR)
1523
+ idefault = ldefault = nil
1524
+ end
1525
+
1526
+ idir = with_config(target + "-include", idefault)
1527
+ $arg_config.last[1] ||= "${#{target}-dir}/include"
1528
+ ldir = with_config(target + "-lib", ldefault)
1529
+ $arg_config.last[1] ||= "${#{target}-dir}/lib"
1530
+
1531
+ idirs = idir ? Array === idir ? idir.dup : idir.split(File::PATH_SEPARATOR) : []
1532
+ if defaults
1533
+ idirs.concat(defaults.collect {|d| d + "/include"})
1534
+ idir = ([idir] + idirs).compact.join(File::PATH_SEPARATOR)
1535
+ end
1536
+ unless idirs.empty?
1537
+ idirs.collect! {|d| "-I" + d}
1538
+ idirs -= Shellwords.shellwords($CPPFLAGS)
1539
+ unless idirs.empty?
1540
+ $CPPFLAGS = (idirs.quote << $CPPFLAGS).join(" ")
1541
+ end
1542
+ end
1543
+
1544
+ ldirs = ldir ? Array === ldir ? ldir.dup : ldir.split(File::PATH_SEPARATOR) : []
1545
+ if defaults
1546
+ ldirs.concat(defaults.collect {|d| d + "/lib"})
1547
+ ldir = ([ldir] + ldirs).compact.join(File::PATH_SEPARATOR)
1548
+ end
1549
+ $LIBPATH = ldirs | $LIBPATH
1550
+
1551
+ [idir, ldir]
1552
+ end
1553
+
1554
+ # :stopdoc:
1555
+
1556
+ # Handles meta information about installed libraries. Uses your platform's
1557
+ # pkg-config program if it has one.
1558
+ def pkg_config(pkg)
1559
+ if pkgconfig = with_config("#{pkg}-config") and find_executable0(pkgconfig)
1560
+ # iff package specific config command is given
1561
+ get = proc {|opt| `#{pkgconfig} --#{opt}`.chomp}
1562
+ elsif ($PKGCONFIG ||=
1563
+ (pkgconfig = with_config("pkg-config", ("pkg-config" unless CROSS_COMPILING))) &&
1564
+ find_executable0(pkgconfig) && pkgconfig) and
1565
+ system("#{$PKGCONFIG} --exists #{pkg}")
1566
+ # default to pkg-config command
1567
+ get = proc {|opt| `#{$PKGCONFIG} --#{opt} #{pkg}`.chomp}
1568
+ elsif find_executable0(pkgconfig = "#{pkg}-config")
1569
+ # default to package specific config command, as a last resort.
1570
+ get = proc {|opt| `#{pkgconfig} --#{opt}`.chomp}
1571
+ end
1572
+ if get
1573
+ cflags = get['cflags']
1574
+ ldflags = get['libs']
1575
+ libs = get['libs-only-l']
1576
+ ldflags = (Shellwords.shellwords(ldflags) - Shellwords.shellwords(libs)).quote.join(" ")
1577
+ $CFLAGS += " " << cflags
1578
+ $LDFLAGS += " " << ldflags
1579
+ $libs += " " << libs
1580
+ Logging::message "package configuration for %s\n", pkg
1581
+ Logging::message "cflags: %s\nldflags: %s\nlibs: %s\n\n",
1582
+ cflags, ldflags, libs
1583
+ [cflags, ldflags, libs]
1584
+ else
1585
+ Logging::message "package configuration for %s is not found\n", pkg
1586
+ nil
1587
+ end
1588
+ end
1589
+
1590
+ def with_destdir(dir)
1591
+ dir = dir.sub($dest_prefix_pattern, '')
1592
+ /\A\$[\(\{]/ =~ dir ? dir : "$(DESTDIR)"+dir
1593
+ end
1594
+
1595
+ # Converts forward slashes to backslashes. Aimed at MS Windows.
1596
+ #
1597
+ # Internal use only.
1598
+ #
1599
+ def winsep(s)
1600
+ s.tr('/', '\\')
1601
+ end
1602
+
1603
+ # Converts native path to format acceptable in Makefile
1604
+ #
1605
+ # Internal use only.
1606
+ #
1607
+ if !CROSS_COMPILING
1608
+ case CONFIG['build_os']
1609
+ when 'mingw32'
1610
+ def mkintpath(path)
1611
+ # mingw uses make from msys and it needs special care
1612
+ # converts from C:\some\path to /C/some/path
1613
+ path = path.dup
1614
+ path.tr!('\\', '/')
1615
+ path.sub!(/\A([A-Za-z]):(?=\/)/, '/\1')
1616
+ path
1617
+ end
1618
+ end
1619
+ end
1620
+ unless defined?(mkintpath)
1621
+ def mkintpath(path)
1622
+ path
1623
+ end
1624
+ end
1625
+
1626
+ def configuration(srcdir)
1627
+ mk = []
1628
+ vpath = $VPATH.dup
1629
+ if !CROSS_COMPILING
1630
+ case CONFIG['build_os']
1631
+ when 'cygwin'
1632
+ if CONFIG['target_os'] != 'cygwin'
1633
+ vpath = vpath.map {|p| p.sub(/.*/, '$(shell cygpath -u \&)')}
1634
+ end
1635
+ end
1636
+ end
1637
+ CONFIG["hdrdir"] ||= $hdrdir
1638
+ mk << %{
1639
+ SHELL = /bin/sh
1640
+
1641
+ # V=0 quiet, V=1 verbose. other values don't work.
1642
+ V = 1
1643
+ Q1 = $(V:1=)
1644
+ Q = $(Q1:0=@)
1645
+ n=$(NULLCMD)
1646
+ ECHO1 = $(V:1=@$n)
1647
+ ECHO = $(ECHO1:0=@echo)
1648
+
1649
+ #### Start of system configuration section. ####
1650
+ #{"top_srcdir = " + $top_srcdir.sub(%r"\A#{Regexp.quote($topdir)}/", "$(topdir)/") if $extmk}
1651
+ srcdir = #{srcdir.gsub(/\$\((srcdir)\)|\$\{(srcdir)\}/) {mkintpath(CONFIG[$1||$2])}.quote}
1652
+ topdir = #{mkintpath($extmk ? CONFIG["topdir"] : $topdir).quote}
1653
+ hdrdir = #{mkintpath(CONFIG["hdrdir"]).quote}
1654
+ arch_hdrdir = #{$arch_hdrdir.quote}
1655
+ VPATH = #{vpath.join(CONFIG['PATH_SEPARATOR'])}
1656
+ }
1657
+ if $extmk
1658
+ mk << "RUBYLIB =\n""RUBYOPT = -\n"
1659
+ end
1660
+ if destdir = CONFIG["prefix"][$dest_prefix_pattern, 1]
1661
+ mk << "\nDESTDIR = #{destdir}\n"
1662
+ end
1663
+ CONFIG.each do |key, var|
1664
+ next unless /prefix$/ =~ key
1665
+ mk << "#{key} = #{with_destdir(var)}\n"
1666
+ end
1667
+ CONFIG.each do |key, var|
1668
+ next if /^abs_/ =~ key
1669
+ next if /^(?:src|top|hdr)dir$/ =~ key
1670
+ next unless /dir$/ =~ key
1671
+ mk << "#{key} = #{with_destdir(var)}\n"
1672
+ end
1673
+ if !$extmk and !$configure_args.has_key?('--ruby') and
1674
+ sep = config_string('BUILD_FILE_SEPARATOR')
1675
+ sep = ":/=#{sep}"
1676
+ else
1677
+ sep = ""
1678
+ end
1679
+ possible_command = (proc {|s| s if /top_srcdir/ !~ s} unless $extmk)
1680
+ extconf_h = $extconf_h ? "-DRUBY_EXTCONF_H=\\\"$(RUBY_EXTCONF_H)\\\" " : $defs.join(" ") << " "
1681
+ mk << %{
1682
+ NULLCMD = #{CONFIG['NULLCMD']}
1683
+
1684
+ CC = #{CONFIG['CC']}
1685
+ CXX = #{CONFIG['CXX']}
1686
+ LIBRUBY = #{CONFIG['LIBRUBY']}
1687
+ LIBRUBY_A = #{CONFIG['LIBRUBY_A']}
1688
+ LIBRUBYARG_SHARED = #$LIBRUBYARG_SHARED
1689
+ LIBRUBYARG_STATIC = #$LIBRUBYARG_STATIC
1690
+ OUTFLAG = #{OUTFLAG}
1691
+ COUTFLAG = #{COUTFLAG}
1692
+
1693
+ RUBY_EXTCONF_H = #{$extconf_h}
1694
+ cflags = #{CONFIG['cflags']}
1695
+ optflags = #{CONFIG['optflags']}
1696
+ debugflags = #{CONFIG['debugflags']}
1697
+ warnflags = #{$warnflags}
1698
+ CFLAGS = #{$static ? '' : CONFIG['CCDLFLAGS']} #$CFLAGS $(ARCH_FLAG)
1699
+ INCFLAGS = -I. #$INCFLAGS
1700
+ DEFS = #{CONFIG['DEFS']}
1701
+ CPPFLAGS = #{extconf_h}#{$CPPFLAGS}
1702
+ CXXFLAGS = $(CFLAGS) #{CONFIG['CXXFLAGS']}
1703
+ ldflags = #{$LDFLAGS} -L/lib/
1704
+ dldflags = #{$DLDFLAGS}
1705
+ ARCH_FLAG = #{$ARCH_FLAG}
1706
+ DLDFLAGS = $(ldflags) $(dldflags) $(ARCH_FLAG)
1707
+ LDSHARED = #{CONFIG['LDSHARED']}
1708
+ LDSHAREDXX = #{config_string('LDSHAREDXX') || '$(LDSHARED)'}
1709
+ AR = #{CONFIG['AR']}
1710
+ EXEEXT = #{CONFIG['EXEEXT']}
1711
+
1712
+ RUBY_BASE_NAME = #{CONFIG['RUBY_BASE_NAME']}
1713
+ RUBY_INSTALL_NAME = #{CONFIG['RUBY_INSTALL_NAME']}
1714
+ RUBY_SO_NAME = #{CONFIG['RUBY_SO_NAME']}
1715
+ arch = #{CONFIG['arch']}
1716
+ sitearch = #{CONFIG['sitearch']}
1717
+ ruby_version = #{RbConfig::CONFIG['ruby_version']}
1718
+ ruby = #{$ruby}
1719
+ RUBY = $(ruby#{sep})
1720
+ RM = #{config_string('RM', &possible_command) || '$(RUBY) -run -e rm -- -f'}
1721
+ RM_RF = #{'$(RUBY) -run -e rm -- -rf'}
1722
+ RMDIRS = #{config_string('RMDIRS', &possible_command) || '$(RUBY) -run -e rmdir -- -p'}
1723
+ MAKEDIRS = #{config_string('MAKEDIRS', &possible_command) || '@$(RUBY) -run -e mkdir -- -p'}
1724
+ INSTALL = #{config_string('INSTALL', &possible_command) || '@$(RUBY) -run -e install -- -vp'}
1725
+ INSTALL_PROG = #{config_string('INSTALL_PROG') || '$(INSTALL) -m 0755'}
1726
+ INSTALL_DATA = #{config_string('INSTALL_DATA') || '$(INSTALL) -m 0644'}
1727
+ COPY = #{config_string('CP', &possible_command) || '@$(RUBY) -run -e cp -- -v'}
1728
+
1729
+ #### End of system configuration section. ####
1730
+
1731
+ preload = #{defined?($preload) && $preload ? $preload.join(' ') : ''}
1732
+ }
1733
+ if $nmake == ?b
1734
+ mk.each do |x|
1735
+ x.gsub!(/^(MAKEDIRS|INSTALL_(?:PROG|DATA))+\s*=.*\n/) do
1736
+ "!ifndef " + $1 + "\n" +
1737
+ $& +
1738
+ "!endif\n"
1739
+ end
1740
+ end
1741
+ end
1742
+ mk
1743
+ end
1744
+ # :startdoc:
1745
+
1746
+ # creates a stub Makefile.
1747
+ #
1748
+ def dummy_makefile(srcdir)
1749
+ configuration(srcdir) << <<RULES << CLEANINGS
1750
+ CLEANFILES = #{$cleanfiles.join(' ')}
1751
+ DISTCLEANFILES = #{$distcleanfiles.join(' ')}
1752
+
1753
+ all install static install-so install-rb: Makefile
1754
+ .PHONY: all install static install-so install-rb
1755
+ .PHONY: clean clean-so clean-rb
1756
+
1757
+ RULES
1758
+ end
1759
+
1760
+ # Processes the data contents of the "depend" file.
1761
+ # Each line of this file is expected to be a file name.
1762
+ #
1763
+ # Returns the output of findings, in Makefile format.
1764
+ #
1765
+ def depend_rules(depend)
1766
+ suffixes = []
1767
+ depout = []
1768
+ cont = implicit = nil
1769
+ impconv = proc do
1770
+ COMPILE_RULES.each {|rule| depout << (rule % implicit[0]) << implicit[1]}
1771
+ implicit = nil
1772
+ end
1773
+ ruleconv = proc do |line|
1774
+ if implicit
1775
+ if /\A\t/ =~ line
1776
+ implicit[1] << line
1777
+ next
1778
+ else
1779
+ impconv[]
1780
+ end
1781
+ end
1782
+ if m = /\A\.(\w+)\.(\w+)(?:\s*:)/.match(line)
1783
+ suffixes << m[1] << m[2]
1784
+ implicit = [[m[1], m[2]], [m.post_match]]
1785
+ next
1786
+ elsif RULE_SUBST and /\A(?!\s*\w+\s*=)[$\w][^#]*:/ =~ line
1787
+ line.gsub!(%r"(\s)(?!\.)([^$(){}+=:\s\/\\,]+)(?=\s|\z)") {$1 + RULE_SUBST % $2}
1788
+ end
1789
+ depout << line
1790
+ end
1791
+ depend.each_line do |line|
1792
+ line.gsub!(/\.o\b/, ".#{$OBJEXT}")
1793
+ line.gsub!(/\$\((?:hdr|top)dir\)\/config.h/, $config_h)
1794
+ line.gsub!(%r"\$\(hdrdir\)/(?!ruby(?![^:;/\s]))(?=[-\w]+\.h)", '\&ruby/')
1795
+ if $nmake && /\A\s*\$\(RM|COPY\)/ =~ line
1796
+ line.gsub!(%r"[-\w\./]{2,}"){$&.tr("/", "\\")}
1797
+ line.gsub!(/(\$\((?!RM|COPY)[^:)]+)(?=\))/, '\1:/=\\')
1798
+ end
1799
+ if /(?:^|[^\\])(?:\\\\)*\\$/ =~ line
1800
+ (cont ||= []) << line
1801
+ next
1802
+ elsif cont
1803
+ line = (cont << line).join
1804
+ cont = nil
1805
+ end
1806
+ ruleconv.call(line)
1807
+ end
1808
+ if cont
1809
+ ruleconv.call(cont.join)
1810
+ elsif implicit
1811
+ impconv.call
1812
+ end
1813
+ unless suffixes.empty?
1814
+ depout.unshift(".SUFFIXES: ." + suffixes.uniq.join(" .") + "\n\n")
1815
+ end
1816
+ depout.unshift("$(OBJS): $(RUBY_EXTCONF_H)\n\n") if $extconf_h
1817
+ depout.flatten!
1818
+ depout
1819
+ end
1820
+
1821
+ # Generates the Makefile for your extension, passing along any options and
1822
+ # preprocessor constants that you may have generated through other methods.
1823
+ #
1824
+ # The +target+ name should correspond the name of the global function name
1825
+ # defined within your C extension, minus the 'Init_'. For example, if your
1826
+ # C extension is defined as 'Init_foo', then your target would simply be 'foo'.
1827
+ #
1828
+ # If any '/' characters are present in the target name, only the last name
1829
+ # is interpreted as the target name, and the rest are considered toplevel
1830
+ # directory names, and the generated Makefile will be altered accordingly to
1831
+ # follow that directory structure.
1832
+ #
1833
+ # For example, if you pass 'test/foo' as a target name, your extension will
1834
+ # be installed under the 'test' directory. This means that in order to
1835
+ # load the file within a Ruby program later, that directory structure will
1836
+ # have to be followed, e.g. "require 'test/foo'".
1837
+ #
1838
+ # The +srcprefix+ should be used when your source files are not in the same
1839
+ # directory as your build script. This will not only eliminate the need for
1840
+ # you to manually copy the source files into the same directory as your build
1841
+ # script, but it also sets the proper +target_prefix+ in the generated
1842
+ # Makefile.
1843
+ #
1844
+ # Setting the +target_prefix+ will, in turn, install the generated binary in
1845
+ # a directory under your RbConfig::CONFIG['sitearchdir'] that mimics your local
1846
+ # filesystem when you run 'make install'.
1847
+ #
1848
+ # For example, given the following file tree:
1849
+ #
1850
+ # ext/
1851
+ # extconf.rb
1852
+ # test/
1853
+ # foo.c
1854
+ #
1855
+ # And given the following code:
1856
+ #
1857
+ # create_makefile('test/foo', 'test')
1858
+ #
1859
+ # That will set the +target_prefix+ in the generated Makefile to 'test'. That,
1860
+ # in turn, will create the following file tree when installed via the
1861
+ # 'make install' command:
1862
+ #
1863
+ # /path/to/ruby/sitearchdir/test/foo.so
1864
+ #
1865
+ # It is recommended that you use this approach to generate your makefiles,
1866
+ # instead of copying files around manually, because some third party
1867
+ # libraries may depend on the +target_prefix+ being set properly.
1868
+ #
1869
+ # The +srcprefix+ argument can be used to override the default source
1870
+ # directory, i.e. the current directory . It is included as part of the VPATH
1871
+ # and added to the list of INCFLAGS.
1872
+ #
1873
+ def create_makefile(target, srcprefix = nil)
1874
+ $target = target
1875
+ libpath = $DEFLIBPATH|$LIBPATH
1876
+ message "creating Makefile\n"
1877
+ rm_f "conftest*"
1878
+ if CONFIG["DLEXT"] == $OBJEXT
1879
+ for lib in libs = $libs.split
1880
+ lib.sub!(/-l(.*)/, %%"lib\\1.#{$LIBEXT}"%)
1881
+ end
1882
+ $defs.push(format("-DEXTLIB='%s'", libs.join(",")))
1883
+ end
1884
+
1885
+ if target.include?('/')
1886
+ target_prefix, target = File.split(target)
1887
+ target_prefix[0,0] = '/'
1888
+ else
1889
+ target_prefix = ""
1890
+ end
1891
+
1892
+ srcprefix ||= "$(srcdir)/#{srcprefix}".chomp('/')
1893
+ RbConfig.expand(srcdir = srcprefix.dup)
1894
+
1895
+ ext = ".#{$OBJEXT}"
1896
+ if not $objs
1897
+ srcs = $srcs || Dir[File.join(srcdir, "*.{#{SRC_EXT.join(%q{,})}}")]
1898
+ objs = srcs.inject(Hash.new {[]}) {|h, f| h[File.basename(f, ".*") << ext] <<= f; h}
1899
+ $objs = objs.keys
1900
+ unless objs.delete_if {|b, f| f.size == 1}.empty?
1901
+ dups = objs.sort.map {|b, f|
1902
+ "#{b[/.*\./]}{#{f.collect {|n| n[/([^.]+)\z/]}.join(',')}}"
1903
+ }
1904
+ abort "source files duplication - #{dups.join(", ")}"
1905
+ end
1906
+ else
1907
+ $objs.collect! {|o| File.basename(o, ".*") << ext} unless $OBJEXT == "o"
1908
+ srcs = $srcs || $objs.collect {|o| o.chomp(ext) << ".c"}
1909
+ end
1910
+ $srcs = srcs
1911
+
1912
+ target = nil if $objs.empty?
1913
+
1914
+ if target and EXPORT_PREFIX
1915
+ if File.exist?(File.join(srcdir, target + '.def'))
1916
+ deffile = "$(srcdir)/$(TARGET).def"
1917
+ unless EXPORT_PREFIX.empty?
1918
+ makedef = %{-pe "$_.sub!(/^(?=\\w)/,'#{EXPORT_PREFIX}') unless 1../^EXPORTS$/i"}
1919
+ end
1920
+ else
1921
+ makedef = %{-e "puts 'EXPORTS', '#{EXPORT_PREFIX}' + 'Init_$(TARGET)'.sub(/\\..*\\z/,'')"}
1922
+ end
1923
+ if makedef
1924
+ $cleanfiles << '$(DEFFILE)'
1925
+ origdef = deffile
1926
+ deffile = "$(TARGET)-$(arch).def"
1927
+ end
1928
+ end
1929
+ origdef ||= ''
1930
+
1931
+ if $extout and $INSTALLFILES
1932
+ $cleanfiles.concat($INSTALLFILES.collect {|files, dir|File.join(dir, files.sub(/\A\.\//, ''))})
1933
+ $distcleandirs.concat($INSTALLFILES.collect {|files, dir| dir})
1934
+ end
1935
+
1936
+ if $extmk and not $extconf_h
1937
+ create_header
1938
+ end
1939
+
1940
+ libpath = libpathflag(libpath)
1941
+
1942
+ dllib = target ? "$(TARGET).#{CONFIG['DLEXT']}" : ""
1943
+ staticlib = target ? "$(TARGET).#$LIBEXT" : ""
1944
+ mfile = open("Makefile", "wb")
1945
+ conf = configuration(srcprefix)
1946
+ conf = yield(conf) if block_given?
1947
+ mfile.puts(conf)
1948
+ mfile.print "
1949
+ libpath = #{($DEFLIBPATH|$LIBPATH).join(" ")}
1950
+ LIBPATH = #{libpath}
1951
+ DEFFILE = #{deffile}
1952
+
1953
+ CLEANFILES = #{$cleanfiles.join(' ')}
1954
+ DISTCLEANFILES = #{$distcleanfiles.join(' ')}
1955
+ DISTCLEANDIRS = #{$distcleandirs.join(' ')}
1956
+
1957
+ extout = #{$extout && $extout.quote}
1958
+ extout_prefix = #{$extout_prefix}
1959
+ target_prefix = #{target_prefix}
1960
+ LOCAL_LIBS = #{$LOCAL_LIBS}
1961
+ LIBS = #{$LIBRUBYARG} #{$libs} #{$LIBS}
1962
+ SRCS = #{srcs.collect(&File.method(:basename)).join(' ')}
1963
+ OBJS = #{$objs.join(" ")}
1964
+ TARGET = #{target}
1965
+ DLLIB = #{dllib}
1966
+ EXTSTATIC = #{$static || ""}
1967
+ STATIC_LIB = #{staticlib unless $static.nil?}
1968
+ #{!$extout && defined?($installed_list) ? "INSTALLED_LIST = #{$installed_list}\n" : ""}
1969
+ " #"
1970
+ # TODO: fixme
1971
+ install_dirs.each {|d| mfile.print("%-14s= %s\n" % d) if /^[[:upper:]]/ =~ d[0]}
1972
+ n = ($extout ? '$(RUBYARCHDIR)/' : '') + '$(TARGET)'
1973
+ mfile.print "
1974
+ TARGET_SO = #{($extout ? '$(RUBYARCHDIR)/' : '')}$(DLLIB)
1975
+ CLEANLIBS = #{n}.#{CONFIG['DLEXT']} #{config_string('cleanlibs') {|t| t.gsub(/\$\*/) {n}}}
1976
+ CLEANOBJS = *.#{$OBJEXT} #{config_string('cleanobjs') {|t| t.gsub(/\$\*/, "$(TARGET)#{deffile ? '-$(arch)': ''}")} if target} *.bak
1977
+
1978
+ all: #{$extout ? "install" : target ? "$(DLLIB)" : "Makefile"}
1979
+ static: $(STATIC_LIB)#{$extout ? " install-rb" : ""}
1980
+ .PHONY: all install static install-so install-rb
1981
+ .PHONY: clean clean-so clean-rb
1982
+ "
1983
+ mfile.print CLEANINGS
1984
+ fsep = config_string('BUILD_FILE_SEPARATOR') {|s| s unless s == "/"}
1985
+ if fsep
1986
+ sep = ":/=#{fsep}"
1987
+ fseprepl = proc {|s|
1988
+ s = s.gsub("/", fsep)
1989
+ s = s.gsub(/(\$\(\w+)(\))/) {$1+sep+$2}
1990
+ s = s.gsub(/(\$\{\w+)(\})/) {$1+sep+$2}
1991
+ }
1992
+ rsep = ":#{fsep}=/"
1993
+ else
1994
+ fseprepl = proc {|s| s}
1995
+ sep = ""
1996
+ rsep = ""
1997
+ end
1998
+ dirs = []
1999
+ mfile.print "install: install-so install-rb\n\n"
2000
+ sodir = (dir = "$(RUBYARCHDIR)").dup
2001
+ mfile.print("install-so: ")
2002
+ if target
2003
+ f = "$(DLLIB)"
2004
+ dest = "#{dir}/#{f}"
2005
+ mfile.puts dir, "install-so: #{dest}"
2006
+ if $extout
2007
+ mfile.print "clean-so::\n"
2008
+ mfile.print "\t@-$(RM) #{fseprepl[dest]}\n"
2009
+ mfile.print "\t@-$(RMDIRS) #{fseprepl[dir]}#{$ignore_error}\n"
2010
+ else
2011
+ mfile.print "#{dest}: #{f}\n\t@-$(MAKEDIRS) $(@D#{sep})\n"
2012
+ mfile.print "\t$(INSTALL_PROG) #{fseprepl[f]} $(@D#{sep})\n"
2013
+ if defined?($installed_list)
2014
+ mfile.print "\t@echo #{dir}/#{File.basename(f)}>>$(INSTALLED_LIST)\n"
2015
+ end
2016
+ end
2017
+ else
2018
+ mfile.puts "Makefile"
2019
+ end
2020
+ mfile.print("install-rb: pre-install-rb install-rb-default\n")
2021
+ mfile.print("install-rb-default: pre-install-rb-default\n")
2022
+ mfile.print("pre-install-rb: Makefile\n")
2023
+ mfile.print("pre-install-rb-default: Makefile\n")
2024
+ for sfx, i in [["-default", [["lib/**/*.rb", "$(RUBYLIBDIR)", "lib"]]], ["", $INSTALLFILES]]
2025
+ files = install_files(mfile, i, nil, srcprefix) or next
2026
+ for dir, *files in files
2027
+ unless dirs.include?(dir)
2028
+ dirs << dir
2029
+ mfile.print "pre-install-rb#{sfx}: #{dir}\n"
2030
+ end
2031
+ for f in files
2032
+ dest = "#{dir}/#{File.basename(f)}"
2033
+ mfile.print("install-rb#{sfx}: #{dest} #{dir}\n")
2034
+ mfile.print("#{dest}: #{f}\n")
2035
+ mfile.print("\t$(Q) $(#{$extout ? 'COPY' : 'INSTALL_DATA'}) #{f} $(@D#{sep})\n")
2036
+ if defined?($installed_list) and !$extout
2037
+ mfile.print("\t@echo #{dest}>>$(INSTALLED_LIST)\n")
2038
+ end
2039
+ if $extout
2040
+ mfile.print("clean-rb#{sfx}::\n")
2041
+ mfile.print("\t@-$(RM) #{fseprepl[dest]}\n")
2042
+ end
2043
+ end
2044
+ end
2045
+ mfile.print "pre-install-rb#{sfx}:\n"
2046
+ mfile.print("\t$(ECHO) installing#{sfx.sub(/^-/, " ")} #{target} libraries\n")
2047
+ if $extout
2048
+ dirs.uniq!
2049
+ unless dirs.empty?
2050
+ mfile.print("clean-rb#{sfx}::\n")
2051
+ for dir in dirs.sort_by {|d| -d.count('/')}
2052
+ mfile.print("\t@-$(RMDIRS) #{fseprepl[dir]}#{$ignore_error}\n")
2053
+ end
2054
+ end
2055
+ end
2056
+ end
2057
+ dirs.unshift(sodir) if target and !dirs.include?(sodir)
2058
+ dirs.each {|d| mfile.print "#{d}:\n\t$(Q) $(MAKEDIRS) $@\n"}
2059
+
2060
+ mfile.print <<-SITEINSTALL
2061
+
2062
+ site-install: site-install-so site-install-rb
2063
+ site-install-so: install-so
2064
+ site-install-rb: install-rb
2065
+
2066
+ SITEINSTALL
2067
+
2068
+ return unless target
2069
+
2070
+ mfile.puts SRC_EXT.collect {|e| ".path.#{e} = $(VPATH)"} if $nmake == ?b
2071
+ mfile.print ".SUFFIXES: .#{SRC_EXT.join(' .')} .#{$OBJEXT}\n"
2072
+ mfile.print "\n"
2073
+
2074
+ compile_command = "\n\t$(ECHO) compiling $(<#{rsep})\n\t$(Q) %s\n\n"
2075
+ CXX_EXT.each do |e|
2076
+ COMPILE_RULES.each do |rule|
2077
+ mfile.printf(rule, e, $OBJEXT)
2078
+ mfile.printf(compile_command, COMPILE_CXX)
2079
+ end
2080
+ end
2081
+ C_EXT.each do |e|
2082
+ COMPILE_RULES.each do |rule|
2083
+ mfile.printf(rule, e, $OBJEXT)
2084
+ mfile.printf(compile_command, COMPILE_C)
2085
+ end
2086
+ end
2087
+
2088
+ mfile.print "$(RUBYARCHDIR)/" if $extout
2089
+ mfile.print "$(DLLIB): "
2090
+ mfile.print "$(DEFFILE) " if makedef
2091
+ mfile.print "$(OBJS) Makefile\n"
2092
+ mfile.print "\t$(ECHO) linking shared-object #{target_prefix.sub(/\A\/(.*)/, '\1/')}$(DLLIB)\n"
2093
+ mfile.print "\t@-$(RM) $(@#{sep})\n"
2094
+ mfile.print "\t@-$(MAKEDIRS) $(@D)\n" if $extout
2095
+ link_so = LINK_SO.gsub(/^/, "\t$(Q) ")
2096
+ if srcs.any?(&%r"\.(?:#{CXX_EXT.join('|')})\z".method(:===))
2097
+ link_so = link_so.sub(/\bLDSHARED\b/, '\&XX')
2098
+ end
2099
+ mfile.print link_so, "\n\n"
2100
+ unless $static.nil?
2101
+ mfile.print "$(STATIC_LIB): $(OBJS)\n\t@-$(RM) $(@#{sep})\n\t"
2102
+ mfile.print "$(ECHO) linking static-library $(@#{rsep})\n\t$(Q) "
2103
+ mfile.print "$(AR) #{config_string('ARFLAGS') || 'cru '}$@ $(OBJS)"
2104
+ config_string('RANLIB') do |ranlib|
2105
+ mfile.print "\n\t@-#{ranlib} $(DLLIB) 2> /dev/null || true"
2106
+ end
2107
+ end
2108
+ mfile.print "\n\n"
2109
+ if makedef
2110
+ mfile.print "$(DEFFILE): #{origdef}\n"
2111
+ mfile.print "\t$(ECHO) generating $(@#{rsep})\n"
2112
+ mfile.print "\t$(Q) $(RUBY) #{makedef} #{origdef} > $@\n\n"
2113
+ end
2114
+
2115
+ depend = File.join(srcdir, "depend")
2116
+ if File.exist?(depend)
2117
+ mfile.print("###\n", *depend_rules(File.read(depend)))
2118
+ else
2119
+ headers = %w[$(hdrdir)/ruby.h $(hdrdir)/ruby/defines.h]
2120
+ if RULE_SUBST
2121
+ headers.each {|h| h.sub!(/.*/, &RULE_SUBST.method(:%))}
2122
+ end
2123
+ headers << $config_h
2124
+ headers << '$(RUBY_EXTCONF_H)' if $extconf_h
2125
+ mfile.print "$(OBJS): ", headers.join(' '), "\n"
2126
+ end
2127
+
2128
+ $makefile_created = true
2129
+ ensure
2130
+ mfile.close if mfile
2131
+ end
2132
+
2133
+ # :stopdoc:
2134
+
2135
+ def init_mkmf(config = CONFIG, rbconfig = RbConfig::CONFIG)
2136
+ $makefile_created = false
2137
+ $arg_config = []
2138
+ $enable_shared = config['ENABLE_SHARED'] == 'yes'
2139
+ $defs = []
2140
+ $extconf_h = nil
2141
+ if $warnflags = CONFIG['warnflags'] and CONFIG['GCC'] == 'yes'
2142
+ # turn warnings into errors only for bundled extensions.
2143
+ config['warnflags'] = $warnflags.gsub(/(\A|\s)-Werror[-=]/, '\1-W')
2144
+ RbConfig.expand(rbconfig['warnflags'] = config['warnflags'].dup)
2145
+ config.each do |key, val|
2146
+ RbConfig.expand(rbconfig[key] = val.dup) if /warnflags/ =~ val
2147
+ end
2148
+ $warnflags = config['warnflags'] unless $extmk
2149
+ end
2150
+ $CFLAGS = with_config("cflags", arg_config("CFLAGS", config["CFLAGS"])).dup
2151
+ $ARCH_FLAG = with_config("arch_flag", arg_config("ARCH_FLAG", config["ARCH_FLAG"])).dup
2152
+ $CPPFLAGS = with_config("cppflags", arg_config("CPPFLAGS", config["CPPFLAGS"])).dup
2153
+ $LDFLAGS = with_config("ldflags", arg_config("LDFLAGS", config["LDFLAGS"])).dup
2154
+ $INCFLAGS = "-I$(arch_hdrdir) -I/usr/include/ -L/lib/"
2155
+ $INCFLAGS << " -I$(hdrdir)/ruby/backward" unless $extmk
2156
+ $INCFLAGS << " -I$(hdrdir) -I$(srcdir)"
2157
+ $DLDFLAGS = with_config("dldflags", arg_config("DLDFLAGS", config["DLDFLAGS"])).dup
2158
+ $LIBEXT = config['LIBEXT'].dup
2159
+ $OBJEXT = config["OBJEXT"].dup
2160
+ $LIBS = "#{config['LIBS']} #{config['DLDLIBS']}"
2161
+ $LIBRUBYARG = ""
2162
+ $LIBRUBYARG_STATIC = config['LIBRUBYARG_STATIC']
2163
+ $LIBRUBYARG_SHARED = config['LIBRUBYARG_SHARED']
2164
+ $DEFLIBPATH = [$extmk ? "$(topdir)" : "$(libdir)"]
2165
+ $DEFLIBPATH.unshift(".")
2166
+ $LIBPATH = []
2167
+ $INSTALLFILES = []
2168
+ $NONINSTALLFILES = [/~\z/, /\A#.*#\z/, /\A\.#/, /\.bak\z/i, /\.orig\z/, /\.rej\z/, /\.l[ao]\z/, /\.o\z/]
2169
+ $VPATH = %w[$(srcdir) $(arch_hdrdir)/ruby $(hdrdir)/ruby]
2170
+
2171
+ $objs = nil
2172
+ $srcs = nil
2173
+ $libs = ""
2174
+ if $enable_shared or RbConfig.expand(config["LIBRUBY"].dup) != RbConfig.expand(config["LIBRUBY_A"].dup)
2175
+ $LIBRUBYARG = config['LIBRUBYARG']
2176
+ end
2177
+
2178
+ $LOCAL_LIBS = ""
2179
+
2180
+ $cleanfiles = config_string('CLEANFILES') {|s| Shellwords.shellwords(s)} || []
2181
+ $cleanfiles << "mkmf.log"
2182
+ $distcleanfiles = config_string('DISTCLEANFILES') {|s| Shellwords.shellwords(s)} || []
2183
+ $distcleandirs = config_string('DISTCLEANDIRS') {|s| Shellwords.shellwords(s)} || []
2184
+
2185
+ $extout ||= nil
2186
+ $extout_prefix ||= nil
2187
+
2188
+ $arg_config.clear
2189
+ dir_config("opt")
2190
+ end
2191
+
2192
+ FailedMessage = <<MESSAGE
2193
+ Could not create Makefile due to some reason, probably lack of
2194
+ necessary libraries and/or headers. Check the mkmf.log file for more
2195
+ details. You may need configuration options.
2196
+
2197
+ Provided configuration options:
2198
+ MESSAGE
2199
+
2200
+ # Returns whether or not the Makefile was successfully generated. If not,
2201
+ # the script will abort with an error message.
2202
+ #
2203
+ # Internal use only.
2204
+ #
2205
+ def mkmf_failed(path)
2206
+ unless $makefile_created or File.exist?("Makefile")
2207
+ opts = $arg_config.collect {|t, n| "\t#{t}#{n ? "=#{n}" : ""}\n"}
2208
+ abort "*** #{path} failed ***\n" + FailedMessage + opts.join
2209
+ end
2210
+ end
2211
+
2212
+ # :startdoc:
2213
+
2214
+ init_mkmf
2215
+
2216
+ $make = with_config("make-prog", ENV["MAKE"] || "make")
2217
+ make, = Shellwords.shellwords($make)
2218
+ $nmake = nil
2219
+ case
2220
+ when $mswin
2221
+ $nmake = ?m if /nmake/i =~ make
2222
+ when $bccwin
2223
+ $nmake = ?b if /Borland/i =~ `#{make} -h`
2224
+ end
2225
+ $ignore_error = $nmake ? '' : ' 2> /dev/null || true'
2226
+
2227
+ RbConfig::CONFIG["srcdir"] = CONFIG["srcdir"] =
2228
+ $srcdir = arg_config("--srcdir", File.dirname($0))
2229
+ $configure_args["--topsrcdir"] ||= $srcdir
2230
+ if $curdir = arg_config("--curdir")
2231
+ RbConfig.expand(curdir = $curdir.dup)
2232
+ else
2233
+ curdir = $curdir = "."
2234
+ end
2235
+ unless File.expand_path(RbConfig::CONFIG["topdir"]) == File.expand_path(curdir)
2236
+ CONFIG["topdir"] = $curdir
2237
+ RbConfig::CONFIG["topdir"] = curdir
2238
+ end
2239
+ $configure_args["--topdir"] ||= $curdir
2240
+ $ruby = arg_config("--ruby", File.join(RbConfig::CONFIG["bindir"], CONFIG["ruby_install_name"]))
2241
+
2242
+ split = Shellwords.method(:shellwords).to_proc
2243
+
2244
+ EXPORT_PREFIX = config_string('EXPORT_PREFIX') {|s| s.strip}
2245
+
2246
+ hdr = ['#include "ruby.h"' "\n"]
2247
+ config_string('COMMON_MACROS') do |s|
2248
+ Shellwords.shellwords(s).each do |w|
2249
+ w, v = w.split(/=/, 2)
2250
+ hdr << "#ifndef #{w}"
2251
+ hdr << "#define #{[w, v].compact.join(" ")}"
2252
+ hdr << "#endif /* #{w} */"
2253
+ end
2254
+ end
2255
+ config_string('COMMON_HEADERS') do |s|
2256
+ Shellwords.shellwords(s).each {|w| hdr << "#include <#{w}>"}
2257
+ end
2258
+ COMMON_HEADERS = hdr.join("\n")
2259
+ COMMON_LIBS = config_string('COMMON_LIBS', &split) || []
2260
+
2261
+ COMPILE_RULES = config_string('COMPILE_RULES', &split) || %w[.%s.%s:]
2262
+ RULE_SUBST = config_string('RULE_SUBST')
2263
+ COMPILE_C = config_string('COMPILE_C') || '$(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $<'
2264
+ COMPILE_CXX = config_string('COMPILE_CXX') || '$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<'
2265
+ TRY_LINK = config_string('TRY_LINK') ||
2266
+ "$(CC) #{OUTFLAG}conftest $(INCFLAGS) $(CPPFLAGS) " \
2267
+ "$(CFLAGS) $(src) $(LIBPATH) $(LDFLAGS) $(ARCH_FLAG) $(LOCAL_LIBS) $(LIBS)"
2268
+ LINK_SO = config_string('LINK_SO') ||
2269
+ if CONFIG["DLEXT"] == $OBJEXT
2270
+ "ld $(DLDFLAGS) -r -o $@ $(OBJS)\n"
2271
+ else
2272
+ "$(LDSHARED) #{OUTFLAG}$@ $(OBJS) " \
2273
+ "$(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)"
2274
+ end
2275
+ LIBPATHFLAG = config_string('LIBPATHFLAG') || ' -L"%s"'
2276
+ RPATHFLAG = config_string('RPATHFLAG') || ''
2277
+ LIBARG = config_string('LIBARG') || '-l%s'
2278
+ MAIN_DOES_NOTHING = config_string('MAIN_DOES_NOTHING') || 'int main() {return 0;}'
2279
+ UNIVERSAL_INTS = config_string('UNIVERSAL_INTS') {|s| Shellwords.shellwords(s)} ||
2280
+ %w[int short long long\ long]
2281
+
2282
+ sep = config_string('BUILD_FILE_SEPARATOR') {|s| ":/=#{s}" if s != "/"} || ""
2283
+ CLEANINGS = "
2284
+ clean-rb-default::
2285
+ clean-rb::
2286
+ clean-so::
2287
+ clean: clean-so clean-rb-default clean-rb
2288
+ \t\t@-$(RM) $(CLEANLIBS#{sep}) $(CLEANOBJS#{sep}) $(CLEANFILES#{sep})
2289
+
2290
+ distclean-rb-default::
2291
+ distclean-rb::
2292
+ distclean-so::
2293
+ distclean: clean distclean-so distclean-rb-default distclean-rb
2294
+ \t\t@-$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log
2295
+ \t\t@-$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES#{sep})
2296
+ \t\t@-$(RMDIRS) $(DISTCLEANDIRS#{sep})#{$ignore_error}
2297
+
2298
+ realclean: distclean
2299
+ "
2300
+
2301
+ if not $extmk and /\A(extconf|makefile).rb\z/ =~ File.basename($0)
2302
+ END {mkmf_failed($0)}
2303
+ end