348 lines
8.3 KiB
Plaintext
Raw Normal View History

#!/System/Library/Frameworks/Ruby.framework/Versions/Current/usr/bin/ruby -W0
$:.unshift Dir["/System/Library/Frameworks/Ruby.framework/Versions/Current/usr/lib/ruby/{1.8,2.0.0}"].first
2014-04-20 19:57:01 -05:00
require 'pathname'
require 'set'
require 'stringio'
class Logger
def initialize
@io = StringIO.new
end
def puts(*args)
@io.puts(*args)
end
def log!
return unless ENV.key? 'HOMEBREW_CC_LOG_PATH'
path = "#{ENV['HOMEBREW_CC_LOG_PATH']}.cc"
puts
File.open(path, File::WRONLY | File::APPEND | File::CREAT) { |f| f.write(@io.string) }
end
end
LOGGER = Logger.new
class Cmd
2015-02-08 20:04:06 -05:00
attr_reader :config, :prefix, :cellar, :tmpdir, :sysroot
attr_reader :archflags, :optflags
2013-11-21 14:50:35 -06:00
2015-02-12 19:13:03 -05:00
def initialize(arg0, args)
@arg0 = arg0
@args = args.freeze
2015-02-08 20:04:06 -05:00
@config = ENV.fetch("HOMEBREW_CCCFG") { "" }
@prefix = ENV['HOMEBREW_PREFIX']
@cellar = ENV['HOMEBREW_CELLAR']
@tmpdir = ENV['HOMEBREW_TEMP']
@sysroot = ENV['HOMEBREW_SDKROOT']
@archflags = ENV.fetch("HOMEBREW_ARCHFLAGS") { "" }.split(" ")
@optflags = ENV.fetch("HOMEBREW_OPTFLAGS") { "" }.split(" ")
end
2014-04-21 00:17:22 -05:00
def mode
if @arg0 == 'cpp' or @arg0 == 'ld'
@arg0.to_sym
elsif @args.include? '-c'
if @arg0 =~ /(?:c|g|clang)\+\+/
:cxx
else
:cc
end
elsif @args.include? '-E'
:ccE
else
if @arg0 =~ /(?:c|g|clang)\+\+/
:cxxld
else
:ccld
end
end
end
2014-04-21 00:17:22 -05:00
def tool
@tool ||= case @arg0
when 'ld' then 'ld'
when 'cpp' then 'cpp'
when /\w\+\+(-\d\.\d)?$/
case ENV['HOMEBREW_CC']
when /clang/
'clang++'
when /llvm-gcc/
'llvm-g++-4.2'
when /gcc(-\d\.\d)?$/
'g++' + $1.to_s
end
else
# Note that this is a universal fallback, so that we'll always invoke
# HOMEBREW_CC regardless of what name under which the tool was invoked.
ENV['HOMEBREW_CC']
end
end
2014-04-21 00:17:22 -05:00
def args
if @args.length == 1 and @args[0] == '-v'
# Don't add linker arguments if -v passed as sole option. This stops gcc
# -v with no other arguments from outputting a linker error. Some
# software uses gcc -v (wrongly) to sniff the GCC version.
return @args.dup
end
if !refurbish_args? || tool == "ld" || configure?
args = @args.dup
else
args = refurbished_args
end
if sysroot
2014-04-21 00:17:22 -05:00
if tool == "ld"
args << "-syslibroot" << sysroot
2014-04-21 00:17:22 -05:00
else
args << "-isysroot" << sysroot << "--sysroot=#{sysroot}"
end
end
allflags = case mode
when :ccld
2013-08-31 10:38:18 -05:00
cflags + args + cppflags + ldflags
when :cxxld
cxxflags + args + cppflags + ldflags
when :cc
2013-08-31 10:38:18 -05:00
cflags + args + cppflags
when :cxx
cxxflags + args + cppflags
when :ccE
args + cppflags
when :cpp
args + cppflags
when :ld
ldflags + args
end.compact
make_fuss(allflags)
allflags
end
2014-04-21 00:17:22 -05:00
def refurbished_args
@lset = Set.new(library_paths + system_library_paths)
@iset = Set.new(isystem_paths + include_paths)
args = []
2014-05-06 15:21:01 -05:00
enum = @args.each
loop do
case arg = enum.next
when "-arch"
if permit_arch_flags?
args << arg << enum.next
else
enum.next
end
2014-05-22 09:18:34 -05:00
when "-m32", "-m64"
args << arg if permit_arch_flags?
when /^-Xarch_/
refurbished = refurbish_arg(enum.next, enum)
unless refurbished.empty?
args << arg
args += refurbished
end
else
args += refurbish_arg(arg, enum)
end
2014-05-06 15:21:01 -05:00
end
args
end
def refurbish_arg(arg, enum)
args = []
case arg
when /^-g\d?/, /^-gstabs\d+/, '-gstabs+', /^-ggdb\d?/, '-gdwarf-2',
/^-march=.+/, /^-mtune=.+/, /^-mcpu=.+/,
2014-05-06 15:21:01 -05:00
/^-O[0-9zs]?$/, '-fast', '-no-cpp-precomp',
'-pedantic', '-pedantic-errors', '-Wno-long-double',
'-Wno-unused-but-set-variable'
2014-05-06 15:21:01 -05:00
when '-fopenmp', '-lgomp', '-mno-fused-madd', '-fforce-addr', '-fno-defer-pop',
'-mno-dynamic-no-pic', '-fearly-inlining', /^-f(?:no-)?inline-functions-called-once/,
2014-05-06 15:21:01 -05:00
/^-finline-limit/, /^-f(?:no-)?check-new/, '-fno-delete-null-pointer-checks',
'-fcaller-saves', '-fthread-jumps', '-fno-reorder-blocks', '-fcse-skip-blocks',
2014-05-08 09:29:32 -07:00
'-frerun-cse-after-loop', '-frerun-loop-opt', '-fcse-follow-jumps',
'-fno-regmove', '-fno-for-scope', '-fno-tree-pre', '-fno-tree-dominator-opts',
'-fuse-linker-plugin'
2014-05-06 15:21:01 -05:00
# clang doesn't support these flags
args << arg if not tool =~ /^clang/
2014-05-06 19:29:18 -05:00
when /^-W[alp],/, /^-Wno-/
args << arg
2014-05-06 15:21:01 -05:00
when /^-W.*/
2014-05-06 19:29:18 -05:00
# prune warnings
2014-05-06 15:21:01 -05:00
when '-macosx_version_min', '-dylib_install_name'
args << "-Wl,#{arg},#{enum.next}"
when '-multiply_definedsuppress'
args << "-Wl,-multiply_defined,suppress"
when '-undefineddynamic_lookup'
args << "-Wl,-undefined,dynamic_lookup"
2014-05-12 22:15:33 -05:00
when /^-isysroot/, /^--sysroot/
2014-05-06 15:21:01 -05:00
# We set the sysroot
enum.next
when '-dylib'
args << "-Wl,#{arg}"
when /^-I(.+)?/
# Support both "-Ifoo" (one argument) and "-I foo" (two arguments)
val = chuzzle($1) || enum.next
path = canonical_path(val)
args << "-I#{val}" if keep?(path) && @iset.add?(path)
when /^-L(.+)?/
val = chuzzle($1) || enum.next
path = canonical_path(val)
args << "-L#{val}" if keep?(path) && @lset.add?(path)
else
args << arg
end
2014-05-06 15:21:01 -05:00
args
end
def keep? path
path.start_with?(prefix, cellar, tmpdir) || !path.start_with?("/opt", "/sw", "/usr/X11")
end
def cflags
args = []
return args unless refurbish_args? || configure?
args << '-pipe'
args << '-w' unless configure?
args << "-#{ENV["HOMEBREW_OPTIMIZATION_LEVEL"]}"
args.concat(optflags)
args.concat(archflags)
args << "-std=#{@arg0}" if @arg0 =~ /c[89]9/
args
end
2014-04-21 00:17:22 -05:00
def cxxflags
args = cflags
args << "-std=c++11" if cxx11?
args << "-stdlib=libc++" if libcxx?
args << "-stdlib=libstdc++" if libstdcxx?
args
end
2014-04-21 00:17:22 -05:00
def cppflags
path_flags("-isystem", isystem_paths) + path_flags("-I", include_paths)
end
2014-04-21 00:17:22 -05:00
def ldflags
args = path_flags("-L", library_paths)
case mode
when :ld
args << "-headerpad_max_install_names"
when :ccld, :cxxld
args << "-Wl,-headerpad_max_install_names"
end
args
end
2014-04-21 00:17:22 -05:00
def isystem_paths
path_split("HOMEBREW_ISYSTEM_PATHS")
end
def include_paths
path_split("HOMEBREW_INCLUDE_PATHS")
end
def library_paths
path_split("HOMEBREW_LIBRARY_PATHS")
end
def system_library_paths
%W{#{sysroot}/usr/lib /usr/local/lib}
end
2014-04-21 00:17:22 -05:00
def make_fuss args
return unless make_fuss?
dels = @args - args
adds = args - @args
LOGGER.puts "superenv removed: #{dels*' '}" unless dels.empty?
LOGGER.puts "superenv added: #{adds*' '}" unless adds.empty?
end
2014-04-21 00:17:22 -05:00
def make_fuss?
refurbish_args? && !configure?
end
2014-04-21 00:17:22 -05:00
def configure?
# configure scripts generated with autoconf 2.61 or later export as_nl
ENV.key? 'as_nl'
end
2014-04-21 00:17:22 -05:00
def refurbish_args?
2015-02-08 20:04:06 -05:00
config.include?("O")
end
def cxx11?
2015-02-08 20:04:06 -05:00
config.include?("x")
end
def libcxx?
2015-02-08 20:04:06 -05:00
config.include?("g")
end
def libstdcxx?
2015-02-08 20:04:06 -05:00
config.include?("h")
end
def permit_arch_flags?
2015-02-08 20:04:06 -05:00
config.include?("K")
end
2014-04-20 19:57:01 -05:00
def canonical_path(path)
path = Pathname.new(path)
path = path.realpath if path.exist?
path.to_s
end
2014-04-21 00:17:22 -05:00
2014-04-20 19:54:32 -05:00
def path_flags(prefix, paths)
paths = paths.uniq.select { |path| File.directory?(path) }
paths.map! { |path| prefix + path }
end
2014-04-21 00:17:22 -05:00
2014-04-20 22:39:47 -05:00
def path_split(key)
ENV.fetch(key) { "" }.split(File::PATH_SEPARATOR)
end
2014-04-21 00:17:22 -05:00
2014-04-20 22:39:47 -05:00
def chuzzle(val)
return val if val.nil?
val = val.chomp
return val unless val.empty?
end
end
2013-03-03 22:11:26 -06:00
if __FILE__ == $PROGRAM_NAME
##################################################################### sanity
abort "The build-tool has reset ENV. --env=std required." unless ENV['HOMEBREW_BREW_FILE']
2014-04-20 22:39:47 -05:00
if (cc = ENV["HOMEBREW_CC"]).nil? || cc.empty? || cc == "cc"
2013-03-03 22:11:26 -06:00
# those values are not allowed
ENV['HOMEBREW_CC'] = 'clang'
end
2013-03-03 22:11:26 -06:00
####################################################################### main
2015-02-12 19:13:03 -05:00
dirname, basename = File.split($0)
2015-02-12 19:13:03 -05:00
LOGGER.puts "#{basename} called with: #{ARGV.join(" ")}"
cmd = Cmd.new(basename, ARGV)
tool, args = cmd.tool, cmd.args
LOGGER.puts "superenv executed: #{tool} #{args.join(" ")}"
LOGGER.log!
args << { :close_others => false } if RUBY_VERSION >= "2.0"
2015-02-12 19:13:03 -05:00
exec "#{dirname}/xcrun", tool, *args
2013-03-03 22:11:26 -06:00
end