rubysl-mkmf 2.0.1 → 2.1

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,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9a3cec3459dba8709d26961f5bfd14b1200ea666
4
- data.tar.gz: 140f79d5b37aeaeff68cdeee470c6212716e5cbd
3
+ metadata.gz: 90e327305c5a453d37ab109423d0f1c8bbbd9bc8
4
+ data.tar.gz: 6871d81235241ac7083b2c63d16400863da6432e
5
5
  SHA512:
6
- metadata.gz: de622c4cb95dcb2e39d2c5af458dc15fc84afd04d6aaf2c79ab3bcc20f3700f04222eb886b77f7c94b4a520a3796333c29f8e44954e6920cef915cfebf87d0ef
7
- data.tar.gz: e0f5b03b5227f440ddc9a61fb8ff5d74030b699e5b49686d42cd0b78ebf984ffcaa592e5eabb2cd8adbbf9153faf35b938a3ec859fcd7a1774c4fb9c83439b2e
6
+ metadata.gz: d414f12ed36e4cbc3cda6b2db7a6570781a4210f29fdf32526239c3f42e3109c1b940d67e4d12daf888fb493e689ebd5217bca0934379f428f804192c0718bae
7
+ data.tar.gz: d5cc103ebda39a91b809b8772a4403a72884cda2e37d4e09b126b93a964f1161334ad4fb1c52600c7949ebcf3ee6b8ddd956e161f3b836ef7e25574529b4b0ee
@@ -1,6 +1,14 @@
1
1
  language: ruby
2
2
  env:
3
3
  - RUBYLIB=lib
4
- script: bundle exec mspec spec
4
+ - RUBYLIB=
5
+ script: mspec spec
5
6
  rvm:
6
- - rbx-nightly-19mode
7
+ - 2.0.0
8
+ - rbx-2.2.1
9
+ matrix:
10
+ exclude:
11
+ - rvm: 2.0.0
12
+ env: RUBYLIB=lib
13
+ - rvm: rbx-2.2.1
14
+ env: RUBYLIB=
@@ -0,0 +1,56 @@
1
+ Ruby is copyrighted free software by Yukihiro Matsumoto <matz@netlab.jp>.
2
+ You can redistribute it and/or modify it under either the terms of the
3
+ 2-clause BSDL (see the file BSDL), or the conditions below:
4
+
5
+ 1. You may make and give away verbatim copies of the source form of the
6
+ software without restriction, provided that you duplicate all of the
7
+ original copyright notices and associated disclaimers.
8
+
9
+ 2. You may modify your copy of the software in any way, provided that
10
+ you do at least ONE of the following:
11
+
12
+ a) place your modifications in the Public Domain or otherwise
13
+ make them Freely Available, such as by posting said
14
+ modifications to Usenet or an equivalent medium, or by allowing
15
+ the author to include your modifications in the software.
16
+
17
+ b) use the modified software only within your corporation or
18
+ organization.
19
+
20
+ c) give non-standard binaries non-standard names, with
21
+ instructions on where to get the original software distribution.
22
+
23
+ d) make other distribution arrangements with the author.
24
+
25
+ 3. You may distribute the software in object code or binary form,
26
+ provided that you do at least ONE of the following:
27
+
28
+ a) distribute the binaries and library files of the software,
29
+ together with instructions (in the manual page or equivalent)
30
+ on where to get the original distribution.
31
+
32
+ b) accompany the distribution with the machine-readable source of
33
+ the software.
34
+
35
+ c) give non-standard binaries non-standard names, with
36
+ instructions on where to get the original software distribution.
37
+
38
+ d) make other distribution arrangements with the author.
39
+
40
+ 4. You may modify and include the part of the software into any other
41
+ software (possibly commercial). But some files in the distribution
42
+ are not written by the author, so that they are not under these terms.
43
+
44
+ For the list of those files and their copying conditions, see the
45
+ file LEGAL.
46
+
47
+ 5. The scripts and library files supplied as input to or produced as
48
+ output from the software do not automatically fall under the
49
+ copyright of the software, but belong to whomever generated them,
50
+ and may be sold commercially, and may be aggregated with this
51
+ software.
52
+
53
+ 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
54
+ IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
55
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
56
+ PURPOSE.
@@ -1 +1,2722 @@
1
- require "rubysl/mkmf"
1
+ # -*- coding: us-ascii -*-
2
+ # frozen-string-literal: false
3
+ # module to create Makefile for extension modules
4
+ # invoke like: ruby -r mkmf extconf.rb
5
+
6
+ require 'rbconfig'
7
+ require 'fileutils'
8
+ require 'shellwords'
9
+
10
+ # :stopdoc:
11
+ class String
12
+ # Wraps a string in escaped quotes if it contains whitespace.
13
+ def quote
14
+ /\s/ =~ self ? "\"#{self}\"" : "#{self}"
15
+ end
16
+
17
+ # Escape whitespaces for Makefile.
18
+ def unspace
19
+ gsub(/\s/, '\\\\\\&')
20
+ end
21
+
22
+ # Generates a string used as cpp macro name.
23
+ def tr_cpp
24
+ strip.upcase.tr_s("^A-Z0-9_*", "_").tr_s("*", "P")
25
+ end
26
+
27
+ def funcall_style
28
+ /\)\z/ =~ self ? dup : "#{self}()"
29
+ end
30
+
31
+ def sans_arguments
32
+ self[/\A[^()]+/]
33
+ end
34
+ end
35
+
36
+ class Array
37
+ # Wraps all strings in escaped quotes if they contain whitespace.
38
+ def quote
39
+ map {|s| s.quote}
40
+ end
41
+ end
42
+ # :startdoc:
43
+
44
+ ##
45
+ # mkmf.rb is used by Ruby C extensions to generate a Makefile which will
46
+ # correctly compile and link the C extension to Ruby and a third-party
47
+ # library.
48
+ module MakeMakefile
49
+ #### defer until this module become global-state free.
50
+ # def self.extended(obj)
51
+ # obj.init_mkmf
52
+ # super
53
+ # end
54
+ #
55
+ # def initialize(*args, rbconfig: RbConfig, **rest)
56
+ # init_mkmf(rbconfig::MAKEFILE_CONFIG, rbconfig::CONFIG)
57
+ # super(*args, **rest)
58
+ # end
59
+
60
+ ##
61
+ # The makefile configuration using the defaults from when Ruby was built.
62
+
63
+ CONFIG = RbConfig::MAKEFILE_CONFIG
64
+ ORIG_LIBPATH = ENV['LIB']
65
+
66
+ ##
67
+ # Extensions for files compiled with a C compiler
68
+
69
+ C_EXT = %w[c m]
70
+
71
+ ##
72
+ # Extensions for files complied with a C++ compiler
73
+
74
+ CXX_EXT = %w[cc mm cxx cpp]
75
+ unless File.exist?(File.join(*File.split(__FILE__).tap {|d, b| b.swapcase}))
76
+ CXX_EXT.concat(%w[C])
77
+ end
78
+
79
+ ##
80
+ # Extensions for source files
81
+
82
+ SRC_EXT = C_EXT + CXX_EXT
83
+
84
+ ##
85
+ # Extensions for header files
86
+
87
+ HDR_EXT = %w[h hpp]
88
+ $static = nil
89
+ $config_h = '$(arch_hdrdir)/ruby/config.h'
90
+ $default_static = $static
91
+
92
+ unless defined? $configure_args
93
+ $configure_args = {}
94
+ args = CONFIG["configure_args"]
95
+ if ENV["CONFIGURE_ARGS"]
96
+ args << " " << ENV["CONFIGURE_ARGS"]
97
+ end
98
+ for arg in Shellwords::shellwords(args)
99
+ arg, val = arg.split('=', 2)
100
+ next unless arg
101
+ arg.tr!('_', '-')
102
+ if arg.sub!(/^(?!--)/, '--')
103
+ val or next
104
+ arg.downcase!
105
+ end
106
+ next if /^--(?:top|topsrc|src|cur)dir$/ =~ arg
107
+ $configure_args[arg] = val || true
108
+ end
109
+ for arg in ARGV
110
+ arg, val = arg.split('=', 2)
111
+ next unless arg
112
+ arg.tr!('_', '-')
113
+ if arg.sub!(/^(?!--)/, '--')
114
+ val or next
115
+ arg.downcase!
116
+ end
117
+ $configure_args[arg] = val || true
118
+ end
119
+ end
120
+
121
+ $libdir = CONFIG["libdir"]
122
+ $rubylibdir = CONFIG["rubylibdir"]
123
+ $archdir = CONFIG["archdir"]
124
+ $sitedir = CONFIG["sitedir"]
125
+ $sitelibdir = CONFIG["sitelibdir"]
126
+ $sitearchdir = CONFIG["sitearchdir"]
127
+ $vendordir = CONFIG["vendordir"]
128
+ $vendorlibdir = CONFIG["vendorlibdir"]
129
+ $vendorarchdir = CONFIG["vendorarchdir"]
130
+
131
+ $mswin = /mswin/ =~ RUBY_PLATFORM
132
+ $bccwin = /bccwin/ =~ RUBY_PLATFORM
133
+ $mingw = /mingw/ =~ RUBY_PLATFORM
134
+ $cygwin = /cygwin/ =~ RUBY_PLATFORM
135
+ $netbsd = /netbsd/ =~ RUBY_PLATFORM
136
+ $haiku = /haiku/ =~ RUBY_PLATFORM
137
+ $solaris = /solaris/ =~ RUBY_PLATFORM
138
+ $universal = /universal/ =~ RUBY_PLATFORM
139
+ $dest_prefix_pattern = (File::PATH_SEPARATOR == ';' ? /\A([[:alpha:]]:)?/ : /\A/)
140
+
141
+ # :stopdoc:
142
+
143
+ def config_string(key, config = CONFIG)
144
+ s = config[key] and !s.empty? and block_given? ? yield(s) : s
145
+ end
146
+ module_function :config_string
147
+
148
+ def dir_re(dir)
149
+ Regexp.new('\$(?:\('+dir+'\)|\{'+dir+'\})(?:\$(?:\(target_prefix\)|\{target_prefix\}))?')
150
+ end
151
+ module_function :dir_re
152
+
153
+ def relative_from(path, base)
154
+ dir = File.join(path, "")
155
+ if File.expand_path(dir) == File.expand_path(dir, base)
156
+ path
157
+ else
158
+ File.join(base, path)
159
+ end
160
+ end
161
+
162
+ INSTALL_DIRS = [
163
+ [dir_re('commondir'), "$(RUBYCOMMONDIR)"],
164
+ [dir_re('sitedir'), "$(RUBYCOMMONDIR)"],
165
+ [dir_re('vendordir'), "$(RUBYCOMMONDIR)"],
166
+ [dir_re('rubylibdir'), "$(RUBYLIBDIR)"],
167
+ [dir_re('archdir'), "$(RUBYARCHDIR)"],
168
+ [dir_re('sitelibdir'), "$(RUBYLIBDIR)"],
169
+ [dir_re('vendorlibdir'), "$(RUBYLIBDIR)"],
170
+ [dir_re('sitearchdir'), "$(RUBYARCHDIR)"],
171
+ [dir_re('vendorarchdir'), "$(RUBYARCHDIR)"],
172
+ [dir_re('rubyhdrdir'), "$(RUBYHDRDIR)"],
173
+ [dir_re('sitehdrdir'), "$(SITEHDRDIR)"],
174
+ [dir_re('vendorhdrdir'), "$(VENDORHDRDIR)"],
175
+ [dir_re('bindir'), "$(BINDIR)"],
176
+ ]
177
+
178
+ def install_dirs(target_prefix = nil)
179
+ if $extout
180
+ dirs = [
181
+ ['BINDIR', '$(extout)/bin'],
182
+ ['RUBYCOMMONDIR', '$(extout)/common'],
183
+ ['RUBYLIBDIR', '$(RUBYCOMMONDIR)$(target_prefix)'],
184
+ ['RUBYARCHDIR', '$(extout)/$(arch)$(target_prefix)'],
185
+ ['HDRDIR', '$(extout)/include/ruby$(target_prefix)'],
186
+ ['ARCHHDRDIR', '$(extout)/include/$(arch)/ruby$(target_prefix)'],
187
+ ['extout', "#$extout"],
188
+ ['extout_prefix', "#$extout_prefix"],
189
+ ]
190
+ elsif $extmk
191
+ dirs = [
192
+ ['BINDIR', '$(bindir)'],
193
+ ['RUBYCOMMONDIR', '$(rubylibdir)'],
194
+ ['RUBYLIBDIR', '$(rubylibdir)$(target_prefix)'],
195
+ ['RUBYARCHDIR', '$(archdir)$(target_prefix)'],
196
+ ['HDRDIR', '$(rubyhdrdir)/ruby$(target_prefix)'],
197
+ ['ARCHHDRDIR', '$(rubyhdrdir)/$(arch)/ruby$(target_prefix)'],
198
+ ]
199
+ elsif $configure_args.has_key?('--vendor')
200
+ dirs = [
201
+ ['BINDIR', '$(bindir)'],
202
+ ['RUBYCOMMONDIR', '$(vendordir)$(target_prefix)'],
203
+ ['RUBYLIBDIR', '$(vendorlibdir)$(target_prefix)'],
204
+ ['RUBYARCHDIR', '$(vendorarchdir)$(target_prefix)'],
205
+ ['HDRDIR', '$(rubyhdrdir)/ruby$(target_prefix)'],
206
+ ['ARCHHDRDIR', '$(rubyhdrdir)/$(arch)/ruby$(target_prefix)'],
207
+ ]
208
+ else
209
+ dirs = [
210
+ ['BINDIR', '$(bindir)'],
211
+ ['RUBYCOMMONDIR', '$(sitedir)$(target_prefix)'],
212
+ ['RUBYLIBDIR', '$(sitelibdir)$(target_prefix)'],
213
+ ['RUBYARCHDIR', '$(sitearchdir)$(target_prefix)'],
214
+ ['HDRDIR', '$(rubyhdrdir)/ruby$(target_prefix)'],
215
+ ['ARCHHDRDIR', '$(rubyhdrdir)/$(arch)/ruby$(target_prefix)'],
216
+ ]
217
+ end
218
+ dirs << ['target_prefix', (target_prefix ? "/#{target_prefix}" : "")]
219
+ dirs
220
+ end
221
+
222
+ def map_dir(dir, map = nil)
223
+ map ||= INSTALL_DIRS
224
+ map.inject(dir) {|d, (orig, new)| d.gsub(orig, new)}
225
+ end
226
+
227
+ topdir = File.dirname(File.dirname(__FILE__))
228
+ path = File.expand_path($0)
229
+ until (dir = File.dirname(path)) == path
230
+ if File.identical?(dir, topdir)
231
+ $extmk = true if %r"\A(?:ext|enc|tool|test)\z" =~ File.basename(path)
232
+ break
233
+ end
234
+ path = dir
235
+ end
236
+ $extmk ||= false
237
+ if not $extmk and File.exist?(($hdrdir = RbConfig::CONFIG["rubyhdrdir"]) + "/ruby/ruby.h")
238
+ $topdir = $hdrdir
239
+ $top_srcdir = $hdrdir
240
+ $arch_hdrdir = RbConfig::CONFIG["rubyarchhdrdir"]
241
+ elsif File.exist?(($hdrdir = ($top_srcdir ||= topdir) + "/include") + "/ruby.h")
242
+ $topdir ||= RbConfig::CONFIG["topdir"]
243
+ $arch_hdrdir = "$(extout)/include/$(arch)"
244
+ else
245
+ abort "mkmf.rb can't find header files for ruby at #{$hdrdir}/ruby.h"
246
+ end
247
+
248
+ CONFTEST = "conftest".freeze
249
+ CONFTEST_C = "#{CONFTEST}.c"
250
+
251
+ OUTFLAG = CONFIG['OUTFLAG']
252
+ COUTFLAG = CONFIG['COUTFLAG']
253
+ CPPOUTFILE = config_string('CPPOUTFILE') {|str| str.sub(/\bconftest\b/, CONFTEST)}
254
+
255
+ def rm_f(*files)
256
+ opt = (Hash === files.last ? [files.pop] : [])
257
+ FileUtils.rm_f(Dir[*files.flatten], *opt)
258
+ end
259
+ module_function :rm_f
260
+
261
+ def rm_rf(*files)
262
+ opt = (Hash === files.last ? [files.pop] : [])
263
+ FileUtils.rm_rf(Dir[*files.flatten], *opt)
264
+ end
265
+ module_function :rm_rf
266
+
267
+ # Returns time stamp of the +target+ file if it exists and is newer than or
268
+ # equal to all of +times+.
269
+ def modified?(target, times)
270
+ (t = File.mtime(target)) rescue return nil
271
+ Array === times or times = [times]
272
+ t if times.all? {|n| n <= t}
273
+ end
274
+
275
+ def split_libs(*strs)
276
+ strs.map {|s| s.split(/\s+(?=-|\z)/)}.flatten
277
+ end
278
+
279
+ def merge_libs(*libs)
280
+ libs.inject([]) do |x, y|
281
+ y = y.inject([]) {|ary, e| ary.last == e ? ary : ary << e}
282
+ y.each_with_index do |v, yi|
283
+ if xi = x.rindex(v)
284
+ x[(xi+1)..-1] = merge_libs(y[(yi+1)..-1], x[(xi+1)..-1])
285
+ x[xi, 0] = y[0...yi]
286
+ break
287
+ end
288
+ end and x.concat(y)
289
+ x
290
+ end
291
+ end
292
+
293
+ # This is a custom logging module. It generates an mkmf.log file when you
294
+ # run your extconf.rb script. This can be useful for debugging unexpected
295
+ # failures.
296
+ #
297
+ # This module and its associated methods are meant for internal use only.
298
+ #
299
+ module Logging
300
+ @log = nil
301
+ @logfile = 'mkmf.log'
302
+ @orgerr = $stderr.dup
303
+ @orgout = $stdout.dup
304
+ @postpone = 0
305
+ @quiet = $extmk
306
+
307
+ def self::log_open
308
+ @log ||= File::open(@logfile, 'wb')
309
+ @log.sync = true
310
+ end
311
+
312
+ def self::log_opened?
313
+ @log and not @log.closed?
314
+ end
315
+
316
+ def self::open
317
+ log_open
318
+ $stderr.reopen(@log)
319
+ $stdout.reopen(@log)
320
+ yield
321
+ ensure
322
+ $stderr.reopen(@orgerr)
323
+ $stdout.reopen(@orgout)
324
+ end
325
+
326
+ def self::message(*s)
327
+ log_open
328
+ @log.printf(*s)
329
+ end
330
+
331
+ def self::logfile file
332
+ @logfile = file
333
+ log_close
334
+ end
335
+
336
+ def self::log_close
337
+ if @log and not @log.closed?
338
+ @log.flush
339
+ @log.close
340
+ @log = nil
341
+ end
342
+ end
343
+
344
+ def self::postpone
345
+ tmplog = "mkmftmp#{@postpone += 1}.log"
346
+ open do
347
+ log, *save = @log, @logfile, @orgout, @orgerr
348
+ @log, @logfile, @orgout, @orgerr = nil, tmplog, log, log
349
+ begin
350
+ log.print(open {yield @log})
351
+ ensure
352
+ @log.close if @log and not @log.closed?
353
+ File::open(tmplog) {|t| FileUtils.copy_stream(t, log)} if File.exist?(tmplog)
354
+ @log, @logfile, @orgout, @orgerr = log, *save
355
+ @postpone -= 1
356
+ MakeMakefile.rm_f tmplog
357
+ end
358
+ end
359
+ end
360
+
361
+ class << self
362
+ attr_accessor :quiet
363
+ end
364
+ end
365
+
366
+ def libpath_env
367
+ # used only if native compiling
368
+ if libpathenv = config_string("LIBPATHENV")
369
+ pathenv = ENV[libpathenv]
370
+ libpath = RbConfig.expand($DEFLIBPATH.join(File::PATH_SEPARATOR))
371
+ {libpathenv => [libpath, pathenv].compact.join(File::PATH_SEPARATOR)}
372
+ else
373
+ {}
374
+ end
375
+ end
376
+
377
+ def xsystem command, opts = nil
378
+ varpat = /\$\((\w+)\)|\$\{(\w+)\}/
379
+ if varpat =~ command
380
+ vars = Hash.new {|h, k| h[k] = ENV[k]}
381
+ command = command.dup
382
+ nil while command.gsub!(varpat) {vars[$1||$2]}
383
+ end
384
+ Logging::open do
385
+ puts command.quote
386
+ if opts and opts[:werror]
387
+ result = nil
388
+ Logging.postpone do |log|
389
+ output = IO.popen(libpath_env, command, &:read)
390
+ result = ($?.success? and File.zero?(log.path))
391
+ output
392
+ end
393
+ result
394
+ else
395
+ system(libpath_env, command)
396
+ end
397
+ end
398
+ end
399
+
400
+ def xpopen command, *mode, &block
401
+ Logging::open do
402
+ case mode[0]
403
+ when nil, /^r/
404
+ puts "#{command} |"
405
+ else
406
+ puts "| #{command}"
407
+ end
408
+ IO.popen(libpath_env, command, *mode, &block)
409
+ end
410
+ end
411
+
412
+ def log_src(src, heading="checked program was")
413
+ src = src.split(/^/)
414
+ fmt = "%#{src.size.to_s.size}d: %s"
415
+ Logging::message <<"EOM"
416
+ #{heading}:
417
+ /* begin */
418
+ EOM
419
+ src.each_with_index {|line, no| Logging::message fmt, no+1, line}
420
+ Logging::message <<"EOM"
421
+ /* end */
422
+
423
+ EOM
424
+ end
425
+
426
+ def create_tmpsrc(src)
427
+ src = "#{COMMON_HEADERS}\n#{src}"
428
+ src = yield(src) if block_given?
429
+ src.gsub!(/[ \t]+$/, '')
430
+ src.gsub!(/\A\n+|^\n+$/, '')
431
+ src.sub!(/[^\n]\z/, "\\&\n")
432
+ count = 0
433
+ begin
434
+ open(CONFTEST_C, "wb") do |cfile|
435
+ cfile.print src
436
+ end
437
+ rescue Errno::EACCES
438
+ if (count += 1) < 5
439
+ sleep 0.2
440
+ retry
441
+ end
442
+ end
443
+ src
444
+ end
445
+
446
+ def have_devel?
447
+ unless defined? $have_devel
448
+ $have_devel = true
449
+ $have_devel = try_link(MAIN_DOES_NOTHING)
450
+ end
451
+ $have_devel
452
+ end
453
+
454
+ def try_do(src, command, *opts, &b)
455
+ unless have_devel?
456
+ raise <<MSG
457
+ The compiler failed to generate an executable file.
458
+ You have to install development tools first.
459
+ MSG
460
+ end
461
+ begin
462
+ src = create_tmpsrc(src, &b)
463
+ xsystem(command, *opts)
464
+ ensure
465
+ log_src(src)
466
+ MakeMakefile.rm_rf "#{CONFTEST}.dSYM"
467
+ end
468
+ end
469
+
470
+ def link_command(ldflags, opt="", libpath=$DEFLIBPATH|$LIBPATH)
471
+ librubyarg = $extmk ? $LIBRUBYARG_STATIC : "$(LIBRUBYARG)"
472
+ conf = RbConfig::CONFIG.merge('hdrdir' => $hdrdir.quote,
473
+ 'src' => "#{CONFTEST_C}",
474
+ 'arch_hdrdir' => $arch_hdrdir.quote,
475
+ 'top_srcdir' => $top_srcdir.quote,
476
+ 'INCFLAGS' => "#$INCFLAGS",
477
+ 'CPPFLAGS' => "#$CPPFLAGS",
478
+ 'CFLAGS' => "#$CFLAGS",
479
+ 'ARCH_FLAG' => "#$ARCH_FLAG",
480
+ 'LDFLAGS' => "#$LDFLAGS #{ldflags}",
481
+ 'LOCAL_LIBS' => "#$LOCAL_LIBS #$libs",
482
+ 'LIBS' => "#{librubyarg} #{opt} #$LIBS")
483
+ conf['LIBPATH'] = libpathflag(libpath.map {|s| RbConfig::expand(s.dup, conf)})
484
+ RbConfig::expand(TRY_LINK.dup, conf)
485
+ end
486
+
487
+ def cc_command(opt="")
488
+ conf = RbConfig::CONFIG.merge('hdrdir' => $hdrdir.quote, 'srcdir' => $srcdir.quote,
489
+ 'arch_hdrdir' => $arch_hdrdir.quote,
490
+ 'top_srcdir' => $top_srcdir.quote)
491
+ RbConfig::expand("$(CC) #$INCFLAGS #$CPPFLAGS #$CFLAGS #$ARCH_FLAG #{opt} -c #{CONFTEST_C}",
492
+ conf)
493
+ end
494
+
495
+ def cpp_command(outfile, opt="")
496
+ conf = RbConfig::CONFIG.merge('hdrdir' => $hdrdir.quote, 'srcdir' => $srcdir.quote,
497
+ 'arch_hdrdir' => $arch_hdrdir.quote,
498
+ 'top_srcdir' => $top_srcdir.quote)
499
+ if $universal and (arch_flag = conf['ARCH_FLAG']) and !arch_flag.empty?
500
+ conf['ARCH_FLAG'] = arch_flag.gsub(/(?:\G|\s)-arch\s+\S+/, '')
501
+ end
502
+ RbConfig::expand("$(CPP) #$INCFLAGS #$CPPFLAGS #$CFLAGS #{opt} #{CONFTEST_C} #{outfile}",
503
+ conf)
504
+ end
505
+
506
+ def libpathflag(libpath=$DEFLIBPATH|$LIBPATH)
507
+ libpath.map{|x|
508
+ case x
509
+ when "$(topdir)", /\A\./
510
+ LIBPATHFLAG
511
+ else
512
+ LIBPATHFLAG+RPATHFLAG
513
+ end % x.quote
514
+ }.join
515
+ end
516
+
517
+ def with_werror(opt, opts = nil)
518
+ if opts
519
+ if opts[:werror] and config_string("WERRORFLAG") {|flag| opt = opt ? "#{opt} #{flag}" : flag}
520
+ (opts = opts.dup).delete(:werror)
521
+ end
522
+ yield(opt, opts)
523
+ else
524
+ yield(opt)
525
+ end
526
+ end
527
+
528
+ def try_link0(src, opt="", *opts, &b) # :nodoc:
529
+ cmd = link_command("", opt)
530
+ if $universal
531
+ require 'tmpdir'
532
+ Dir.mktmpdir("mkmf_", oldtmpdir = ENV["TMPDIR"]) do |tmpdir|
533
+ begin
534
+ ENV["TMPDIR"] = tmpdir
535
+ try_do(src, cmd, *opts, &b)
536
+ ensure
537
+ ENV["TMPDIR"] = oldtmpdir
538
+ end
539
+ end
540
+ else
541
+ try_do(src, cmd, *opts, &b)
542
+ end and File.executable?(CONFTEST+$EXEEXT)
543
+ end
544
+
545
+ # Returns whether or not the +src+ can be compiled as a C source and linked
546
+ # with its depending libraries successfully. +opt+ is passed to the linker
547
+ # as options. Note that +$CFLAGS+ and +$LDFLAGS+ are also passed to the
548
+ # linker.
549
+ #
550
+ # If a block given, it is called with the source before compilation. You can
551
+ # modify the source in the block.
552
+ #
553
+ # [+src+] a String which contains a C source
554
+ # [+opt+] a String which contains linker options
555
+ def try_link(src, opt="", *opts, &b)
556
+ try_link0(src, opt, *opts, &b)
557
+ ensure
558
+ MakeMakefile.rm_f "#{CONFTEST}*", "c0x32*"
559
+ end
560
+
561
+ # Returns whether or not the +src+ can be compiled as a C source. +opt+ is
562
+ # passed to the C compiler as options. Note that +$CFLAGS+ is also passed to
563
+ # the compiler.
564
+ #
565
+ # If a block given, it is called with the source before compilation. You can
566
+ # modify the source in the block.
567
+ #
568
+ # [+src+] a String which contains a C source
569
+ # [+opt+] a String which contains compiler options
570
+ def try_compile(src, opt="", *opts, &b)
571
+ with_werror(opt, *opts) {|_opt, *| try_do(src, cc_command(_opt), *opts, &b)} and
572
+ File.file?("#{CONFTEST}.#{$OBJEXT}")
573
+ ensure
574
+ MakeMakefile.rm_f "#{CONFTEST}*"
575
+ end
576
+
577
+ # Returns whether or not the +src+ can be preprocessed with the C
578
+ # preprocessor. +opt+ is passed to the preprocessor as options. Note that
579
+ # +$CFLAGS+ is also passed to the preprocessor.
580
+ #
581
+ # If a block given, it is called with the source before preprocessing. You
582
+ # can modify the source in the block.
583
+ #
584
+ # [+src+] a String which contains a C source
585
+ # [+opt+] a String which contains preprocessor options
586
+ def try_cpp(src, opt="", *opts, &b)
587
+ try_do(src, cpp_command(CPPOUTFILE, opt), *opts, &b) and
588
+ File.file?("#{CONFTEST}.i")
589
+ ensure
590
+ MakeMakefile.rm_f "#{CONFTEST}*"
591
+ end
592
+
593
+ alias_method :try_header, (config_string('try_header') || :try_cpp)
594
+
595
+ def cpp_include(header)
596
+ if header
597
+ header = [header] unless header.kind_of? Array
598
+ header.map {|h| String === h ? "#include <#{h}>\n" : h}.join
599
+ else
600
+ ""
601
+ end
602
+ end
603
+
604
+ def with_cppflags(flags)
605
+ cppflags = $CPPFLAGS
606
+ $CPPFLAGS = flags
607
+ ret = yield
608
+ ensure
609
+ $CPPFLAGS = cppflags unless ret
610
+ end
611
+
612
+ def try_cppflags(flags, opts = {})
613
+ try_header(MAIN_DOES_NOTHING, flags, {:werror => true}.update(opts))
614
+ end
615
+
616
+ def append_cppflags(flags, *opts)
617
+ Array(flags).each do |flag|
618
+ if checking_for("whether #{flag} is accepted as CPPFLAGS") {
619
+ try_cppflags(flag, *opts)
620
+ }
621
+ $CPPFLAGS << " " << flag
622
+ end
623
+ end
624
+ end
625
+
626
+ def with_cflags(flags)
627
+ cflags = $CFLAGS
628
+ $CFLAGS = flags
629
+ ret = yield
630
+ ensure
631
+ $CFLAGS = cflags unless ret
632
+ end
633
+
634
+ def try_cflags(flags, opts = {})
635
+ try_compile(MAIN_DOES_NOTHING, flags, {:werror => true}.update(opts))
636
+ end
637
+
638
+ def append_cflags(flags, *opts)
639
+ Array(flags).each do |flag|
640
+ if checking_for("whether #{flag} is accepted as CFLAGS") {
641
+ try_cflags(flag, *opts)
642
+ }
643
+ $CFLAGS << " " << flag
644
+ end
645
+ end
646
+ end
647
+
648
+ def with_ldflags(flags)
649
+ ldflags = $LDFLAGS
650
+ $LDFLAGS = flags
651
+ ret = yield
652
+ ensure
653
+ $LDFLAGS = ldflags unless ret
654
+ end
655
+
656
+ def try_ldflags(flags, opts = {})
657
+ try_link(MAIN_DOES_NOTHING, flags, {:werror => true}.update(opts))
658
+ end
659
+
660
+ def append_ldflags(flags, *opts)
661
+ Array(flags).each do |flag|
662
+ if checking_for("whether #{flag} is accepted as LDFLAGS") {
663
+ try_ldflags(flag, *opts)
664
+ }
665
+ $LDFLAGS << " " << flag
666
+ end
667
+ end
668
+ end
669
+
670
+ def try_static_assert(expr, headers = nil, opt = "", &b)
671
+ headers = cpp_include(headers)
672
+ try_compile(<<SRC, opt, &b)
673
+ #{headers}
674
+ /*top*/
675
+ int conftest_const[(#{expr}) ? 1 : -1];
676
+ SRC
677
+ end
678
+
679
+ def try_constant(const, headers = nil, opt = "", &b)
680
+ includes = cpp_include(headers)
681
+ neg = try_static_assert("#{const} < 0", headers, opt)
682
+ if CROSS_COMPILING
683
+ if neg
684
+ const = "-(#{const})"
685
+ elsif try_static_assert("#{const} > 0", headers, opt)
686
+ # positive constant
687
+ elsif try_static_assert("#{const} == 0", headers, opt)
688
+ return 0
689
+ else
690
+ # not a constant
691
+ return nil
692
+ end
693
+ upper = 1
694
+ until try_static_assert("#{const} <= #{upper}", headers, opt)
695
+ lower = upper
696
+ upper <<= 1
697
+ end
698
+ return nil unless lower
699
+ while upper > lower + 1
700
+ mid = (upper + lower) / 2
701
+ if try_static_assert("#{const} > #{mid}", headers, opt)
702
+ lower = mid
703
+ else
704
+ upper = mid
705
+ end
706
+ end
707
+ upper = -upper if neg
708
+ return upper
709
+ else
710
+ src = %{#{includes}
711
+ #include <stdio.h>
712
+ /*top*/
713
+ typedef#{neg ? '' : ' unsigned'}
714
+ #ifdef PRI_LL_PREFIX
715
+ #define PRI_CONFTEST_PREFIX PRI_LL_PREFIX
716
+ LONG_LONG
717
+ #else
718
+ #define PRI_CONFTEST_PREFIX "l"
719
+ long
720
+ #endif
721
+ conftest_type;
722
+ conftest_type conftest_const = (conftest_type)(#{const});
723
+ int main() {printf("%"PRI_CONFTEST_PREFIX"#{neg ? 'd' : 'u'}\\n", conftest_const); return 0;}
724
+ }
725
+ begin
726
+ if try_link0(src, opt, &b)
727
+ xpopen("./#{CONFTEST}") do |f|
728
+ return Integer(f.gets)
729
+ end
730
+ end
731
+ ensure
732
+ MakeMakefile.rm_f "#{CONFTEST}*"
733
+ end
734
+ end
735
+ nil
736
+ end
737
+
738
+ # You should use +have_func+ rather than +try_func+.
739
+ #
740
+ # [+func+] a String which contains a symbol name
741
+ # [+libs+] a String which contains library names.
742
+ # [+headers+] a String or an Array of strings which contains names of header
743
+ # files.
744
+ def try_func(func, libs, headers = nil, opt = "", &b)
745
+ headers = cpp_include(headers)
746
+ case func
747
+ when /^&/
748
+ decltype = proc {|x|"const volatile void *#{x}"}
749
+ when /\)$/
750
+ call = func
751
+ else
752
+ call = "#{func}()"
753
+ decltype = proc {|x| "void ((*#{x})())"}
754
+ end
755
+ if opt and !opt.empty?
756
+ [[:to_str], [:join, " "], [:to_s]].each do |meth, *args|
757
+ if opt.respond_to?(meth)
758
+ break opt = opt.send(meth, *args)
759
+ end
760
+ end
761
+ opt = "#{opt} #{libs}"
762
+ else
763
+ opt = libs
764
+ end
765
+ decltype && try_link(<<"SRC", opt, &b) or
766
+ #{headers}
767
+ /*top*/
768
+ extern int t(void);
769
+ #{MAIN_DOES_NOTHING 't'}
770
+ int t(void) { #{decltype["volatile p"]}; p = (#{decltype[]})#{func}; return !p; }
771
+ SRC
772
+ call && try_link(<<"SRC", opt, &b)
773
+ #{headers}
774
+ /*top*/
775
+ extern int t(void);
776
+ #{MAIN_DOES_NOTHING 't'}
777
+ #{"extern void #{call};" if decltype}
778
+ int t(void) { #{call}; return 0; }
779
+ SRC
780
+ end
781
+
782
+ # You should use +have_var+ rather than +try_var+.
783
+ def try_var(var, headers = nil, opt = "", &b)
784
+ headers = cpp_include(headers)
785
+ try_compile(<<"SRC", opt, &b)
786
+ #{headers}
787
+ /*top*/
788
+ extern int t(void);
789
+ #{MAIN_DOES_NOTHING 't'}
790
+ int t(void) { const volatile void *volatile p; p = &(&#{var})[0]; return !p; }
791
+ SRC
792
+ end
793
+
794
+ # Returns whether or not the +src+ can be preprocessed with the C
795
+ # preprocessor and matches with +pat+.
796
+ #
797
+ # If a block given, it is called with the source before compilation. You can
798
+ # modify the source in the block.
799
+ #
800
+ # [+pat+] a Regexp or a String
801
+ # [+src+] a String which contains a C source
802
+ # [+opt+] a String which contains preprocessor options
803
+ #
804
+ # NOTE: When pat is a Regexp the matching will be checked in process,
805
+ # otherwise egrep(1) will be invoked to check it.
806
+ def egrep_cpp(pat, src, opt = "", &b)
807
+ src = create_tmpsrc(src, &b)
808
+ xpopen(cpp_command('', opt)) do |f|
809
+ if Regexp === pat
810
+ puts(" ruby -ne 'print if #{pat.inspect}'")
811
+ f.grep(pat) {|l|
812
+ puts "#{f.lineno}: #{l}"
813
+ return true
814
+ }
815
+ false
816
+ else
817
+ puts(" egrep '#{pat}'")
818
+ begin
819
+ stdin = $stdin.dup
820
+ $stdin.reopen(f)
821
+ system("egrep", pat)
822
+ ensure
823
+ $stdin.reopen(stdin)
824
+ end
825
+ end
826
+ end
827
+ ensure
828
+ MakeMakefile.rm_f "#{CONFTEST}*"
829
+ log_src(src)
830
+ end
831
+
832
+ # This is used internally by the have_macro? method.
833
+ def macro_defined?(macro, src, opt = "", &b)
834
+ src = src.sub(/[^\n]\z/, "\\&\n")
835
+ try_compile(src + <<"SRC", opt, &b)
836
+ /*top*/
837
+ #ifndef #{macro}
838
+ # error
839
+ |:/ === #{macro} undefined === /:|
840
+ #endif
841
+ SRC
842
+ end
843
+
844
+ # Returns whether or not:
845
+ # * the +src+ can be compiled as a C source,
846
+ # * the result object can be linked with its depending libraries
847
+ # successfully,
848
+ # * the linked file can be invoked as an executable
849
+ # * and the executable exits successfully
850
+ #
851
+ # +opt+ is passed to the linker as options. Note that +$CFLAGS+ and
852
+ # +$LDFLAGS+ are also passed to the linker.
853
+ #
854
+ # If a block given, it is called with the source before compilation. You can
855
+ # modify the source in the block.
856
+ #
857
+ # [+src+] a String which contains a C source
858
+ # [+opt+] a String which contains linker options
859
+ #
860
+ # Returns true when the executable exits successfully, false when it fails,
861
+ # or nil when preprocessing, compilation or link fails.
862
+ def try_run(src, opt = "", &b)
863
+ raise "cannot run test program while cross compiling" if CROSS_COMPILING
864
+ if try_link0(src, opt, &b)
865
+ xsystem("./#{CONFTEST}")
866
+ else
867
+ nil
868
+ end
869
+ ensure
870
+ MakeMakefile.rm_f "#{CONFTEST}*"
871
+ end
872
+
873
+ def install_files(mfile, ifiles, map = nil, srcprefix = nil)
874
+ ifiles or return
875
+ ifiles.empty? and return
876
+ srcprefix ||= "$(srcdir)/#{srcprefix}".chomp('/')
877
+ RbConfig::expand(srcdir = srcprefix.dup)
878
+ dirs = []
879
+ path = Hash.new {|h, i| h[i] = dirs.push([i])[-1]}
880
+ ifiles.each do |files, dir, prefix|
881
+ dir = map_dir(dir, map)
882
+ prefix &&= %r|\A#{Regexp.quote(prefix)}/?|
883
+ if /\A\.\// =~ files
884
+ # install files which are in current working directory.
885
+ files = files[2..-1]
886
+ len = nil
887
+ else
888
+ # install files which are under the $(srcdir).
889
+ files = File.join(srcdir, files)
890
+ len = srcdir.size
891
+ end
892
+ f = nil
893
+ Dir.glob(files) do |fx|
894
+ f = fx
895
+ f[0..len] = "" if len
896
+ case File.basename(f)
897
+ when *$NONINSTALLFILES
898
+ next
899
+ end
900
+ d = File.dirname(f)
901
+ d.sub!(prefix, "") if prefix
902
+ d = (d.empty? || d == ".") ? dir : File.join(dir, d)
903
+ f = File.join(srcprefix, f) if len
904
+ path[d] << f
905
+ end
906
+ unless len or f
907
+ d = File.dirname(files)
908
+ d.sub!(prefix, "") if prefix
909
+ d = (d.empty? || d == ".") ? dir : File.join(dir, d)
910
+ path[d] << files
911
+ end
912
+ end
913
+ dirs
914
+ end
915
+
916
+ def install_rb(mfile, dest, srcdir = nil)
917
+ install_files(mfile, [["lib/**/*.rb", dest, "lib"]], nil, srcdir)
918
+ end
919
+
920
+ def append_library(libs, lib) # :no-doc:
921
+ format(LIBARG, lib) + " " + libs
922
+ end
923
+
924
+ def message(*s)
925
+ unless Logging.quiet and not $VERBOSE
926
+ printf(*s)
927
+ $stdout.flush
928
+ end
929
+ end
930
+
931
+ # This emits a string to stdout that allows users to see the results of the
932
+ # various have* and find* methods as they are tested.
933
+ #
934
+ # Internal use only.
935
+ #
936
+ def checking_for(m, fmt = nil)
937
+ f = caller[0][/in `([^<].*)'$/, 1] and f << ": " #` for vim #'
938
+ m = "checking #{/\Acheck/ =~ f ? '' : 'for '}#{m}... "
939
+ message "%s", m
940
+ a = r = nil
941
+ Logging::postpone do
942
+ r = yield
943
+ a = (fmt ? "#{fmt % r}" : r ? "yes" : "no") << "\n"
944
+ "#{f}#{m}-------------------- #{a}\n"
945
+ end
946
+ message(a)
947
+ Logging::message "--------------------\n\n"
948
+ r
949
+ end
950
+
951
+ def checking_message(target, place = nil, opt = nil)
952
+ [["in", place], ["with", opt]].inject("#{target}") do |msg, (pre, noun)|
953
+ if noun
954
+ [[:to_str], [:join, ","], [:to_s]].each do |meth, *args|
955
+ if noun.respond_to?(meth)
956
+ break noun = noun.send(meth, *args)
957
+ end
958
+ end
959
+ msg << " #{pre} #{noun}" unless noun.empty?
960
+ end
961
+ msg
962
+ end
963
+ end
964
+
965
+ # :startdoc:
966
+
967
+ # Returns whether or not +macro+ is defined either in the common header
968
+ # files or within any +headers+ you provide.
969
+ #
970
+ # Any options you pass to +opt+ are passed along to the compiler.
971
+ #
972
+ def have_macro(macro, headers = nil, opt = "", &b)
973
+ checking_for checking_message(macro, headers, opt) do
974
+ macro_defined?(macro, cpp_include(headers), opt, &b)
975
+ end
976
+ end
977
+
978
+ # Returns whether or not the given entry point +func+ can be found within
979
+ # +lib+. If +func+ is +nil+, the <code>main()</code> entry point is used by
980
+ # default. If found, it adds the library to list of libraries to be used
981
+ # when linking your extension.
982
+ #
983
+ # If +headers+ are provided, it will include those header files as the
984
+ # header files it looks in when searching for +func+.
985
+ #
986
+ # The real name of the library to be linked can be altered by
987
+ # <code>--with-FOOlib</code> configuration option.
988
+ #
989
+ def have_library(lib, func = nil, headers = nil, opt = "", &b)
990
+ func = "main" if !func or func.empty?
991
+ lib = with_config(lib+'lib', lib)
992
+ checking_for checking_message(func.funcall_style, LIBARG%lib, opt) do
993
+ if COMMON_LIBS.include?(lib)
994
+ true
995
+ else
996
+ libs = append_library($libs, lib)
997
+ if try_func(func, libs, headers, opt, &b)
998
+ $libs = libs
999
+ true
1000
+ else
1001
+ false
1002
+ end
1003
+ end
1004
+ end
1005
+ end
1006
+
1007
+ # Returns whether or not the entry point +func+ can be found within the
1008
+ # library +lib+ in one of the +paths+ specified, where +paths+ is an array
1009
+ # of strings. If +func+ is +nil+ , then the <code>main()</code> function is
1010
+ # used as the entry point.
1011
+ #
1012
+ # If +lib+ is found, then the path it was found on is added to the list of
1013
+ # library paths searched and linked against.
1014
+ #
1015
+ def find_library(lib, func, *paths, &b)
1016
+ func = "main" if !func or func.empty?
1017
+ lib = with_config(lib+'lib', lib)
1018
+ paths = paths.collect {|path| path.split(File::PATH_SEPARATOR)}.flatten
1019
+ checking_for checking_message(func.funcall_style, LIBARG%lib) do
1020
+ libpath = $LIBPATH
1021
+ libs = append_library($libs, lib)
1022
+ begin
1023
+ until r = try_func(func, libs, &b) or paths.empty?
1024
+ $LIBPATH = libpath | [paths.shift]
1025
+ end
1026
+ if r
1027
+ $libs = libs
1028
+ libpath = nil
1029
+ end
1030
+ ensure
1031
+ $LIBPATH = libpath if libpath
1032
+ end
1033
+ r
1034
+ end
1035
+ end
1036
+
1037
+ # Returns whether or not the function +func+ can be found in the common
1038
+ # header files, or within any +headers+ that you provide. If found, a macro
1039
+ # is passed as a preprocessor constant to the compiler using the function
1040
+ # name, in uppercase, prepended with +HAVE_+.
1041
+ #
1042
+ # To check functions in an additional library, you need to check that
1043
+ # library first using <code>have_library()</code>. The +func+ shall be
1044
+ # either mere function name or function name with arguments.
1045
+ #
1046
+ # For example, if <code>have_func('foo')</code> returned +true+, then the
1047
+ # +HAVE_FOO+ preprocessor macro would be passed to the compiler.
1048
+ #
1049
+ def have_func(func, headers = nil, opt = "", &b)
1050
+ checking_for checking_message(func.funcall_style, headers, opt) do
1051
+ if try_func(func, $libs, headers, opt, &b)
1052
+ $defs << "-DHAVE_#{func.sans_arguments.tr_cpp}"
1053
+ true
1054
+ else
1055
+ false
1056
+ end
1057
+ end
1058
+ end
1059
+
1060
+ # Returns whether or not the variable +var+ can be found in the common
1061
+ # header files, or within any +headers+ that you provide. If found, a macro
1062
+ # is passed as a preprocessor constant to the compiler using the variable
1063
+ # name, in uppercase, prepended with +HAVE_+.
1064
+ #
1065
+ # To check variables in an additional library, you need to check that
1066
+ # library first using <code>have_library()</code>.
1067
+ #
1068
+ # For example, if <code>have_var('foo')</code> returned true, then the
1069
+ # +HAVE_FOO+ preprocessor macro would be passed to the compiler.
1070
+ #
1071
+ def have_var(var, headers = nil, opt = "", &b)
1072
+ checking_for checking_message(var, headers, opt) do
1073
+ if try_var(var, headers, opt, &b)
1074
+ $defs.push(format("-DHAVE_%s", var.tr_cpp))
1075
+ true
1076
+ else
1077
+ false
1078
+ end
1079
+ end
1080
+ end
1081
+
1082
+ # Returns whether or not the given +header+ file can be found on your system.
1083
+ # If found, a macro is passed as a preprocessor constant to the compiler
1084
+ # using the header file name, in uppercase, prepended with +HAVE_+.
1085
+ #
1086
+ # For example, if <code>have_header('foo.h')</code> returned true, then the
1087
+ # +HAVE_FOO_H+ preprocessor macro would be passed to the compiler.
1088
+ #
1089
+ def have_header(header, preheaders = nil, opt = "", &b)
1090
+ checking_for header do
1091
+ if try_header(cpp_include(preheaders)+cpp_include(header), opt, &b)
1092
+ $defs.push(format("-DHAVE_%s", header.tr_cpp))
1093
+ true
1094
+ else
1095
+ false
1096
+ end
1097
+ end
1098
+ end
1099
+
1100
+ # Returns whether or not the given +framework+ can be found on your system.
1101
+ # If found, a macro is passed as a preprocessor constant to the compiler
1102
+ # using the framework name, in uppercase, prepended with +HAVE_FRAMEWORK_+.
1103
+ #
1104
+ # For example, if <code>have_framework('Ruby')</code> returned true, then
1105
+ # the +HAVE_FRAMEWORK_RUBY+ preprocessor macro would be passed to the
1106
+ # compiler.
1107
+ #
1108
+ # If +fw+ is a pair of the framework name and its header file name
1109
+ # that header file is checked, instead of the normally used header
1110
+ # file which is named same as the framework.
1111
+ def have_framework(fw, &b)
1112
+ if Array === fw
1113
+ fw, header = *fw
1114
+ else
1115
+ header = "#{fw}.h"
1116
+ end
1117
+ checking_for fw do
1118
+ src = cpp_include("#{fw}/#{header}") << "\n" "int main(void){return 0;}"
1119
+ opt = " -framework #{fw}"
1120
+ if try_link(src, opt, &b) or (objc = try_link(src, "-ObjC#{opt}", &b))
1121
+ $defs.push(format("-DHAVE_FRAMEWORK_%s", fw.tr_cpp))
1122
+ # TODO: non-worse way than this hack, to get rid of separating
1123
+ # option and its argument.
1124
+ $LDFLAGS << " -ObjC" if objc and /(\A|\s)-ObjC(\s|\z)/ !~ $LDFLAGS
1125
+ $LIBS << opt
1126
+ true
1127
+ else
1128
+ false
1129
+ end
1130
+ end
1131
+ end
1132
+
1133
+ # Instructs mkmf to search for the given +header+ in any of the +paths+
1134
+ # provided, and returns whether or not it was found in those paths.
1135
+ #
1136
+ # If the header is found then the path it was found on is added to the list
1137
+ # of included directories that are sent to the compiler (via the
1138
+ # <code>-I</code> switch).
1139
+ #
1140
+ def find_header(header, *paths)
1141
+ message = checking_message(header, paths)
1142
+ header = cpp_include(header)
1143
+ checking_for message do
1144
+ if try_header(header)
1145
+ true
1146
+ else
1147
+ found = false
1148
+ paths.each do |dir|
1149
+ opt = "-I#{dir}".quote
1150
+ if try_header(header, opt)
1151
+ $INCFLAGS << " " << opt
1152
+ found = true
1153
+ break
1154
+ end
1155
+ end
1156
+ found
1157
+ end
1158
+ end
1159
+ end
1160
+
1161
+ # Returns whether or not the struct of type +type+ contains +member+. If
1162
+ # it does not, or the struct type can't be found, then false is returned.
1163
+ # You may optionally specify additional +headers+ in which to look for the
1164
+ # struct (in addition to the common header files).
1165
+ #
1166
+ # If found, a macro is passed as a preprocessor constant to the compiler
1167
+ # using the type name and the member name, in uppercase, prepended with
1168
+ # +HAVE_+.
1169
+ #
1170
+ # For example, if <code>have_struct_member('struct foo', 'bar')</code>
1171
+ # returned true, then the +HAVE_STRUCT_FOO_BAR+ preprocessor macro would be
1172
+ # passed to the compiler.
1173
+ #
1174
+ # +HAVE_ST_BAR+ is also defined for backward compatibility.
1175
+ #
1176
+ def have_struct_member(type, member, headers = nil, opt = "", &b)
1177
+ checking_for checking_message("#{type}.#{member}", headers) do
1178
+ if try_compile(<<"SRC", opt, &b)
1179
+ #{cpp_include(headers)}
1180
+ /*top*/
1181
+ int s = (char *)&((#{type}*)0)->#{member} - (char *)0;
1182
+ #{MAIN_DOES_NOTHING}
1183
+ SRC
1184
+ $defs.push(format("-DHAVE_%s_%s", type.tr_cpp, member.tr_cpp))
1185
+ $defs.push(format("-DHAVE_ST_%s", member.tr_cpp)) # backward compatibility
1186
+ true
1187
+ else
1188
+ false
1189
+ end
1190
+ end
1191
+ end
1192
+
1193
+ # Returns whether or not the static type +type+ is defined.
1194
+ #
1195
+ # See also +have_type+
1196
+ #
1197
+ def try_type(type, headers = nil, opt = "", &b)
1198
+ if try_compile(<<"SRC", opt, &b)
1199
+ #{cpp_include(headers)}
1200
+ /*top*/
1201
+ typedef #{type} conftest_type;
1202
+ int conftestval[sizeof(conftest_type)?1:-1];
1203
+ SRC
1204
+ $defs.push(format("-DHAVE_TYPE_%s", type.tr_cpp))
1205
+ true
1206
+ else
1207
+ false
1208
+ end
1209
+ end
1210
+
1211
+ # Returns whether or not the static type +type+ is defined. You may
1212
+ # optionally pass additional +headers+ to check against in addition to the
1213
+ # common header files.
1214
+ #
1215
+ # You may also pass additional flags to +opt+ which are then passed along to
1216
+ # the compiler.
1217
+ #
1218
+ # If found, a macro is passed as a preprocessor constant to the compiler
1219
+ # using the type name, in uppercase, prepended with +HAVE_TYPE_+.
1220
+ #
1221
+ # For example, if <code>have_type('foo')</code> returned true, then the
1222
+ # +HAVE_TYPE_FOO+ preprocessor macro would be passed to the compiler.
1223
+ #
1224
+ def have_type(type, headers = nil, opt = "", &b)
1225
+ checking_for checking_message(type, headers, opt) do
1226
+ try_type(type, headers, opt, &b)
1227
+ end
1228
+ end
1229
+
1230
+ # Returns where the static type +type+ is defined.
1231
+ #
1232
+ # You may also pass additional flags to +opt+ which are then passed along to
1233
+ # the compiler.
1234
+ #
1235
+ # See also +have_type+.
1236
+ #
1237
+ def find_type(type, opt, *headers, &b)
1238
+ opt ||= ""
1239
+ fmt = "not found"
1240
+ def fmt.%(x)
1241
+ x ? x.respond_to?(:join) ? x.join(",") : x : self
1242
+ end
1243
+ checking_for checking_message(type, nil, opt), fmt do
1244
+ headers.find do |h|
1245
+ try_type(type, h, opt, &b)
1246
+ end
1247
+ end
1248
+ end
1249
+
1250
+ # Returns whether or not the constant +const+ is defined.
1251
+ #
1252
+ # See also +have_const+
1253
+ #
1254
+ def try_const(const, headers = nil, opt = "", &b)
1255
+ const, type = *const
1256
+ if try_compile(<<"SRC", opt, &b)
1257
+ #{cpp_include(headers)}
1258
+ /*top*/
1259
+ typedef #{type || 'int'} conftest_type;
1260
+ conftest_type conftestval = #{type ? '' : '(int)'}#{const};
1261
+ SRC
1262
+ $defs.push(format("-DHAVE_CONST_%s", const.tr_cpp))
1263
+ true
1264
+ else
1265
+ false
1266
+ end
1267
+ end
1268
+
1269
+ # Returns whether or not the constant +const+ is defined. You may
1270
+ # optionally pass the +type+ of +const+ as <code>[const, type]</code>,
1271
+ # such as:
1272
+ #
1273
+ # have_const(%w[PTHREAD_MUTEX_INITIALIZER pthread_mutex_t], "pthread.h")
1274
+ #
1275
+ # You may also pass additional +headers+ to check against in addition to the
1276
+ # common header files, and additional flags to +opt+ which are then passed
1277
+ # along to the compiler.
1278
+ #
1279
+ # If found, a macro is passed as a preprocessor constant to the compiler
1280
+ # using the type name, in uppercase, prepended with +HAVE_CONST_+.
1281
+ #
1282
+ # For example, if <code>have_const('foo')</code> returned true, then the
1283
+ # +HAVE_CONST_FOO+ preprocessor macro would be passed to the compiler.
1284
+ #
1285
+ def have_const(const, headers = nil, opt = "", &b)
1286
+ checking_for checking_message([*const].compact.join(' '), headers, opt) do
1287
+ try_const(const, headers, opt, &b)
1288
+ end
1289
+ end
1290
+
1291
+ # :stopdoc:
1292
+ STRING_OR_FAILED_FORMAT = "%s"
1293
+ def STRING_OR_FAILED_FORMAT.%(x) # :nodoc:
1294
+ x ? super : "failed"
1295
+ end
1296
+
1297
+ def typedef_expr(type, headers)
1298
+ typename, member = type.split('.', 2)
1299
+ prelude = cpp_include(headers).split(/$/)
1300
+ prelude << "typedef #{typename} rbcv_typedef_;\n"
1301
+ return "rbcv_typedef_", member, prelude
1302
+ end
1303
+
1304
+ def try_signedness(type, member, headers = nil, opts = nil)
1305
+ raise ArgumentError, "don't know how to tell signedness of members" if member
1306
+ if try_static_assert("(#{type})-1 < 0", headers, opts)
1307
+ return -1
1308
+ elsif try_static_assert("(#{type})-1 > 0", headers, opts)
1309
+ return +1
1310
+ end
1311
+ end
1312
+
1313
+ # :startdoc:
1314
+
1315
+ # Returns the size of the given +type+. You may optionally specify
1316
+ # additional +headers+ to search in for the +type+.
1317
+ #
1318
+ # If found, a macro is passed as a preprocessor constant to the compiler
1319
+ # using the type name, in uppercase, prepended with +SIZEOF_+, followed by
1320
+ # the type name, followed by <code>=X</code> where "X" is the actual size.
1321
+ #
1322
+ # For example, if <code>check_sizeof('mystruct')</code> returned 12, then
1323
+ # the <code>SIZEOF_MYSTRUCT=12</code> preprocessor macro would be passed to
1324
+ # the compiler.
1325
+ #
1326
+ def check_sizeof(type, headers = nil, opts = "", &b)
1327
+ typedef, member, prelude = typedef_expr(type, headers)
1328
+ prelude << "#{typedef} *rbcv_ptr_;\n"
1329
+ prelude = [prelude]
1330
+ expr = "sizeof((*rbcv_ptr_)#{"." << member if member})"
1331
+ fmt = STRING_OR_FAILED_FORMAT
1332
+ checking_for checking_message("size of #{type}", headers), fmt do
1333
+ if size = try_constant(expr, prelude, opts, &b)
1334
+ $defs.push(format("-DSIZEOF_%s=%s", type.tr_cpp, size))
1335
+ size
1336
+ end
1337
+ end
1338
+ end
1339
+
1340
+ # Returns the signedness of the given +type+. You may optionally specify
1341
+ # additional +headers+ to search in for the +type+.
1342
+ #
1343
+ # If the +type+ is found and is a numeric type, a macro is passed as a
1344
+ # preprocessor constant to the compiler using the +type+ name, in uppercase,
1345
+ # prepended with +SIGNEDNESS_OF_+, followed by the +type+ name, followed by
1346
+ # <code>=X</code> where "X" is positive integer if the +type+ is unsigned
1347
+ # and a negative integer if the +type+ is signed.
1348
+ #
1349
+ # For example, if +size_t+ is defined as unsigned, then
1350
+ # <code>check_signedness('size_t')</code> would return +1 and the
1351
+ # <code>SIGNEDNESS_OF_SIZE_T=+1</code> preprocessor macro would be passed to
1352
+ # the compiler. The <code>SIGNEDNESS_OF_INT=-1</code> macro would be set
1353
+ # for <code>check_signedness('int')</code>
1354
+ #
1355
+ def check_signedness(type, headers = nil, opts = nil, &b)
1356
+ typedef, member, prelude = typedef_expr(type, headers)
1357
+ signed = nil
1358
+ checking_for("signedness of #{type}", STRING_OR_FAILED_FORMAT) do
1359
+ signed = try_signedness(typedef, member, [prelude], opts, &b) or next nil
1360
+ $defs.push("-DSIGNEDNESS_OF_%s=%+d" % [type.tr_cpp, signed])
1361
+ signed < 0 ? "signed" : "unsigned"
1362
+ end
1363
+ signed
1364
+ end
1365
+
1366
+ # Returns the convertible integer type of the given +type+. You may
1367
+ # optionally specify additional +headers+ to search in for the +type+.
1368
+ # _convertible_ means actually the same type, or typedef'd from the same
1369
+ # type.
1370
+ #
1371
+ # If the +type+ is a integer type and the _convertible_ type is found,
1372
+ # the following macros are passed as preprocessor constants to the compiler
1373
+ # using the +type+ name, in uppercase.
1374
+ #
1375
+ # * +TYPEOF_+, followed by the +type+ name, followed by <code>=X</code>
1376
+ # where "X" is the found _convertible_ type name.
1377
+ # * +TYP2NUM+ and +NUM2TYP+,
1378
+ # where +TYP+ is the +type+ name in uppercase with replacing an +_t+
1379
+ # suffix with "T", followed by <code>=X</code> where "X" is the macro name
1380
+ # to convert +type+ to an Integer object, and vice versa.
1381
+ #
1382
+ # For example, if +foobar_t+ is defined as unsigned long, then
1383
+ # <code>convertible_int("foobar_t")</code> would return "unsigned long", and
1384
+ # define these macros:
1385
+ #
1386
+ # #define TYPEOF_FOOBAR_T unsigned long
1387
+ # #define FOOBART2NUM ULONG2NUM
1388
+ # #define NUM2FOOBART NUM2ULONG
1389
+ #
1390
+ def convertible_int(type, headers = nil, opts = nil, &b)
1391
+ type, macname = *type
1392
+ checking_for("convertible type of #{type}", STRING_OR_FAILED_FORMAT) do
1393
+ if UNIVERSAL_INTS.include?(type)
1394
+ type
1395
+ else
1396
+ typedef, member, prelude = typedef_expr(type, headers, &b)
1397
+ if member
1398
+ prelude << "static rbcv_typedef_ rbcv_var;"
1399
+ compat = UNIVERSAL_INTS.find {|t|
1400
+ try_static_assert("sizeof(rbcv_var.#{member}) == sizeof(#{t})", [prelude], opts, &b)
1401
+ }
1402
+ else
1403
+ next unless signed = try_signedness(typedef, member, [prelude])
1404
+ u = "unsigned " if signed > 0
1405
+ prelude << "extern rbcv_typedef_ foo();"
1406
+ compat = UNIVERSAL_INTS.find {|t|
1407
+ try_compile([prelude, "extern #{u}#{t} foo();"].join("\n"), opts, :werror=>true, &b)
1408
+ }
1409
+ end
1410
+ if compat
1411
+ macname ||= type.sub(/_(?=t\z)/, '').tr_cpp
1412
+ conv = (compat == "long long" ? "LL" : compat.upcase)
1413
+ compat = "#{u}#{compat}"
1414
+ typename = type.tr_cpp
1415
+ $defs.push(format("-DSIZEOF_%s=SIZEOF_%s", typename, compat.tr_cpp))
1416
+ $defs.push(format("-DTYPEOF_%s=%s", typename, compat.quote))
1417
+ $defs.push(format("-DPRI_%s_PREFIX=PRI_%s_PREFIX", macname, conv))
1418
+ conv = (u ? "U" : "") + conv
1419
+ $defs.push(format("-D%s2NUM=%s2NUM", macname, conv))
1420
+ $defs.push(format("-DNUM2%s=NUM2%s", macname, conv))
1421
+ compat
1422
+ end
1423
+ end
1424
+ end
1425
+ end
1426
+ # :stopdoc:
1427
+
1428
+ # Used internally by the what_type? method to determine if +type+ is a scalar
1429
+ # pointer.
1430
+ def scalar_ptr_type?(type, member = nil, headers = nil, &b)
1431
+ try_compile(<<"SRC", &b) # pointer
1432
+ #{cpp_include(headers)}
1433
+ /*top*/
1434
+ volatile #{type} conftestval;
1435
+ extern int t(void);
1436
+ #{MAIN_DOES_NOTHING 't'}
1437
+ int t(void) {return (int)(1-*(conftestval#{member ? ".#{member}" : ""}));}
1438
+ SRC
1439
+ end
1440
+
1441
+ # Used internally by the what_type? method to determine if +type+ is a scalar
1442
+ # pointer.
1443
+ def scalar_type?(type, member = nil, headers = nil, &b)
1444
+ try_compile(<<"SRC", &b) # pointer
1445
+ #{cpp_include(headers)}
1446
+ /*top*/
1447
+ volatile #{type} conftestval;
1448
+ extern int t(void);
1449
+ #{MAIN_DOES_NOTHING 't'}
1450
+ int t(void) {return (int)(1-(conftestval#{member ? ".#{member}" : ""}));}
1451
+ SRC
1452
+ end
1453
+
1454
+ # Used internally by the what_type? method to check if the _typeof_ GCC
1455
+ # extension is available.
1456
+ def have_typeof?
1457
+ return $typeof if defined?($typeof)
1458
+ $typeof = %w[__typeof__ typeof].find do |t|
1459
+ try_compile(<<SRC)
1460
+ int rbcv_foo;
1461
+ #{t}(rbcv_foo) rbcv_bar;
1462
+ SRC
1463
+ end
1464
+ end
1465
+
1466
+ def what_type?(type, member = nil, headers = nil, &b)
1467
+ m = "#{type}"
1468
+ var = val = "*rbcv_var_"
1469
+ func = "rbcv_func_(void)"
1470
+ if member
1471
+ m << "." << member
1472
+ else
1473
+ type, member = type.split('.', 2)
1474
+ end
1475
+ if member
1476
+ val = "(#{var}).#{member}"
1477
+ end
1478
+ prelude = [cpp_include(headers).split(/^/)]
1479
+ prelude << ["typedef #{type} rbcv_typedef_;\n",
1480
+ "extern rbcv_typedef_ *#{func};\n",
1481
+ "rbcv_typedef_ #{var};\n",
1482
+ ]
1483
+ type = "rbcv_typedef_"
1484
+ fmt = member && !(typeof = have_typeof?) ? "seems %s" : "%s"
1485
+ if typeof
1486
+ var = "*rbcv_member_"
1487
+ func = "rbcv_mem_func_(void)"
1488
+ member = nil
1489
+ type = "rbcv_mem_typedef_"
1490
+ prelude[-1] << "typedef #{typeof}(#{val}) #{type};\n"
1491
+ prelude[-1] << "extern #{type} *#{func};\n"
1492
+ prelude[-1] << "#{type} #{var};\n"
1493
+ val = var
1494
+ end
1495
+ def fmt.%(x)
1496
+ x ? super : "unknown"
1497
+ end
1498
+ checking_for checking_message(m, headers), fmt do
1499
+ if scalar_ptr_type?(type, member, prelude, &b)
1500
+ if try_static_assert("sizeof(*#{var}) == 1", prelude)
1501
+ return "string"
1502
+ end
1503
+ ptr = "*"
1504
+ elsif scalar_type?(type, member, prelude, &b)
1505
+ unless member and !typeof or try_static_assert("(#{type})-1 < 0", prelude)
1506
+ unsigned = "unsigned"
1507
+ end
1508
+ ptr = ""
1509
+ else
1510
+ next
1511
+ end
1512
+ type = UNIVERSAL_INTS.find do |t|
1513
+ pre = prelude
1514
+ unless member
1515
+ pre += [["#{unsigned} #{t} #{ptr}#{var};\n",
1516
+ "extern #{unsigned} #{t} #{ptr}*#{func};\n"]]
1517
+ end
1518
+ try_static_assert("sizeof(#{ptr}#{val}) == sizeof(#{unsigned} #{t})", pre)
1519
+ end
1520
+ type or next
1521
+ [unsigned, type, ptr].join(" ").strip
1522
+ end
1523
+ end
1524
+
1525
+ # This method is used internally by the find_executable method.
1526
+ #
1527
+ # Internal use only.
1528
+ #
1529
+ def find_executable0(bin, path = nil)
1530
+ executable_file = proc do |name|
1531
+ begin
1532
+ stat = File.stat(name)
1533
+ rescue SystemCallError
1534
+ else
1535
+ next name if stat.file? and stat.executable?
1536
+ end
1537
+ end
1538
+
1539
+ exts = config_string('EXECUTABLE_EXTS') {|s| s.split} || config_string('EXEEXT') {|s| [s]}
1540
+ if File.expand_path(bin) == bin
1541
+ return bin if executable_file.call(bin)
1542
+ if exts
1543
+ exts.each {|ext| executable_file.call(file = bin + ext) and return file}
1544
+ end
1545
+ return nil
1546
+ end
1547
+ if path ||= ENV['PATH']
1548
+ path = path.split(File::PATH_SEPARATOR)
1549
+ else
1550
+ path = %w[/usr/local/bin /usr/ucb /usr/bin /bin]
1551
+ end
1552
+ file = nil
1553
+ path.each do |dir|
1554
+ return file if executable_file.call(file = File.join(dir, bin))
1555
+ if exts
1556
+ exts.each {|ext| executable_file.call(ext = file + ext) and return ext}
1557
+ end
1558
+ end
1559
+ nil
1560
+ end
1561
+
1562
+ # :startdoc:
1563
+
1564
+ # Searches for the executable +bin+ on +path+. The default path is your
1565
+ # +PATH+ environment variable. If that isn't defined, it will resort to
1566
+ # searching /usr/local/bin, /usr/ucb, /usr/bin and /bin.
1567
+ #
1568
+ # If found, it will return the full path, including the executable name, of
1569
+ # where it was found.
1570
+ #
1571
+ # Note that this method does not actually affect the generated Makefile.
1572
+ #
1573
+ def find_executable(bin, path = nil)
1574
+ checking_for checking_message(bin, path) do
1575
+ find_executable0(bin, path)
1576
+ end
1577
+ end
1578
+
1579
+ # :stopdoc:
1580
+
1581
+ def arg_config(config, default=nil, &block)
1582
+ $arg_config << [config, default]
1583
+ defaults = []
1584
+ if default
1585
+ defaults << default
1586
+ elsif !block
1587
+ defaults << nil
1588
+ end
1589
+ $configure_args.fetch(config.tr('_', '-'), *defaults, &block)
1590
+ end
1591
+
1592
+ # :startdoc:
1593
+
1594
+ # Tests for the presence of a <tt>--with-</tt>_config_ or
1595
+ # <tt>--without-</tt>_config_ option. Returns +true+ if the with option is
1596
+ # given, +false+ if the without option is given, and the default value
1597
+ # otherwise.
1598
+ #
1599
+ # This can be useful for adding custom definitions, such as debug
1600
+ # information.
1601
+ #
1602
+ # Example:
1603
+ #
1604
+ # if with_config("debug")
1605
+ # $defs.push("-DOSSL_DEBUG") unless $defs.include? "-DOSSL_DEBUG"
1606
+ # end
1607
+ #
1608
+ def with_config(config, default=nil)
1609
+ config = config.sub(/^--with[-_]/, '')
1610
+ val = arg_config("--with-"+config) do
1611
+ if arg_config("--without-"+config)
1612
+ false
1613
+ elsif block_given?
1614
+ yield(config, default)
1615
+ else
1616
+ break default
1617
+ end
1618
+ end
1619
+ case val
1620
+ when "yes"
1621
+ true
1622
+ when "no"
1623
+ false
1624
+ else
1625
+ val
1626
+ end
1627
+ end
1628
+
1629
+ # Tests for the presence of an <tt>--enable-</tt>_config_ or
1630
+ # <tt>--disable-</tt>_config_ option. Returns +true+ if the enable option is
1631
+ # given, +false+ if the disable option is given, and the default value
1632
+ # otherwise.
1633
+ #
1634
+ # This can be useful for adding custom definitions, such as debug
1635
+ # information.
1636
+ #
1637
+ # Example:
1638
+ #
1639
+ # if enable_config("debug")
1640
+ # $defs.push("-DOSSL_DEBUG") unless $defs.include? "-DOSSL_DEBUG"
1641
+ # end
1642
+ #
1643
+ def enable_config(config, default=nil)
1644
+ if arg_config("--enable-"+config)
1645
+ true
1646
+ elsif arg_config("--disable-"+config)
1647
+ false
1648
+ elsif block_given?
1649
+ yield(config, default)
1650
+ else
1651
+ return default
1652
+ end
1653
+ end
1654
+
1655
+ # Generates a header file consisting of the various macro definitions
1656
+ # generated by other methods such as have_func and have_header. These are
1657
+ # then wrapped in a custom <code>#ifndef</code> based on the +header+ file
1658
+ # name, which defaults to "extconf.h".
1659
+ #
1660
+ # For example:
1661
+ #
1662
+ # # extconf.rb
1663
+ # require 'mkmf'
1664
+ # have_func('realpath')
1665
+ # have_header('sys/utime.h')
1666
+ # create_header
1667
+ # create_makefile('foo')
1668
+ #
1669
+ # The above script would generate the following extconf.h file:
1670
+ #
1671
+ # #ifndef EXTCONF_H
1672
+ # #define EXTCONF_H
1673
+ # #define HAVE_REALPATH 1
1674
+ # #define HAVE_SYS_UTIME_H 1
1675
+ # #endif
1676
+ #
1677
+ # Given that the create_header method generates a file based on definitions
1678
+ # set earlier in your extconf.rb file, you will probably want to make this
1679
+ # one of the last methods you call in your script.
1680
+ #
1681
+ def create_header(header = "extconf.h")
1682
+ message "creating %s\n", header
1683
+ sym = header.tr_cpp
1684
+ hdr = ["#ifndef #{sym}\n#define #{sym}\n"]
1685
+ for line in $defs
1686
+ case line
1687
+ when /^-D([^=]+)(?:=(.*))?/
1688
+ hdr << "#define #$1 #{$2 ? Shellwords.shellwords($2)[0].gsub(/(?=\t+)/, "\\\n") : 1}\n"
1689
+ when /^-U(.*)/
1690
+ hdr << "#undef #$1\n"
1691
+ end
1692
+ end
1693
+ hdr << "#endif\n"
1694
+ hdr = hdr.join("")
1695
+ log_src(hdr, "#{header} is")
1696
+ unless (IO.read(header) == hdr rescue false)
1697
+ open(header, "wb") do |hfile|
1698
+ hfile.write(hdr)
1699
+ end
1700
+ end
1701
+ $extconf_h = header
1702
+ end
1703
+
1704
+ # call-seq:
1705
+ # dir_config(target)
1706
+ # dir_config(target, prefix)
1707
+ # dir_config(target, idefault, ldefault)
1708
+ #
1709
+ # Sets a +target+ name that the user can then use to configure
1710
+ # various "with" options with on the command line by using that
1711
+ # name. For example, if the target is set to "foo", then the user
1712
+ # could use the <code>--with-foo-dir=prefix</code>,
1713
+ # <code>--with-foo-include=dir</code> and
1714
+ # <code>--with-foo-lib=dir</code> command line options to tell where
1715
+ # to search for header/library files.
1716
+ #
1717
+ # You may pass along additional parameters to specify default
1718
+ # values. If one is given it is taken as default +prefix+, and if
1719
+ # two are given they are taken as "include" and "lib" defaults in
1720
+ # that order.
1721
+ #
1722
+ # In any case, the return value will be an array of determined
1723
+ # "include" and "lib" directories, either of which can be nil if no
1724
+ # corresponding command line option is given when no default value
1725
+ # is specified.
1726
+ #
1727
+ # Note that dir_config only adds to the list of places to search for
1728
+ # libraries and include files. It does not link the libraries into your
1729
+ # application.
1730
+ #
1731
+ def dir_config(target, idefault=nil, ldefault=nil)
1732
+ if dir = with_config(target + "-dir", (idefault unless ldefault))
1733
+ defaults = Array === dir ? dir : dir.split(File::PATH_SEPARATOR)
1734
+ idefault = ldefault = nil
1735
+ end
1736
+
1737
+ idir = with_config(target + "-include", idefault)
1738
+ $arg_config.last[1] ||= "${#{target}-dir}/include"
1739
+ ldir = with_config(target + "-lib", ldefault)
1740
+ $arg_config.last[1] ||= "${#{target}-dir}/#{_libdir_basename}"
1741
+
1742
+ idirs = idir ? Array === idir ? idir.dup : idir.split(File::PATH_SEPARATOR) : []
1743
+ if defaults
1744
+ idirs.concat(defaults.collect {|d| d + "/include"})
1745
+ idir = ([idir] + idirs).compact.join(File::PATH_SEPARATOR)
1746
+ end
1747
+ unless idirs.empty?
1748
+ idirs.collect! {|d| "-I" + d}
1749
+ idirs -= Shellwords.shellwords($CPPFLAGS)
1750
+ unless idirs.empty?
1751
+ $CPPFLAGS = (idirs.quote << $CPPFLAGS).join(" ")
1752
+ end
1753
+ end
1754
+
1755
+ ldirs = ldir ? Array === ldir ? ldir.dup : ldir.split(File::PATH_SEPARATOR) : []
1756
+ if defaults
1757
+ ldirs.concat(defaults.collect {|d| "#{d}/#{_libdir_basename}"})
1758
+ ldir = ([ldir] + ldirs).compact.join(File::PATH_SEPARATOR)
1759
+ end
1760
+ $LIBPATH = ldirs | $LIBPATH
1761
+
1762
+ [idir, ldir]
1763
+ end
1764
+
1765
+ # Returns compile/link information about an installed library in a
1766
+ # tuple of <code>[cflags, ldflags, libs]</code>, by using the
1767
+ # command found first in the following commands:
1768
+ #
1769
+ # 1. If <code>--with-{pkg}-config={command}</code> is given via
1770
+ # command line option: <code>{command} {option}</code>
1771
+ #
1772
+ # 2. <code>{pkg}-config {option}</code>
1773
+ #
1774
+ # 3. <code>pkg-config {option} {pkg}</code>
1775
+ #
1776
+ # Where {option} is, for instance, <code>--cflags</code>.
1777
+ #
1778
+ # The values obtained are appended to +$CFLAGS+, +$LDFLAGS+ and
1779
+ # +$libs+.
1780
+ #
1781
+ # If an <code>option</code> argument is given, the config command is
1782
+ # invoked with the option and a stripped output string is returned
1783
+ # without modifying any of the global values mentioned above.
1784
+ def pkg_config(pkg, option=nil)
1785
+ if pkgconfig = with_config("#{pkg}-config") and find_executable0(pkgconfig)
1786
+ # iff package specific config command is given
1787
+ elsif ($PKGCONFIG ||=
1788
+ (pkgconfig = with_config("pkg-config", ("pkg-config" unless CROSS_COMPILING))) &&
1789
+ find_executable0(pkgconfig) && pkgconfig) and
1790
+ xsystem("#{$PKGCONFIG} --exists #{pkg}")
1791
+ # default to pkg-config command
1792
+ pkgconfig = $PKGCONFIG
1793
+ get = proc {|opt|
1794
+ opt = xpopen("#{$PKGCONFIG} --#{opt} #{pkg}", err:[:child, :out], &:read)
1795
+ Logging.open {puts opt.each_line.map{|s|"=> #{s.inspect}"}}
1796
+ opt.strip if $?.success?
1797
+ }
1798
+ elsif find_executable0(pkgconfig = "#{pkg}-config")
1799
+ # default to package specific config command, as a last resort.
1800
+ else
1801
+ pkgconfig = nil
1802
+ end
1803
+ if pkgconfig
1804
+ get ||= proc {|opt|
1805
+ opt = xpopen("#{pkgconfig} --#{opt}", err:[:child, :out], &:read)
1806
+ Logging.open {puts opt.each_line.map{|s|"=> #{s.inspect}"}}
1807
+ opt.strip if $?.success?
1808
+ }
1809
+ end
1810
+ orig_ldflags = $LDFLAGS
1811
+ if get and option
1812
+ get[option]
1813
+ elsif get and try_ldflags(ldflags = get['libs'])
1814
+ if incflags = get['cflags-only-I']
1815
+ $INCFLAGS << " " << incflags
1816
+ cflags = get['cflags-only-other']
1817
+ else
1818
+ cflags = get['cflags']
1819
+ end
1820
+ libs = get['libs-only-l']
1821
+ if cflags
1822
+ $CFLAGS += " " << cflags
1823
+ $CXXFLAGS += " " << cflags
1824
+ end
1825
+ if libs
1826
+ ldflags = (Shellwords.shellwords(ldflags) - Shellwords.shellwords(libs)).quote.join(" ")
1827
+ else
1828
+ libs, ldflags = Shellwords.shellwords(ldflags).partition {|s| s =~ /-l([^ ]+)/ }.map {|l|l.quote.join(" ")}
1829
+ end
1830
+ $libs += " " << libs
1831
+
1832
+ $LDFLAGS = [orig_ldflags, ldflags].join(' ')
1833
+ Logging::message "package configuration for %s\n", pkg
1834
+ Logging::message "cflags: %s\nldflags: %s\nlibs: %s\n\n",
1835
+ cflags, ldflags, libs
1836
+ [cflags, ldflags, libs]
1837
+ else
1838
+ Logging::message "package configuration for %s is not found\n", pkg
1839
+ nil
1840
+ end
1841
+ end
1842
+
1843
+ # :stopdoc:
1844
+
1845
+ def with_destdir(dir)
1846
+ dir = dir.sub($dest_prefix_pattern, '')
1847
+ /\A\$[\(\{]/ =~ dir ? dir : "$(DESTDIR)"+dir
1848
+ end
1849
+
1850
+ # Converts forward slashes to backslashes. Aimed at MS Windows.
1851
+ #
1852
+ # Internal use only.
1853
+ #
1854
+ def winsep(s)
1855
+ s.tr('/', '\\')
1856
+ end
1857
+
1858
+ # Converts native path to format acceptable in Makefile
1859
+ #
1860
+ # Internal use only.
1861
+ #
1862
+ if !CROSS_COMPILING
1863
+ case CONFIG['build_os']
1864
+ when 'mingw32'
1865
+ def mkintpath(path)
1866
+ # mingw uses make from msys and it needs special care
1867
+ # converts from C:\some\path to /C/some/path
1868
+ path = path.dup
1869
+ path.tr!('\\', '/')
1870
+ path.sub!(/\A([A-Za-z]):(?=\/)/, '/\1')
1871
+ path
1872
+ end
1873
+ when 'cygwin'
1874
+ if CONFIG['target_os'] != 'cygwin'
1875
+ def mkintpath(path)
1876
+ IO.popen(["cygpath", "-u", path], &:read).chomp
1877
+ end
1878
+ end
1879
+ end
1880
+ end
1881
+ unless method_defined?(:mkintpath)
1882
+ def mkintpath(path)
1883
+ path
1884
+ end
1885
+ end
1886
+
1887
+ def configuration(srcdir)
1888
+ mk = []
1889
+ vpath = $VPATH.dup
1890
+ CONFIG["hdrdir"] ||= $hdrdir
1891
+ mk << %{
1892
+ SHELL = /bin/sh
1893
+
1894
+ # V=0 quiet, V=1 verbose. other values don't work.
1895
+ V = 0
1896
+ Q1 = $(V:1=)
1897
+ Q = $(Q1:0=@)
1898
+ ECHO1 = $(V:1=@#{CONFIG['NULLCMD']})
1899
+ ECHO = $(ECHO1:0=@echo)
1900
+ NULLCMD = #{CONFIG['NULLCMD']}
1901
+
1902
+ #### Start of system configuration section. ####
1903
+ #{"top_srcdir = " + $top_srcdir.sub(%r"\A#{Regexp.quote($topdir)}/", "$(topdir)/") if $extmk}
1904
+ srcdir = #{srcdir.gsub(/\$\((srcdir)\)|\$\{(srcdir)\}/) {mkintpath(CONFIG[$1||$2]).unspace}}
1905
+ topdir = #{mkintpath(topdir = $extmk ? CONFIG["topdir"] : $topdir).unspace}
1906
+ hdrdir = #{(hdrdir = CONFIG["hdrdir"]) == topdir ? "$(topdir)" : mkintpath(hdrdir).unspace}
1907
+ arch_hdrdir = #{$arch_hdrdir.quote}
1908
+ PATH_SEPARATOR = #{CONFIG['PATH_SEPARATOR']}
1909
+ VPATH = #{vpath.join(CONFIG['PATH_SEPARATOR'])}
1910
+ }
1911
+ if $extmk
1912
+ mk << "RUBYLIB =\n""RUBYOPT = -\n"
1913
+ end
1914
+ prefix = mkintpath(CONFIG["prefix"])
1915
+ if destdir = prefix[$dest_prefix_pattern, 1]
1916
+ mk << "\nDESTDIR = #{destdir}\n"
1917
+ prefix = prefix[destdir.size..-1]
1918
+ end
1919
+ mk << "prefix = #{with_destdir(prefix).unspace}\n"
1920
+ CONFIG.each do |key, var|
1921
+ mk << "#{key} = #{with_destdir(mkintpath(var)).unspace}\n" if /.prefix$/ =~ key
1922
+ end
1923
+ CONFIG.each do |key, var|
1924
+ next if /^abs_/ =~ key
1925
+ next if /^(?:src|top(?:_src)?|build|hdr)dir$/ =~ key
1926
+ next unless /dir$/ =~ key
1927
+ mk << "#{key} = #{with_destdir(var)}\n"
1928
+ end
1929
+ if !$extmk and !$configure_args.has_key?('--ruby') and
1930
+ sep = config_string('BUILD_FILE_SEPARATOR')
1931
+ sep = ":/=#{sep}"
1932
+ else
1933
+ sep = ""
1934
+ end
1935
+ possible_command = (proc {|s| s if /top_srcdir/ !~ s} unless $extmk)
1936
+ extconf_h = $extconf_h ? "-DRUBY_EXTCONF_H=\\\"$(RUBY_EXTCONF_H)\\\" " : $defs.join(" ") << " "
1937
+ headers = %w[
1938
+ $(hdrdir)/ruby.h
1939
+ $(hdrdir)/ruby/ruby.h
1940
+ $(hdrdir)/ruby/defines.h
1941
+ $(hdrdir)/ruby/missing.h
1942
+ $(hdrdir)/ruby/intern.h
1943
+ $(hdrdir)/ruby/st.h
1944
+ $(hdrdir)/ruby/subst.h
1945
+ ]
1946
+ if RULE_SUBST
1947
+ headers.each {|h| h.sub!(/.*/, &RULE_SUBST.method(:%))}
1948
+ end
1949
+ headers << $config_h
1950
+ headers << '$(RUBY_EXTCONF_H)' if $extconf_h
1951
+ mk << %{
1952
+
1953
+ CC = #{CONFIG['CC']}
1954
+ CXX = #{CONFIG['CXX']}
1955
+ LIBRUBY = #{CONFIG['LIBRUBY']}
1956
+ LIBRUBY_A = #{CONFIG['LIBRUBY_A']}
1957
+ LIBRUBYARG_SHARED = #$LIBRUBYARG_SHARED
1958
+ LIBRUBYARG_STATIC = #$LIBRUBYARG_STATIC
1959
+ empty =
1960
+ OUTFLAG = #{OUTFLAG}$(empty)
1961
+ COUTFLAG = #{COUTFLAG}$(empty)
1962
+
1963
+ RUBY_EXTCONF_H = #{$extconf_h}
1964
+ cflags = #{CONFIG['cflags']}
1965
+ cxxflags = #{CONFIG['cxxflags']}
1966
+ optflags = #{CONFIG['optflags']}
1967
+ debugflags = #{CONFIG['debugflags']}
1968
+ warnflags = #{$warnflags}
1969
+ CCDLFLAGS = #{$static ? '' : CONFIG['CCDLFLAGS']}
1970
+ CFLAGS = $(CCDLFLAGS) #$CFLAGS $(ARCH_FLAG)
1971
+ INCFLAGS = -I. #$INCFLAGS
1972
+ DEFS = #{CONFIG['DEFS']}
1973
+ CPPFLAGS = #{extconf_h}#{$CPPFLAGS}
1974
+ CXXFLAGS = $(CCDLFLAGS) #$CXXFLAGS $(ARCH_FLAG)
1975
+ ldflags = #{$LDFLAGS}
1976
+ dldflags = #{$DLDFLAGS} #{CONFIG['EXTDLDFLAGS']}
1977
+ ARCH_FLAG = #{$ARCH_FLAG}
1978
+ DLDFLAGS = $(ldflags) $(dldflags) $(ARCH_FLAG)
1979
+ LDSHARED = #{CONFIG['LDSHARED']}
1980
+ LDSHAREDXX = #{config_string('LDSHAREDXX') || '$(LDSHARED)'}
1981
+ AR = #{CONFIG['AR']}
1982
+ EXEEXT = #{CONFIG['EXEEXT']}
1983
+
1984
+ }
1985
+ CONFIG.each do |key, val|
1986
+ mk << "#{key} = #{val}\n" if /^RUBY.*NAME/ =~ key
1987
+ end
1988
+ mk << %{
1989
+ arch = #{CONFIG['arch']}
1990
+ sitearch = #{CONFIG['sitearch']}
1991
+ ruby_version = #{RbConfig::CONFIG['ruby_version']}
1992
+ ruby = #{$ruby.sub(%r[\A#{Regexp.quote(RbConfig::CONFIG['bindir'])}(?=/|\z)]) {'$(bindir)'}}
1993
+ RUBY = $(ruby#{sep})
1994
+ ruby_headers = #{headers.join(' ')}
1995
+
1996
+ RM = #{config_string('RM', &possible_command) || '$(RUBY) -run -e rm -- -f'}
1997
+ RM_RF = #{'$(RUBY) -run -e rm -- -rf'}
1998
+ RMDIRS = #{config_string('RMDIRS', &possible_command) || '$(RUBY) -run -e rmdir -- -p'}
1999
+ MAKEDIRS = #{config_string('MAKEDIRS', &possible_command) || '@$(RUBY) -run -e mkdir -- -p'}
2000
+ INSTALL = #{config_string('INSTALL', &possible_command) || '@$(RUBY) -run -e install -- -vp'}
2001
+ INSTALL_PROG = #{config_string('INSTALL_PROG') || '$(INSTALL) -m 0755'}
2002
+ INSTALL_DATA = #{config_string('INSTALL_DATA') || '$(INSTALL) -m 0644'}
2003
+ COPY = #{config_string('CP', &possible_command) || '@$(RUBY) -run -e cp -- -v'}
2004
+ TOUCH = exit >
2005
+
2006
+ #### End of system configuration section. ####
2007
+
2008
+ preload = #{defined?($preload) && $preload ? $preload.join(' ') : ''}
2009
+ }
2010
+ if $nmake == ?b
2011
+ mk.each do |x|
2012
+ x.gsub!(/^(MAKEDIRS|INSTALL_(?:PROG|DATA))+\s*=.*\n/) do
2013
+ "!ifndef " + $1 + "\n" +
2014
+ $& +
2015
+ "!endif\n"
2016
+ end
2017
+ end
2018
+ end
2019
+ mk
2020
+ end
2021
+
2022
+ def timestamp_file(name, target_prefix = nil)
2023
+ if target_prefix
2024
+ pat = []
2025
+ install_dirs.each do |n, d|
2026
+ pat << n if /\$\(target_prefix\)\z/ =~ d
2027
+ end
2028
+ name = name.gsub(/\$\((#{pat.join("|")})\)/) {$&+target_prefix}
2029
+ end
2030
+ name = name.gsub(/(\$[({]|[})])|(\/+)|[^-.\w]+/) {$1 ? "" : $2 ? ".-." : "_"}
2031
+ "$(TIMESTAMP_DIR)/.#{name}.time"
2032
+ end
2033
+ # :startdoc:
2034
+
2035
+ # creates a stub Makefile.
2036
+ #
2037
+ def dummy_makefile(srcdir)
2038
+ configuration(srcdir) << <<RULES << CLEANINGS
2039
+ CLEANFILES = #{$cleanfiles.join(' ')}
2040
+ DISTCLEANFILES = #{$distcleanfiles.join(' ')}
2041
+
2042
+ all install static install-so install-rb: Makefile
2043
+ .PHONY: all install static install-so install-rb
2044
+ .PHONY: clean clean-so clean-static clean-rb
2045
+
2046
+ RULES
2047
+ end
2048
+
2049
+ def each_compile_rules # :nodoc:
2050
+ vpath_splat = /\$\(\*VPATH\*\)/
2051
+ COMPILE_RULES.each do |rule|
2052
+ if vpath_splat =~ rule
2053
+ $VPATH.each do |path|
2054
+ yield rule.sub(vpath_splat) {path}
2055
+ end
2056
+ else
2057
+ yield rule
2058
+ end
2059
+ end
2060
+ end
2061
+
2062
+ # Processes the data contents of the "depend" file. Each line of this file
2063
+ # is expected to be a file name.
2064
+ #
2065
+ # Returns the output of findings, in Makefile format.
2066
+ #
2067
+ def depend_rules(depend)
2068
+ suffixes = []
2069
+ depout = []
2070
+ cont = implicit = nil
2071
+ impconv = proc do
2072
+ each_compile_rules {|rule| depout << (rule % implicit[0]) << implicit[1]}
2073
+ implicit = nil
2074
+ end
2075
+ ruleconv = proc do |line|
2076
+ if implicit
2077
+ if /\A\t/ =~ line
2078
+ implicit[1] << line
2079
+ next
2080
+ else
2081
+ impconv[]
2082
+ end
2083
+ end
2084
+ if m = /\A\.(\w+)\.(\w+)(?:\s*:)/.match(line)
2085
+ suffixes << m[1] << m[2]
2086
+ implicit = [[m[1], m[2]], [m.post_match]]
2087
+ next
2088
+ elsif RULE_SUBST and /\A(?!\s*\w+\s*=)[$\w][^#]*:/ =~ line
2089
+ line.sub!(/\s*\#.*$/, '')
2090
+ comment = $&
2091
+ line.gsub!(%r"(\s)(?!\.)([^$(){}+=:\s\\,]+)(?=\s|\z)") {$1 + RULE_SUBST % $2}
2092
+ line = line.chomp + comment + "\n" if comment
2093
+ end
2094
+ depout << line
2095
+ end
2096
+ depend.each_line do |line|
2097
+ line.gsub!(/\.o\b/, ".#{$OBJEXT}")
2098
+ line.gsub!(/\{\$\(VPATH\)\}/, "") unless $nmake
2099
+ line.gsub!(/\$\((?:hdr|top)dir\)\/config.h/, $config_h)
2100
+ line.gsub!(%r"\$\(hdrdir\)/(?!ruby(?![^:;/\s]))(?=[-\w]+\.h)", '\&ruby/')
2101
+ if $nmake && /\A\s*\$\(RM|COPY\)/ =~ line
2102
+ line.gsub!(%r"[-\w\./]{2,}"){$&.tr("/", "\\")}
2103
+ line.gsub!(/(\$\((?!RM|COPY)[^:)]+)(?=\))/, '\1:/=\\')
2104
+ end
2105
+ if /(?:^|[^\\])(?:\\\\)*\\$/ =~ line
2106
+ (cont ||= []) << line
2107
+ next
2108
+ elsif cont
2109
+ line = (cont << line).join
2110
+ cont = nil
2111
+ end
2112
+ ruleconv.call(line)
2113
+ end
2114
+ if cont
2115
+ ruleconv.call(cont.join)
2116
+ elsif implicit
2117
+ impconv.call
2118
+ end
2119
+ unless suffixes.empty?
2120
+ depout.unshift(".SUFFIXES: ." + suffixes.uniq.join(" .") + "\n\n")
2121
+ end
2122
+ depout.unshift("$(OBJS): $(RUBY_EXTCONF_H)\n\n") if $extconf_h
2123
+ depout.flatten!
2124
+ depout
2125
+ end
2126
+
2127
+ # Generates the Makefile for your extension, passing along any options and
2128
+ # preprocessor constants that you may have generated through other methods.
2129
+ #
2130
+ # The +target+ name should correspond the name of the global function name
2131
+ # defined within your C extension, minus the +Init_+. For example, if your
2132
+ # C extension is defined as +Init_foo+, then your target would simply be
2133
+ # "foo".
2134
+ #
2135
+ # If any "/" characters are present in the target name, only the last name
2136
+ # is interpreted as the target name, and the rest are considered toplevel
2137
+ # directory names, and the generated Makefile will be altered accordingly to
2138
+ # follow that directory structure.
2139
+ #
2140
+ # For example, if you pass "test/foo" as a target name, your extension will
2141
+ # be installed under the "test" directory. This means that in order to
2142
+ # load the file within a Ruby program later, that directory structure will
2143
+ # have to be followed, e.g. <code>require 'test/foo'</code>.
2144
+ #
2145
+ # The +srcprefix+ should be used when your source files are not in the same
2146
+ # directory as your build script. This will not only eliminate the need for
2147
+ # you to manually copy the source files into the same directory as your
2148
+ # build script, but it also sets the proper +target_prefix+ in the generated
2149
+ # Makefile.
2150
+ #
2151
+ # Setting the +target_prefix+ will, in turn, install the generated binary in
2152
+ # a directory under your <code>RbConfig::CONFIG['sitearchdir']</code> that
2153
+ # mimics your local filesystem when you run <code>make install</code>.
2154
+ #
2155
+ # For example, given the following file tree:
2156
+ #
2157
+ # ext/
2158
+ # extconf.rb
2159
+ # test/
2160
+ # foo.c
2161
+ #
2162
+ # And given the following code:
2163
+ #
2164
+ # create_makefile('test/foo', 'test')
2165
+ #
2166
+ # That will set the +target_prefix+ in the generated Makefile to "test".
2167
+ # That, in turn, will create the following file tree when installed via the
2168
+ # <code>make install</code> command:
2169
+ #
2170
+ # /path/to/ruby/sitearchdir/test/foo.so
2171
+ #
2172
+ # It is recommended that you use this approach to generate your makefiles,
2173
+ # instead of copying files around manually, because some third party
2174
+ # libraries may depend on the +target_prefix+ being set properly.
2175
+ #
2176
+ # The +srcprefix+ argument can be used to override the default source
2177
+ # directory, i.e. the current directory. It is included as part of the
2178
+ # +VPATH+ and added to the list of +INCFLAGS+.
2179
+ #
2180
+ def create_makefile(target, srcprefix = nil)
2181
+ $target = target
2182
+ libpath = $DEFLIBPATH|$LIBPATH
2183
+ message "creating Makefile\n"
2184
+ MakeMakefile.rm_f "#{CONFTEST}*"
2185
+ if CONFIG["DLEXT"] == $OBJEXT
2186
+ for lib in libs = $libs.split
2187
+ lib.sub!(/-l(.*)/, %%"lib\\1.#{$LIBEXT}"%)
2188
+ end
2189
+ $defs.push(format("-DEXTLIB='%s'", libs.join(",")))
2190
+ end
2191
+
2192
+ if target.include?('/')
2193
+ target_prefix, target = File.split(target)
2194
+ target_prefix[0,0] = '/'
2195
+ else
2196
+ target_prefix = ""
2197
+ end
2198
+
2199
+ srcprefix ||= "$(srcdir)/#{srcprefix}".chomp('/')
2200
+ RbConfig.expand(srcdir = srcprefix.dup)
2201
+
2202
+ ext = ".#{$OBJEXT}"
2203
+ orig_srcs = Dir[File.join(srcdir, "*.{#{SRC_EXT.join(%q{,})}}")]
2204
+ if not $objs
2205
+ srcs = $srcs || orig_srcs
2206
+ objs = srcs.inject(Hash.new {[]}) {|h, f| h[File.basename(f, ".*") << ext] <<= f; h}
2207
+ $objs = objs.keys
2208
+ unless objs.delete_if {|b, f| f.size == 1}.empty?
2209
+ dups = objs.sort.map {|b, f|
2210
+ "#{b[/.*\./]}{#{f.collect {|n| n[/([^.]+)\z/]}.join(',')}}"
2211
+ }
2212
+ abort "source files duplication - #{dups.join(", ")}"
2213
+ end
2214
+ else
2215
+ $objs.collect! {|o| File.basename(o, ".*") << ext} unless $OBJEXT == "o"
2216
+ srcs = $srcs || $objs.collect {|o| o.chomp(ext) << ".c"}
2217
+ end
2218
+ $srcs = srcs
2219
+
2220
+ hdrs = Dir[File.join(srcdir, "*.{#{HDR_EXT.join(%q{,})}}")]
2221
+
2222
+ target = nil if $objs.empty?
2223
+
2224
+ if target and EXPORT_PREFIX
2225
+ if File.exist?(File.join(srcdir, target + '.def'))
2226
+ deffile = "$(srcdir)/$(TARGET).def"
2227
+ unless EXPORT_PREFIX.empty?
2228
+ makedef = %{$(RUBY) -pe "$$_.sub!(/^(?=\\w)/,'#{EXPORT_PREFIX}') unless 1../^EXPORTS$/i" #{deffile}}
2229
+ end
2230
+ else
2231
+ makedef = %{(echo EXPORTS && echo $(TARGET_ENTRY))}
2232
+ end
2233
+ if makedef
2234
+ $cleanfiles << '$(DEFFILE)'
2235
+ origdef = deffile
2236
+ deffile = "$(TARGET)-$(arch).def"
2237
+ end
2238
+ end
2239
+ origdef ||= ''
2240
+
2241
+ if $extout and $INSTALLFILES
2242
+ $cleanfiles.concat($INSTALLFILES.collect {|files, dir|File.join(dir, files.sub(/\A\.\//, ''))})
2243
+ $distcleandirs.concat($INSTALLFILES.collect {|files, dir| dir})
2244
+ end
2245
+
2246
+ if $extmk and $static
2247
+ $defs << "-DRUBY_EXPORT=1"
2248
+ end
2249
+
2250
+ if $extmk and not $extconf_h
2251
+ create_header
2252
+ end
2253
+
2254
+ libpath = libpathflag(libpath)
2255
+
2256
+ dllib = target ? "$(TARGET).#{CONFIG['DLEXT']}" : ""
2257
+ staticlib = target ? "$(TARGET).#$LIBEXT" : ""
2258
+ mfile = open("Makefile", "wb")
2259
+ conf = configuration(srcprefix)
2260
+ conf = yield(conf) if block_given?
2261
+ mfile.puts(conf)
2262
+ mfile.print "
2263
+ libpath = #{($DEFLIBPATH|$LIBPATH).join(" ")}
2264
+ LIBPATH = #{libpath}
2265
+ DEFFILE = #{deffile}
2266
+
2267
+ CLEANFILES = #{$cleanfiles.join(' ')}
2268
+ DISTCLEANFILES = #{$distcleanfiles.join(' ')}
2269
+ DISTCLEANDIRS = #{$distcleandirs.join(' ')}
2270
+
2271
+ extout = #{$extout && $extout.quote}
2272
+ extout_prefix = #{$extout_prefix}
2273
+ target_prefix = #{target_prefix}
2274
+ LOCAL_LIBS = #{$LOCAL_LIBS}
2275
+ LIBS = #{$LIBRUBYARG} #{$libs} #{$LIBS}
2276
+ ORIG_SRCS = #{orig_srcs.collect(&File.method(:basename)).join(' ')}
2277
+ SRCS = $(ORIG_SRCS) #{(srcs - orig_srcs).collect(&File.method(:basename)).join(' ')}
2278
+ OBJS = #{$objs.join(" ")}
2279
+ HDRS = #{hdrs.map{|h| '$(srcdir)/' + File.basename(h)}.join(' ')}
2280
+ TARGET = #{target}
2281
+ TARGET_NAME = #{target && target[/\A\w+/]}
2282
+ TARGET_ENTRY = #{EXPORT_PREFIX || ''}Init_$(TARGET_NAME)
2283
+ DLLIB = #{dllib}
2284
+ EXTSTATIC = #{$static || ""}
2285
+ STATIC_LIB = #{staticlib unless $static.nil?}
2286
+ #{!$extout && defined?($installed_list) ? "INSTALLED_LIST = #{$installed_list}\n" : ""}
2287
+ TIMESTAMP_DIR = #{$extout ? '$(extout)/.timestamp' : '.'}
2288
+ " #"
2289
+ # TODO: fixme
2290
+ install_dirs.each {|d| mfile.print("%-14s= %s\n" % d) if /^[[:upper:]]/ =~ d[0]}
2291
+ n = ($extout ? '$(RUBYARCHDIR)/' : '') + '$(TARGET)'
2292
+ mfile.print "
2293
+ TARGET_SO = #{($extout ? '$(RUBYARCHDIR)/' : '')}$(DLLIB)
2294
+ CLEANLIBS = #{n}.#{CONFIG['DLEXT']} #{config_string('cleanlibs') {|t| t.gsub(/\$\*/) {n}}}
2295
+ CLEANOBJS = *.#{$OBJEXT} #{config_string('cleanobjs') {|t| t.gsub(/\$\*/, "$(TARGET)#{deffile ? '-$(arch)': ''}")} if target} *.bak
2296
+
2297
+ all: #{$extout ? "install" : target ? "$(DLLIB)" : "Makefile"}
2298
+ static: #{$extmk && !$static ? "all" : "$(STATIC_LIB)#{!$extmk ? " install-rb" : ""}"}
2299
+ .PHONY: all install static install-so install-rb
2300
+ .PHONY: clean clean-so clean-static clean-rb
2301
+ "
2302
+ mfile.print CLEANINGS
2303
+ fsep = config_string('BUILD_FILE_SEPARATOR') {|s| s unless s == "/"}
2304
+ if fsep
2305
+ sep = ":/=#{fsep}"
2306
+ fseprepl = proc {|s|
2307
+ s = s.gsub("/", fsep)
2308
+ s = s.gsub(/(\$\(\w+)(\))/) {$1+sep+$2}
2309
+ s.gsub(/(\$\{\w+)(\})/) {$1+sep+$2}
2310
+ }
2311
+ rsep = ":#{fsep}=/"
2312
+ else
2313
+ fseprepl = proc {|s| s}
2314
+ sep = ""
2315
+ rsep = ""
2316
+ end
2317
+ dirs = []
2318
+ mfile.print "install: install-so install-rb\n\n"
2319
+ sodir = (dir = "$(RUBYARCHDIR)").dup
2320
+ mfile.print("install-so: ")
2321
+ if target
2322
+ f = "$(DLLIB)"
2323
+ dest = "#{dir}/#{f}"
2324
+ stamp = timestamp_file(dir, target_prefix)
2325
+ if $extout
2326
+ mfile.puts dest
2327
+ mfile.print "clean-so::\n"
2328
+ mfile.print "\t-$(Q)$(RM) #{fseprepl[dest]} #{fseprepl[stamp]}\n"
2329
+ mfile.print "\t-$(Q)$(RMDIRS) #{fseprepl[dir]}#{$ignore_error}\n"
2330
+ else
2331
+ mfile.print "#{f} #{stamp}\n"
2332
+ mfile.print "\t$(INSTALL_PROG) #{fseprepl[f]} #{dir}\n"
2333
+ if defined?($installed_list)
2334
+ mfile.print "\t@echo #{dir}/#{File.basename(f)}>>$(INSTALLED_LIST)\n"
2335
+ end
2336
+ end
2337
+ mfile.print "clean-static::\n"
2338
+ mfile.print "\t-$(Q)$(RM) $(STATIC_LIB)\n"
2339
+ else
2340
+ mfile.puts "Makefile"
2341
+ end
2342
+ mfile.print("install-rb: pre-install-rb install-rb-default\n")
2343
+ mfile.print("install-rb-default: pre-install-rb-default\n")
2344
+ mfile.print("pre-install-rb: Makefile\n")
2345
+ mfile.print("pre-install-rb-default: Makefile\n")
2346
+ for sfx, i in [["-default", [["lib/**/*.rb", "$(RUBYLIBDIR)", "lib"]]], ["", $INSTALLFILES]]
2347
+ files = install_files(mfile, i, nil, srcprefix) or next
2348
+ for dir, *files in files
2349
+ unless dirs.include?(dir)
2350
+ dirs << dir
2351
+ mfile.print "pre-install-rb#{sfx}: #{timestamp_file(dir, target_prefix)}\n"
2352
+ end
2353
+ for f in files
2354
+ dest = "#{dir}/#{File.basename(f)}"
2355
+ mfile.print("install-rb#{sfx}: #{dest}\n")
2356
+ mfile.print("#{dest}: #{f} #{timestamp_file(dir, target_prefix)}\n")
2357
+ mfile.print("\t$(Q) $(#{$extout ? 'COPY' : 'INSTALL_DATA'}) #{f} $(@D)\n")
2358
+ if defined?($installed_list) and !$extout
2359
+ mfile.print("\t@echo #{dest}>>$(INSTALLED_LIST)\n")
2360
+ end
2361
+ if $extout
2362
+ mfile.print("clean-rb#{sfx}::\n")
2363
+ mfile.print("\t-$(Q)$(RM) #{fseprepl[dest]}\n")
2364
+ end
2365
+ end
2366
+ end
2367
+ mfile.print "pre-install-rb#{sfx}:\n"
2368
+ if files.empty?
2369
+ mfile.print("\t@$(NULLCMD)\n")
2370
+ else
2371
+ mfile.print("\t$(ECHO) installing#{sfx.sub(/^-/, " ")} #{target} libraries\n")
2372
+ end
2373
+ if $extout
2374
+ dirs.uniq!
2375
+ unless dirs.empty?
2376
+ mfile.print("clean-rb#{sfx}::\n")
2377
+ for dir in dirs.sort_by {|d| -d.count('/')}
2378
+ stamp = timestamp_file(dir, target_prefix)
2379
+ mfile.print("\t-$(Q)$(RM) #{fseprepl[stamp]}\n")
2380
+ mfile.print("\t-$(Q)$(RMDIRS) #{fseprepl[dir]}#{$ignore_error}\n")
2381
+ end
2382
+ end
2383
+ end
2384
+ end
2385
+ dirs.unshift(sodir) if target and !dirs.include?(sodir)
2386
+ dirs.each do |d|
2387
+ t = timestamp_file(d, target_prefix)
2388
+ mfile.print "#{t}:\n\t$(Q) $(MAKEDIRS) $(@D) #{d}\n\t$(Q) $(TOUCH) $@\n"
2389
+ end
2390
+
2391
+ mfile.print <<-SITEINSTALL
2392
+
2393
+ site-install: site-install-so site-install-rb
2394
+ site-install-so: install-so
2395
+ site-install-rb: install-rb
2396
+
2397
+ SITEINSTALL
2398
+
2399
+ return unless target
2400
+
2401
+ mfile.puts SRC_EXT.collect {|e| ".path.#{e} = $(VPATH)"} if $nmake == ?b
2402
+ mfile.print ".SUFFIXES: .#{(SRC_EXT + [$OBJEXT, $ASMEXT]).compact.join(' .')}\n"
2403
+ mfile.print "\n"
2404
+
2405
+ compile_command = "\n\t$(ECHO) compiling $(<#{rsep})\n\t$(Q) %s\n\n"
2406
+ command = compile_command % COMPILE_CXX
2407
+ asm_command = compile_command.sub(/compiling/, 'translating') % ASSEMBLE_CXX
2408
+ CXX_EXT.each do |e|
2409
+ each_compile_rules do |rule|
2410
+ mfile.printf(rule, e, $OBJEXT)
2411
+ mfile.print(command)
2412
+ mfile.printf(rule, e, $ASMEXT)
2413
+ mfile.print(asm_command)
2414
+ end
2415
+ end
2416
+ command = compile_command % COMPILE_C
2417
+ asm_command = compile_command.sub(/compiling/, 'translating') % ASSEMBLE_C
2418
+ C_EXT.each do |e|
2419
+ each_compile_rules do |rule|
2420
+ mfile.printf(rule, e, $OBJEXT)
2421
+ mfile.print(command)
2422
+ mfile.printf(rule, e, $ASMEXT)
2423
+ mfile.print(asm_command)
2424
+ end
2425
+ end
2426
+
2427
+ mfile.print "$(RUBYARCHDIR)/" if $extout
2428
+ mfile.print "$(DLLIB): "
2429
+ mfile.print "$(DEFFILE) " if makedef
2430
+ mfile.print "$(OBJS) Makefile"
2431
+ mfile.print " #{timestamp_file('$(RUBYARCHDIR)', target_prefix)}" if $extout
2432
+ mfile.print "\n"
2433
+ mfile.print "\t$(ECHO) linking shared-object #{target_prefix.sub(/\A\/(.*)/, '\1/')}$(DLLIB)\n"
2434
+ mfile.print "\t-$(Q)$(RM) $(@#{sep})\n"
2435
+ link_so = LINK_SO.gsub(/^/, "\t$(Q) ")
2436
+ if srcs.any?(&%r"\.(?:#{CXX_EXT.join('|')})\z".method(:===))
2437
+ link_so = link_so.sub(/\bLDSHARED\b/, '\&XX')
2438
+ end
2439
+ mfile.print link_so, "\n\n"
2440
+ unless $static.nil?
2441
+ mfile.print "$(STATIC_LIB): $(OBJS)\n\t-$(Q)$(RM) $(@#{sep})\n\t"
2442
+ mfile.print "$(ECHO) linking static-library $(@#{rsep})\n\t$(Q) "
2443
+ mfile.print "$(AR) #{config_string('ARFLAGS') || 'cru '}$@ $(OBJS)"
2444
+ config_string('RANLIB') do |ranlib|
2445
+ mfile.print "\n\t-$(Q)#{ranlib} $(@) 2> /dev/null || true"
2446
+ end
2447
+ end
2448
+ mfile.print "\n\n"
2449
+ if makedef
2450
+ mfile.print "$(DEFFILE): #{origdef}\n"
2451
+ mfile.print "\t$(ECHO) generating $(@#{rsep})\n"
2452
+ mfile.print "\t$(Q) #{makedef} > $@\n\n"
2453
+ end
2454
+
2455
+ depend = File.join(srcdir, "depend")
2456
+ if File.exist?(depend)
2457
+ mfile.print("###\n", *depend_rules(File.read(depend)))
2458
+ else
2459
+ mfile.print "$(OBJS): $(HDRS) $(ruby_headers)\n"
2460
+ end
2461
+
2462
+ $makefile_created = true
2463
+ ensure
2464
+ mfile.close if mfile
2465
+ end
2466
+
2467
+ # :stopdoc:
2468
+
2469
+ def init_mkmf(config = CONFIG, rbconfig = RbConfig::CONFIG)
2470
+ $makefile_created = false
2471
+ $arg_config = []
2472
+ $enable_shared = config['ENABLE_SHARED'] == 'yes'
2473
+ $defs = []
2474
+ $extconf_h = nil
2475
+ if $warnflags = CONFIG['warnflags'] and CONFIG['GCC'] == 'yes'
2476
+ # turn warnings into errors only for bundled extensions.
2477
+ config['warnflags'] = $warnflags.gsub(/(\A|\s)-Werror[-=]/, '\1-W')
2478
+ if /icc\z/ =~ config['CC']
2479
+ config['warnflags'].gsub!(/(\A|\s)-W(?:division-by-zero|deprecated-declarations)/, '\1')
2480
+ end
2481
+ RbConfig.expand(rbconfig['warnflags'] = config['warnflags'].dup)
2482
+ config.each do |key, val|
2483
+ RbConfig.expand(rbconfig[key] = val.dup) if /warnflags/ =~ val
2484
+ end
2485
+ $warnflags = config['warnflags'] unless $extmk
2486
+ end
2487
+ $CFLAGS = with_config("cflags", arg_config("CFLAGS", config["CFLAGS"])).dup
2488
+ $CXXFLAGS = (with_config("cxxflags", arg_config("CXXFLAGS", config["CXXFLAGS"]))||'').dup
2489
+ $ARCH_FLAG = with_config("arch_flag", arg_config("ARCH_FLAG", config["ARCH_FLAG"])).dup
2490
+ $CPPFLAGS = with_config("cppflags", arg_config("CPPFLAGS", config["CPPFLAGS"])).dup
2491
+ $LDFLAGS = with_config("ldflags", arg_config("LDFLAGS", config["LDFLAGS"])).dup
2492
+ $INCFLAGS = "-I$(arch_hdrdir)"
2493
+ $INCFLAGS << " -I$(hdrdir)/ruby/backward" unless $extmk
2494
+ $INCFLAGS << " -I$(hdrdir) -I$(srcdir)"
2495
+ $DLDFLAGS = with_config("dldflags", arg_config("DLDFLAGS", config["DLDFLAGS"])).dup
2496
+ $LIBEXT = config['LIBEXT'].dup
2497
+ $OBJEXT = config["OBJEXT"].dup
2498
+ $EXEEXT = config["EXEEXT"].dup
2499
+ $ASMEXT = config_string('ASMEXT', &:dup) || 'S'
2500
+ $LIBS = "#{config['LIBS']} #{config['DLDLIBS']}"
2501
+ $LIBRUBYARG = ""
2502
+ $LIBRUBYARG_STATIC = config['LIBRUBYARG_STATIC']
2503
+ $LIBRUBYARG_SHARED = config['LIBRUBYARG_SHARED']
2504
+ $DEFLIBPATH = [$extmk ? "$(topdir)" : "$(#{config["libdirname"] || "libdir"})"]
2505
+ $DEFLIBPATH.unshift(".")
2506
+ $LIBPATH = []
2507
+ $INSTALLFILES = []
2508
+ $NONINSTALLFILES = [/~\z/, /\A#.*#\z/, /\A\.#/, /\.bak\z/i, /\.orig\z/, /\.rej\z/, /\.l[ao]\z/, /\.o\z/]
2509
+ $VPATH = %w[$(srcdir) $(arch_hdrdir)/ruby $(hdrdir)/ruby]
2510
+
2511
+ $objs = nil
2512
+ $srcs = nil
2513
+ $libs = ""
2514
+ if $enable_shared or RbConfig.expand(config["LIBRUBY"].dup) != RbConfig.expand(config["LIBRUBY_A"].dup)
2515
+ $LIBRUBYARG = config['LIBRUBYARG']
2516
+ end
2517
+
2518
+ $LOCAL_LIBS = ""
2519
+
2520
+ $cleanfiles = config_string('CLEANFILES') {|s| Shellwords.shellwords(s)} || []
2521
+ $cleanfiles << "mkmf.log"
2522
+ $distcleanfiles = config_string('DISTCLEANFILES') {|s| Shellwords.shellwords(s)} || []
2523
+ $distcleandirs = config_string('DISTCLEANDIRS') {|s| Shellwords.shellwords(s)} || []
2524
+
2525
+ $extout ||= nil
2526
+ $extout_prefix ||= nil
2527
+
2528
+ $arg_config.clear
2529
+ dir_config("opt")
2530
+ end
2531
+
2532
+ FailedMessage = <<MESSAGE
2533
+ Could not create Makefile due to some reason, probably lack of necessary
2534
+ libraries and/or headers. Check the mkmf.log file for more details. You may
2535
+ need configuration options.
2536
+
2537
+ Provided configuration options:
2538
+ MESSAGE
2539
+
2540
+ # Returns whether or not the Makefile was successfully generated. If not,
2541
+ # the script will abort with an error message.
2542
+ #
2543
+ # Internal use only.
2544
+ #
2545
+ def mkmf_failed(path)
2546
+ unless $makefile_created or File.exist?("Makefile")
2547
+ opts = $arg_config.collect {|t, n| "\t#{t}#{n ? "=#{n}" : ""}\n"}
2548
+ abort "*** #{path} failed ***\n" + FailedMessage + opts.join
2549
+ end
2550
+ end
2551
+
2552
+ private
2553
+
2554
+ def _libdir_basename
2555
+ @libdir_basename ||= config_string("libdir") {|name| name[/\A\$\(exec_prefix\)\/(.*)/, 1]} || "lib"
2556
+ end
2557
+
2558
+ def MAIN_DOES_NOTHING(*refs)
2559
+ src = MAIN_DOES_NOTHING
2560
+ unless refs.empty?
2561
+ src = src.sub(/\{/) do
2562
+ $& +
2563
+ "\n if (argc > 1000000) {\n" +
2564
+ refs.map {|n|" printf(\"%p\", &#{n});\n"}.join("") +
2565
+ " }\n"
2566
+ end
2567
+ end
2568
+ src
2569
+ end
2570
+
2571
+ extend self
2572
+ init_mkmf
2573
+
2574
+ $make = with_config("make-prog", ENV["MAKE"] || "make")
2575
+ make, = Shellwords.shellwords($make)
2576
+ $nmake = nil
2577
+ case
2578
+ when $mswin
2579
+ $nmake = ?m if /nmake/i =~ make
2580
+ end
2581
+ $ignore_error = $nmake ? '' : ' 2> /dev/null || true'
2582
+
2583
+ RbConfig::CONFIG["srcdir"] = CONFIG["srcdir"] =
2584
+ $srcdir = arg_config("--srcdir", File.dirname($0))
2585
+ $configure_args["--topsrcdir"] ||= $srcdir
2586
+ if $curdir = arg_config("--curdir")
2587
+ RbConfig.expand(curdir = $curdir.dup)
2588
+ else
2589
+ curdir = $curdir = "."
2590
+ end
2591
+ unless File.expand_path(RbConfig::CONFIG["topdir"]) == File.expand_path(curdir)
2592
+ CONFIG["topdir"] = $curdir
2593
+ RbConfig::CONFIG["topdir"] = curdir
2594
+ end
2595
+ $configure_args["--topdir"] ||= $curdir
2596
+ $ruby = arg_config("--ruby", File.join(RbConfig::CONFIG["bindir"], CONFIG["ruby_install_name"]))
2597
+
2598
+ RbConfig.expand(CONFIG["RUBY_SO_NAME"])
2599
+
2600
+ # :startdoc:
2601
+
2602
+ split = Shellwords.method(:shellwords).to_proc
2603
+
2604
+ EXPORT_PREFIX = config_string('EXPORT_PREFIX') {|s| s.strip}
2605
+
2606
+ hdr = ['#include "ruby.h"' "\n"]
2607
+ config_string('COMMON_MACROS') do |s|
2608
+ Shellwords.shellwords(s).each do |w|
2609
+ w, v = w.split(/=/, 2)
2610
+ hdr << "#ifndef #{w}"
2611
+ hdr << "#define #{[w, v].compact.join(" ")}"
2612
+ hdr << "#endif /* #{w} */"
2613
+ end
2614
+ end
2615
+ config_string('COMMON_HEADERS') do |s|
2616
+ Shellwords.shellwords(s).each {|w| hdr << "#include <#{w}>"}
2617
+ end
2618
+
2619
+ ##
2620
+ # Common headers for Ruby C extensions
2621
+
2622
+ COMMON_HEADERS = hdr.join("\n")
2623
+
2624
+ ##
2625
+ # Common libraries for Ruby C extensions
2626
+
2627
+ COMMON_LIBS = config_string('COMMON_LIBS', &split) || []
2628
+
2629
+ ##
2630
+ # make compile rules
2631
+
2632
+ COMPILE_RULES = config_string('COMPILE_RULES', &split) || %w[.%s.%s:]
2633
+ RULE_SUBST = config_string('RULE_SUBST')
2634
+
2635
+ ##
2636
+ # Command which will compile C files in the generated Makefile
2637
+
2638
+ COMPILE_C = config_string('COMPILE_C') || '$(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $<'
2639
+
2640
+ ##
2641
+ # Command which will compile C++ files in the generated Makefile
2642
+
2643
+ COMPILE_CXX = config_string('COMPILE_CXX') || '$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<'
2644
+
2645
+ ##
2646
+ # Command which will translate C files to assembler sources in the generated Makefile
2647
+
2648
+ ASSEMBLE_C = config_string('ASSEMBLE_C') || COMPILE_C.sub(/(?<=\s)-c(?=\s)/, '-S')
2649
+
2650
+ ##
2651
+ # Command which will translate C++ files to assembler sources in the generated Makefile
2652
+
2653
+ ASSEMBLE_CXX = config_string('ASSEMBLE_CXX') || COMPILE_CXX.sub(/(?<=\s)-c(?=\s)/, '-S')
2654
+
2655
+ ##
2656
+ # Command which will compile a program in order to test linking a library
2657
+
2658
+ TRY_LINK = config_string('TRY_LINK') ||
2659
+ "$(CC) #{OUTFLAG}#{CONFTEST}#{$EXEEXT} $(INCFLAGS) $(CPPFLAGS) " \
2660
+ "$(CFLAGS) $(src) $(LIBPATH) $(LDFLAGS) $(ARCH_FLAG) $(LOCAL_LIBS) $(LIBS)"
2661
+
2662
+ ##
2663
+ # Command which will link a shared library
2664
+
2665
+ LINK_SO = (config_string('LINK_SO') || "").sub(/^$/) do
2666
+ if CONFIG["DLEXT"] == $OBJEXT
2667
+ "ld $(DLDFLAGS) -r -o $@ $(OBJS)\n"
2668
+ else
2669
+ "$(LDSHARED) #{OUTFLAG}$@ $(OBJS) " \
2670
+ "$(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)"
2671
+ end
2672
+ end
2673
+
2674
+ ##
2675
+ # Argument which will add a library path to the linker
2676
+
2677
+ LIBPATHFLAG = config_string('LIBPATHFLAG') || ' -L%s'
2678
+ RPATHFLAG = config_string('RPATHFLAG') || ''
2679
+
2680
+ ##
2681
+ # Argument which will add a library to the linker
2682
+
2683
+ LIBARG = config_string('LIBARG') || '-l%s'
2684
+
2685
+ ##
2686
+ # A C main function which does no work
2687
+
2688
+ MAIN_DOES_NOTHING = config_string('MAIN_DOES_NOTHING') || "int main(int argc, char **argv)\n{\n return 0;\n}"
2689
+ UNIVERSAL_INTS = config_string('UNIVERSAL_INTS') {|s| Shellwords.shellwords(s)} ||
2690
+ %w[int short long long\ long]
2691
+
2692
+ sep = config_string('BUILD_FILE_SEPARATOR') {|s| ":/=#{s}" if s != "/"} || ""
2693
+
2694
+ ##
2695
+ # Makefile rules that will clean the extension build directory
2696
+
2697
+ CLEANINGS = "
2698
+ clean-static::
2699
+ clean-rb-default::
2700
+ clean-rb::
2701
+ clean-so::
2702
+ clean: clean-so clean-static clean-rb-default clean-rb
2703
+ \t\t-$(Q)$(RM) $(CLEANLIBS#{sep}) $(CLEANOBJS#{sep}) $(CLEANFILES#{sep}) .*.time
2704
+
2705
+ distclean-rb-default::
2706
+ distclean-rb::
2707
+ distclean-so::
2708
+ distclean-static::
2709
+ distclean: clean distclean-so distclean-static distclean-rb-default distclean-rb
2710
+ \t\t-$(Q)$(RM) Makefile $(RUBY_EXTCONF_H) #{CONFTEST}.* mkmf.log
2711
+ \t\t-$(Q)$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES#{sep})
2712
+ \t\t-$(Q)$(RMDIRS) $(DISTCLEANDIRS#{sep})#{$ignore_error}
2713
+
2714
+ realclean: distclean
2715
+ "
2716
+ end
2717
+
2718
+ include MakeMakefile
2719
+
2720
+ if not $extmk and /\A(extconf|makefile).rb\z/ =~ File.basename($0)
2721
+ END {mkmf_failed($0)}
2722
+ end