2014-07-02 21:57:52 -05:00
|
|
|
require "compilers"
|
2016-07-29 20:31:32 -06:00
|
|
|
require "development_tools"
|
2013-11-27 17:29:06 -06:00
|
|
|
|
2015-08-29 10:56:24 +01:00
|
|
|
# Homebrew extends Ruby's `ENV` to make our code more readable.
|
|
|
|
# Implemented in {SharedEnvExtension} and either {Superenv} or
|
|
|
|
# {Stdenv} (depending on the build mode).
|
|
|
|
# @see Superenv
|
|
|
|
# @see Stdenv
|
|
|
|
# @see http://www.rubydoc.info/stdlib/Env Ruby's ENV API
|
2013-08-19 12:32:59 -05:00
|
|
|
module SharedEnvExtension
|
2014-07-02 21:57:52 -05:00
|
|
|
include CompilerConstants
|
|
|
|
|
2015-08-29 10:56:24 +01:00
|
|
|
# @private
|
2016-09-11 17:53:00 +01:00
|
|
|
CC_FLAG_VARS = %w[CFLAGS CXXFLAGS OBJCFLAGS OBJCXXFLAGS].freeze
|
2015-08-29 10:56:24 +01:00
|
|
|
# @private
|
2016-09-11 17:53:00 +01:00
|
|
|
FC_FLAG_VARS = %w[FCFLAGS FFLAGS].freeze
|
2015-08-29 10:56:24 +01:00
|
|
|
# @private
|
2014-05-26 14:10:24 -05:00
|
|
|
SANITIZED_VARS = %w[
|
2017-01-16 20:35:56 +00:00
|
|
|
CDPATH CLICOLOR_FORCE
|
2014-05-26 14:10:24 -05:00
|
|
|
CPATH C_INCLUDE_PATH CPLUS_INCLUDE_PATH OBJC_INCLUDE_PATH
|
|
|
|
CC CXX OBJC OBJCXX CPP MAKE LD LDSHARED
|
|
|
|
CFLAGS CXXFLAGS OBJCFLAGS OBJCXXFLAGS LDFLAGS CPPFLAGS
|
|
|
|
MACOSX_DEPLOYMENT_TARGET SDKROOT DEVELOPER_DIR
|
|
|
|
CMAKE_PREFIX_PATH CMAKE_INCLUDE_PATH CMAKE_FRAMEWORK_PATH
|
2016-02-19 23:38:32 +00:00
|
|
|
GOBIN GOPATH GOROOT PERL_MB_OPT PERL_MM_OPT
|
2018-08-14 11:45:40 -07:00
|
|
|
LIBRARY_PATH LD_LIBRARY_PATH LD_PRELOAD LD_RUN_PATH
|
2016-09-11 17:53:00 +01:00
|
|
|
].freeze
|
2014-05-26 14:10:24 -05:00
|
|
|
|
2015-08-29 10:56:24 +01:00
|
|
|
# @private
|
2015-08-03 13:09:07 +01:00
|
|
|
def setup_build_environment(formula = nil)
|
2014-09-18 15:50:54 -05:00
|
|
|
@formula = formula
|
2014-09-18 16:43:56 -05:00
|
|
|
reset
|
2014-09-18 15:50:54 -05:00
|
|
|
end
|
|
|
|
|
2015-08-29 10:56:24 +01:00
|
|
|
# @private
|
2014-05-26 14:10:24 -05:00
|
|
|
def reset
|
|
|
|
SANITIZED_VARS.each { |k| delete(k) }
|
|
|
|
end
|
|
|
|
|
2013-08-19 12:32:59 -05:00
|
|
|
def remove_cc_etc
|
2015-08-03 13:09:07 +01:00
|
|
|
keys = %w[CC CXX OBJC OBJCXX LD CPP CFLAGS CXXFLAGS OBJCFLAGS OBJCXXFLAGS LDFLAGS CPPFLAGS]
|
2015-08-06 17:12:35 +08:00
|
|
|
removed = Hash[*keys.flat_map { |key| [key, self[key]] }]
|
2013-08-19 12:32:59 -05:00
|
|
|
keys.each do |key|
|
|
|
|
delete(key)
|
|
|
|
end
|
|
|
|
removed
|
|
|
|
end
|
2015-08-03 13:09:07 +01:00
|
|
|
|
|
|
|
def append_to_cflags(newflags)
|
2013-08-19 12:32:59 -05:00
|
|
|
append(CC_FLAG_VARS, newflags)
|
|
|
|
end
|
2015-08-03 13:09:07 +01:00
|
|
|
|
|
|
|
def remove_from_cflags(val)
|
2013-08-19 12:32:59 -05:00
|
|
|
remove CC_FLAG_VARS, val
|
|
|
|
end
|
2015-08-03 13:09:07 +01:00
|
|
|
|
2018-07-12 12:14:44 -05:00
|
|
|
def append_to_cccfg(value)
|
2018-07-12 19:59:06 +01:00
|
|
|
append("HOMEBREW_CCCFG", value, "")
|
2018-07-12 12:14:44 -05:00
|
|
|
end
|
|
|
|
|
2015-08-03 13:09:07 +01:00
|
|
|
def append(keys, value, separator = " ")
|
2013-08-19 12:32:59 -05:00
|
|
|
value = value.to_s
|
|
|
|
Array(keys).each do |key|
|
2014-07-18 11:43:37 -05:00
|
|
|
old = self[key]
|
|
|
|
if old.nil? || old.empty?
|
2013-08-26 15:02:51 -05:00
|
|
|
self[key] = value
|
2014-07-18 11:43:37 -05:00
|
|
|
else
|
|
|
|
self[key] += separator + value
|
2013-08-19 12:32:59 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2015-08-03 13:09:07 +01:00
|
|
|
|
|
|
|
def prepend(keys, value, separator = " ")
|
2013-08-26 15:02:51 -05:00
|
|
|
value = value.to_s
|
2013-08-19 12:32:59 -05:00
|
|
|
Array(keys).each do |key|
|
2014-07-18 11:43:37 -05:00
|
|
|
old = self[key]
|
|
|
|
if old.nil? || old.empty?
|
2013-08-26 15:02:51 -05:00
|
|
|
self[key] = value
|
2014-07-18 11:43:37 -05:00
|
|
|
else
|
|
|
|
self[key] = value + separator + old
|
2013-08-19 12:32:59 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2013-08-19 17:21:13 -05:00
|
|
|
|
2015-08-03 13:09:07 +01:00
|
|
|
def append_path(key, path)
|
2017-04-27 10:44:44 +02:00
|
|
|
self[key] = PATH.new(self[key]).append(path)
|
2013-08-19 17:21:13 -05:00
|
|
|
end
|
|
|
|
|
2015-08-29 10:56:24 +01:00
|
|
|
# Prepends a directory to `PATH`.
|
|
|
|
# Is the formula struggling to find the pkgconfig file? Point it to it.
|
|
|
|
# This is done automatically for `keg_only` formulae.
|
|
|
|
# <pre>ENV.prepend_path "PKG_CONFIG_PATH", "#{Formula["glib"].opt_lib}/pkgconfig"</pre>
|
2017-03-10 07:28:55 -08:00
|
|
|
# Prepending a system path such as /usr/bin is a no-op so that requirements
|
|
|
|
# don't accidentally override superenv shims or formulae's `bin` directories
|
|
|
|
# (e.g. <pre>ENV.prepend_path "PATH", which("emacs").dirname</pre>)
|
2015-08-03 13:09:07 +01:00
|
|
|
def prepend_path(key, path)
|
2017-03-10 07:28:55 -08:00
|
|
|
return if %w[/usr/bin /bin /usr/sbin /sbin].include? path.to_s
|
2018-09-17 02:45:00 +02:00
|
|
|
|
2017-04-27 10:44:44 +02:00
|
|
|
self[key] = PATH.new(self[key]).prepend(path)
|
2013-08-19 12:32:59 -05:00
|
|
|
end
|
2013-08-19 17:21:13 -05:00
|
|
|
|
2015-08-03 13:09:07 +01:00
|
|
|
def prepend_create_path(key, path)
|
2014-01-04 12:49:01 +00:00
|
|
|
path = Pathname.new(path) unless path.is_a? Pathname
|
|
|
|
path.mkpath
|
|
|
|
prepend_path key, path
|
|
|
|
end
|
|
|
|
|
2015-08-03 13:09:07 +01:00
|
|
|
def remove(keys, value)
|
2016-11-13 23:37:40 +01:00
|
|
|
return if value.nil?
|
2018-09-17 02:45:00 +02:00
|
|
|
|
2013-08-19 12:32:59 -05:00
|
|
|
Array(keys).each do |key|
|
|
|
|
next unless self[key]
|
2018-09-17 02:45:00 +02:00
|
|
|
|
2015-08-03 13:09:07 +01:00
|
|
|
self[key] = self[key].sub(value, "")
|
2014-07-18 11:43:37 -05:00
|
|
|
delete(key) if self[key].empty?
|
2016-11-13 23:37:40 +01:00
|
|
|
end
|
2013-08-19 12:32:59 -05:00
|
|
|
end
|
|
|
|
|
2015-08-03 13:09:07 +01:00
|
|
|
def cc
|
|
|
|
self["CC"]
|
|
|
|
end
|
|
|
|
|
|
|
|
def cxx
|
|
|
|
self["CXX"]
|
|
|
|
end
|
|
|
|
|
|
|
|
def cflags
|
|
|
|
self["CFLAGS"]
|
|
|
|
end
|
|
|
|
|
|
|
|
def cxxflags
|
|
|
|
self["CXXFLAGS"]
|
|
|
|
end
|
|
|
|
|
|
|
|
def cppflags
|
|
|
|
self["CPPFLAGS"]
|
|
|
|
end
|
|
|
|
|
|
|
|
def ldflags
|
|
|
|
self["LDFLAGS"]
|
|
|
|
end
|
|
|
|
|
|
|
|
def fc
|
|
|
|
self["FC"]
|
|
|
|
end
|
|
|
|
|
|
|
|
def fflags
|
|
|
|
self["FFLAGS"]
|
|
|
|
end
|
|
|
|
|
|
|
|
def fcflags
|
|
|
|
self["FCFLAGS"]
|
|
|
|
end
|
2013-08-19 12:32:59 -05:00
|
|
|
|
2015-08-29 10:56:24 +01:00
|
|
|
# Outputs the current compiler.
|
|
|
|
# @return [Symbol]
|
2018-07-05 20:15:57 +01:00
|
|
|
# <pre># Do something only for the system clang
|
2015-08-29 10:56:24 +01:00
|
|
|
# if ENV.compiler == :clang
|
|
|
|
# # modify CFLAGS CXXFLAGS OBJCFLAGS OBJCXXFLAGS in one go:
|
|
|
|
# ENV.append_to_cflags "-I ./missing/includes"
|
|
|
|
# end</pre>
|
2013-08-24 14:03:16 -07:00
|
|
|
def compiler
|
2014-09-18 15:50:54 -05:00
|
|
|
@compiler ||= if (cc = ARGV.cc)
|
2015-06-21 21:18:23 -04:00
|
|
|
warn_about_non_apple_gcc($&) if cc =~ GNU_GCC_REGEXP
|
2014-09-18 15:50:54 -05:00
|
|
|
fetch_compiler(cc, "--cc")
|
|
|
|
elsif (cc = homebrew_cc)
|
2015-06-21 21:18:23 -04:00
|
|
|
warn_about_non_apple_gcc($&) if cc =~ GNU_GCC_REGEXP
|
2014-09-18 15:50:54 -05:00
|
|
|
compiler = fetch_compiler(cc, "HOMEBREW_CC")
|
|
|
|
|
|
|
|
if @formula
|
|
|
|
compilers = [compiler] + CompilerSelector.compilers
|
|
|
|
compiler = CompilerSelector.select_for(@formula, compilers)
|
2013-08-22 22:29:49 -07:00
|
|
|
end
|
2014-09-18 15:50:54 -05:00
|
|
|
|
|
|
|
compiler
|
|
|
|
elsif @formula
|
|
|
|
CompilerSelector.select_for(@formula)
|
2013-08-24 14:03:16 -07:00
|
|
|
else
|
2016-04-25 18:01:03 +01:00
|
|
|
DevelopmentTools.default_compiler
|
2013-08-24 14:03:16 -07:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-08-29 10:56:24 +01:00
|
|
|
# @private
|
2014-06-18 16:12:32 -04:00
|
|
|
def determine_cc
|
|
|
|
COMPILER_SYMBOL_MAP.invert.fetch(compiler, compiler)
|
|
|
|
end
|
|
|
|
|
2014-06-22 18:43:01 -05:00
|
|
|
COMPILERS.each do |compiler|
|
|
|
|
define_method(compiler) do
|
|
|
|
@compiler = compiler
|
2014-06-18 16:12:32 -04:00
|
|
|
self.cc = determine_cc
|
|
|
|
self.cxx = determine_cxx
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-08-29 10:56:24 +01:00
|
|
|
# Snow Leopard defines an NCURSES value the opposite of most distros.
|
2015-01-04 05:02:27 +01:00
|
|
|
# See: https://bugs.python.org/issue6848
|
2015-08-29 10:56:24 +01:00
|
|
|
# Currently only used by aalib in core.
|
2013-08-19 12:32:59 -05:00
|
|
|
def ncurses_define
|
2015-08-03 13:09:07 +01:00
|
|
|
append "CPPFLAGS", "-DNCURSES_OPAQUE=0"
|
2013-08-19 12:32:59 -05:00
|
|
|
end
|
|
|
|
|
2015-08-29 10:56:24 +01:00
|
|
|
# @private
|
2013-08-19 12:32:59 -05:00
|
|
|
def userpaths!
|
2017-04-28 15:07:46 +02:00
|
|
|
path = PATH.new(self["PATH"]).select do |p|
|
|
|
|
# put Superenv.bin and opt path at the first
|
|
|
|
p.start_with?("#{HOMEBREW_REPOSITORY}/Library/ENV", "#{HOMEBREW_PREFIX}/opt")
|
|
|
|
end
|
|
|
|
path.append(HOMEBREW_PREFIX/"bin") # XXX hot fix to prefer brewed stuff (e.g. python) over /usr/bin.
|
|
|
|
path.append(self["PATH"]) # reset of self["PATH"]
|
|
|
|
path.append(
|
|
|
|
# user paths
|
|
|
|
ORIGINAL_PATHS.map do |p|
|
|
|
|
begin
|
|
|
|
p.realpath.to_s
|
|
|
|
rescue
|
|
|
|
nil
|
|
|
|
end
|
|
|
|
end - %w[/usr/X11/bin /opt/X11/bin],
|
|
|
|
)
|
|
|
|
self["PATH"] = path
|
2013-08-19 12:32:59 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def fortran
|
2015-12-18 17:04:58 +01:00
|
|
|
# Ignore repeated calls to this function as it will misleadingly warn about
|
|
|
|
# building with an alternative Fortran compiler without optimization flags,
|
|
|
|
# despite it often being the Homebrew-provided one set up in the first call.
|
|
|
|
return if @fortran_setup_done
|
2018-09-17 02:45:00 +02:00
|
|
|
|
2015-12-18 17:04:58 +01:00
|
|
|
@fortran_setup_done = true
|
|
|
|
|
2013-08-30 19:07:10 -05:00
|
|
|
flags = []
|
|
|
|
|
2013-08-30 19:00:19 -05:00
|
|
|
if fc
|
2013-08-19 12:32:59 -05:00
|
|
|
ohai "Building with an alternative Fortran compiler"
|
|
|
|
puts "This is unsupported."
|
2015-08-03 13:09:07 +01:00
|
|
|
self["F77"] ||= fc
|
2013-08-19 12:32:59 -05:00
|
|
|
|
2015-08-03 13:09:07 +01:00
|
|
|
if ARGV.include? "--default-fortran-flags"
|
2013-08-30 19:07:10 -05:00
|
|
|
flags = FC_FLAG_VARS.reject { |key| self[key] }
|
2013-08-30 18:59:58 -05:00
|
|
|
elsif values_at(*FC_FLAG_VARS).compact.empty?
|
2017-10-15 02:28:32 +02:00
|
|
|
opoo <<~EOS
|
2013-08-19 12:32:59 -05:00
|
|
|
No Fortran optimization information was provided. You may want to consider
|
|
|
|
setting FCFLAGS and FFLAGS or pass the `--default-fortran-flags` option to
|
|
|
|
`brew install` if your compiler is compatible with GCC.
|
|
|
|
|
|
|
|
If you like the default optimization level of your compiler, ignore this
|
|
|
|
warning.
|
|
|
|
EOS
|
|
|
|
end
|
|
|
|
|
2014-02-02 12:57:46 -06:00
|
|
|
else
|
2015-08-03 13:09:07 +01:00
|
|
|
if (gfortran = which("gfortran", (HOMEBREW_PREFIX/"bin").to_s))
|
2014-02-02 12:57:46 -06:00
|
|
|
ohai "Using Homebrew-provided fortran compiler."
|
2017-04-27 10:44:44 +02:00
|
|
|
elsif (gfortran = which("gfortran", PATH.new(ORIGINAL_PATHS)))
|
2014-02-02 12:57:46 -06:00
|
|
|
ohai "Using a fortran compiler found at #{gfortran}."
|
|
|
|
end
|
|
|
|
if gfortran
|
|
|
|
puts "This may be changed by setting the FC environment variable."
|
2015-08-03 13:09:07 +01:00
|
|
|
self["FC"] = self["F77"] = gfortran
|
2014-02-02 12:57:46 -06:00
|
|
|
flags = FC_FLAG_VARS
|
|
|
|
end
|
2013-08-19 12:32:59 -05:00
|
|
|
end
|
2013-08-30 19:07:10 -05:00
|
|
|
|
|
|
|
flags.each { |key| self[key] = cflags }
|
|
|
|
set_cpu_flags(flags)
|
2013-08-19 12:32:59 -05:00
|
|
|
end
|
2013-06-04 10:18:14 -05:00
|
|
|
|
2013-09-28 14:57:17 -07:00
|
|
|
# ld64 is a newer linker provided for Xcode 2.5
|
2015-08-29 10:56:24 +01:00
|
|
|
# @private
|
2013-09-28 14:57:17 -07:00
|
|
|
def ld64
|
2015-08-03 13:09:07 +01:00
|
|
|
ld64 = Formulary.factory("ld64")
|
|
|
|
self["LD"] = ld64.bin/"ld"
|
2014-04-04 22:02:48 -05:00
|
|
|
append "LDFLAGS", "-B#{ld64.bin}/"
|
2013-09-28 14:57:17 -07:00
|
|
|
end
|
|
|
|
|
2015-08-29 10:56:24 +01:00
|
|
|
# @private
|
2015-06-21 21:18:23 -04:00
|
|
|
def gcc_version_formula(name)
|
|
|
|
version = name[GNU_GCC_REGEXP, 1]
|
2017-02-03 10:47:44 -08:00
|
|
|
gcc_version_name = "gcc@#{version}"
|
2014-04-29 08:51:56 +01:00
|
|
|
|
2015-06-22 21:00:40 -04:00
|
|
|
gcc = Formulary.factory("gcc")
|
2015-09-12 11:47:14 -07:00
|
|
|
if gcc.version_suffix == version
|
2015-06-22 21:00:40 -04:00
|
|
|
gcc
|
2014-04-30 12:38:22 +01:00
|
|
|
else
|
2015-06-21 21:18:24 -04:00
|
|
|
Formulary.factory(gcc_version_name)
|
2014-04-29 08:51:56 +01:00
|
|
|
end
|
2014-04-19 09:11:52 +01:00
|
|
|
end
|
|
|
|
|
2015-08-29 10:56:24 +01:00
|
|
|
# @private
|
2015-06-21 21:18:23 -04:00
|
|
|
def warn_about_non_apple_gcc(name)
|
2013-06-04 10:18:14 -05:00
|
|
|
begin
|
2015-06-21 21:18:23 -04:00
|
|
|
gcc_formula = gcc_version_formula(name)
|
2015-06-22 21:08:27 -04:00
|
|
|
rescue FormulaUnavailableError => e
|
2017-10-15 02:28:32 +02:00
|
|
|
raise <<~EOS
|
|
|
|
Homebrew GCC requested, but formula #{e.name} not found!
|
2015-06-21 21:18:23 -04:00
|
|
|
EOS
|
|
|
|
end
|
|
|
|
|
2016-09-23 22:02:23 +02:00
|
|
|
return if gcc_formula.opt_prefix.exist?
|
2018-09-17 02:45:00 +02:00
|
|
|
|
2017-10-15 02:28:32 +02:00
|
|
|
raise <<~EOS
|
|
|
|
The requested Homebrew GCC was not installed. You must:
|
|
|
|
brew install #{gcc_formula.full_name}
|
2016-09-23 22:02:23 +02:00
|
|
|
EOS
|
2013-06-04 10:18:14 -05:00
|
|
|
end
|
2014-05-14 00:00:59 -05:00
|
|
|
|
|
|
|
def permit_arch_flags; end
|
2014-05-18 14:34:31 -05:00
|
|
|
|
2016-08-22 10:39:38 +01:00
|
|
|
# A no-op until we enable this by default again (which we may never do).
|
2016-08-17 22:55:16 -07:00
|
|
|
def permit_weak_imports; end
|
|
|
|
|
2018-07-05 20:15:57 +01:00
|
|
|
# @private
|
|
|
|
def compiler_any_clang?(cc = compiler)
|
|
|
|
%w[clang llvm_clang].include?(cc.to_s)
|
|
|
|
end
|
|
|
|
|
|
|
|
# @private
|
|
|
|
def compiler_with_cxx11_support?(cc)
|
|
|
|
return if compiler_any_clang?(cc)
|
2018-09-17 02:45:00 +02:00
|
|
|
|
2018-07-05 20:15:57 +01:00
|
|
|
version = cc[/^gcc-(\d+(?:\.\d+)?)$/, 1]
|
|
|
|
version && Version.create(version) >= Version.create("4.8")
|
|
|
|
end
|
|
|
|
|
2014-05-18 14:34:31 -05:00
|
|
|
private
|
|
|
|
|
2015-08-03 13:09:07 +01:00
|
|
|
def cc=(val)
|
2014-05-18 14:34:31 -05:00
|
|
|
self["CC"] = self["OBJC"] = val.to_s
|
|
|
|
end
|
|
|
|
|
2015-08-03 13:09:07 +01:00
|
|
|
def cxx=(val)
|
2014-05-18 14:34:31 -05:00
|
|
|
self["CXX"] = self["OBJCXX"] = val.to_s
|
|
|
|
end
|
2014-05-18 14:34:31 -05:00
|
|
|
|
|
|
|
def homebrew_cc
|
|
|
|
self["HOMEBREW_CC"]
|
|
|
|
end
|
2014-09-18 15:50:54 -05:00
|
|
|
|
|
|
|
def fetch_compiler(value, source)
|
|
|
|
COMPILER_SYMBOL_MAP.fetch(value) do |other|
|
|
|
|
case other
|
|
|
|
when GNU_GCC_REGEXP
|
|
|
|
other
|
|
|
|
else
|
|
|
|
raise "Invalid value for #{source}: #{other}"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2015-12-09 10:37:49 -05:00
|
|
|
|
|
|
|
def check_for_compiler_universal_support
|
2016-09-23 22:02:23 +02:00
|
|
|
return unless homebrew_cc =~ GNU_GCC_REGEXP
|
2018-09-17 02:45:00 +02:00
|
|
|
|
2016-09-23 22:02:23 +02:00
|
|
|
raise "Non-Apple GCC can't build universal binaries"
|
2015-12-09 10:37:49 -05:00
|
|
|
end
|
2013-08-19 12:32:59 -05:00
|
|
|
end
|
2016-08-16 13:47:22 +01:00
|
|
|
|
|
|
|
require "extend/os/extend/ENV/shared"
|