brew/Library/Homebrew/superenv.rb
Samuel John c6b0b563e8 Better superenv support for Xcode elsewhere
- The Library/ENV/4.3/xcrun shim now respects
  ENV['DEVELOPER_DIR'] instead assuming the location
  of /Applications/Xcode.app/Contents/Developer.
- The env var DEVELOPER_DIR is set if it is not
  already. So, during superenv this var is always set
  and we no longer have to care about people with unset
  or wrongly set xcode-select stuff. This has been
  a major PITA in the past.
- determine_developer_dir (which is used to set
  the DEVELOPER_DIR var) now uses MacOS::Xcode.prefix
  which is proven and very capable and uses splotlight
  correctly.
- Replace (and remove) MacSystem.xcode43_developer_dir
  with Xcode.prefix

Closes Homebrew/homebrew#18618
2013-03-21 17:10:32 +01:00

283 lines
8.9 KiB
Ruby

require 'extend/ENV'
require 'macos'
require 'superenv/macsystem'
### Why `superenv`?
# 1) Only specify the environment we need (NO LDFLAGS for cmake)
# 2) Only apply compiler specific options when we are calling that compiler
# 3) Force all incpaths and libpaths into the cc instantiation (less bugs)
# 4) Cater toolchain usage to specific Xcode versions
# 5) Remove flags that we don't want or that will break builds
# 6) Simpler code
# 7) Simpler formula that *just work*
# 8) Build-system agnostic configuration of the tool-chain
def superbin
@bin ||= (HOMEBREW_REPOSITORY/"Library/ENV").children.reject{|d| d.basename.to_s > MacOS::Xcode.version }.max
end
def superenv?
not (MacSystem.xcode43_without_clt? and
MacOS.sdk_path.nil?) and # because superenv will fail to find stuff
superbin and superbin.directory? and
not ARGV.include? "--env=std"
rescue # blanket rescue because there are naked raises
false
end
class << ENV
attr_accessor :keg_only_deps, :deps, :x11
alias_method :x11?, :x11
def reset
%w{CC CXX OBJC OBJCXX CPP MAKE LD
CFLAGS CXXFLAGS OBJCFLAGS OBJCXXFLAGS LDFLAGS CPPFLAGS
MACOS_DEPLOYMENT_TARGET SDKROOT
CMAKE_PREFIX_PATH CMAKE_INCLUDE_PATH CMAKE_FRAMEWORK_PATH
CPATH C_INCLUDE_PATH CPLUS_INCLUDE_PATH OBJC_INCLUDE_PATH}.
each{ |x| delete(x) }
delete('CDPATH') # avoid make issues that depend on changing directories
delete('GREP_OPTIONS') # can break CMake
delete('CLICOLOR_FORCE') # autotools doesn't like this
end
def setup_build_environment
reset
ENV['CC'] = 'cc'
ENV['CXX'] = 'c++'
ENV['OBJC'] = 'cc'
ENV['OBJCXX'] = 'c++'
ENV['DEVELOPER_DIR'] = determine_developer_dir # effects later settings
ENV['MAKEFLAGS'] ||= "-j#{determine_make_jobs}"
ENV['PATH'] = determine_path
ENV['PKG_CONFIG_PATH'] = determine_pkg_config_path
ENV['PKG_CONFIG_LIBDIR'] = determine_pkg_config_libdir
ENV['HOMEBREW_CC'] = determine_cc
ENV['HOMEBREW_CCCFG'] = determine_cccfg
ENV['HOMEBREW_BREW_FILE'] = HOMEBREW_BREW_FILE
ENV['HOMEBREW_SDKROOT'] = "#{MacOS.sdk_path}" if MacSystem.xcode43_without_clt?
ENV['CMAKE_PREFIX_PATH'] = determine_cmake_prefix_path
ENV['CMAKE_FRAMEWORK_PATH'] = "#{MacOS.sdk_path}/System/Library/Frameworks" if MacSystem.xcode43_without_clt?
ENV['CMAKE_INCLUDE_PATH'] = determine_cmake_include_path
ENV['CMAKE_LIBRARY_PATH'] = determine_cmake_library_path
ENV['ACLOCAL_PATH'] = determine_aclocal_path
end
def universal_binary
append 'HOMEBREW_CCCFG', "u", ''
end
# m32 on superenv does not add any flags. It prevents "-m32" from being erased.
def m32
append 'HOMEBREW_CCCFG', "3", ''
end
private
def determine_cc
if ARGV.include? '--use-gcc'
# fall back to something else on systems without Apple gcc
MacOS.locate('gcc-4.2') ? "gcc-4.2" : raise("gcc-4.2 not found!")
elsif ARGV.include? '--use-llvm'
"llvm-gcc"
elsif ARGV.include? '--use-clang'
"clang"
elsif ENV['HOMEBREW_USE_CLANG']
opoo %{HOMEBREW_USE_CLANG is deprecated, use HOMEBREW_CC="clang" instead}
"clang"
elsif ENV['HOMEBREW_USE_LLVM']
opoo %{HOMEBREW_USE_LLVM is deprecated, use HOMEBREW_CC="llvm" instead}
"llvm-gcc"
elsif ENV['HOMEBREW_USE_GCC']
opoo %{HOMEBREW_USE_GCC is deprecated, use HOMEBREW_CC="gcc" instead}
"gcc"
elsif ENV['HOMEBREW_CC']
case ENV['HOMEBREW_CC']
when 'clang', 'gcc' then ENV['HOMEBREW_CC']
when 'llvm', 'llvm-gcc' then 'llvm-gcc'
else
opoo "Invalid value for HOMEBREW_CC: #{ENV['HOMEBREW_CC']}"
raise # use default
end
else
raise
end
rescue
"clang"
end
def determine_path
paths = [superbin]
if MacSystem.xcode43_without_clt?
paths << "#{MacOS::Xcode.prefix}/usr/bin"
paths << "#{MacOS::Xcode.prefix}/Toolchains/XcodeDefault.xctoolchain/usr/bin"
end
paths += deps.map{|dep| "#{HOMEBREW_PREFIX}/opt/#{dep}/bin" }
paths << "#{HOMEBREW_PREFIX}/opt/python/bin" if brewed_python?
paths << "#{MacSystem.x11_prefix}/bin" if x11?
paths += %w{/usr/bin /bin /usr/sbin /sbin}
paths.to_path_s
end
def determine_pkg_config_path
paths = deps.map{|dep| "#{HOMEBREW_PREFIX}/opt/#{dep}/lib/pkgconfig" }
paths += deps.map{|dep| "#{HOMEBREW_PREFIX}/opt/#{dep}/share/pkgconfig" }
paths.to_path_s
end
def determine_pkg_config_libdir
paths = %W{/usr/lib/pkgconfig #{HOMEBREW_REPOSITORY}/Library/ENV/pkgconfig/#{MacOS.version}}
paths << "#{MacSystem.x11_prefix}/lib/pkgconfig" << "#{MacSystem.x11_prefix}/share/pkgconfig" if x11?
paths.to_path_s
end
def determine_cmake_prefix_path
paths = keg_only_deps.map{|dep| "#{HOMEBREW_PREFIX}/opt/#{dep}" }
paths << HOMEBREW_PREFIX.to_s # put ourselves ahead of everything else
paths << "#{MacOS.sdk_path}/usr" if MacSystem.xcode43_without_clt?
paths.to_path_s
end
def determine_cmake_include_path
sdk = MacOS.sdk_path if MacSystem.xcode43_without_clt?
paths = []
paths << "#{MacSystem.x11_prefix}/include/freetype2" if x11?
paths << "#{sdk}/usr/include/libxml2" unless deps.include? 'libxml2'
if MacSystem.xcode43_without_clt?
paths << "#{sdk}/usr/include/apache2"
paths << if brewed_python?
"#{HOMEBREW_PREFIX}/opt/python/Frameworks/Python.framework/Headers"
else
"#{sdk}/System/Library/Frameworks/Python.framework/Versions/Current/include/python2.7"
end
end
paths << "#{sdk}/System/Library/Frameworks/OpenGL.framework/Versions/Current/Headers/" unless x11?
paths << "#{MacSystem.x11_prefix}/include" if x11?
paths.to_path_s
end
def determine_cmake_library_path
sdk = MacOS.sdk_path if MacSystem.xcode43_without_clt?
paths = []
# things expect to find GL headers since X11 used to be a default, so we add them
paths << "#{sdk}/System/Library/Frameworks/OpenGL.framework/Versions/Current/Libraries" unless x11?
paths << "#{MacSystem.x11_prefix}/lib" if x11?
paths.to_path_s
end
def determine_aclocal_path
paths = keg_only_deps.map{|dep| "#{HOMEBREW_PREFIX}/opt/#{dep}/share/aclocal" }
paths << "#{HOMEBREW_PREFIX}/share/aclocal"
paths << "/opt/X11/share/aclocal" if x11?
paths.to_path_s
end
def determine_make_jobs
if (j = ENV['HOMEBREW_MAKE_JOBS'].to_i) < 1
Hardware.processor_count
else
j
end
end
def determine_cccfg
s = ""
s << 'b' if ARGV.build_bottle?
# Fix issue with sed barfing on unicode characters on Mountain Lion
s << 's' if MacOS.version >= :mountain_lion
# Fix issue with 10.8 apr-1-config having broken paths
s << 'a' if MacOS.version == :mountain_lion
s
end
def determine_developer_dir
# If Xcode path is fucked then this is basically a fix. In the case where
# nothing is valid, it still fixes most usage to supply a valid path that
# is not "/".
MacOS::Xcode.prefix || ENV['DEVELOPER_DIR']
end
def brewed_python?
require 'formula'
Formula.factory('python').linked_keg.directory?
end
public
### NO LONGER NECESSARY OR NO LONGER SUPPORTED
def noop(*args); end
%w[m64 gcc_4_0_1 fast O4 O3 O2 Os Og O1 libxml2 minimal_optimization
no_optimization enable_warnings x11
set_cpu_flags
macosxsdk remove_macosxsdk].each{|s| alias_method s, :noop }
### DEPRECATE THESE
def compiler
case ENV['HOMEBREW_CC']
when "llvm-gcc" then :llvm
when "gcc-4.2" then :gcc
when "gcc", "clang" then ENV['HOMEBREW_CC'].to_sym
else
raise
end
end
def deparallelize
delete('MAKEFLAGS')
end
alias_method :j1, :deparallelize
def gcc
ENV['CC'] = ENV['OBJC'] = ENV['HOMEBREW_CC'] = "gcc"
ENV['CXX'] = ENV['OBJCXX'] = "g++"
end
def llvm
ENV['CC'] = ENV['OBJC'] = ENV['HOMEBREW_CC'] = "llvm-gcc"
ENV['CXX'] = ENV['OBJCXX'] = "g++"
end
def clang
ENV['CC'] = ENV['OBJC'] = ENV['HOMEBREW_CC'] = "clang"
ENV['CXX'] = ENV['OBJCXX'] = "clang++"
end
def make_jobs
ENV['MAKEFLAGS'] =~ /-\w*j(\d)+/
[$1.to_i, 1].max
end
# Many formula assume that CFLAGS etc. will not be nil.
# This should be a safe hack to prevent that exception cropping up.
# Main consqeuence of this is that ENV['CFLAGS'] is never nil even when it
# is which can break if checks, but we don't do such a check in our code.
def [] key
if has_key? key
fetch(key)
elsif %w{CPPFLAGS CFLAGS LDFLAGS}.include? key
class << (a = "")
attr_accessor :key
def + value
ENV[key] = value
end
alias_method '<<', '+'
end
a.key = key
a
end
end
end if superenv?
if not superenv?
ENV.extend(HomebrewEnvExtension)
# we must do this or tools like pkg-config won't get found by configure scripts etc.
ENV.prepend 'PATH', "#{HOMEBREW_PREFIX}/bin", ':' unless ORIGINAL_PATHS.include? HOMEBREW_PREFIX/'bin'
else
ENV.keg_only_deps = []
ENV.deps = []
end
class Array
def to_path_s
map(&:to_s).uniq.select{|s| File.directory? s }.join(':').chuzzle
end
end