Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

FormulaInstaller: allow formulae to pass options to deps

Formulae can now pass build options to dependencies. The following
syntax is supported:

  depends_on 'foo' => 'with-bar'
  depends_on 'foo' => ['with-bar', 'with-baz']

If a dependency is already installed but lacks the required build
options, an exception is raised. Eventually we may be able to just stash
the existing keg and reinstall it with the combined set of used_options
and passed options, but enabling that is left for another day.
  • Loading branch information...
commit 64a4c0ff42b5784aa73daf8d08118c90fe15b6b2 1 parent 05542a3
Jack Nagel authored
2  Library/Homebrew/build_options.rb
View
@@ -3,7 +3,7 @@
# This class holds the build-time options defined for a Formula,
# and provides named access to those options during install.
class BuildOptions
- attr_writer :args
+ attr_accessor :args
include Enumerable
def initialize args
15 Library/Homebrew/dependencies.rb
View
@@ -138,7 +138,7 @@ def recommended?
end
def options
- tags.reject { |tag| RESERVED_TAGS.include? tag }.map { |tag| '--'+tag.to_s }
+ Options.new((tags - RESERVED_TAGS).map { |o| Option.new(o) })
end
end
@@ -171,13 +171,24 @@ def hash
end
def to_formula
- Formula.factory(name)
+ f = Formula.factory(name)
+ # Add this dependency's options to the formula's build args
+ f.build.args = f.build.args.concat(options)
+ f
+ end
+
+ def installed?
+ to_formula.installed?
end
def requested?
ARGV.formulae.include?(to_formula) rescue false
end
+ def universal!
+ tags << 'universal' if to_formula.build.has_option? 'universal'
+ end
+
# Expand the dependencies of f recursively, optionally yielding
# [f, dep] to allow callers to apply arbitrary filters to the list.
# The default filter, which is used when a block is not supplied,
47 Library/Homebrew/formula_installer.rb
View
@@ -8,6 +8,7 @@
class FormulaInstaller
attr :f
attr :tab, true
+ attr :options, true
attr :show_summary_heading, true
attr :ignore_deps, true
attr :show_header, true
@@ -116,20 +117,6 @@ def check_requirements
end
end
- def dep_needed? dep
- dep_f = dep.to_formula
- if dep_f.installed?
- # If the dep is already installed, skip it.
- false
- elsif install_bottle and dep.build?
- # We skip build-time deps when installing bottles.
- false
- else
- # Otherwise, we need to install it.
- true
- end
- end
-
def effective_deps
@deps ||= begin
deps = Set.new
@@ -138,15 +125,34 @@ def effective_deps
# any influential flags (--HEAD, --devel, etc.) the user has passed
# when we check the installed status.
requested_deps = f.recursive_dependencies.select do |dep|
- dep_f = dep.to_formula
- dep_f.requested? and not dep_f.installed?
+ dep.requested? && !dep.installed?
end
# Otherwise, we filter these influential flags so that they do not
# affect installation prefixes and other properties when we decide
# whether or not the dep is needed.
necessary_deps = ARGV.filter_for_dependencies do
- f.recursive_dependencies.select { |d| dep_needed? d }
+ f.recursive_dependencies do |dependent, dep|
+ if dep.optional? || dep.recommended?
+ Dependency.prune unless dependent.build.with?(dep.name)
+ elsif dep.build?
+ Dependency.prune if pour_bottle?
+ end
+
+ dep.universal! if f.build.universal?
+
+ dep_f = dep.to_formula
+ dep_tab = Tab.for_formula(dep)
+ missing = dep.options - dep_tab.used_options
+
+ if dep.installed?
+ if missing.empty?
+ Dependency.prune
+ else
+ raise "#{f} dependency #{dep} not installed with:\n #{missing*', '}"
+ end
+ end
+ end
end
deps.merge(requested_deps)
@@ -171,12 +177,14 @@ def install_dependencies
def install_dependency dep
dep_tab = Tab.for_formula(dep)
+ dep_options = dep.options
dep = dep.to_formula
outdated_keg = Keg.new(dep.linked_keg.realpath) rescue nil
fi = FormulaInstaller.new(dep)
fi.tab = dep_tab
+ fi.options = dep_options
fi.ignore_deps = true
fi.show_header = false
oh1 "Installing #{f} dependency: #{Tty.green}#{dep}#{Tty.reset}"
@@ -258,7 +266,10 @@ def build
# FIXME: enforce the download of the non-bottled package
# in the spawned Ruby process.
args << '--build-from-source'
- args.uniq! # Just in case some dupes were added
+ # Add any options that were passed into this FormulaInstaller instance.
+ # Usually this represents options being passed by a dependent formula.
+ args.concat options
+ args.uniq!
fork do
begin
3  Library/Homebrew/test/test_dependency.rb
View
@@ -1,5 +1,6 @@
require 'testing_env'
require 'dependencies'
+require 'options'
class DependableTests < Test::Unit::TestCase
def setup
@@ -8,7 +9,7 @@ def setup
end
def test_options
- assert_equal %w{--foo --bar}.sort, @dep.options.sort
+ assert_equal %w{--foo --bar}.sort, @dep.options.as_flags.sort
end
def test_interrogation
1  Library/Homebrew/test/test_dependency_collector.rb
View
@@ -1,5 +1,6 @@
require 'testing_env'
require 'dependencies'
+require 'options'
require 'extend/set'
module DependencyCollectorTestExtension
Please sign in to comment.
Something went wrong with that request. Please try again.