215 lines
6.0 KiB
Ruby
Executable File
215 lines
6.0 KiB
Ruby
Executable File
#!/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
|
|
|
|
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'
|
|
:cc
|
|
elsif @args.include? '-E'
|
|
:cpp
|
|
else
|
|
:ccld
|
|
end
|
|
end
|
|
def tool
|
|
@tool ||= case @arg0
|
|
when 'ld' then 'ld'
|
|
when 'cc', 'c99', 'c89', 'cpp'
|
|
# Ideally we would run `cx9`, however these tools are POSIX compliant
|
|
# and don't support many flags. We need -isystem for instance, but also
|
|
# reliability is generally much higher if we just get clang/gcc to do
|
|
# the work since Makefiles are dumb and include a lot of excess flags.
|
|
ENV['HOMEBREW_CC']
|
|
when 'c++'
|
|
if ENV['HOMEBREW_CC'] =~ /llvm-gcc/
|
|
'g++'
|
|
elsif ENV['HOMEBREW_CC'] =~ /gcc-4.2/
|
|
'g++-4.2'
|
|
else
|
|
'clang++'
|
|
end
|
|
else
|
|
@arg0
|
|
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?
|
|
case mode
|
|
when :cpp
|
|
%w{-E} + args + cppflags
|
|
when :ld
|
|
ldflags + args
|
|
when :cc
|
|
cflags + args + cppflags
|
|
when :ccld
|
|
cflags + args + cppflags + ldflags
|
|
end.compact
|
|
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=.+/, '-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 '-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
|
|
make_fuss(args)
|
|
args
|
|
end
|
|
def cflags
|
|
if cccfg? 'Ob'
|
|
%w{-mtune=generic -Oz}
|
|
elsif cccfg? 'O'
|
|
args = %w{-pipe -w -Os}
|
|
args << '-march=native' if tool =~ /clang/
|
|
args += %w{-arch i386 -arch x86_64} if cccfg? 'u'
|
|
args << "-std=#{@arg0}" if @arg0 =~ /c[89]9/
|
|
args
|
|
else
|
|
[]
|
|
end
|
|
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{ "#$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
|
|
libpath.to_flags('-L')
|
|
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
|
|
end
|
|
|
|
if __FILE__ == $PROGRAM_NAME
|
|
##################################################################### sanity
|
|
abort "The build-tool has reset ENV. --env=std required." unless ENV['HOMEBREW_BREW_FILE']
|
|
|
|
case ENV['HOMEBREW_CC'].chuzzle when 'cc', nil
|
|
# those values are not allowed
|
|
ENV['HOMEBREW_CC'] = 'clang'
|
|
end
|
|
|
|
####################################################################### main
|
|
extend(ExecLogExtension) if ENV['HOMEBREW_LOG']
|
|
cmd = Cmd.new($0, ARGV)
|
|
exec "xcrun", cmd.tool, *cmd.args
|
|
end
|