aboutsummaryrefslogtreecommitdiffstats
path: root/Library/Homebrew
diff options
context:
space:
mode:
Diffstat (limited to 'Library/Homebrew')
-rwxr-xr-xLibrary/Homebrew/build.rb61
-rw-r--r--Library/Homebrew/cmd/--env.rb6
-rw-r--r--Library/Homebrew/cmd/audit.rb3
-rw-r--r--Library/Homebrew/extend/ENV.rb121
-rw-r--r--Library/Homebrew/formula.rb4
-rw-r--r--Library/Homebrew/macos.rb10
-rw-r--r--Library/Homebrew/superenv.rb240
7 files changed, 339 insertions, 106 deletions
diff --git a/Library/Homebrew/build.rb b/Library/Homebrew/build.rb
index dd3e02442..6742f4203 100755
--- a/Library/Homebrew/build.rb
+++ b/Library/Homebrew/build.rb
@@ -13,22 +13,6 @@ at_exit do
error_pipe = nil
begin
- raise $! if $! # an exception was already thrown when parsing the formula
-
- require 'extend/ENV'
- require 'hardware'
- require 'keg'
-
- ENV.extend(HomebrewEnvExtension)
- ENV.setup_build_environment
- # 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'
-
- # Force any future invocations of sudo to require the user's password to be
- # re-entered. This is in-case any build script call sudo. Certainly this is
- # can be inconvenient for the user. But we need to be safe.
- system "/usr/bin/sudo -k"
-
# The main Homebrew process expects to eventually see EOF on the error
# pipe in FormulaInstaller#build. However, if any child process fails to
# terminate (i.e, fails to close the descriptor), this won't happen, and
@@ -41,6 +25,16 @@ at_exit do
error_pipe.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
end
+ raise $! if $! # an exception was already thrown when parsing the formula
+
+ require 'hardware'
+ require 'keg'
+
+ # Force any future invocations of sudo to require the user's password to be
+ # re-entered. This is in-case any build script call sudo. Certainly this is
+ # can be inconvenient for the user. But we need to be safe.
+ system "/usr/bin/sudo -k"
+
install(Formula.factory($0))
rescue Exception => e
unless error_pipe.nil?
@@ -56,27 +50,36 @@ at_exit do
end
def install f
- f.recursive_requirements.each { |req| req.modify_build_environment }
+ keg_only_deps = f.recursive_deps.uniq.select{|dep| dep.keg_only? }
- f.recursive_deps.uniq.each do |dep|
- dep = Formula.factory dep
- if dep.keg_only?
- opt = HOMEBREW_PREFIX/:opt/dep.name
+ require 'superenv'
- raise "#{opt} not present\nReinstall #{dep}." unless opt.directory?
+ ENV.setup_build_environment unless superenv?
- ENV.prepend 'LDFLAGS', "-L#{opt}/lib"
- ENV.prepend 'CPPFLAGS', "-I#{opt}/include"
- ENV.prepend 'PATH', "#{opt}/bin", ':'
+ keg_only_deps.each do |dep|
+ opt = HOMEBREW_PREFIX/:opt/dep.name
- pcdir = opt/'lib/pkgconfig'
- ENV.prepend 'PKG_CONFIG_PATH', pcdir, ':' if pcdir.directory?
+ #TODO try to fix, if only one key, easy, otherwise check formula.version
+ raise "#{opt} not present\nReinstall #{dep}. Sorry :(" unless opt.directory?
- acdir = opt/'share/aclocal'
- ENV.prepend 'ACLOCAL_PATH', acdir, ':' if acdir.directory?
+ if not superenv?
+ ENV.prepend_path 'PATH', "#{opt}/bin"
+ ENV.prepend_path 'PKG_CONFIG_PATH', "#{opt}/lib/pkgconfig"
+ ENV.prepend_path 'PKG_CONFIG_PATH', "#{opt}/share/pkgconfig"
+ ENV.prepend_path 'ACLOCAL_PATH', "#{opt}/share/aclocal"
+ ENV.prepend_path 'CMAKE_PREFIX_PATH', opt
+ ENV.prepend 'LDFLAGS', "-L#{opt}/lib" if (opt/:lib).directory?
+ ENV.prepend 'CPPFLAGS', "-I#{opt}/include" if (opt/:include).directory?
end
end
+ if superenv?
+ ENV.deps = keg_only_deps.map(&:to_s)
+ ENV.setup_build_environment
+ end
+
+ f.recursive_requirements.each { |req| req.modify_build_environment }
+
if f.fails_with? ENV.compiler
cs = CompilerSelector.new f
cs.select_compiler
diff --git a/Library/Homebrew/cmd/--env.rb b/Library/Homebrew/cmd/--env.rb
index 79323c300..b5d1253fe 100644
--- a/Library/Homebrew/cmd/--env.rb
+++ b/Library/Homebrew/cmd/--env.rb
@@ -1,9 +1,8 @@
-require 'extend/ENV'
+require 'superenv'
require 'hardware'
module Homebrew extend self
def __env
- ENV.extend(HomebrewEnvExtension)
ENV.setup_build_environment
ENV.universal_binary if ARGV.build_universal?
if $stdout.tty?
@@ -17,10 +16,11 @@ module Homebrew extend self
def build_env_keys env
%w[ CC CXX LD CFLAGS CXXFLAGS CPPFLAGS LDFLAGS SDKROOT
- CMAKE_PREFIX_PATH CMAKE_INBLUDE_PATH CMAKE_FRAMEWORK_PATH MAKEFLAGS
+ CMAKE_PREFIX_PATH CMAKE_INCLUDE_PATH CMAKE_FRAMEWORK_PATH MAKEFLAGS
MACOSX_DEPLOYMENT_TARGET PKG_CONFIG_PATH HOMEBREW_BUILD_FROM_SOURCE
HOMEBREW_DEBUG HOMEBREW_MAKE_JOBS HOMEBREW_VERBOSE HOMEBREW_USE_CLANG
HOMEBREW_USE_GCC HOMEBREW_USE_LLVM HOMEBREW_SVN
+ MAKE GIT CPP
ACLOCAL_PATH OBJC PATH ].select{ |key| env[key] }
end
diff --git a/Library/Homebrew/cmd/audit.rb b/Library/Homebrew/cmd/audit.rb
index 18382de59..8244d40aa 100644
--- a/Library/Homebrew/cmd/audit.rb
+++ b/Library/Homebrew/cmd/audit.rb
@@ -1,6 +1,6 @@
require 'formula'
require 'utils'
-require 'extend/ENV'
+require 'superenv'
module Homebrew extend self
def audit
@@ -245,7 +245,6 @@ class FormulaAuditor
def audit_patches
# Some formulae use ENV in patches, so set up an environment
- ENV.extend(HomebrewEnvExtension)
ENV.setup_build_environment
Patches.new(f.patches).select { |p| p.external? }.each do |p|
diff --git a/Library/Homebrew/extend/ENV.rb b/Library/Homebrew/extend/ENV.rb
index 90ff517b1..69947879e 100644
--- a/Library/Homebrew/extend/ENV.rb
+++ b/Library/Homebrew/extend/ENV.rb
@@ -178,6 +178,8 @@ module HomebrewEnvExtension
end
def fortran
+ fc_flag_vars = %w{FCFLAGS FFLAGS}
+
if self['FC']
ohai "Building with an alternative Fortran compiler. This is unsupported."
self['F77'] = self['FC'] unless self['F77']
@@ -333,28 +335,6 @@ Please take one of the following actions:
remove_from_cflags '-Qunused-arguments'
end
- # Snow Leopard defines an NCURSES value the opposite of most distros
- # See: http://bugs.python.org/issue6848
- def ncurses_define
- append 'CPPFLAGS', "-DNCURSES_OPAQUE=0"
- end
-
- # Shortcuts for reading common flags
- def cc; self['CC'] or "gcc"; end
- def cxx; self['CXX'] or "g++"; end
- def cflags; self['CFLAGS']; end
- def cxxflags;self['CXXFLAGS']; end
- def cppflags;self['CPPFLAGS']; end
- def ldflags; self['LDFLAGS']; end
-
- # Shortcuts for lists of common flags
- def cc_flag_vars
- %w{CFLAGS CXXFLAGS OBJCFLAGS OBJCXXFLAGS}
- end
- def fc_flag_vars
- %w{FCFLAGS FFLAGS}
- end
-
def m64
append_to_cflags '-m64'
append 'LDFLAGS', '-arch x86_64'
@@ -376,49 +356,6 @@ Please take one of the following actions:
end
end
- def prepend key, value, separator = ' '
- # Value should be a string, but if it is a pathname then coerce it.
- value = value.to_s
-
- [*key].each do |key|
- unless self[key].to_s.empty?
- self[key] = value + separator + self[key]
- else
- self[key] = value
- end
- end
- end
-
- def append key, value, separator = ' '
- # Value should be a string, but if it is a pathname then coerce it.
- value = value.to_s
-
- [*key].each do |key|
- unless self[key].to_s.empty?
- self[key] = self[key] + separator + value
- else
- self[key] = value
- end
- end
- end
-
- def append_to_cflags f
- append cc_flag_vars, f
- end
-
- def remove key, value
- [*key].each do |key|
- next if self[key].nil?
- self[key] = self[key].sub value, '' # can't use sub! on ENV
- self[key] = self[key].gsub /\s+/, ' ' # compact whitespace
- self[key] = nil if self[key].empty? # keep things clean
- end
- end
-
- def remove_from_cflags f
- remove cc_flag_vars, f
- end
-
def replace_in_cflags before, after
cc_flag_vars.each do |key|
self[key] = self[key].sub before, after if self[key]
@@ -491,13 +428,65 @@ Please take one of the following actions:
Hardware.processor_count
end
end
+end
+class << ENV
def remove_cc_etc
keys = %w{CC CXX LD CPP CFLAGS CXXFLAGS OBJCFLAGS OBJCXXFLAGS LDFLAGS CPPFLAGS}
removed = Hash[*keys.map{ |key| [key, self[key]] }.flatten]
keys.each do |key|
- self[key] = nil
+ delete(key)
end
removed
end
+ def cc_flag_vars
+ %w{CFLAGS CXXFLAGS OBJCFLAGS OBJCXXFLAGS}
+ end
+ def append_to_cflags newflags
+ append(cc_flag_vars, newflags)
+ end
+ def remove_from_cflags f
+ remove cc_flag_vars, f
+ end
+ def append key, value, separator = ' '
+ value = value.to_s
+ [*key].each do |key|
+ unless self[key].to_s.empty?
+ self[key] = self[key] + separator + value.to_s
+ else
+ self[key] = value.to_s
+ end
+ end
+ end
+ def prepend key, value, separator = ' '
+ [*key].each do |key|
+ unless self[key].to_s.empty?
+ self[key] = value.to_s + separator + self[key]
+ else
+ self[key] = value.to_s
+ end
+ end
+ end
+ def prepend_path key, path
+ prepend key, path, ':' if File.directory? path
+ end
+ def remove key, value
+ [*key].each do |key|
+ next unless self[key]
+ self[key] = self[key].sub(value, '')
+ delete(key) if self[key].to_s.empty?
+ end if value
+ end
+ def cc; self['CC'] or "cc"; end
+ def cxx; self['CXX'] or "c++"; end
+ def cflags; self['CFLAGS']; end
+ def cxxflags;self['CXXFLAGS']; end
+ def cppflags;self['CPPFLAGS']; end
+ def ldflags; self['LDFLAGS']; end
+
+ # Snow Leopard defines an NCURSES value the opposite of most distros
+ # See: http://bugs.python.org/issue6848
+ def ncurses_define
+ append 'CPPFLAGS', "-DNCURSES_OPAQUE=0"
+ end
end
diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb
index 78209feb7..08e01a7d7 100644
--- a/Library/Homebrew/formula.rb
+++ b/Library/Homebrew/formula.rb
@@ -470,6 +470,8 @@ protected
removed_ENV_variables = case if args.empty? then cmd.split(' ').first else cmd end
when "xcodebuild"
ENV.remove_cc_etc
+ when /^make\b/
+ ENV.append 'HOMEBREW_CCCFG', "O", ''
end
if ARGV.verbose?
@@ -500,6 +502,8 @@ protected
rescue
raise BuildError.new(self, cmd, args, $?)
+ ensure
+ ENV['HOMEBREW_CCCFG'] = ENV['HOMEBREW_CCCFG'].delete('O') if ENV['HOMEBREW_CCCFG']
end
public
diff --git a/Library/Homebrew/macos.rb b/Library/Homebrew/macos.rb
index e6b0fbee3..a50639d20 100644
--- a/Library/Homebrew/macos.rb
+++ b/Library/Homebrew/macos.rb
@@ -1,7 +1,5 @@
module MacOS extend self
- MDITEM_BUNDLE_ID_KEY = "kMDItemCFBundleIdentifier"
-
def version
require 'version'
MacOSVersion.new(MACOS_VERSION.to_s)
@@ -212,12 +210,12 @@ module MacOS extend self
end
def app_with_bundle_id id
- mdfind(MDITEM_BUNDLE_ID_KEY, id)
+ path = mdfind(id).first
+ Pathname.new(path) unless path.nil? or path.empty?
end
- def mdfind attribute, id
- path = `/usr/bin/mdfind "#{attribute} == '#{id}'"`.split("\n").first
- Pathname.new(path) unless path.nil? or path.empty?
+ def mdfind id
+ `/usr/bin/mdfind "kMDItemCFBundleIdentifier == '#{id}'"`.split("\n")
end
def pkgutil_info id
diff --git a/Library/Homebrew/superenv.rb b/Library/Homebrew/superenv.rb
new file mode 100644
index 000000000..8061abaf4
--- /dev/null
+++ b/Library/Homebrew/superenv.rb
@@ -0,0 +1,240 @@
+require 'extend/ENV'
+require 'macos'
+
+### 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 superenv_bin
+ @bin ||= (HOMEBREW_REPOSITORY/"Library/ENV").children.reject{|d| d.basename.to_s > MacOS::Xcode.version }.max
+end
+
+def superenv?
+ not MacOS::Xcode.bad_xcode_select_path? and # because xcrun won't work
+ not MacOS::Xcode.folder.nil? and # because xcrun won't work
+ superenv_bin.directory? and
+ not ARGV.include? "--env=std"
+end
+
+class << ENV
+ attr :deps, true
+
+ def reset
+ %w{CC CXX LD CPP OBJC MAKE
+ CFLAGS CXXFLAGS OBJCFLAGS OBJCXXFLAGS LDFLAGS CPPFLAGS
+ MACOS_DEPLOYMENT_TARGET SDKROOT
+ CMAKE_PREFIX_PATH CMAKE_INCLUDE_PATH CMAKE_FRAMEWORK_PATH
+ HOMEBREW_CCCFG HOMEBREW_DEP_PREFIXES
+ MAKEFLAGS MAKEJOBS}.
+ 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
+
+ if MacOS.mountain_lion?
+ # Fix issue with sed barfing on unicode characters on Mountain Lion
+ delete('LC_ALL')
+ ENV['LC_CTYPE'] = "C"
+ end
+ end
+
+ def setup_build_environment
+ reset
+ ENV['CC'] = 'cc'
+ ENV['CXX'] = 'c++'
+ ENV['LD'] = 'ld'
+ ENV['CPP'] = 'cpp'
+ ENV['MAKE'] = 'make'
+ ENV['MAKEFLAGS'] ||= "-j#{Hardware.processor_count}"
+ ENV['PATH'] = determine_path
+ ENV['PKG_CONFIG_PATH'] = determine_pkg_config_path
+ ENV['HOMEBREW_CC'] = determine_cc
+ ENV['HOMEBREW_CCCFG'] = 'b' if ARGV.build_bottle?
+ 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['ACLOCAL_PATH'] = determine_aclocal_path
+ end
+
+ def universal_binary
+ append 'HOMEBREW_CCCFG', "u", ''
+ end
+
+ private
+
+ def determine_cc
+ if ARGV.include? '--use-gcc'
+ "gcc"
+ 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 = [superenv_bin]
+ if MacSystem.xcode43_without_clt?
+ paths << "#{MacSystem.xcode43_developer_dir}/usr/bin"
+ paths << "#{MacSystem.xcode43_developer_dir}/Toolchains/XcodeDefault.xctoolchain/usr/bin"
+ end
+ paths += deps.map{|dep| "#{HOMEBREW_PREFIX}/opt/#{dep}/bin" }
+ paths << HOMEBREW_PREFIX/:bin
+ paths << "#{MacSystem.x11_prefix}/bin"
+ 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 << "#{HOMEBREW_REPOSITORY}/lib/pkgconfig"
+ paths << "#{HOMEBREW_REPOSITORY}/share/pkgconfig"
+ # we put our paths before X because we dupe some of the X libraries
+ paths << "#{MacSystem.x11_prefix}/lib/pkgconfig" << "#{MacSystem.x11_prefix}/share/pkgconfig"
+ # Mountain Lion no longer ships some .pcs; ensure we pick up our versions
+ paths << "#{HOMEBREW_REPOSITORY}/Library/Homebrew/pkgconfig" if MacOS.mountain_lion?
+ paths.to_path_s
+ end
+
+ def determine_cmake_prefix_path
+ paths = deps.map{|dep| "#{HOMEBREW_PREFIX}/opt/#{dep}" }
+ paths << "#{MacOS.sdk_path}/usr" if MacSystem.xcode43_without_clt?
+ paths << HOMEBREW_PREFIX.to_s # again always put ourselves ahead of X11
+ paths << MacSystem.x11_prefix
+ paths.to_path_s
+ end
+
+ def determine_cmake_include_path
+ sdk = MacOS.sdk_path if MacSystem.xcode43_without_clt?
+ paths = %W{#{MacSystem.x11_prefix}/include/freetype2}
+ paths << "#{sdk}/usr/include/libxml2" unless deps.include? 'libxml2'
+ # TODO prolly shouldn't always do this?
+ paths << "#{sdk}/System/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7" if MacSystem.xcode43_without_clt?
+ paths.to_path_s
+ end
+
+ def determine_aclocal_path
+ paths = deps.map{|dep| "#{HOMEBREW_PREFIX}/opt/#{dep}/share/aclocal" }
+ paths << "#{HOMEBREW_PREFIX}/share/aclocal"
+ paths << "/opt/X11/share/aclocal"
+ paths.to_path_s
+ end
+
+ public
+
+### NO LONGER NECESSARY OR NO LONGER SUPPORTED
+ def noop(*args); end
+ %w[m64 m32 gcc_4_0_1 fast O4 O3 O2 Os Og O1 libxml2 minimal_optimization
+ no_optimization enable_warnings fortran x11
+ macosxsdk remove_macosxsdk].each{|s| alias_method s, :noop }
+
+### DEPRECATE THESE
+ def compiler
+ case ENV['HOMEBREW_CC']
+ when "llvm-gcc" then :llvm
+ 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'] = "gcc"
+ ENV['CXX'] = "g++"
+ end
+ def llvm
+ ENV['CC'] = "llvm-gcc"
+ ENV['CXX'] = "llvm-g++"
+ end
+ def clang
+ ENV['CC'] = "clang"
+ ENV['CXX'] = "clang++"
+ end
+ def make_jobs
+ ENV['MAKEFLAGS'] =~ /-\w*j(\d)+/
+ [$1.to_i, 1].max
+ 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.deps = []
+end
+
+
+class Array
+ def to_path_s
+ map(&:to_s).select{|s| s and File.directory? s }.join(':').chuzzle
+ end
+end
+
+# new code because I don't really trust the Xcode code now having researched it more
+module MacSystem extend self
+ def xcode_clt_installed?
+ File.executable? "/usr/bin/clang" and File.executable? "/usr/bin/lldb"
+ end
+
+ def xcode43_without_clt?
+ MacOS::Xcode.version >= "4.3" and not MacSystem.xcode_clt_installed?
+ end
+
+ def x11_prefix
+ @x11_prefix ||= %W[/usr/X11 /opt/X11
+ #{MacOS.sdk_path}/usr/X11].find{|path| File.directory? "#{path}/include" }
+ end
+
+ def xcode43_developer_dir
+ @xcode43_developer_dir ||=
+ tst(ENV['DEVELOPER_DIR']) ||
+ tst(`xcode-select -print-path 2>/dev/null`) ||
+ tst("/Applications/Xcode.app/Contents/Developer") ||
+ MacOS.mdfind("com.apple.dt.Xcode").find{|path| tst(path) }
+ raise unless @xcode43_developer_dir
+ @xcode43_developer_dir
+ end
+
+ private
+
+ def tst prefix
+ prefix = prefix.to_s.chomp
+ xcrun = "#{prefix}/usr/bin/xcrun"
+ prefix if xcrun != "/usr/bin/xcrun" and File.executable? xcrun
+ end
+end