summaryrefslogtreecommitdiff
path: root/tool/mkrunnable.rb
blob: 01756a3529f5fb62769fe299be89b4d745b888c6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#!./miniruby
# -*- coding: us-ascii -*-

# Used by "make runnable" target, to make symbolic links from a build
# directory.

require './rbconfig'
require 'fileutils'

case ARGV[0]
when "-n"
  ARGV.shift
  include FileUtils::DryRun
when "-v"
  ARGV.shift
  include FileUtils::Verbose
else
  include FileUtils
end

module Mswin
  def ln_safe(src, dest, *opt)
    cmd = ["mklink", dest.tr("/", "\\"), src.tr("/", "\\")]
    cmd[1, 0] = opt
    return if system("cmd", "/c", *cmd)
    # TODO: use RUNAS or something
    puts cmd.join(" ")
  end

  def ln_dir_safe(src, dest)
    ln_safe(src, dest, "/d")
  end
end

def clean_link(src, dest)
  begin
    link = File.readlink(dest)
  rescue
  else
    return if link == src
    File.unlink(dest)
  end
  yield src, dest
end

def ln_safe(src, dest)
  ln_sf(src, dest)
end

alias ln_dir_safe ln_safe

if !File.respond_to?(:symlink) && /mingw|mswin/ =~ (CROSS_COMPILING || RUBY_PLATFORM)
  extend Mswin
end

def clean_path(path)
  path = "#{path}/".gsub(/(\A|\/)(?:\.\/)+/, '\1').tr_s('/', '/')
  nil while path.sub!(/[^\/]+\/\.\.\//, '')
  path
end

def relative_path_from(path, base)
  path = clean_path(path)
  base = clean_path(base)
  path, base = [path, base].map{|s|s.split("/")}
  until path.empty? or base.empty? or path[0] != base[0]
      path.shift
      base.shift
  end
  path, base = [path, base].map{|s|s.join("/")}
  if /(\A|\/)\.\.\// =~ base
    File.expand_path(path)
  else
    base.gsub!(/[^\/]+/, '..')
    File.join(base, path)
  end
end

def ln_relative(src, dest)
  return if File.identical?(src, dest)
  parent = File.dirname(dest)
  File.directory?(parent) or mkdir_p(parent)
  clean_link(relative_path_from(src, parent), dest) {|s, d| ln_safe(s, d)}
end

def ln_dir_relative(src, dest)
  return if File.identical?(src, dest)
  parent = File.dirname(dest)
  File.directory?(parent) or mkdir_p(parent)
  clean_link(relative_path_from(src, parent), dest) {|s, d| ln_dir_safe(s, d)}
end

config = RbConfig::MAKEFILE_CONFIG.merge("prefix" => ".", "exec_prefix" => ".")
config.each_value {|s| RbConfig.expand(s, config)}
srcdir = config["srcdir"] ||= File.dirname(__FILE__)
top_srcdir = config["top_srcdir"] ||= File.dirname(srcdir)
extout = ARGV[0] || config["EXTOUT"]
arch = config["arch"]
bindir = config["bindir"]
libdirname = config["libdirname"]
libdir = config[libdirname || "libdir"]
vendordir = config["vendordir"]
rubylibdir = config["rubylibdir"]
rubyarchdir = config["rubyarchdir"]
archdir = "#{extout}/#{arch}"
[bindir, libdir, archdir].uniq.each do |dir|
  File.directory?(dir) or mkdir_p(dir)
end

exeext = config["EXEEXT"]
ruby_install_name = config["ruby_install_name"]
rubyw_install_name = config["rubyw_install_name"]
goruby_install_name = "go" + ruby_install_name
[ruby_install_name, rubyw_install_name, goruby_install_name].map do |ruby|
  ruby += exeext
  if ruby and !ruby.empty? and !File.file?(target = "#{bindir}/#{ruby}")
    ln_relative(ruby, target)
  end
end
so = config["LIBRUBY_SO"]
libruby = [config["LIBRUBY_A"]]
if /\.dll\z/i =~ so
  ln_relative(so, "#{bindir}/#{so}")
else
  libruby << so
end
libruby.concat(config["LIBRUBY_ALIASES"].split)
libruby.each {|lib|ln_relative(lib, "#{libdir}/#{lib}")}
ln_dir_relative("#{extout}/common", rubylibdir)
rubyarchdir.sub!(rubylibdir, "#{extout}/common")
vendordir.sub!(rubylibdir, "#{extout}/common")
ln_dir_relative(archdir, rubyarchdir)
vendordir.sub!(rubyarchdir, archdir)
ln_dir_relative("#{top_srcdir}/lib", vendordir)
ln_relative("rbconfig.rb", "#{archdir}/rbconfig.rb")