Create active symlinks for installed formula

Similar to the LinkedKegs record, we write a symlink for installed kegs to PREFIX/opt.

Unlike the linked-keg record, unlinking doesn't remove the link, only uninstalling, and keg-only formula have a record too.

The reason for this addition is so that formula that depend on keg-only formula can build against the opt directory and not the cellar keg. Thus surviving upgrades.

To enforce this fix_install_names and built were adapted to use the opt path.

Standard kegs also create an opt symlink so that caveats can now refer to the opt directory and thus provide steps that survive upgrades too.

Thus the choice of /opt. It is short, neat and the right choice: POSIX dictates that opt is for stand-alone prefixes of software.
This commit is contained in:
Max Howell 2012-08-10 16:33:22 -04:00
parent 50767c6077
commit f02d81ecbf
6 changed files with 56 additions and 10 deletions

View File

@ -61,14 +61,18 @@ def install f
f.recursive_deps.uniq.each do |dep| f.recursive_deps.uniq.each do |dep|
dep = Formula.factory dep dep = Formula.factory dep
if dep.keg_only? if dep.keg_only?
ENV.prepend 'LDFLAGS', "-L#{dep.lib}" opt = HOMEBREW_PREFIX/:opt/dep.name
ENV.prepend 'CPPFLAGS', "-I#{dep.include}"
ENV.prepend 'PATH', "#{dep.bin}", ':'
pcdir = dep.lib/'pkgconfig' raise "#{opt} not present\nReinstall #{dep}." unless opt.directory?
ENV.prepend 'LDFLAGS', "-L#{opt}/lib"
ENV.prepend 'CPPFLAGS', "-I#{opt}/include"
ENV.prepend 'PATH', "#{opt}/bin", ':'
pcdir = opt/'lib/pkgconfig'
ENV.prepend 'PKG_CONFIG_PATH', pcdir, ':' if pcdir.directory? ENV.prepend 'PKG_CONFIG_PATH', pcdir, ':' if pcdir.directory?
acdir = dep.share/'aclocal' acdir = opt/'share/aclocal'
ENV.prepend 'ACLOCAL_PATH', acdir, ':' if acdir.directory? ENV.prepend 'ACLOCAL_PATH', acdir, ':' if acdir.directory?
end end
end end

View File

@ -10,6 +10,7 @@ module Homebrew extend self
puts "Uninstalling #{keg}..." puts "Uninstalling #{keg}..."
keg.unlink keg.unlink
keg.uninstall keg.uninstall
rm_opt_link keg.fname
end end
else else
ARGV.named.each do |name| ARGV.named.each do |name|
@ -30,10 +31,18 @@ module Homebrew extend self
end end
rack.rmtree rack.rmtree
end end
rm_opt_link name
end end
end end
rescue MultipleVersionsInstalledError => e rescue MultipleVersionsInstalledError => e
ofail e ofail e
puts "Use `brew remove --force #{e.name}` to remove all versions." puts "Use `brew remove --force #{e.name}` to remove all versions."
end end
def rm_opt_link name
optlink = HOMEBREW_PREFIX/:opt/name
optlink.unlink if optlink.symlink?
end
end end

View File

@ -148,6 +148,8 @@ class Formula
self.class.build self.class.build
end end
def opt_prefix; HOMEBREW_PREFIX/:opt/name end
# Use the @active_spec to detect the download strategy. # Use the @active_spec to detect the download strategy.
# Can be overriden to force a custom download strategy # Can be overriden to force a custom download strategy
def download_strategy def download_strategy

View File

@ -172,10 +172,18 @@ class FormulaInstaller
def finish def finish
ohai 'Finishing up' if ARGV.verbose? ohai 'Finishing up' if ARGV.verbose?
unless f.keg_only? if f.keg_only?
begin
Keg.new(f.prefix).optlink
rescue Exception => e
onoe "Failed to create: #{f.opt_prefix}"
puts "Things that depend on #{f} will probably not build."
end
else
link link
check_PATH check_PATH unless f.keg_only?
end end
fix_install_names fix_install_names
ohai "Summary" if ARGV.verbose? or show_summary_heading ohai "Summary" if ARGV.verbose? or show_summary_heading

View File

@ -42,7 +42,7 @@ class Keg < Pathname
Find.prune if src.directory? Find.prune if src.directory?
end end
end end
linked_keg_record.unlink if linked_keg_record.exist? linked_keg_record.unlink if linked_keg_record.symlink?
n n
end end
@ -126,7 +126,25 @@ class Keg < Pathname
linked_keg_record.make_relative_symlink(self) unless mode == :dryrun linked_keg_record.make_relative_symlink(self) unless mode == :dryrun
optlink unless mode == :dryrun
return $n + $d return $n + $d
rescue Exception
opoo "Could not link #{fname}. Unlinking..."
unlink
raise
end
def optlink
from = HOMEBREW_PREFIX/:opt/fname
if from.symlink?
from.delete
elsif from.directory?
from.rmdir
elsif from.exist?
from.delete
end
from.make_relative_symlink(self)
end end
protected protected

View File

@ -56,8 +56,13 @@ class Keg
end end
# the shortpath ensures that library upgrades dont break installed tools # the shortpath ensures that library upgrades dont break installed tools
shortpath = HOMEBREW_PREFIX + Pathname.new(file).relative_path_from(self) relative_path = Pathname.new(file).relative_path_from(self)
id = if shortpath.exist? then shortpath else file end shortpath = HOMEBREW_PREFIX.join(relative_path)
id = if shortpath.exist?
shortpath
else
"#{HOMEBREW_PREFIX}/opt/#{fname}/#{relative_path}"
end
yield id, install_names yield id, install_names
end end