1#!./miniruby -s 2 3# This script, which is run when ruby is built, generates rbconfig.rb by 4# parsing information from config.status. rbconfig.rb contains build 5# information for ruby (compiler flags, paths, etc.) and is used e.g. by 6# mkmf to build compatible native extensions. 7 8# avoid warnings with -d. 9$install_name ||= nil 10$so_name ||= nil 11$unicode_version ||= nil 12$unicode_emoji_version ||= nil 13arch = $arch or raise "missing -arch" 14version = $version or raise "missing -version" 15 16srcdir = File.expand_path('../..', __FILE__) 17$:.unshift(".") 18 19mkconfig = File.basename($0) 20 21fast = {'prefix'=>true, 'ruby_install_name'=>true, 'INSTALL'=>true, 'EXEEXT'=>true} 22 23win32 = /mswin/ =~ arch 24universal = /universal.*darwin/ =~ arch 25v_fast = [] 26v_others = [] 27vars = {} 28continued_name = nil 29continued_line = nil 30install_name = nil 31so_name = nil 32File.foreach "config.status" do |line| 33 next if /^#/ =~ line 34 name = nil 35 case line 36 when /^s([%,])@(\w+)@\1(?:\|\#_!!_\#\|)?(.*)\1/ 37 name = $2 38 val = $3.gsub(/\\(?=,)/, '') 39 when /^S\["(\w+)"\]\s*=\s*"(.*)"\s*(\\)?$/ 40 name = $1 41 val = $2 42 if $3 43 continued_line = [val] 44 continued_name = name 45 next 46 end 47 when /^"(.*)"\s*(\\)?$/ 48 next if !continued_line 49 continued_line << $1 50 next if $2 51 continued_line.each {|s| s.sub!(/\\n\z/, "\n")} 52 val = continued_line.join 53 name = continued_name 54 continued_line = nil 55 when /^(?:ac_given_)?INSTALL=(.*)/ 56 v_fast << " CONFIG[\"INSTALL\"] = " + $1 + "\n" 57 end 58 59 if name 60 case name 61 when /^(?:ac_.*|configure_input|(?:top_)?srcdir|\w+OBJS)$/; next 62 when /^(?:X|(?:MINI|RUN|(?:HAVE_)?BASE|BOOTSTRAP|BTEST)RUBY(?:_COMMAND)?$)/; next 63 when /^INSTALLDOC|TARGET$/; next 64 when /^DTRACE/; next 65 when /^MJIT_(CC|SUPPORT)/; # pass 66 when /^MJIT_/; next 67 when /^(?:MAJOR|MINOR|TEENY)$/; vars[name] = val; next 68 when /^LIBRUBY_D?LD/; next 69 when /^RUBY_INSTALL_NAME$/; next vars[name] = (install_name = val).dup if $install_name 70 when /^RUBY_SO_NAME$/; next vars[name] = (so_name = val).dup if $so_name 71 when /^arch$/; if val.empty? then val = arch else arch = val end 72 when /^sitearch$/; val = '$(arch)' if val.empty? 73 when /^DESTDIR$/; next 74 when /RUBYGEMS/; next 75 end 76 case val 77 when /^\$\(ac_\w+\)$/; next 78 when /^\$\{ac_\w+\}$/; next 79 when /^\$ac_\w+$/; next 80 end 81 if /^program_transform_name$/ =~ name 82 val.sub!(/\As(\\?\W)(?:\^|\${1,2})\1\1(;|\z)/, '') 83 if val.empty? 84 $install_name ||= "ruby" 85 next 86 end 87 unless $install_name 88 $install_name = "ruby" 89 val.gsub!(/\$\$/, '$') 90 val.scan(%r[\G[\s;]*(/(?:\\.|[^/])*/)?([sy])(\\?\W)((?:(?!\3)(?:\\.|.))*)\3((?:(?!\3)(?:\\.|.))*)\3([gi]*)]) do 91 |addr, cmd, sep, pat, rep, opt| 92 if addr 93 Regexp.new(addr[/\A\/(.*)\/\z/, 1]) =~ $install_name or next 94 end 95 case cmd 96 when 's' 97 pat = Regexp.new(pat, opt.include?('i')) 98 if opt.include?('g') 99 $install_name.gsub!(pat, rep) 100 else 101 $install_name.sub!(pat, rep) 102 end 103 when 'y' 104 $install_name.tr!(Regexp.quote(pat), rep) 105 end 106 end 107 end 108 end 109 eq = win32 && vars[name] ? '<< "\n"' : '=' 110 vars[name] = val 111 if name == "configure_args" 112 val.gsub!(/--with-out-ext/, "--without-ext") 113 end 114 val = val.gsub(/\$(?:\$|\{?(\w+)\}?)/) {$1 ? "$(#{$1})" : $&}.dump 115 case name 116 when /^prefix$/ 117 val = "(TOPDIR || DESTDIR + #{val})" 118 when /^ARCH_FLAG$/ 119 val = "arch_flag || #{val}" if universal 120 when /^UNIVERSAL_ARCHNAMES$/ 121 universal, val = val, 'universal' if universal 122 when /^arch$/ 123 if universal 124 val.sub!(/universal/, %q[#{arch && universal[/(?:\A|\s)#{Regexp.quote(arch)}=(\S+)/, 1] || '\&'}]) 125 end 126 when /^oldincludedir$/ 127 val = '"$(SDKROOT)"'+val if /darwin/ =~ arch 128 end 129 v = " CONFIG[\"#{name}\"] #{eq} #{val}\n" 130 if fast[name] 131 v_fast << v 132 else 133 v_others << v 134 end 135 case name 136 when "RUBY_PROGRAM_VERSION" 137 version = val[/\A"(.*)"\z/, 1] 138 end 139 end 140# break if /^CEOF/ 141end 142 143drive = File::PATH_SEPARATOR == ';' 144 145def vars.expand(val, config = self) 146 newval = val.gsub(/\$\$|\$\(([^()]+)\)|\$\{([^{}]+)\}/) { 147 var = $& 148 if !(v = $1 || $2) 149 '$' 150 elsif key = config[v = v[/\A[^:]+(?=(?::(.*?)=(.*))?\z)/]] 151 pat, sub = $1, $2 152 config[v] = false 153 config[v] = expand(key, config) 154 key = key.gsub(/#{Regexp.quote(pat)}(?=\s|\z)/n) {sub} if pat 155 key 156 else 157 var 158 end 159 } 160 val.replace(newval) unless newval == val 161 val 162end 163prefix = vars.expand(vars["rubyarchdir"]) 164major, minor, *rest = RUBY_VERSION.split('.') 165rubyarchdir = "/lib/ruby/#{major}.#{minor}/#{arch}" 166relative_archdir = rubyarchdir.rindex(prefix, 0) ? rubyarchdir[prefix.size..-1] : rubyarchdir 167puts %[\ 168# encoding: ascii-8bit 169# frozen-string-literal: false 170# 171# The module storing Ruby interpreter configurations on building. 172# 173# This file was created by #{mkconfig} when ruby was built. It contains 174# build information for ruby which is used e.g. by mkmf to build 175# compatible native extensions. Any changes made to this file will be 176# lost the next time ruby is built. 177 178module RbConfig 179 RUBY_VERSION.start_with?("#{version[/^[0-9]+\.[0-9]+\./] || version}") or 180 raise "ruby lib version (#{version}) doesn't match executable version (\#{RUBY_VERSION})" 181 182] 183print " # Ruby installed directory.\n" 184print " TOPDIR = File.dirname(__FILE__).chomp!(#{relative_archdir.dump})\n" 185print " # DESTDIR on make install.\n" 186print " DESTDIR = ", (drive ? "TOPDIR && TOPDIR[/\\A[a-z]:/i] || " : ""), "'' unless defined? DESTDIR\n" 187print <<'ARCH' if universal 188 arch_flag = ENV['ARCHFLAGS'] || ((e = ENV['RC_ARCHS']) && e.split.uniq.map {|a| "-arch #{a}"}.join(' ')) 189 arch = arch_flag && arch_flag[/\A\s*-arch\s+(\S+)\s*\z/, 1] 190ARCH 191print " universal = #{universal}\n" if universal 192print " # The hash configurations stored.\n" 193print " CONFIG = {}\n" 194print " CONFIG[\"DESTDIR\"] = DESTDIR\n" 195 196versions = {} 197IO.foreach(File.join(srcdir, "version.h")) do |l| 198 m = /^\s*#\s*define\s+RUBY_(PATCHLEVEL)\s+(-?\d+)/.match(l) 199 if m 200 versions[m[1]] = m[2] 201 break if versions.size == 4 202 next 203 end 204 m = /^\s*#\s*define\s+RUBY_VERSION\s+\W?([.\d]+)/.match(l) 205 if m 206 versions['MAJOR'], versions['MINOR'], versions['TEENY'] = m[1].split('.') 207 break if versions.size == 4 208 next 209 end 210end 211%w[MAJOR MINOR TEENY PATCHLEVEL].each do |v| 212 print " CONFIG[#{v.dump}] = #{versions[v].dump}\n" 213end 214 215dest = drive ? %r'= "(?!\$[\(\{])(?i:[a-z]:)' : %r'= "(?!\$[\(\{])' 216v_disabled = {} 217v_others.collect! do |x| 218 if /^\s*CONFIG\["((?!abs_|old)[a-z]+(?:_prefix|dir))"\]/ === x 219 name = $1 220 if /= "no"$/ =~ x 221 v_disabled[name] = true 222 v_others.delete(name) 223 next 224 end 225 x.sub(dest, '= "$(DESTDIR)') 226 else 227 x 228 end 229end 230v_others.compact! 231 232if $install_name 233 if install_name and vars.expand("$(RUBY_INSTALL_NAME)") == $install_name 234 $install_name = install_name 235 end 236 v_fast << " CONFIG[\"ruby_install_name\"] = \"" + $install_name + "\"\n" 237 v_fast << " CONFIG[\"RUBY_INSTALL_NAME\"] = \"" + $install_name + "\"\n" 238end 239if $so_name 240 if so_name and vars.expand("$(RUBY_SO_NAME)") == $so_name 241 $so_name = so_name 242 end 243 v_fast << " CONFIG[\"RUBY_SO_NAME\"] = \"" + $so_name + "\"\n" 244end 245 246print(*v_fast) 247print(*v_others) 248print <<EOS if $unicode_version 249 CONFIG["UNICODE_VERSION"] = #{$unicode_version.dump} 250EOS 251print <<EOS if $unicode_emoji_version 252 CONFIG["UNICODE_EMOJI_VERSION"] = #{$unicode_emoji_version.dump} 253EOS 254print <<EOS if /darwin/ =~ arch 255 CONFIG["SDKROOT"] = "\#{ENV['SDKROOT']}" # don't run xcrun every time, usually useless. 256EOS 257print <<EOS 258 CONFIG["archdir"] = "$(rubyarchdir)" 259 CONFIG["topdir"] = File.dirname(__FILE__) 260 # Almost same with CONFIG. MAKEFILE_CONFIG has other variable 261 # reference like below. 262 # 263 # MAKEFILE_CONFIG["bindir"] = "$(exec_prefix)/bin" 264 # 265 # The values of this constant is used for creating Makefile. 266 # 267 # require 'rbconfig' 268 # 269 # print <<-END_OF_MAKEFILE 270 # prefix = \#{Config::MAKEFILE_CONFIG['prefix']} 271 # exec_prefix = \#{Config::MAKEFILE_CONFIG['exec_prefix']} 272 # bindir = \#{Config::MAKEFILE_CONFIG['bindir']} 273 # END_OF_MAKEFILE 274 # 275 # => prefix = /usr/local 276 # exec_prefix = $(prefix) 277 # bindir = $(exec_prefix)/bin MAKEFILE_CONFIG = {} 278 # 279 # RbConfig.expand is used for resolving references like above in rbconfig. 280 # 281 # require 'rbconfig' 282 # p Config.expand(Config::MAKEFILE_CONFIG["bindir"]) 283 # # => "/usr/local/bin" 284 MAKEFILE_CONFIG = {} 285 CONFIG.each{|k,v| MAKEFILE_CONFIG[k] = v.dup} 286 287 # call-seq: 288 # 289 # RbConfig.expand(val) -> string 290 # RbConfig.expand(val, config) -> string 291 # 292 # expands variable with given +val+ value. 293 # 294 # RbConfig.expand("$(bindir)") # => /home/foobar/all-ruby/ruby19x/bin 295 def RbConfig::expand(val, config = CONFIG) 296 newval = val.gsub(/\\$\\$|\\$\\(([^()]+)\\)|\\$\\{([^{}]+)\\}/) { 297 var = $& 298 if !(v = $1 || $2) 299 '$' 300 elsif key = config[v = v[/\\A[^:]+(?=(?::(.*?)=(.*))?\\z)/]] 301 pat, sub = $1, $2 302 config[v] = false 303 config[v] = RbConfig::expand(key, config) 304 key = key.gsub(/\#{Regexp.quote(pat)}(?=\\s|\\z)/n) {sub} if pat 305 key 306 else 307 var 308 end 309 } 310 val.replace(newval) unless newval == val 311 val 312 end 313 CONFIG.each_value do |val| 314 RbConfig::expand(val) 315 end 316 317 # :nodoc: 318 # call-seq: 319 # 320 # RbConfig.fire_update!(key, val) -> string 321 # RbConfig.fire_update!(key, val, mkconf, conf) -> string 322 # 323 # updates +key+ in +mkconf+ with +val+, and all values depending on 324 # the +key+ in +mkconf+. 325 # 326 # RbConfig::MAKEFILE_CONFIG.values_at("CC", "LDSHARED") # => ["gcc", "$(CC) -shared"] 327 # RbConfig::CONFIG.values_at("CC", "LDSHARED") # => ["gcc", "gcc -shared"] 328 # RbConfig.fire_update!("CC", "gcc-8") # => ["CC", "LDSHARED"] 329 # RbConfig::MAKEFILE_CONFIG.values_at("CC", "LDSHARED") # => ["gcc-8", "$(CC) -shared"] 330 # RbConfig::CONFIG.values_at("CC", "LDSHARED") # => ["gcc-8", "gcc-8 -shared"] 331 # 332 # returns updated keys list, or +nil+ if nothing changed. 333 def RbConfig.fire_update!(key, val, mkconf = MAKEFILE_CONFIG, conf = CONFIG) 334 return if (old = mkconf[key]) == val 335 mkconf[key] = val 336 keys = [key] 337 deps = [] 338 begin 339 re = Regexp.new("\\\\$\\\\((?:%1$s)\\\\)|\\\\$\\\\{(?:%1$s)\\\\}" % keys.join('|')) 340 deps |= keys 341 keys.clear 342 mkconf.each {|k,v| keys << k if re =~ v} 343 end until keys.empty? 344 deps.each {|k| conf[k] = mkconf[k].dup} 345 deps.each {|k| expand(conf[k])} 346 deps 347 end 348 349 # call-seq: 350 # 351 # RbConfig.ruby -> path 352 # 353 # returns the absolute pathname of the ruby command. 354 def RbConfig.ruby 355 File.join( 356 RbConfig::CONFIG["bindir"], 357 RbConfig::CONFIG["ruby_install_name"] + RbConfig::CONFIG["EXEEXT"] 358 ) 359 end 360end 361CROSS_COMPILING = nil unless defined? CROSS_COMPILING 362EOS 363 364# vi:set sw=2: 365