260 lines
7.1 KiB
Plaintext
Raw Normal View History

#!/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby -W0
#TODO make it work with homebrew/dupes/gcc
#TODO? If we find -mmacosx-version-min=10.8, change sdkroot? warn visibly if no such SDK?
#TODO fix pkg-config files, should point to /usr/local or /usr/local/opt
#TODO create mechanism to specify build effects like %w{-O0 -O4 vanilla-arg-parsing sdk=10.6} etc.
require "#{File.dirname __FILE__}/../libsuperenv"
require 'set'
def cccfg? flags
flags.split('').all?{|c| ENV['HOMEBREW_CCCFG'].include? c } if ENV['HOMEBREW_CCCFG']
end
def nclt?
$sdkroot != nil
end
def syspath
if nclt?
%W{#$sdkroot/usr #$sdkroot/usr/local}
else
%W{/usr /usr/local}
end
end
2012-09-29 09:57:37 -04:00
module ExecLogExtension
def exec *args
path = File.expand_path('~/Library/Logs/Homebrew/cc.log')
open(path, 'a') do |f|
f.print '[', $0
f.print " -%s" % ENV['HOMEBREW_CCCFG'] if ENV['HOMEBREW_CCCFG']
f.print '] '
f.puts args.join(' ')
f.puts
end
Kernel.exec *args
end
end
class Cmd
def initialize path, args
@arg0 = path.basename.freeze
@args = args.freeze
end
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
def tool
@tool ||= case @arg0
when 'ld' then 'ld'
when 'cpp' then 'cpp'
when /\w\+\+$/
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
def args
args = if not cccfg? 'O' or tool == 'ld'
@args.dup
else
refurbished_args
end
if tool != 'ld'
args << "--sysroot=#$sdkroot"
else
args << "-syslibroot" << $sdkroot
end if nclt?
allflags = case mode
when :ccld, :cxxld
2013-08-31 10:38:18 -05:00
cflags + args + cppflags + ldflags
when :cc, :cxx
2013-08-31 10:38:18 -05:00
cflags + args + cppflags
when :ccE
args + cppflags
when :cpp
args + cppflags
when :ld
ldflags + args
end.compact
make_fuss(allflags) if verbose? and cccfg? 'O'
allflags
end
def refurbished_args
lset = Set.new(libpath + syslibpath)
iset = Set.new(cpath.flatten)
args = []
whittler = @args.each
loop do
case arg = whittler.next
when '-arch', /^-Xarch_/
whittler.next
when '-m32'
# If ENV.m32 was set, we allow the "-m32" flag, but we don't add anything
args << '-m32' if cccfg? '3'
when /^-g\d?/, /^-gstabs\d+/, '-gstabs+', /^-ggdb\d?/, '-gdwarf-2',
/^-march=.+/, /^-mtune=.+/, /^-mcpu=.+/, '-m64',
/^-O[0-9zs]?$/, '-fast',
'-pedantic', '-pedantic-errors'
when '-fopenmp', '-lgomp'
# clang doesn't support OpenMP
args << arg if not tool =~ /^clang/
when /^-W.*/
args << arg if arg =~ /^-W[alp],/
when '-macosx_version_min', '-dylib_install_name'
args << "-Wl,#{arg},#{whittler.next}"
when /^-isysroot/
# We set the sysroot
whittler.next
when '-dylib'
args << "-Wl,#{arg}"
when /^-I(.+)/
# it is okay to add a space after the -I; so let's support it
path = $1.chuzzle || whittler.next
args << "-I#{path}" if iset.add?(path.cleanpath)
when /^-L(.+)/
path = $1.chuzzle || whittler.next
doit = case path.cleanpath
when %r{^#$brewfix}
# maybe homebrew is installed to /sw or /opt/brew
true
when %r{^/opt}, %r{^/sw}, %r{/usr/X11}
false
else
true
end
args << "-L#{path}" if doit and lset.add?(path.cleanpath)
else
args << arg
end
end
args
end
def cflags
args = []
if mode == :cxx
args << '-std=c++11' if cccfg? 'x'
args << '-stdlib=libc++' if cccfg? 'g'
args << '-stdlib=libstdc++' if cccfg? 'h'
end
return args unless cccfg? 'O'
args << '-pipe' << '-w' << '-Os'
# When bottling use the oldest supported CPU type.
if cccfg? 'bc'
# Custom bottle specified during the build
args << ENV['HOMEBREW_ARCHFLAGS']
elsif cccfg? 'bi6'
args << '-march=core2'
elsif cccfg? 'bi'
args << '-march=prescott'
elsif cccfg? 'bpA'
args << '-mcpu=7400'
elsif cccfg? 'bp'
args << '-mcpu=750'
else
args << '-march=native' if tool =~ /clang/
end
ENV['HOMEBREW_ARCHS'].split(',').each { |a| args << "-arch" << a } if cccfg? 'u'
args << "-std=#{@arg0}" if @arg0 =~ /c[89]9/
args
end
def syslibpath
# We reject brew's lib as we explicitly add this as a -L flag, thus it
# is given higher priority by cc, so it surpasses the system libpath.
# NOTE this only counts if Homebrew is installed at /usr/local
syspath.map{|d| "#{d}/lib" }.reject{|d| d == "#$brewfix/lib" }
end
def syscpath
isystem, _ = cpath
isystem + syspath.map{|d| "#{d}/include" }
end
def cpath
cpath = ENV['CMAKE_PREFIX_PATH'].split(':').map{|d| "#{d}/include" } + ENV['CMAKE_INCLUDE_PATH'].split(':')
opt = cpath.select{|prefix| prefix =~ %r{^#$brewfix/opt} }
sys = cpath - opt
[sys, opt]
end
def libpath
ENV['CMAKE_PREFIX_PATH'].split(':').map{|d| "#{d}/lib" } +
ENV['CMAKE_LIBRARY_PATH'].split(':') -
syslibpath
end
def ldflags
args = libpath.to_flags('-L')
case mode
when :ld then args << '-headerpad_max_install_names'
when :ccld then args << '-Wl,-headerpad_max_install_names'
when :cxxld
args << '-Wl,-headerpad_max_install_names'
args << '-stdlib=libc++' if cccfg? 'g'
args << '-stdlib=libstdc++' if cccfg? 'h'
end
args
end
def cppflags
sys, opt = cpath
# we want our keg-only includes to be found before system includes *and*
# before any other includes the build-system adds
sys.to_flags('-isystem') + opt.to_flags('-I')
end
def make_fuss args
dels = @args - args
adds = args - @args
dups = dels & args
STDERR.puts "brew: superenv removed: #{dels*' '}" unless dels.empty?
STDERR.puts "brew: superenv deduped: #{dups}" unless dups.empty?
STDERR.puts "brew: superenv added: #{adds*' '}" unless adds.empty?
end
def verbose?
!ENV['VERBOSE'].nil? || !ENV['HOMEBREW_VERBOSE'].nil?
end
end
2013-03-03 22:11:26 -06:00
if __FILE__ == $PROGRAM_NAME
STDOUT.sync = STDERR.sync = true
2013-03-03 22:11:26 -06:00
##################################################################### sanity
abort "The build-tool has reset ENV. --env=std required." unless ENV['HOMEBREW_BREW_FILE']
2013-03-03 22:11:26 -06:00
case ENV['HOMEBREW_CC'].chuzzle when 'cc', nil
# those values are not allowed
ENV['HOMEBREW_CC'] = 'clang'
end
2013-03-03 22:11:26 -06:00
####################################################################### main
extend(ExecLogExtension) if ENV['HOMEBREW_LOG']
2013-03-03 22:11:26 -06:00
cmd = Cmd.new($0, ARGV)
exec "xcrun", cmd.tool, *cmd.args
end