-
Alex Wang authored
Clang has fully implemented OpenMP support as of LLVM 3.7, so if OpenMP is required by a formula gcc is no longer the only choice of compiler. Clang should be preferred over gcc because using gcc meant linking against libstdc++, which is ABI incompatible with libc++. This may be unnoticeable for some users, but it causes other builds to fail, e.g. pstoedit when imagemagick was built with OpenMP. pstoedit is required for the octave formula, so for some users this could be a significant problem.
Alex Wang authoredClang has fully implemented OpenMP support as of LLVM 3.7, so if OpenMP is required by a formula gcc is no longer the only choice of compiler. Clang should be preferred over gcc because using gcc meant linking against libstdc++, which is ABI incompatible with libc++. This may be unnoticeable for some users, but it causes other builds to fail, e.g. pstoedit when imagemagick was built with OpenMP. pstoedit is required for the octave formula, so for some users this could be a significant problem.
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
cc 9.89 KiB
#!/bin/sh
# Make sure this shim uses the same Ruby interpreter that is used by Homebrew.
unset RUBYLIB
unset RUBYOPT
if [ -z "$HOMEBREW_RUBY_PATH" ]
then
echo "${0##*/}: The build tool has reset ENV; --env=std required." >&2
exit 1
fi
exec "$HOMEBREW_RUBY_PATH" -x "$0" "$@"
#!/usr/bin/env ruby -W0
require "pathname"
require "set"
class Cmd
attr_reader :config, :prefix, :cellar, :opt, :tmpdir, :sysroot, :deps
attr_reader :archflags, :optflags, :keg_regex, :formula_prefix
def initialize(arg0, args)
@arg0 = arg0
@args = args.freeze
@config = ENV.fetch("HOMEBREW_CCCFG") { "" }
@prefix = ENV["HOMEBREW_PREFIX"]
@cellar = ENV["HOMEBREW_CELLAR"]
@opt = ENV["HOMEBREW_OPT"]
@tmpdir = ENV["HOMEBREW_TEMP"]
@sysroot = ENV["HOMEBREW_SDKROOT"]
@archflags = ENV.fetch("HOMEBREW_ARCHFLAGS") { "" }.split(" ")
@optflags = ENV.fetch("HOMEBREW_OPTFLAGS") { "" }.split(" ")
@deps = Set.new(ENV.fetch("HOMEBREW_DEPENDENCIES") { "" }.split(","))
@formula_prefix = ENV["HOMEBREW_FORMULA_PREFIX"]
# matches opt or cellar prefix and formula name
@keg_regex = %r[(#{Regexp.escape(opt)}|#{Regexp.escape(cellar)})/([\w\-_\+]+)]
end
def mode
if @arg0 == "cpp" || @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 /llvm_(clang(\+\+)?)/
"#{ENV["HOMEBREW_PREFIX"]}/opt/llvm/bin/#{$1}"
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
def args
if @args.length == 1 && @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
if tool == "ld"
args << "-syslibroot" << sysroot
else
args << "-isysroot" << sysroot << "--sysroot=#{sysroot}"
end
end
case mode
when :ccld
cflags + args + cppflags + ldflags
when :cxxld
cxxflags + args + cppflags + ldflags
when :cc
cflags + args + cppflags
when :cxx
cxxflags + args + cppflags
when :ccE
args + cppflags
when :cpp
args + cppflags
when :ld
ldflags + args
end
end
def refurbished_args
@lset = Set.new(library_paths + system_library_paths)
@iset = Set.new(isystem_paths + include_paths)
args = []
enum = @args.each
loop do
case arg = enum.next
when "-arch"
if permit_arch_flags?
args << arg << enum.next
else
enum.next
end
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
end
args
end
def refurbish_arg(arg, enum)
args = []
case arg
when /^-g\d?$/, /^-gstabs\d+/, "-gstabs+", /^-ggdb\d?/,
/^-march=.+/, /^-mtune=.+/, /^-mcpu=.+/,
/^-O[0-9zs]?$/, "-fast", "-no-cpp-precomp",
"-pedantic", "-pedantic-errors", "-Wno-long-double",
"-Wno-unused-but-set-variable"
when "-mno-fused-madd", "-fforce-addr", "-fno-defer-pop",
"-mno-dynamic-no-pic", "-fearly-inlining", /^-f(?:no-)?inline-functions-called-once/,
/^-finline-limit/, /^-f(?:no-)?check-new/, "-fno-delete-null-pointer-checks",
"-fcaller-saves", "-fthread-jumps", "-fno-reorder-blocks", "-fcse-skip-blocks",
"-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", "-frounding-math"
# clang doesn't support these flags
args << arg unless tool =~ /^clang/
when "-fopenmp", "-lgomp"
args << arg if tool =~ /^llvm_clang/
when "--fast-math"
arg = "-ffast-math" if tool =~ /^clang/
args << arg
when "-Wno-deprecated-register"
# older gccs don't support these flags
args << arg unless tool =~ /^g..-4.[02]/
when /^-Wl,-z,defs/
# -Wl,-undefined,error is already the default
when /^-W[alp],/, /^-Wno-/
args << arg
when /^-W.*/
# prune warnings
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"
when /^-isysroot/, /^--sysroot/
sdk = enum.next
# We set the sysroot for macOS SDKs
args << "-isysroot" << sdk unless sdk.downcase.include? "osx"
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
args
end
def keep?(path)
# The logic in this method will eventually become the default,
# but is currently opt-in.
return keep_orig?(path) unless ENV["HOMEBREW_EXPERIMENTAL_FILTER_FLAGS_ON_DEPS"]
# Allow references to self
if formula_prefix && path.start_with?("#{formula_prefix}/")
true
# first two paths: reject references to Cellar or opt paths
# for unspecified dependencies
elsif path.start_with?(cellar) || path.start_with?(opt)
dep = path[keg_regex, 2]
dep && @deps.include?(dep)
elsif path.start_with?(prefix)
true
else
# ignore MacPorts, Boxen's Homebrew, X11, fink
!path.start_with?("/opt/local", "/opt/boxen/homebrew", "/opt/X11", "/sw", "/usr/X11")
end
end
# The original less-smart version of keep_orig; will eventually be removed
def keep_orig?(path)
path.start_with?(prefix, cellar, tmpdir) || !path.start_with?("/opt/local", "/opt/boxen/homebrew", "/opt/X11", "/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
def cxxflags
args = cflags
args << "-std=c++11" if cxx11?
args << "-stdlib=libc++" if libcxx?
args << "-stdlib=libstdc++" if libstdcxx?
args
end
def cppflags
path_flags("-isystem", isystem_paths) + path_flags("-I", include_paths)
end
def ldflags
args = path_flags("-L", library_paths)
case mode
when :ld
args << "-headerpad_max_install_names"
args << "-no_weak_imports" if no_weak_imports?
when :ccld, :cxxld
args << "-Wl,-headerpad_max_install_names"
args << "-Wl,-no_weak_imports" if no_weak_imports?
end
args
end
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
paths = ["#{sysroot}/usr/lib"]
paths << "/usr/local/lib" unless sysroot || ENV["SDKROOT"]
paths
end
def configure?
# configure scripts generated with autoconf 2.61 or later export as_nl
ENV.key? "as_nl"
end
def refurbish_args?
config.include?("O")
end
def cxx11?
config.include?("x")
end
def libcxx?
config.include?("g")
end
def libstdcxx?
config.include?("h")
end
def permit_arch_flags?
config.include?("K")
end
def no_weak_imports?
config.include?("w")
end
def canonical_path(path)
path = Pathname.new(path)
path = path.realpath if path.exist?
path.to_s
end
def path_flags(prefix, paths)
paths = paths.uniq.select { |path| File.directory?(path) }
paths.map! { |path| prefix + path }
end
def path_split(key)
ENV.fetch(key) { "" }.split(File::PATH_SEPARATOR)
end
def chuzzle(val)
return val if val.nil?
val = val.chomp
return val unless val.empty?
end
end
def log(basename, argv, tool, args)
return unless ENV.key?("HOMEBREW_CC_LOG_PATH")
adds = args - argv
dels = argv - args
s = ""
s << "#{basename} called with: #{argv.join(" ")}\n"
s << "superenv removed: #{dels.join(" ")}\n" unless dels.empty?
s << "superenv added: #{adds.join(" ")}\n" unless adds.empty?
s << "superenv executed: #{tool} #{args.join(" ")}\n\n"
File.open("#{ENV["HOMEBREW_CC_LOG_PATH"]}.cc", "a+") { |f| f.write(s) }
end
if __FILE__ == $PROGRAM_NAME
##################################################################### sanity
if (cc = ENV["HOMEBREW_CC"]).nil? || cc.empty? || cc == "cc"
# those values are not allowed
ENV["HOMEBREW_CC"] = "clang"
end
####################################################################### main
dirname, basename = File.split($0)
cmd = Cmd.new(basename, ARGV)
tool = cmd.tool
args = cmd.args
log(basename, ARGV, tool, args)
args << { :close_others => false }
exec "#{dirname}/xcrun", tool, *args
end