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
|
#!/usr/bin/env ruby
require 'rbconfig'
require 'optparse'
require 'pathname'
def expand_require(out, filename, dirs, main, included={})
open(filename) {|f|
comment = false
test = false
f.each {|line|
if /^=begin/ =~ line
comment = true
out.print line
elsif /^=end/ =~ line
comment = false
out.print line
elsif comment
out.print line
elsif !main && (/^if __FILE__ == \$0/ =~ line || /^if \$0 == __FILE__/ =~ line)
test = true
out.print "#", line
elsif test && /^end/ =~ line
test = false
out.print "#", line
elsif test
out.print "#", line
elsif /^require '([^']*)'/ =~ line && %r{^/} !~ (req = $1)
if included[req]
out.print "#", line
else
dir = dirs.find {|d| (d + "#{req}.rb").exist? }
if dir
out.print "#", line
filename = dir + "#{req}.rb"
included[req] = filename
#endmark = 'End_' + [req].pack("m*").delete("\n")
#out.print "eval <<'#{endmark}', TOPLEVEL_BINDING, #{"[#{filename}]".dump}, #{out.output_line+1}\n"
expand_require(out, filename, dirs, false, included)
#out.print "#{endmark}\n"
else
out.print line
end
end
elsif /^__END__$/ =~ line
break
else
out.print line
end
}
}
end
module CountOutputLine
def output_line
@output_line = 1 unless defined? @output_line
@output_line
end
def write(str)
@output_line = output_line + str.count("\n")
super
end
end
def parse_options
$output_filename = nil
$dep_output_filename = nil
ARGV.options {|q|
q.banner = 'rb-link [opts] script-file [library-directories...]'
q.def_option('--help', 'show this message') {puts q; exit(0)}
q.def_option('--output=filename', '-o', 'specify output file') {|filename| $output_filename = filename}
q.def_option('--dependency=filename', '-d', 'specify dependency output file') {|filename| $dep_output_filename = filename}
q.parse!
}
end
def open_output
if $output_filename
File.open($output_filename, 'w') {|f|
yield f
f.chmod 0755
}
else
yield STDOUT
end
end
def main
parse_options
script = ARGV.shift
if ARGV.empty?
libdirs = [Pathname.new('.')]
else
libdirs = ARGV.map {|f| Pathname.new(f) }
end
open_output {|out|
out.extend CountOutputLine
interpreter_path = File.join(Config::CONFIG["bindir"], Config::CONFIG["ruby_install_name"])
out.print "#!#{interpreter_path}\n"
included = {}
expand_require(out, script, libdirs, true, included)
if $dep_output_filename
open($dep_output_filename, 'w') {|f|
incs = included.values.sort
if incs.empty?
f.puts "#{$output_filename} : #{script}"
else
f.puts "#{$output_filename} : #{script} #{incs.join(' ')}"
incs.each {|inc|
f.puts "#{inc} :"
}
end
}
end
}
end
main
|