Python 2.x and 3.x support

New `depends_on :python` Dependency.
New `depends_on :python3` Dependency.

To avoid having multiple formulae with endings -py2 and -py3,
we will handle support for different pythons (2.x vs. 3.x)
in the same formula.
Further brewed vs. external python will be transparently supported.

The formula also gets a new object `python`, which is false if
no Python is available or the user has disabled it. Otherwise
it is defined and provides several support methods:

python.site_packages # the site-packages in the formula's Cellar
python.global_site_packages
python.binary # the full path to the python binary
python.prefix
python.version
python.version.major
python.version.minor
python.xy # => e.g. "python2.7"
python.incdir # includes of python
python.libdir # the python dylib library
python.pkg_config_path # used internally by brew
python.from_osx?
python.framework?
python.universal?
python.pypy?
python.standard_caveats # Text to set PYTHONPATH for python.from_osx?
python.if3then3 # => "" for 2.x and to "3" for 3.x.

Further, to avoid code duplication, `python` takes an optional
block that is run twice if the formula defines depends_on
:python AND :python3.

python do
  system python, 'setup.py', "--prefix=#{prefix}"
end

Read more in the Homebrew wiki.
This commit is contained in:
Samuel John 2013-01-21 10:33:56 +01:00
parent 9647954a60
commit c524895666
15 changed files with 511 additions and 25 deletions

View File

@ -85,4 +85,19 @@ class BuildOptions
def unused_options
Options.new(@options - @args)
end
# Some options are implicitly ON because they are not explictly turned off
# by their counterpart option. This applies only to with-/without- options.
# implicit_options are needed because `depends_on 'spam' => 'with-stuff'`
# complains if 'spam' has stuff as default and only defines `--without-stuff`.
def implicit_options
implicit = unused_options.map do |o|
if o.name =~ /^with-(.+)$/ && without?($1)
Option.new("without-#{$1}") # we loose the description, but that's ok
elsif o.name =~ /^without-(.+)$/ && with?($1)
Option.new("with-#{$1}")
end
end.compact
Options.new(implicit)
end
end

View File

@ -148,11 +148,18 @@ class FormulaAuditor
problem <<-EOS.undent unless dep.tags.any? || f.name =~ /automake/ && dep.name == 'autoconf'
#{dep} dependency should be "depends_on '#{dep}' => :build"
EOS
when "git", "python", "ruby", "emacs", "mysql", "mercurial"
when "git", "ruby", "emacs", "mysql", "mercurial"
problem <<-EOS.undent
Don't use #{dep} as a dependency. We allow non-Homebrew
#{dep} installations.
EOS
when 'python', 'python2', 'python3'
problem <<-EOS.undent
Don't use #{dep} as a dependency (string).
We have special `depends_on :python` (or :python2 or :python3 )
that works with brewed and system Python and allows us to support
bindings for 2.x and 3.x in parallel and much more.
EOS
when "postgresql"
# Postgis specifically requires a Homebrewed postgresql
unless f.name == "postgis"
@ -232,7 +239,7 @@ class FormulaAuditor
end
if p =~ %r[^http://prdownloads\.]
problem "Don't use prdownloads in SourceForge urls (url is #{p}).\n" +
problem "Don't use prdownloads in SourceForge urls (url is #{p}).\n" +
"\tSee: http://librelist.com/browser/homebrew/2011/1/12/prdownloads-is-bad/"
end
@ -249,7 +256,7 @@ class FormulaAuditor
# Check for http:// GitHub repo urls, https:// is preferred.
urls.grep(%r[^http://github\.com/.*\.git$]) do |u|
problem "Use https:// URLs for accessing GitHub repositories (url is #{u})."
end
end
# Use new-style archive downloads
urls.select { |u| u =~ %r[https://.*/(?:tar|zip)ball/] and not u =~ %r[\.git$] }.each do |u|
@ -427,6 +434,14 @@ class FormulaAuditor
problem "Reference '#{$1}' without dashes"
end
if text =~ /build\.with\?\s+['"]-?-?with-(.*)['"]/
problem "No double 'with': Use `build.with? '#{$1}'` to check for \"--with-#{$1}\""
end
if text =~ /build\.without\?\s+['"]-?-?without-(.*)['"]/
problem "No double 'without': Use `build.without? '#{$1}'` to check for \"--without-#{$1}\""
end
if text =~ /ARGV\.(?!(debug\?|verbose\?|find[\(\s]))/
problem "Use build instead of ARGV to check options"
end
@ -457,6 +472,52 @@ class FormulaAuditor
end
end
def audit_python
if text =~ /system\(?\s*['"]python/
# Todo: In `def test` it is okay to do it this way. It's even recommended!
problem "Instead of `system 'python', ...`, call `system python, ...`."
end
if text =~ /system\(?\s*python\.binary/
problem "Instead of `system python.binary, ...`, call `system python, ...`."
end
if text =~ /(def\s*)?which_python/
problem "Replace `which_python` by `python.xy`, which returns e.g. 'python2.7'."
end
if text =~ /which\(?["']python/
problem "Don't locate python with `which 'python'`, use `python.binary` instead"
end
if f.requirements.any?{ |r| r.kind_of?(PythonInstalled) }
# Don't check this for all formulae, because some are allowed to set the
# PYTHONPATH. E.g. python.rb itself needs to set it.
if text =~ /ENV\.append.*PYTHONPATH/ || text =~ /ENV\[['"]PYTHONPATH['"]\]\s*=[^=]/
problem "Don't set the PYTHONPATH, instead declare `depends_on :python`."
end
end
if text =~ /(\s*)def\s+caveats((.*\n)*?)(\1end)/ || /(\s*)def\s+caveats;(.*?)end/
caveats_body = $2
if caveats_body =~ /(python[23]?)\.(.*\w)/
# So if in the body of caveats there is a `python.whatever` called,
# check that there is a guard like `if python` or similiar:
python = $1
method = $2
unless caveats_body =~ /(if python[23]?)|(if build\.with\?\s?\(?['"]python)|(unless build.without\?\s?\(?['"]python)/
problem "Please guard `#{python}.#{method}` like so `#{python}.#{method} if #{python}`"
end
end
end
# Todo:
# The python do ... end block is possibly executed twice. Once for
# python 2.x and once for 3.x. So if a `system 'make'` is called, a
# `system 'make clean'` should also be called at the end of the block.
end
def audit
audit_file
audit_specs
@ -465,6 +526,7 @@ class FormulaAuditor
audit_conflicts
audit_patches
audit_text
audit_python
end
private

View File

@ -47,7 +47,7 @@ class Dependency
end
def missing_options
options - Tab.for_formula(to_formula).used_options
options - Tab.for_formula(to_formula).used_options - to_formula.build.implicit_options
end
def universal!

View File

@ -17,7 +17,7 @@ require 'set'
class DependencyCollector
# Define the languages that we can handle as external dependencies.
LANGUAGE_MODULES = Set[
:chicken, :jruby, :lua, :node, :ocaml, :perl, :python, :rbx, :ruby
:chicken, :jruby, :lua, :node, :ocaml, :perl, :python, :python2, :python3, :rbx, :ruby
].freeze
attr_reader :deps, :requirements
@ -92,6 +92,9 @@ class DependencyCollector
when :clt then CLTDependency.new(tags)
when :arch then ArchRequirement.new(tags)
when :hg then MercurialDependency.new(tags)
when :python then PythonInstalled.new(tags)
when :python2 then PythonInstalled.new("2", tags)
when :python3 then PythonInstalled.new("3", tags)
else
raise "Unsupported special dependency #{spec}"
end

View File

@ -548,6 +548,7 @@ class MercurialDownloadStrategy < AbstractDownloadStrategy
def cached_location; @clone; end
def hgpath
# #{HOMEBREW_PREFIX}/share/python/hg is deprecated, but we levae it in for a while
@path ||= %W[
#{which("hg")}
#{HOMEBREW_PREFIX}/bin/hg

View File

@ -305,6 +305,21 @@ class Formula
]
end
def python(options={:allowed_major_versions => [2, 3]}, &block)
require 'python_helper'
self.instance_eval{ python_helper(options, &block) }
end
# Explicitly only execute the block for 2.x (if a python 2.x is available)
def python2 &block
python(:allowed_major_versions => [2], &block)
end
# Explicitly only execute the block for 3.x (if a python 3.x is available)
def python3 &block
python(:allowed_major_versions => [3], &block)
end
def self.class_s name
# remove invalid characters and then camelcase it
name.capitalize.gsub(/[-_.\s]([a-zA-Z0-9])/) { $1.upcase } \
@ -558,7 +573,7 @@ class Formula
@exec_count ||= 0
@exec_count += 1
logd = HOMEBREW_LOGS/name
logfn = "#{logd}/%02d.%s" % [@exec_count, File.basename(cmd).split(' ').first]
logfn = "#{logd}/%02d.%s" % [@exec_count, File.basename(cmd.to_s).split(' ').first]
mkdir_p(logd)
rd, wr = IO.pipe
@ -567,7 +582,7 @@ class Formula
$stdout.reopen wr
$stderr.reopen wr
args.collect!{|arg| arg.to_s}
exec(cmd, *args) rescue nil
exec(cmd.to_s, *args) rescue nil
puts "Failed to execute: #{cmd}"
exit! 1 # never gets here unless exec threw or failed
end

View File

@ -210,15 +210,18 @@ class Keg < Pathname
def link_dir foo, mode=OpenStruct.new
root = self+foo
return unless root.exist?
root.find do |src|
next if src == root
dst = HOMEBREW_PREFIX+src.relative_path_from(self)
dst.extend ObserverPathnameExtension
if src.file?
Find.prune if File.basename(src) == '.DS_Store'
# Don't link pyc files because Python overwrites these cached object
# files and next time brew wants to link, the pyc file is in the way.
if src.extname.to_s == '.pyc' && src.to_s =~ /site-packages/
Find.prune
end
case yield src.relative_path_from(root)
when :skip_file, nil
@ -233,7 +236,6 @@ class Keg < Pathname
elsif src.directory?
# if the dst dir already exists, then great! walk the rest of the tree tho
next if dst.directory? and not dst.symlink?
# no need to put .app bundles in the path, the user can just use
# spotlight, or the open command and actual mac apps use an equivalent
Find.prune if src.extname.to_s == '.app'

View File

@ -0,0 +1,80 @@
# The python_helper is used in the Formula class when the user calls
# `python`, `python2` or `python3`.
# This method has a dual nature. For one, it takes a &block and sets up
# the ENV such that a Python, as defined in the requirements, is the default.
# If there are multiple `PythonInstalled` requirements, the block is evaluated
# once for each Python. This makes it possible to easily support 2.x and
# 3.x Python bindings without code duplication in formulae.
# If you need to special case stuff, set :allowed_major_versions.
# Second, inside the block, a formula author may call this method to access
# certain convienience methods for the currently selected Python, e.g.
# `python.site_packages`.
def python_helper(options={:allowed_major_versions => [2, 3]}, &block)
if !block_given? and !@current_python.nil?
# We are already inside of a `python do ... end` block, so just return
# the current_python or false if the version.major is not allowed.
if options[:allowed_major_versions].include?(@current_python.version.major)
@current_python
else
false
end
else
# Look for PythonInstalled requirements for this formula
python_reqs = requirements.select{ |r| r.kind_of?(PythonInstalled) }
if python_reqs.empty?
raise "If you use python in the formula, you have to add `depends_on :python` (or :python3)!"
end
# Now select those that are satisfied and matching the version.major
python_reqs = python_reqs.select do |p|
p.satisfied? &&
options[:allowed_major_versions].include?(p.version.major) &&
if p.optional? || p.recommended?
self.build.with?(p.name)
else
true
end
end
# Allow to use an else-branch like so: `if python do ... end; else ... end`
return false if python_reqs.empty?
# Sort by version, so the older 2.x will be used first and if no
# block_given? then 2.x is preferred because it is returned.
# Further note, having 3.x last allows us to run `2to3 --write .`
# which modifies the sources in-place (for some packages that need this).
python_reqs.sort_by{ |py| py.version }.map do |py|
# Now is the time to set the site_packages to the correct value
py.site_packages = lib/py.xy/'site-packages'
if block_given?
puts "brew: Python block (#{py.binary})..." if ARGV.verbose?
require 'superenv'
# Ensure env changes are only temporary by using `with_build_environment`
ENV.with_build_environment do
# In order to install into the Cellar, the dir must exist and be in the
# PYTHONPATH. This will be executed in the context of the formula
# so that lib points to the HOMEBREW_PREFIX/Cellar/<formula>/<version>/lib
puts "brew: Setting PYTHONPATH=#{py.site_packages}" if ARGV.verbose?
mkdir_p py.site_packages
ENV.append 'PYTHONPATH', py.site_packages, ':'
ENV['PYTHON'] = py.binary
ENV.prepend 'CMAKE_INCLUDE_PATH', py.incdir, ':'
ENV.prepend 'PKG_CONFIG_PATH', py.pkg_config_path, ':' if py.pkg_config_path
ENV.prepend 'PATH', py.binary.dirname, ':' unless py.from_osx?
# Track the state of the currently selected python for this block,
# so if this python_helper is called again _inside_ the block, we can
# just return the right python (see `else`-branch a few lines down):
@current_python = py
res = instance_eval(&block)
@current_python = nil
res
end
else
puts "brew: Using #{py.binary}" if ARGV.verbose?
# We return here with intention, because no block_given?
return py
end
end
end
end

View File

@ -3,6 +3,7 @@ require 'requirements/conflict_requirement'
require 'requirements/language_module_dependency'
require 'requirements/x11_dependency'
require 'requirements/mpi_dependency'
require 'requirements/python_dependency'
class XcodeDependency < Requirement
fatal true

View File

@ -27,7 +27,8 @@ class LanguageModuleDependency < Requirement
when :node then %W{/usr/bin/env node -e require('#{@import_name}');}
when :ocaml then %W{/usr/bin/env opam list #{@import_name} | grep #{@import_name}}
when :perl then %W{/usr/bin/env perl -e use\ #{@import_name}}
when :python then %W{/usr/bin/env python -c import\ #{@import_name}}
when :python then %W{/usr/bin/env python2 -c import\ #{@import_name}}
when :python3 then %W{/usr/bin/env python3 -c import\ #{@import_name}}
when :ruby then %W{/usr/bin/env ruby -rubygems -e require\ '#{@import_name}'}
when :rbx then %W{/usr/bin/env rbx -rubygems -e require\ '#{@import_name}'}
end
@ -42,6 +43,7 @@ class LanguageModuleDependency < Requirement
when :ocaml then "opam install"
when :perl then "cpan -i"
when :python then "pip install"
when :python3 then "pip3 install"
when :rbx then "rbx gem install"
when :ruby then "gem install"
end

View File

@ -0,0 +1,296 @@
require 'requirement'
# We support Python 2.x and 3.x, either brewed or external.
# This requirement locates the correct CPython binary (no PyPy), provides
# support methods like `site_packages`, and writes our sitecustomize.py file.
# In `dependency_collector.rb`, special `:python` and `:python3` shortcuts are
# defined. You can specify a minimum version of the Python that needs to be
# present, but since not every package is ported to 3.x yet,
# `PythonInstalled("2")` is not satisfied by 3.x.
# In a formula that shall provide support for 2.x and 3.x, the idiom is:
# depends_on :python
# depends_on :python3 => :optional # or :recommended
#
# Todo:
# - Allow further options that choose: universal, framework?, brewed?...
class PythonInstalled < Requirement
attr_reader :min_version
attr_reader :if3then3
attr_reader :site_packages
attr_accessor :site_packages
fatal true # you can still make Python optional by `depends_on :python => :optional`
class PythonVersion < Version
def major
to_a[0].to_s.to_i # Python's major.minor are always ints.
end
def minor
to_a[1].to_s.to_i
end
end
def initialize(*tags)
# Extract the min_version if given. Default to python 2.X else
tags.flatten!
if /(\d+\.)*\d+/ === tags.first
@min_version = PythonVersion.new(tags.shift)
else
@min_version = PythonVersion.new("2.7") # default
end
# often used idiom: e.g. sipdir = "share/sip" + python.if3then3
if @min_version.major == 3
@if3then3 = "3"
else
@if3then3 = ""
end
# Set name according to the major version.
# The name is used to generate the options like --without-python3
@name = "python" + @if3then3
# will be set later by the python_helper, because it needs the
# formula prefix to set site_packages
@site_packages = nil
super tags
end
# Note that during `satisfy` we still have the PATH as the user has set.
# We look for a brewed python or an external Python and store the loc of
# that binary for later usage. (See Formula#python)
satisfy :build_env => false do
@unsatisfied_because = "This formula needs #{@name}.\n"
if binary.nil?
@unsatisfied_because += "But no `#{@name}` found in your PATH! Consider to `brew install #{@name}`."
false
elsif pypy?
@unsatisfied_because += "Your #{@name} executable appears to be a PyPy, which is not supported."
false
elsif version.major != @min_version.major
@unsatisfied_because += "No Python #{@min_version.major}.x found!"
false
elsif version < @min_version
@unsatisfied_because += "Python version #{version} is too old (need at least #{@min_version})."
false
elsif @min_version.major == 2 && `python -c "import sys; print(sys.version_info.major)"`.strip == "3"
@unsatisfied_because += "Your `python` points to a Python 3.x. This is not supported."
false
else
true
end
end
# The full path to the python or python3 executable, depending on `version`.
def binary
if brewed?
# If the python is brewed we always prefer it!
# Note, we don't support homebrew/versions/pythonXX.rb, though.
Formula.factory(@name).opt_prefix/"bin/python#{@min_version.major}"
else
p = which(@name)
raise "PythonInstalled: #{p} is not executable" if !p.nil? && !p.executable?
p
end
end
# The python prefix (special cased for a brewed python to point into the opt_prefix)
def prefix
if brewed?
# Homebrew since a long while only supports frameworked python
HOMEBREW_PREFIX/"opt/#{name}/Frameworks/Python.framework/Versions/#{version.major}.#{version.minor}"
elsif from_osx?
# Python on OS X has been stripped off its includes (unless you install the CLT), therefore we use the MacOS.sdk.
Pathname.new("#{MacOS.sdk_path}/System/Library/Frameworks/Python.framework/Versions/#{version.major}.#{version.minor}")
else
# What Python knows about itself
Pathname.new(`#{binary} -c 'import sys;print(sys.prefix)'`.strip)
end
end
# Get the actual x.y.z version by asking python (or python3 if @min_version>=3)
def version
@version ||= PythonVersion.new(`#{binary} -c 'import sys;print(sys.version[:5])'`.strip)
end
# python.xy => "python2.7" is often used (and many formulae had this as `which_python`).
def xy
"python#{version.major}.#{version.minor}"
end
# Homebrew's global site-packages. The local ones are populated by the
# python_helper method when the `prefix` of a formula is known.
def global_site_packages
HOMEBREW_PREFIX/"lib/#{xy}/site-packages"
end
# Dir containing Python.h and others.
def incdir
if (from_osx? || brewed?) && framework?
prefix/"Headers"
else
# For all other we use Python's own standard method (works with a non-framework version, too)
Pathname.new(`#{binary} -c 'from distutils import sysconfig; print(sysconfig.get_python_inc())'`.strip)
end
end
# Dir containing e.g. libpython2.7.dylib
def libdir
if brewed? || from_osx?
prefix/"lib/#{xy}/config"
else
Pathname.new(`#{binary} -c "from distutils import sysconfig; print(sysconfig.get_config_var('LIBPL'))"`.strip)
end
end
# Pkgconfig (pc) files of python
def pkg_config_path
if from_osx?
# No matter if CLT-only or Xcode-only, the pc file is always here on OS X:
path = Pathname.new("/System/Library/Frameworks/Python.framework/Versions/#{version.major}.#{version.minor}/lib/pkgconfig")
path if path.exist?
else
prefix/"lib/pkgconfig"
end
end
# Is the Python brewed (and linked)?
def brewed?
@brewed ||= begin
require 'formula'
f = Formula.factory(@name)
f.installed? && f.linked_keg.exist?
end
end
# Is the python the one from OS X?
def from_osx?
@from_osx ||= begin
p = `#{binary} -c "import sys; print(sys.prefix)"`.strip
p.start_with?("/System/Library/Frameworks/Python.framework")
end
end
# Is the `python` a PyPy?
def pypy?
@pypy ||= !(`#{binary} -c "import sys; print(sys.version)"`.downcase =~ /.*pypy.*/).nil?
end
# Is this python a framework-style install (OS X only)?
def framework?
@framework ||= /Python[0-9]*\.framework/ === prefix.to_s
end
def universal?
@universal ||= archs_for_command(binary).universal?
end
def standard_caveats
if brewed?
"" # empty string, so we can concat this
else
<<-EOS.undent
For non-homebrew #{@name} (#{@min_version.major}.x), you need to amend your PYTHONPATH like so:
export PYTHONPATH=#{global_site_packages}:$PYTHONPATH
EOS
end
end
def modify_build_environment
# Write our sitecustomize.py
file = global_site_packages/"sitecustomize.py"
ohai "Writing #{file}" if ARGV.verbose? || ARGV.homebrew_developer?
[".pyc", ".pyo", ".py"].map{ |f|
global_site_packages/"sitecustomize#{f}"
}.each{ |f| f.delete if f.exist? }
file.write(sitecustomize)
# For non-system python's we add the opt_prefix/bin of python to the path.
ENV.prepend 'PATH', binary.dirname, ':' unless from_osx?
ENV['PYTHONHOME'] = nil # to avoid fuck-ups.
ENV['PYTHONNOUSERSITE'] = '1'
# Python respects the ARCHFLAGS var if set. Shall we set them here?
# ENV['ARCHFLAGS'] = ??? # FIXME
ENV.append 'CMAKE_INCLUDE_PATH', incdir, ':'
ENV.append 'PKG_CONFIG_PATH', pkg_config_path, ':' if pkg_config_path
# Udpate distutils.cfg (later we can remove this, but people still have
# their old brewed pythons and we have to update it here)
# Todo: If Jack's formula revisions arrive, we can get rid of this here!
if brewed?
require 'formula'
file = Formula.factory(@name).prefix/"Frameworks/Python.framework/Versions/#{version.major}.#{version.minor}/lib/#{xy}/distutils/distutils.cfg"
ohai "Writing #{file}" if ARGV.verbose? || ARGV.homebrew_developer?
file.delete if file.exist?
file.write <<-EOF.undent
[global]
verbose=1
[install]
force=1
prefix=#{HOMEBREW_PREFIX}
EOF
end
end
def sitecustomize
<<-EOF.undent
# This file is created by Homebrew and is executed on each python startup.
# Don't print from here, or else universe will collapse.
import sys
if sys.version_info.major == #{version.major} and sys.version_info.minor == #{version.minor}:
if sys.executable.startswith('#{HOMEBREW_PREFIX}'):
# Fix 1)
# A setuptools.pth and/or easy-install.pth sitting either in
# /Library/Python/2.7/site-packages or in
# ~/Library/Python/2.7/site-packages can inject the
# /System's Python site-packages. People then report
# "OSError: [Errno 13] Permission denied" because pip/easy_install
# attempts to install into
# /System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python
# See: https://github.com/mxcl/homebrew/issues/14712
# Fix 2)
# Remove brewed Python's hard-coded Cellar-site-packages
sys.path = [ p for p in sys.path
if not (p.startswith('/System') or
p.startswith('#{HOMEBREW_PREFIX}/Cellar/python') and p.endswith('site-packages')) ]
# Fix 3)
# Set the sys.executable to use the opt_prefix
sys.executable = '#{HOMEBREW_PREFIX}/opt/#{name}/bin/python#{version.major}.#{version.minor}'
# Fix 4)
# Make LINKFORSHARED (and python-confing --ldflags) return the
# full path to the lib (yes, "Python" is actually the lib, not a
# dir) so that third-party software does not need to add the
# -F/#{HOMEBREW_PREFIX}/Frameworks switch.
# Assume Framework style build (default since months in brew)
try:
from _sysconfigdata import build_time_vars
build_time_vars['LINKFORSHARED'] = '-u _PyMac_Error #{HOMEBREW_PREFIX}/opt/#{name}/Frameworks/Python.framework/Versions/#{version.major}.#{version.minor}/Python'
except:
pass # remember: don't print here. Better to fail silent.
# Fix 5)
# For all Pythons of the right major.minor version: Tell about homebrew's
# site-packages location. This is needed for Python to parse *.pth.
import site
site.addsitedir('#{global_site_packages}')
EOF
end
def message
@unsatisfied_because
end
def <=> other
version <=> other.version
end
def to_s
binary.to_s
end
def hash
to_s.hash
end
end

View File

@ -30,7 +30,7 @@ class << ENV
alias_method :x11?, :x11
def reset
%w{CC CXX OBJC OBJCXX CPP MAKE LD
%w{CC CXX OBJC OBJCXX CPP MAKE LD LDSHARED
CFLAGS CXXFLAGS OBJCFLAGS OBJCXXFLAGS LDFLAGS CPPFLAGS
MACOS_DEPLOYMENT_TARGET SDKROOT
CMAKE_PREFIX_PATH CMAKE_INCLUDE_PATH CMAKE_FRAMEWORK_PATH
@ -57,7 +57,7 @@ class << ENV
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_FRAMEWORK_PATH'] = determine_cmake_frameworks_path
ENV['CMAKE_INCLUDE_PATH'] = determine_cmake_include_path
ENV['CMAKE_LIBRARY_PATH'] = determine_cmake_library_path
ENV['ACLOCAL_PATH'] = determine_aclocal_path
@ -133,7 +133,6 @@ class << ENV
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
@ -158,6 +157,14 @@ class << ENV
paths.to_path_s
end
def determine_cmake_frameworks_path
# XXX: keg_only_deps perhaps? but Qt does not link its Frameworks because of Ruby's Find.find ignoring symlinks!!
paths = deps.map{|dep| "#{HOMEBREW_PREFIX}/opt/#{dep}/Frameworks" }
paths << "#{HOMEBREW_PREFIX}/Frameworks"
paths << "#{MacOS.sdk_path}/System/Library/Frameworks" 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 = []
@ -165,11 +172,6 @@ class << ENV
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?
@ -227,11 +229,6 @@ class << ENV
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

View File

@ -42,4 +42,15 @@ class BuildOptionsTests < Test::Unit::TestCase
def test_unused_options
assert @build.unused_options.include?("--without-baz")
end
def test_implicit_options
# --without-baz is not explicitly specified on the command line
# therefore --with-baz should be implicitly assumed:
assert @build.implicit_options.include?("--with-baz")
# But all these should not be in the implict_options:
assert !@build.implicit_options.include?("--without-baz")
assert !@build.implicit_options.include?("--with-bar")
assert !@build.implicit_options.include?("--without-bar")
assert !@build.implicit_options.include?("--with-qux")
end
end

View File

@ -0,0 +1 @@
#TODO!

View File

@ -97,7 +97,7 @@ module Homebrew
fork do
yield if block_given?
args.collect!{|arg| arg.to_s}
exec(cmd, *args) rescue nil
exec(cmd.to_s, *args) rescue nil
exit! 1 # never gets here unless exec failed
end
Process.wait