From fcbf63e62c627deae76c1b8cb8c0876c536ed811 Mon Sep 17 00:00:00 2001 From: Jari Vetoniemi Date: Mon, 16 Mar 2020 18:49:26 +0900 Subject: Fresh start --- jni/ruby/tool/rbinstall.rb | 763 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 763 insertions(+) create mode 100755 jni/ruby/tool/rbinstall.rb (limited to 'jni/ruby/tool/rbinstall.rb') diff --git a/jni/ruby/tool/rbinstall.rb b/jni/ruby/tool/rbinstall.rb new file mode 100755 index 0000000..db36a21 --- /dev/null +++ b/jni/ruby/tool/rbinstall.rb @@ -0,0 +1,763 @@ +#!./miniruby + +begin + load "./rbconfig.rb" +rescue LoadError + CONFIG = Hash.new {""} +else + include RbConfig + $".unshift File.expand_path("./rbconfig.rb") +end + +srcdir = File.expand_path('../..', __FILE__) +unless defined?(CROSS_COMPILING) and CROSS_COMPILING + $:.replace([srcdir+"/lib", Dir.pwd]) +end +require 'fileutils' +require 'shellwords' +require 'optparse' +require 'optparse/shellwords' +require 'ostruct' +require 'rubygems' + +STDOUT.sync = true +File.umask(0) + +def parse_args(argv = ARGV) + $mantype = 'doc' + $destdir = nil + $extout = nil + $make = 'make' + $mflags = [] + $install = [] + $installed_list = nil + $dryrun = false + $rdocdir = nil + $data_mode = 0644 + $prog_mode = 0755 + $dir_mode = nil + $script_mode = nil + $strip = false + $cmdtype = (if File::ALT_SEPARATOR == '\\' + File.exist?("rubystub.exe") ? 'exe' : 'bat' + end) + mflags = [] + opt = OptionParser.new + opt.on('-n', '--dry-run') {$dryrun = true} + opt.on('--dest-dir=DIR') {|dir| $destdir = dir} + opt.on('--extout=DIR') {|dir| $extout = (dir unless dir.empty?)} + opt.on('--make=COMMAND') {|make| $make = make} + opt.on('--mantype=MAN') {|man| $mantype = man} + opt.on('--make-flags=FLAGS', '--mflags', Shellwords) do |v| + if arg = v.first + arg.insert(0, '-') if /\A[^-][^=]*\Z/ =~ arg + end + $mflags.concat(v) + end + opt.on('-i', '--install=TYPE', $install_procs.keys) do |ins| + $install << ins + end + opt.on('--data-mode=OCTAL-MODE', OptionParser::OctalInteger) do |mode| + $data_mode = mode + end + opt.on('--prog-mode=OCTAL-MODE', OptionParser::OctalInteger) do |mode| + $prog_mode = mode + end + opt.on('--dir-mode=OCTAL-MODE', OptionParser::OctalInteger) do |mode| + $dir_mode = mode + end + opt.on('--script-mode=OCTAL-MODE', OptionParser::OctalInteger) do |mode| + $script_mode = mode + end + opt.on('--installed-list [FILENAME]') {|name| $installed_list = name} + opt.on('--rdoc-output [DIR]') {|dir| $rdocdir = dir} + opt.on('--cmd-type=TYPE', %w[bat cmd plain]) {|cmd| $cmdtype = (cmd unless cmd == 'plain')} + opt.on('--[no-]strip') {|strip| $strip = strip} + + opt.order!(argv) do |v| + case v + when /\AINSTALL[-_]([-\w]+)=(.*)/ + argv.unshift("--#{$1.tr('_', '-')}=#{$2}") + when /\A\w[-\w+]*=\z/ + mflags << v + when /\A\w[-\w+]*\z/ + $install << v.intern + else + raise OptionParser::InvalidArgument, v + end + end rescue abort "#{$!.message}\n#{opt.help}" + + unless defined?(RbConfig) + puts opt.help + exit + end + + $make, *rest = Shellwords.shellwords($make) + $mflags.unshift(*rest) unless rest.empty? + $mflags.unshift(*mflags) + + def $mflags.set?(flag) + grep(/\A-(?!-).*#{flag.chr}/i) { return true } + false + end + def $mflags.defined?(var) + grep(/\A#{var}=(.*)/) {return block_given? ? yield($1) : $1} + false + end + + if $mflags.set?(?n) + $dryrun = true + else + $mflags << '-n' if $dryrun + end + + $destdir ||= $mflags.defined?("DESTDIR") + if $extout ||= $mflags.defined?("EXTOUT") + RbConfig.expand($extout) + end + + $continue = $mflags.set?(?k) + + if $installed_list ||= $mflags.defined?('INSTALLED_LIST') + RbConfig.expand($installed_list, RbConfig::CONFIG) + $installed_list = open($installed_list, "ab") + $installed_list.sync = true + end + + $rdocdir ||= $mflags.defined?('RDOCOUT') + + $dir_mode ||= $prog_mode | 0700 + $script_mode ||= $prog_mode +end + +$install_procs = Hash.new {[]} +def install?(*types, &block) + $install_procs[:all] <<= block + types.each do |type| + $install_procs[type] <<= block + end +end + +def strip_file(files) + if !defined?($strip_command) and (cmd = CONFIG["STRIP"]) + case cmd + when "", "true", ":" then return + else $strip_command = Shellwords.shellwords(cmd) + end + elsif !$strip_command + return + end + system(*($strip_command + [files].flatten)) +end + +def install(src, dest, options = {}) + options = options.clone + strip = options.delete(:strip) + options[:preserve] = true + d = with_destdir(dest) + super(src, d, options) + srcs = Array(src) + if strip + d = srcs.map {|src| File.join(d, File.basename(src))} if $made_dirs[dest] + strip_file(d) + end + if $installed_list + dest = srcs.map {|src| File.join(dest, File.basename(src))} if $made_dirs[dest] + $installed_list.puts dest + end +end + +def ln_sf(src, dest) + super(src, with_destdir(dest)) + $installed_list.puts dest if $installed_list +end + +$made_dirs = {} +def makedirs(dirs) + dirs = fu_list(dirs) + dirs.collect! do |dir| + realdir = with_destdir(dir) + realdir unless $made_dirs.fetch(dir) do + $made_dirs[dir] = true + $installed_list.puts(File.join(dir, "")) if $installed_list + File.directory?(realdir) + end + end.compact! + super(dirs, :mode => $dir_mode) unless dirs.empty? +end + +FalseProc = proc {false} +def path_matcher(pat) + if pat and !pat.empty? + proc {|f| pat.any? {|n| File.fnmatch?(n, f)}} + else + FalseProc + end +end + +def install_recursive(srcdir, dest, options = {}) + opts = options.clone + noinst = opts.delete(:no_install) + glob = opts.delete(:glob) || "*" + maxdepth = opts.delete(:maxdepth) + subpath = (srcdir.size+1)..-1 + prune = [] + skip = [] + if noinst + if Array === noinst + prune = noinst.grep(/#{File::SEPARATOR}/o).map!{|f| f.chomp(File::SEPARATOR)} + skip = noinst.grep(/\A[^#{File::SEPARATOR}]*\z/o) + else + if noinst.index(File::SEPARATOR) + prune = [noinst] + else + skip = [noinst] + end + end + end + skip |= %w"#*# *~ *.old *.bak *.orig *.rej *.diff *.patch *.core" + prune = path_matcher(prune) + skip = path_matcher(skip) + File.directory?(srcdir) or return rescue return + paths = [[srcdir, dest, 0]] + found = [] + while file = paths.shift + found << file + file, d, dir = *file + if dir + depth = dir + 1 + next if maxdepth and maxdepth < depth + files = [] + Dir.foreach(file) do |f| + src = File.join(file, f) + d = File.join(dest, dir = src[subpath]) + stat = File.lstat(src) rescue next + if stat.directory? + files << [src, d, depth] if maxdepth != depth and /\A\./ !~ f and !prune[dir] + elsif stat.symlink? + # skip + else + files << [src, d, false] if File.fnmatch?(glob, f) and !skip[f] + end + end + paths.insert(0, *files) + end + end + for src, d, dir in found + if dir + makedirs(d) + else + makedirs(d[/.*(?=\/)/m]) + if block_given? + yield src, d, opts + else + install src, d, opts + end + end + end +end + +def open_for_install(path, mode) + data = open(realpath = with_destdir(path), "rb") {|f| f.read} rescue nil + newdata = yield + unless $dryrun + unless newdata == data + open(realpath, "wb", mode) {|f| f.write newdata} + end + File.chmod(mode, realpath) + end + $installed_list.puts path if $installed_list +end + +def with_destdir(dir) + return dir if !$destdir or $destdir.empty? + dir = dir.sub(/\A\w:/, '') if File::PATH_SEPARATOR == ';' + $destdir + dir +end + +def prepare(mesg, basedir, subdirs=nil) + return unless basedir + case + when !subdirs + dirs = basedir + when subdirs.size == 0 + subdirs = nil + when subdirs.size == 1 + dirs = [basedir = File.join(basedir, subdirs)] + subdirs = nil + else + dirs = [basedir, *subdirs.collect {|dir| File.join(basedir, dir)}] + end + printf("installing %-18s %s%s\n", "#{mesg}:", basedir, + (subdirs ? " (#{subdirs.join(', ')})" : "")) + makedirs(dirs) +end + +def CONFIG.[](name, mandatory = false) + value = super(name) + if mandatory + raise "CONFIG['#{name}'] must be set" if !value or value.empty? + end + value +end + +exeext = CONFIG["EXEEXT"] + +ruby_install_name = CONFIG["ruby_install_name", true] +rubyw_install_name = CONFIG["rubyw_install_name"] +goruby_install_name = "go" + ruby_install_name + +bindir = CONFIG["bindir", true] +libdir = CONFIG[CONFIG.fetch("libdirname", "libdir"), true] +rubyhdrdir = CONFIG["rubyhdrdir", true] +archhdrdir = CONFIG["rubyarchhdrdir"] || (rubyhdrdir + "/" + CONFIG['arch']) +rubylibdir = CONFIG["rubylibdir", true] +archlibdir = CONFIG["rubyarchdir", true] +sitelibdir = CONFIG["sitelibdir"] +sitearchlibdir = CONFIG["sitearchdir"] +vendorlibdir = CONFIG["vendorlibdir"] +vendorarchlibdir = CONFIG["vendorarchdir"] +mandir = CONFIG["mandir", true] +docdir = CONFIG["docdir", true] +configure_args = Shellwords.shellwords(CONFIG["configure_args"]) +enable_shared = CONFIG["ENABLE_SHARED"] == 'yes' +dll = CONFIG["LIBRUBY_SO", enable_shared] +lib = CONFIG["LIBRUBY", true] +arc = CONFIG["LIBRUBY_A", true] +major = CONFIG["MAJOR", true] +minor = CONFIG["MINOR", true] +load_relative = configure_args.include?("--enable-load-relative") + +install?(:local, :arch, :bin, :'bin-arch') do + prepare "binary commands", bindir + + install ruby_install_name+exeext, bindir, :mode => $prog_mode, :strip => $strip + if rubyw_install_name and !rubyw_install_name.empty? + install rubyw_install_name+exeext, bindir, :mode => $prog_mode, :strip => $strip + end + if File.exist? goruby_install_name+exeext + install goruby_install_name+exeext, bindir, :mode => $prog_mode, :strip => $strip + end + if enable_shared and dll != lib + install dll, bindir, :mode => $prog_mode, :strip => $strip + end +end + +install?(:local, :arch, :lib) do + prepare "base libraries", libdir + + install lib, libdir, :mode => $prog_mode, :strip => $strip unless lib == arc + install arc, libdir, :mode => $data_mode + if dll == lib and dll != arc + for link in CONFIG["LIBRUBY_ALIASES"].split + ln_sf(dll, File.join(libdir, link)) + end + end + + prepare "arch files", archlibdir + install "rbconfig.rb", archlibdir, :mode => $data_mode + if CONFIG["ARCHFILE"] + for file in CONFIG["ARCHFILE"].split + install file, archlibdir, :mode => $data_mode + end + end +end + +install?(:local, :arch, :data) do + pc = CONFIG["ruby_pc"] + if pc and File.file?(pc) and File.size?(pc) + prepare "pkgconfig data", pkgconfigdir = File.join(libdir, "pkgconfig") + install pc, pkgconfigdir, :mode => $data_mode + end +end + +install?(:ext, :arch, :'ext-arch') do + prepare "extension objects", archlibdir + noinst = %w[-* -*/] | (CONFIG["no_install_files"] || "").split + install_recursive("#{$extout}/#{CONFIG['arch']}", archlibdir, :no_install => noinst, :mode => $prog_mode, :strip => $strip) + prepare "extension objects", sitearchlibdir + prepare "extension objects", vendorarchlibdir +end +install?(:ext, :arch, :hdr, :'arch-hdr') do + prepare "extension headers", archhdrdir + install_recursive("#{$extout}/include/#{CONFIG['arch']}", archhdrdir, :glob => "*.h", :mode => $data_mode) +end +install?(:ext, :comm, :'ext-comm') do + prepare "extension scripts", rubylibdir + install_recursive("#{$extout}/common", rubylibdir, :mode => $data_mode) + prepare "extension scripts", sitelibdir + prepare "extension scripts", vendorlibdir +end +install?(:ext, :comm, :hdr, :'comm-hdr') do + hdrdir = rubyhdrdir + "/ruby" + prepare "extension headers", hdrdir + install_recursive("#{$extout}/include/ruby", hdrdir, :glob => "*.h", :mode => $data_mode) +end + +install?(:doc, :rdoc) do + if $rdocdir + ridatadir = File.join(CONFIG['ridir'], CONFIG['ruby_version'], "system") + prepare "rdoc", ridatadir + install_recursive($rdocdir, ridatadir, :mode => $data_mode) + end +end +install?(:doc, :capi) do + prepare "capi-docs", docdir + install_recursive "doc/capi", docdir+"/capi", :mode => $data_mode +end + +if load_relative + PROLOG_SCRIPT = </dev/null; pwd` +EOS + if CONFIG["LIBRUBY_RELATIVE"] != 'yes' and libpathenv = CONFIG["LIBPATHENV"] + pathsep = File::PATH_SEPARATOR + PROLOG_SCRIPT << < 1) do |src, cmd| + cmd = cmd.sub(/[^\/]*\z/m) {|n| RbConfig.expand(trans[n])} + + shebang = '' + body = '' + open(src, "rb") do |f| + shebang = f.gets + body = f.read + end + shebang or raise "empty file - #{src}" + if PROLOG_SCRIPT + shebang.sub!(/\A(\#!.*?ruby\b)?/) {PROLOG_SCRIPT + ($1 || "#!ruby\n")} + else + shebang.sub!(/\A\#!.*?ruby\b/) {"#!" + ruby_shebang} + end + shebang.sub!(/\r$/, '') + body.gsub!(/\r$/, '') + + cmd << ".#{$cmdtype}" if $cmdtype + open_for_install(cmd, $script_mode) do + case $cmdtype + when "exe" + stub + shebang + body + when "bat" + [<<-"EOH".gsub(/^\s+/, ''), shebang, body, "__END__\n:endofruby\n"].join.gsub(/$/, "\r") + @echo off + @if not "%~d0" == "~d0" goto WinNT + #{ruby_bin} -x "#{cmd}" %1 %2 %3 %4 %5 %6 %7 %8 %9 + @goto endofruby + :WinNT + "%~dp0#{ruby_install_name}" -x "%~f0" %* + @goto endofruby + EOH + when "cmd" + <<"/EOH" << shebang << body +@"%~dp0#{ruby_install_name}" -x "%~f0" %* +@exit /b %ERRORLEVEL% +/EOH + else + shebang + body + end + end + end +end + +install?(:local, :comm, :lib) do + prepare "library scripts", rubylibdir + noinst = %w[README* *.txt *.rdoc *.gemspec] + install_recursive(File.join(srcdir, "lib"), rubylibdir, :no_install => noinst, :mode => $data_mode) +end + +install?(:local, :comm, :hdr, :'comm-hdr') do + prepare "common headers", rubyhdrdir + + noinst = [] + unless RUBY_PLATFORM =~ /mswin|mingw|bccwin/ + noinst << "win32.h" + end + noinst = nil if noinst.empty? + install_recursive(File.join(srcdir, "include"), rubyhdrdir, :no_install => noinst, :glob => "*.h", :mode => $data_mode) +end + +install?(:local, :comm, :man) do + mdocs = Dir["#{srcdir}/man/*.[1-9]"] + prepare "manpages", mandir, ([] | mdocs.collect {|mdoc| mdoc[/\d+$/]}).sort.collect {|sec| "man#{sec}"} + + mandir = File.join(mandir, "man") + has_goruby = File.exist?(goruby_install_name+exeext) + require File.join(srcdir, "tool/mdoc2man.rb") if $mantype != "doc" + mdocs.each do |mdoc| + next unless File.file?(mdoc) and open(mdoc){|fh| fh.read(1) == '.'} + base = File.basename(mdoc) + if base == "goruby.1" + next unless has_goruby + end + + destdir = mandir + (section = mdoc[/\d+$/]) + destname = ruby_install_name.sub(/ruby/, base.chomp(".#{section}")) + destfile = File.join(destdir, "#{destname}.#{section}") + + if $mantype == "doc" + install mdoc, destfile, :mode => $data_mode + else + class << (w = []) + alias print push + end + open(mdoc) {|r| Mdoc2Man.mdoc2man(r, w)} + open_for_install(destfile, $data_mode) {w.join("")} + end + end +end + +module RbInstall + module Specs + class FileCollector + def initialize(base_dir) + @base_dir = base_dir + end + + def collect + (ruby_libraries + built_libraries).sort + end + + private + def type + /\/(ext|lib)?\/.*?\z/ =~ @base_dir + $1 + end + + def ruby_libraries + case type + when "ext" + prefix = "#{$extout}/common/" + base = "#{prefix}#{relative_base}" + when "lib" + base = @base_dir + prefix = base.sub(/lib\/.*?\z/, "") + "lib/" + end + + Dir.glob("#{base}{.rb,/**/*.rb}").collect do |ruby_source| + remove_prefix(prefix, ruby_source) + end + end + + def built_libraries + case type + when "ext" + prefix = "#{$extout}/#{CONFIG['arch']}/" + base = "#{prefix}#{relative_base}" + Dir.glob("#{base}{.so,/**/*.so}").collect do |built_library| + remove_prefix(prefix, built_library) + end + when "lib" + [] + end + end + + def relative_base + /\/#{Regexp.escape(type)}\/(.*?)\z/ =~ @base_dir + $1 + end + + def remove_prefix(prefix, string) + string.sub(/\A#{Regexp.escape(prefix)}/, "") + end + end + + class Reader < Struct.new(:src) + def gemspec + @gemspec ||= begin + spec = Gem::Specification.load(src) || raise("invalid spec in #{src}") + file_collector = FileCollector.new(File.dirname(src)) + spec.files = file_collector.collect + spec + end + end + + def spec_source + @gemspec.to_ruby + end + end + + class Generator < Struct.new(:name, :base_dir, :src, :execs) + def gemspec + @gemspec ||= eval spec_source + end + + def spec_source + <<-GEMSPEC +Gem::Specification.new do |s| + s.name = #{name.dump} + s.version = #{version.dump} + s.summary = "This #{name} is bundled with Ruby" + s.executables = #{execs.inspect} + s.files = #{files.inspect} +end + GEMSPEC + end + + private + def version + version = open(src) { |f| + f.find { |s| /^\s*\w*VERSION\s*=(?!=)/ =~ s } + } or return + version.split(%r"=\s*", 2)[1].strip[/\A([\'\"])(.*?)\1/, 2] + end + + def files + file_collector = FileCollector.new(base_dir) + file_collector.collect + end + end + end +end +# :startdoc: + +install?(:ext, :comm, :gem) do + $:.unshift(File.join(srcdir, "lib")) + require("rubygems.rb") + gem_dir = Gem.default_dir + directories = Gem.ensure_gem_subdirectories(gem_dir, :mode => $dir_mode) + prepare "default gems", gem_dir, directories + + spec_dir = File.join(gem_dir, directories.grep(/^spec/)[0]) + default_spec_dir = "#{spec_dir}/default" + makedirs(default_spec_dir) + + gems = {} + File.foreach(File.join(srcdir, "defs/default_gems")) do |line| + line.chomp! + line.sub!(/\s*#.*/, '') + next if line.empty? + words = [] + line.scan(/\G\s*([^\[\]\s]+|\[([^\[\]]*)\])/) do + words << ($2 ? $2.split : $1) + end + name, base_dir, src, execs = *words + next unless name and base_dir and src + + src = File.join(srcdir, src) + base_dir = File.join(srcdir, base_dir) + specgen = RbInstall::Specs::Generator.new(name, base_dir, src, execs || []) + gems[name] ||= specgen + end + + Dir.glob(srcdir+"/{lib,ext}/**/*.gemspec").each do |src| + specgen = RbInstall::Specs::Reader.new(src) + gems[specgen.gemspec.name] ||= specgen + end + + gems.sort.each do |name, specgen| + gemspec = specgen.gemspec + base_dir = specgen.src.sub(/\A#{Regexp.escape(srcdir)}\//, "") + full_name = "#{gemspec.name}-#{gemspec.version}" + + puts "#{" "*30}#{gemspec.name} #{gemspec.version}" + gemspec_path = File.join(default_spec_dir, "#{full_name}.gemspec") + open_for_install(gemspec_path, $data_mode) do + specgen.spec_source + end + + unless gemspec.executables.empty? then + bin_dir = File.join(gem_dir, 'gems', full_name, 'bin') + makedirs(bin_dir) + + execs = gemspec.executables.map {|exec| File.join(srcdir, 'bin', exec)} + install(execs, bin_dir, :mode => $prog_mode) + end + end +end + +install?(:ext, :comm, :gem) do + begin + require "zlib" + rescue LoadError + end + if defined?(Zlib) + require 'pathname' + gem_dir = Gem.default_dir + directories = Gem.ensure_gem_subdirectories(gem_dir, :mode => $dir_mode) + prepare "bundle gems", gem_dir, directories + Dir.glob(srcdir+'/gems/*.gem').each do |gem| + Gem.install gem, Gem::Requirement.default, :install_dir => with_destdir(Gem.dir), :domain => :local, :ignore_dependencies => true + gemname = Pathname(gem).basename + puts "#{" "*30}#{gemname}" + end + # fix directory permissions + # TODO: Gem.install should accept :dir_mode option or something + File.chmod($dir_mode, *Dir.glob(with_destdir(Gem.dir)+"/**/")) + # fix .gemspec permissions + File.chmod($data_mode, *Dir.glob(with_destdir(Gem.dir)+"/specifications/*.gemspec")) + else + puts "skip installing bundle gems because of lacking zlib" + end +end + +parse_args() + +include FileUtils +include FileUtils::NoWrite if $dryrun +@fileutils_output = STDOUT +@fileutils_label = '' + +all = $install.delete(:all) +$install << :local << :ext if $install.empty? +installs = $install.map do |inst| + if !(procs = $install_procs[inst]) || procs.empty? + next warn("unknown install target - #{inst}") + end + procs +end +installs.flatten! +installs.uniq! +installs |= $install_procs[:all] if all +installs.each do |block| + dir = Dir.pwd + begin + block.call + ensure + Dir.chdir(dir) + end +end + +# vi:set sw=2: -- cgit v1.2.3