diff --git a/Library/Homebrew/build.rb b/Library/Homebrew/build.rb index e59b5be6aa..96245f0223 100755 --- a/Library/Homebrew/build.rb +++ b/Library/Homebrew/build.rb @@ -59,8 +59,10 @@ class Build def initialize(f) @f = f + # Expand requirements before dependencies, as requirements + # may add dependencies if a default formula is activated. + @reqs = expand_reqs @deps = expand_deps - @reqs = f.recursive_requirements end def post_superenv_hacks @@ -77,6 +79,19 @@ class Build not ARGV.include? '--env=super' end + def expand_reqs + f.recursive_requirements do |dependent, req| + if (req.optional? || req.recommended?) && dependent.build.without?(req.name) + Requirement.prune + elsif req.build? && dependent != f + Requirement.prune + elsif req.satisfied? && req.default_formula? && (dep = req.to_dependency).installed? + dependent.deps << dep + Requirement.prune + end + end + end + def expand_deps f.recursive_dependencies do |dependent, dep| if dep.optional? || dep.recommended? @@ -84,18 +99,18 @@ class Build elsif dep.build? Dependency.prune unless dependent == f end - end.map(&:to_formula) + end end def install - keg_only_deps = deps.select(&:keg_only?) + keg_only_deps = deps.map(&:to_formula).select(&:keg_only?) pre_superenv_hacks require 'superenv' deps.each do |dep| opt = HOMEBREW_PREFIX/:opt/dep - fixopt(dep) unless opt.directory? or ARGV.ignore_deps? + fixopt(dep.to_formula) unless opt.directory? or ARGV.ignore_deps? end if superenv? @@ -105,9 +120,11 @@ class Build ENV.setup_build_environment post_superenv_hacks reqs.each(&:modify_build_environment) + deps.each(&:modify_build_environment) else ENV.setup_build_environment reqs.each(&:modify_build_environment) + deps.each(&:modify_build_environment) keg_only_deps.each do |dep| opt = dep.opt_prefix diff --git a/Library/Homebrew/dependency.rb b/Library/Homebrew/dependency.rb index a6905bc37e..91def84422 100644 --- a/Library/Homebrew/dependency.rb +++ b/Library/Homebrew/dependency.rb @@ -5,6 +5,7 @@ class Dependency include Dependable attr_reader :name, :tags + attr_accessor :env_proc def initialize(name, tags=[]) @name = name @@ -54,6 +55,10 @@ class Dependency tags << 'universal' if to_formula.build.has_option? 'universal' end + def modify_build_environment + env_proc.call unless env_proc.nil? + end + class << self # Expand the dependencies of dependent recursively, optionally yielding # [dependent, dep] pairs to allow callers to apply arbitrary filters to diff --git a/Library/Homebrew/formula_installer.rb b/Library/Homebrew/formula_installer.rb index fa7578c4f5..3c6dd46068 100644 --- a/Library/Homebrew/formula_installer.rb +++ b/Library/Homebrew/formula_installer.rb @@ -120,13 +120,16 @@ class FormulaInstaller def check_requirements unsatisfied = ARGV.filter_for_dependencies do f.recursive_requirements do |dependent, req| - if req.optional? || req.recommended? - Requirement.prune unless dependent.build.with?(req.name) - elsif req.build? - Requirement.prune if install_bottle?(dependent) + if (req.optional? || req.recommended?) && dependent.build.without?(req.name) + Requirement.prune + elsif req.build? && install_bottle?(dependent) + Requirement.prune + elsif req.satisfied? + Requirement.prune + elsif req.default_formula? + dependent.deps << req.to_dependency + Requirement.prune end - - Requirement.prune if req.satisfied? end end diff --git a/Library/Homebrew/requirement.rb b/Library/Homebrew/requirement.rb index a5e9367422..dcacf45e0b 100644 --- a/Library/Homebrew/requirement.rb +++ b/Library/Homebrew/requirement.rb @@ -1,4 +1,5 @@ require 'dependable' +require 'dependency' require 'build_environment' # A base class for non-formula requirements needed by formulae. @@ -36,6 +37,10 @@ class Requirement self.class.fatal || false end + def default_formula? + self.class.default_formula || false + end + # Overriding #modify_build_environment is deprecated. # Pass a block to the the env DSL method instead. def modify_build_environment @@ -54,6 +59,14 @@ class Requirement [name, *tags].hash end + def to_dependency + f = self.class.default_formula + raise "No default formula defined for #{inspect}" if f.nil? + dep = Dependency.new(f, tags) + dep.env_proc = method(:modify_build_environment) + dep + end + private def infer_name @@ -136,11 +149,6 @@ class Requirement requirements.each do |req| if prune?(dependent, req, &block) next - # TODO: Do this in a cleaner way, perhaps with another type of - # dependency type. - elsif req.class.default_formula - dependent.class.depends_on(req.class.default_formula) - next else reqs << req end diff --git a/Library/Homebrew/test/test_requirement.rb b/Library/Homebrew/test/test_requirement.rb index ccf137e4d2..5d89defb05 100644 --- a/Library/Homebrew/test/test_requirement.rb +++ b/Library/Homebrew/test/test_requirement.rb @@ -96,4 +96,28 @@ class RequirementTests < Test::Unit::TestCase ensure klass.send(:remove_const, const) if klass.const_defined?(const) end + + def test_dsl_default_formula + req = Class.new(Requirement) { default_formula 'foo' }.new + assert req.default_formula? + end + + def test_to_dependency + req = Class.new(Requirement) { default_formula 'foo' }.new + assert_equal Dependency.new('foo'), req.to_dependency + end + + def test_to_dependency_calls_requirement_modify_build_environment + error = Class.new(StandardError) + + req = Class.new(Requirement) do + default_formula 'foo' + satisfy { true } + env { raise error } + end.new + + assert_raises(error) do + req.to_dependency.modify_build_environment + end + end end