2010-07-06 11:48:36 -07:00
|
|
|
class ExecutionError <RuntimeError
|
|
|
|
attr :exit_status
|
|
|
|
attr :command
|
|
|
|
|
|
|
|
def initialize cmd, args = [], es = nil
|
|
|
|
@command = cmd
|
|
|
|
super "Failure while executing: #{cmd} #{pretty(args)*' '}"
|
|
|
|
@exit_status = es.exitstatus rescue 1
|
|
|
|
end
|
|
|
|
|
|
|
|
def was_running_configure?
|
|
|
|
@command == './configure'
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
def pretty args
|
|
|
|
args.collect do |arg|
|
|
|
|
if arg.to_s.include? ' '
|
|
|
|
"'#{ arg.gsub "'", "\\'" }'"
|
|
|
|
else
|
|
|
|
arg
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
class BuildError <ExecutionError
|
|
|
|
attr :env
|
|
|
|
|
|
|
|
def initialize cmd, args = [], es = nil
|
|
|
|
super
|
|
|
|
@env = ENV.to_hash
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2009-10-15 14:42:19 +01:00
|
|
|
class Tty
|
|
|
|
class <<self
|
|
|
|
def blue; bold 34; end
|
|
|
|
def white; bold 39; end
|
|
|
|
def red; underline 31; end
|
|
|
|
def yellow; underline 33 ; end
|
|
|
|
def reset; escape 0; end
|
2009-11-11 18:36:50 +00:00
|
|
|
def em; underline 39; end
|
2009-10-15 14:42:19 +01:00
|
|
|
|
|
|
|
private
|
|
|
|
def color n
|
|
|
|
escape "0;#{n}"
|
|
|
|
end
|
|
|
|
def bold n
|
|
|
|
escape "1;#{n}"
|
|
|
|
end
|
|
|
|
def underline n
|
|
|
|
escape "4;#{n}"
|
|
|
|
end
|
|
|
|
def escape n
|
|
|
|
"\033[#{n}m" if $stdout.tty?
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2009-08-08 14:05:09 +01:00
|
|
|
# args are additional inputs to puts until a nil arg is encountered
|
2009-09-16 19:29:43 +01:00
|
|
|
def ohai title, *sput
|
2009-10-23 16:05:32 +01:00
|
|
|
title = title.to_s[0, `/usr/bin/tput cols`.strip.to_i-4] unless ARGV.verbose?
|
2009-10-15 14:42:19 +01:00
|
|
|
puts "#{Tty.blue}==>#{Tty.white} #{title}#{Tty.reset}"
|
2009-09-16 19:29:43 +01:00
|
|
|
puts *sput unless sput.empty?
|
2009-07-31 02:51:17 +01:00
|
|
|
end
|
2009-07-31 03:56:46 +01:00
|
|
|
|
|
|
|
def opoo warning
|
2009-10-15 14:42:19 +01:00
|
|
|
puts "#{Tty.red}Warning#{Tty.reset}: #{warning}"
|
2009-08-10 16:48:30 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
def onoe error
|
2009-10-01 15:41:15 +01:00
|
|
|
lines = error.to_s.split'\n'
|
2009-10-15 14:42:19 +01:00
|
|
|
puts "#{Tty.red}Error#{Tty.reset}: #{lines.shift}"
|
2009-10-01 15:41:15 +01:00
|
|
|
puts *lines unless lines.empty?
|
2009-08-10 16:48:30 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
def pretty_duration s
|
2009-09-03 20:58:33 +01:00
|
|
|
return "2 seconds" if s < 3 # avoids the plural problem ;)
|
|
|
|
return "#{s.to_i} seconds" if s < 120
|
|
|
|
return "%.1f minutes" % (s/60)
|
2009-08-10 16:48:30 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
def interactive_shell
|
2010-06-11 17:18:05 -07:00
|
|
|
fork {exec ENV['SHELL'] }
|
2009-11-09 17:44:29 +00:00
|
|
|
Process.wait
|
|
|
|
unless $?.success?
|
|
|
|
puts "Aborting due to non-zero exit status"
|
|
|
|
exit $?
|
|
|
|
end
|
2009-07-31 03:56:46 +01:00
|
|
|
end
|
2009-08-11 12:20:55 -07:00
|
|
|
|
2010-01-13 09:00:51 +00:00
|
|
|
module Homebrew
|
|
|
|
def self.system cmd, *args
|
|
|
|
puts "#{cmd} #{args*' '}" if ARGV.verbose?
|
|
|
|
fork do
|
|
|
|
yield if block_given?
|
|
|
|
args.collect!{|arg| arg.to_s}
|
|
|
|
exec(cmd, *args) rescue nil
|
|
|
|
exit! 1 # never gets here unless exec failed
|
|
|
|
end
|
|
|
|
Process.wait
|
|
|
|
$?.success?
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2009-08-11 12:20:55 -07:00
|
|
|
# Kernel.system but with exceptions
|
|
|
|
def safe_system cmd, *args
|
2010-01-13 09:00:51 +00:00
|
|
|
raise ExecutionError.new(cmd, args, $?) unless Homebrew.system(cmd, *args)
|
|
|
|
end
|
|
|
|
|
|
|
|
# prints no output
|
|
|
|
def quiet_system cmd, *args
|
|
|
|
Homebrew.system(cmd, *args) do
|
|
|
|
$stdout.close
|
|
|
|
$stderr.close
|
2009-11-09 17:44:29 +00:00
|
|
|
end
|
2009-08-11 12:20:55 -07:00
|
|
|
end
|
|
|
|
|
2009-09-04 15:28:18 +01:00
|
|
|
def curl *args
|
|
|
|
safe_system 'curl', '-f#LA', HOMEBREW_USER_AGENT, *args unless args.empty?
|
2009-08-11 12:20:55 -07:00
|
|
|
end
|
2009-09-04 15:22:25 -07:00
|
|
|
|
|
|
|
def puts_columns items, cols = 4
|
2009-12-18 16:28:30 -08:00
|
|
|
return if items.empty?
|
|
|
|
|
2009-09-22 20:43:06 +02:00
|
|
|
if $stdout.tty?
|
2009-11-14 13:43:07 +13:00
|
|
|
# determine the best width to display for different console sizes
|
2010-01-16 13:12:38 +00:00
|
|
|
console_width = `/bin/stty size`.chomp.split(" ").last.to_i
|
|
|
|
console_width = 80 if console_width <= 0
|
2009-11-14 13:43:07 +13:00
|
|
|
longest = items.sort_by { |item| item.length }.last
|
|
|
|
optimal_col_width = (console_width.to_f / (longest.length + 2).to_f).floor
|
|
|
|
cols = optimal_col_width > 1 ? optimal_col_width : 1
|
|
|
|
|
2010-03-06 03:11:30 +02:00
|
|
|
IO.popen("/usr/bin/pr -#{cols} -t -w#{console_width}", "w"){|io| io.puts(items) }
|
2009-09-22 20:43:06 +02:00
|
|
|
else
|
2009-09-23 16:44:10 +01:00
|
|
|
puts *items
|
2009-09-22 20:43:06 +02:00
|
|
|
end
|
2009-09-04 15:22:25 -07:00
|
|
|
end
|
2009-09-05 14:03:41 -04:00
|
|
|
|
|
|
|
def exec_editor *args
|
|
|
|
editor=ENV['EDITOR']
|
|
|
|
if editor.nil?
|
2009-09-23 16:44:10 +01:00
|
|
|
if system "/usr/bin/which -s mate"
|
2009-09-05 14:03:41 -04:00
|
|
|
editor='mate'
|
|
|
|
else
|
2009-09-23 16:44:10 +01:00
|
|
|
editor='/usr/bin/vim'
|
2009-09-05 14:03:41 -04:00
|
|
|
end
|
|
|
|
end
|
2009-09-08 22:10:14 +01:00
|
|
|
# we split the editor because especially on mac "mate -w" is common
|
|
|
|
# but we still want to use the comma-delimited version of exec because then
|
|
|
|
# we don't have to escape args, and escaping 100% is tricky
|
|
|
|
exec *(editor.split+args)
|
2009-09-05 14:03:41 -04:00
|
|
|
end
|
2009-09-08 15:31:28 -07:00
|
|
|
|
2010-01-29 10:15:33 -08:00
|
|
|
# GZips the given path, and returns the gzipped file
|
|
|
|
def gzip path
|
|
|
|
system "/usr/bin/gzip", path
|
|
|
|
return Pathname.new(path+".gz")
|
|
|
|
end
|
|
|
|
|
2010-05-10 10:14:20 -07:00
|
|
|
module ArchitectureListExtension
|
|
|
|
def universal?
|
|
|
|
self.include? :i386 and self.include? :x86_64
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# Returns array of architectures that the given command or library is built for.
|
2010-01-13 11:14:58 +00:00
|
|
|
def archs_for_command cmd
|
2010-04-03 11:51:46 -07:00
|
|
|
cmd = cmd.to_s # If we were passed a Pathname, turn it into a string.
|
|
|
|
cmd = `/usr/bin/which #{cmd}` unless Pathname.new(cmd).absolute?
|
|
|
|
cmd.gsub! ' ', '\\ ' # Escape spaces in the filename.
|
|
|
|
|
2010-05-10 10:14:20 -07:00
|
|
|
archs = IO.popen("/usr/bin/file #{cmd}").readlines.inject([]) do |archs, line|
|
2010-04-03 11:51:46 -07:00
|
|
|
case line
|
2010-05-10 10:14:20 -07:00
|
|
|
when /Mach-O (executable|dynamically linked shared library) ppc/
|
2010-04-03 11:51:46 -07:00
|
|
|
archs << :ppc7400
|
2010-05-10 10:14:20 -07:00
|
|
|
when /Mach-O 64-bit (executable|dynamically linked shared library) ppc64/
|
2010-04-03 11:51:46 -07:00
|
|
|
archs << :ppc64
|
2010-05-10 10:14:20 -07:00
|
|
|
when /Mach-O (executable|dynamically linked shared library) i386/
|
2010-04-03 11:51:46 -07:00
|
|
|
archs << :i386
|
2010-05-10 10:14:20 -07:00
|
|
|
when /Mach-O 64-bit (executable|dynamically linked shared library) x86_64/
|
2010-04-03 11:51:46 -07:00
|
|
|
archs << :x86_64
|
|
|
|
else
|
|
|
|
archs
|
2009-09-08 15:31:28 -07:00
|
|
|
end
|
2010-04-03 11:51:46 -07:00
|
|
|
end
|
2010-05-10 10:14:20 -07:00
|
|
|
archs.extend(ArchitectureListExtension)
|
2009-09-08 15:31:28 -07:00
|
|
|
end
|
2009-10-15 12:36:09 +01:00
|
|
|
|
2010-02-09 09:21:25 -08:00
|
|
|
# String extensions added by inreplace below.
|
2009-12-17 12:41:54 -08:00
|
|
|
module HomebrewInreplaceExtension
|
|
|
|
# Looks for Makefile style variable defintions and replaces the
|
|
|
|
# value with "new_value", or removes the definition entirely.
|
2010-02-09 09:21:25 -08:00
|
|
|
def change_make_var! flag, new_value
|
|
|
|
new_value = "#{flag}=#{new_value}"
|
2010-03-16 11:57:55 -07:00
|
|
|
gsub! Regexp.new("^#{flag}[ \\t]*=[ \\t]*(.*)$"), new_value
|
2009-12-17 12:41:54 -08:00
|
|
|
end
|
2010-02-09 09:21:25 -08:00
|
|
|
# Removes variable assignments completely.
|
2009-12-17 12:41:54 -08:00
|
|
|
def remove_make_var! flags
|
2010-02-09 09:21:25 -08:00
|
|
|
flags.each do |flag|
|
|
|
|
# Also remove trailing \n, if present.
|
2010-03-16 11:57:55 -07:00
|
|
|
gsub! Regexp.new("^#{flag}[ \\t]*=(.*)$\n?"), ""
|
2010-02-09 09:21:25 -08:00
|
|
|
end
|
2009-12-17 12:41:54 -08:00
|
|
|
end
|
2010-04-03 17:52:58 -07:00
|
|
|
# Finds the specified variable
|
|
|
|
def get_make_var flag
|
|
|
|
m = match Regexp.new("^#{flag}[ \\t]*=[ \\t]*(.*)$")
|
|
|
|
return m[1] if m
|
|
|
|
return nil
|
|
|
|
end
|
2009-12-17 12:41:54 -08:00
|
|
|
end
|
|
|
|
|
|
|
|
def inreplace path, before=nil, after=nil
|
2010-02-20 02:07:51 +00:00
|
|
|
[*path].each do |path|
|
2010-02-19 15:56:21 +00:00
|
|
|
f = File.open(path, 'r')
|
|
|
|
s = f.read
|
2009-12-17 12:41:54 -08:00
|
|
|
|
2010-02-19 15:56:21 +00:00
|
|
|
if before == nil and after == nil
|
|
|
|
s.extend(HomebrewInreplaceExtension)
|
|
|
|
yield s
|
|
|
|
else
|
|
|
|
s.gsub!(before, after)
|
|
|
|
end
|
2009-12-17 12:41:54 -08:00
|
|
|
|
2010-02-19 15:56:21 +00:00
|
|
|
f.reopen(path, 'w').write(s)
|
|
|
|
f.close
|
|
|
|
end
|
2009-10-15 12:36:09 +01:00
|
|
|
end
|
2009-11-06 17:09:14 +00:00
|
|
|
|
|
|
|
def ignore_interrupts
|
|
|
|
std_trap = trap("INT") {}
|
|
|
|
yield
|
|
|
|
ensure
|
|
|
|
trap("INT", std_trap)
|
|
|
|
end
|
2009-11-09 18:24:36 +00:00
|
|
|
|
|
|
|
def nostdout
|
|
|
|
if ARGV.verbose?
|
|
|
|
yield
|
|
|
|
else
|
|
|
|
begin
|
|
|
|
require 'stringio'
|
|
|
|
real_stdout = $stdout
|
|
|
|
$stdout = StringIO.new
|
|
|
|
yield
|
|
|
|
ensure
|
|
|
|
$stdout = real_stdout
|
|
|
|
end
|
|
|
|
end
|
2010-01-13 09:00:51 +00:00
|
|
|
end
|
2010-04-07 21:01:12 -07:00
|
|
|
|
|
|
|
def dump_build_env env
|
|
|
|
puts "\"--use-llvm\" was specified" if ARGV.include? '--use-llvm'
|
|
|
|
|
Add command "brew --env"
"brew --env" will set up a build environment and then dump certain ENV
variables (CC, CXX, LD, CFLAGS, CXXFLAGS, MAKEFLAGS).
If any of CC, CXX, LD are symlinks, now also output the target compiler.
(Typically these will be symlinks from eg /usr/bin/cc to /usr/bin/gcc-4.2).
This is a diagnostic command which may be merged into --config, turned
into an external command, or removed if it doesn't turn out to be useful.
2010-07-13 14:20:52 -07:00
|
|
|
%w[ CC CXX LD ].each do |k|
|
|
|
|
value = env[k]
|
|
|
|
if value
|
|
|
|
results = value
|
|
|
|
if File.exists? value and File.symlink? value
|
|
|
|
target = Pathname.new(value)
|
|
|
|
results += " => #{target.dirname+target.readlink}"
|
|
|
|
end
|
|
|
|
puts "#{k}: #{results}"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
%w[ CFLAGS CXXFLAGS CPPFLAGS LDFLAGS MACOSX_DEPLOYMENT_TARGET MAKEFLAGS PKG_CONFIG_PATH
|
2010-06-28 14:55:31 -07:00
|
|
|
HOMEBREW_DEBUG HOMEBREW_VERBOSE HOMEBREW_USE_LLVM HOMEBREW_SVN ].each do |k|
|
2010-04-07 21:01:12 -07:00
|
|
|
value = env[k]
|
|
|
|
puts "#{k}: #{value}" if value
|
|
|
|
end
|
|
|
|
end
|