aboutsummaryrefslogtreecommitdiffstats
path: root/Library/Homebrew/cmd/doctor.rb
diff options
context:
space:
mode:
Diffstat (limited to 'Library/Homebrew/cmd/doctor.rb')
-rw-r--r--Library/Homebrew/cmd/doctor.rb633
1 files changed, 633 insertions, 0 deletions
diff --git a/Library/Homebrew/cmd/doctor.rb b/Library/Homebrew/cmd/doctor.rb
new file mode 100644
index 000000000..bad3a5dc0
--- /dev/null
+++ b/Library/Homebrew/cmd/doctor.rb
@@ -0,0 +1,633 @@
+class Volumes
+ def initialize
+ @volumes = []
+ raw_mounts=`mount`
+ raw_mounts.split("\n").each do |line|
+ case line
+ when /^(.+) on (\S+) \(/
+ @volumes << [$1, $2]
+ end
+ end
+ # Sort volumes by longest path prefix first
+ @volumes.sort! {|a,b| b[1].length <=> a[1].length}
+ end
+
+ def which path
+ @volumes.each_index do |i|
+ vol = @volumes[i]
+ return i if is_prefix?(vol[1], path)
+ end
+
+ return -1
+ end
+end
+
+
+def is_prefix? prefix, longer_string
+ p = prefix.to_s
+ longer_string.to_s[0,p.length] == p
+end
+
+# Installing MacGPG2 interferes with Homebrew in a big way
+# http://sourceforge.net/projects/macgpg2/files/
+def check_for_macgpg2
+ if File.exist? "/Applications/start-gpg-agent.app" or
+ File.exist? "/Library/Receipts/libiconv1.pkg"
+ puts <<-EOS.undent
+ If you have installed MacGPG2 via the package installer, several other
+ checks in this script will turn up problems, such as stray .dylibs in
+ /usr/local and permissions issues with share and man in /usr/local/.
+
+ EOS
+ end
+end
+
+def check_for_stray_dylibs
+ unbrewed_dylibs = Dir['/usr/local/lib/*.dylib'].select { |f| File.file? f and not File.symlink? f }
+
+ # Dylibs which are generally OK should be added to this list,
+ # with a short description of the software they come with.
+ white_list = {
+ "libfuse.2.dylib" => "MacFuse",
+ "libfuse_ino64.2.dylib" => "MacFuse"
+ }
+
+ bad_dylibs = unbrewed_dylibs.reject {|d| white_list.key? File.basename(d) }
+ return if bad_dylibs.empty?
+
+ opoo "Unbrewed dylibs were found in /usr/local/lib"
+ puts <<-EOS.undent
+ You have unbrewed dylibs in /usr/local/lib. If you didn't put them there on purpose,
+ they could cause problems when building Homebrew formulae.
+
+ Unexpected dylibs (delete if they are no longer needed):
+ EOS
+ puts *bad_dylibs.collect { |f| " #{f}" }
+ puts
+end
+
+def check_for_x11
+ unless x11_installed?
+ opoo "X11 not installed."
+ puts <<-EOS.undent
+ You don't have X11 installed as part of your Xcode installation.
+ This isn't required for all formulae, but is expected by some.
+
+ EOS
+ end
+end
+
+def check_for_nonstandard_x11
+ return unless File.exists? '/usr/X11'
+ x11 = Pathname.new('/usr/X11')
+ if x11.symlink?
+ puts <<-EOS.undent
+ "/usr/X11" was found, but it is a symlink to:
+ #{x11.resolved_path}
+
+ Homebrew's X11 support has only be tested with Apple's X11.
+ In particular, "XQuartz" and "XDarwin" are not known to be compatible.
+
+ EOS
+ end
+end
+
+def check_for_other_package_managers
+ if macports_or_fink_installed?
+ puts <<-EOS.undent
+ You have Macports or Fink installed. This can cause trouble.
+ You don't have to uninstall them, but you may like to try temporarily
+ moving them away, eg.
+
+ sudo mv /opt/local ~/macports
+
+ EOS
+ end
+end
+
+def check_gcc_versions
+ gcc_42 = gcc_42_build
+ gcc_40 = gcc_40_build
+
+ if gcc_42 == nil
+ puts <<-EOS.undent
+ We couldn't detect gcc 4.2.x. Some formulae require this compiler.
+
+ EOS
+ elsif gcc_42 < RECOMMENDED_GCC_42
+ puts <<-EOS.undent
+ Your gcc 4.2.x version is older than the recommended version. It may be advisable
+ to upgrade to the latest release of Xcode.
+
+ EOS
+ end
+
+ if gcc_40 == nil
+ puts <<-EOS.undent
+ We couldn't detect gcc 4.0.x. Some formulae require this compiler.
+
+ EOS
+ elsif gcc_40 < RECOMMENDED_GCC_40
+ puts <<-EOS.undent
+ Your gcc 4.0.x version is older than the recommended version. It may be advisable
+ to upgrade to the latest release of Xcode.
+
+ EOS
+ end
+end
+
+def check_cc_symlink
+ which_cc = Pathname.new('/usr/bin/cc').realpath.basename.to_s
+ if which_cc == "llvm-gcc-4.2"
+ puts <<-EOS.undent
+ You changed your cc to symlink to llvm.
+ This bypasses LLVM checks, and some formulae may mysteriously fail to work.
+ You may want to change /usr/bin/cc to point back at gcc.
+
+ To force Homebrew to use LLVM, you can set the "HOMEBREW_LLVM" environmental
+ variable, or pass "--use-llvm" to "brew install".
+
+ EOS
+ end
+end
+
+def __check_subdir_access base
+ target = HOMEBREW_PREFIX+base
+ return unless target.exist?
+
+ cant_read = []
+
+ target.find do |d|
+ next unless d.directory?
+ cant_read << d unless d.writable?
+ end
+
+ cant_read.sort!
+ if cant_read.length > 0
+ puts <<-EOS.undent
+ Some folders in #{target} aren't writable.
+ This can happen if you "sudo make install" software that isn't managed
+ by Homebrew. If a brew tries to add locale information to one of these
+ folders, then the install will fail during the link step.
+ You should probably `chown` them:
+
+ EOS
+ puts *cant_read.collect { |f| " #{f}" }
+ puts
+ end
+end
+
+def check_access_share_locale
+ __check_subdir_access 'share/locale'
+end
+
+def check_access_share_man
+ __check_subdir_access 'share/man'
+end
+
+def check_access_pkgconfig
+ # If PREFIX/lib/pkgconfig already exists, "sudo make install" of
+ # non-brew installed software may cause installation failures.
+ pkgconfig = HOMEBREW_PREFIX+'lib/pkgconfig'
+ return unless pkgconfig.exist?
+
+ unless pkgconfig.writable?
+ puts <<-EOS.undent
+ #{pkgconfig} isn't writable.
+ This can happen if you "sudo make install" software that isn't managed
+ by Homebrew. If a brew tries to write a .pc file to this folder, the
+ install will fail during the link step.
+
+ You should probably `chown` #{pkgconfig}
+
+ EOS
+ end
+end
+
+def check_access_include
+ # Installing MySQL manually (for instance) can chown include to root.
+ include_folder = HOMEBREW_PREFIX+'include'
+ return unless include_folder.exist?
+
+ unless include_folder.writable?
+ puts <<-EOS.undent
+ #{include_folder} isn't writable.
+ This can happen if you "sudo make install" software that isn't managed
+ by Homebrew. If a brew tries to write a header file to this folder, the
+ install will fail during the link step.
+
+ You should probably `chown` #{include_folder}
+
+ EOS
+ end
+end
+
+def check_access_etc
+ etc_folder = HOMEBREW_PREFIX+'etc'
+ return unless etc_folder.exist?
+
+ unless etc_folder.writable?
+ puts <<-EOS.undent
+ #{etc_folder} isn't writable.
+ This can happen if you "sudo make install" software that isn't managed
+ by Homebrew. If a brew tries to write a file to this folder, the install
+ will fail during the link step.
+
+ You should probably `chown` #{etc_folder}
+
+ EOS
+ end
+end
+
+def check_usr_bin_ruby
+ if /^1\.9/.match RUBY_VERSION
+ puts <<-EOS.undent
+ Ruby version #{RUBY_VERSION} is unsupported.
+ Homebrew is developed and tested on Ruby 1.8.x, and may not work correctly
+ on Ruby 1.9.x. Patches are accepted as long as they don't break on 1.8.x.
+
+ EOS
+ end
+end
+
+def check_homebrew_prefix
+ unless HOMEBREW_PREFIX.to_s == '/usr/local'
+ puts <<-EOS.undent
+ You can install Homebrew anywhere you want, but some brews may only work
+ correctly if you install to /usr/local.
+
+ EOS
+ end
+end
+
+def check_user_path
+ seen_prefix_bin = false
+ seen_prefix_sbin = false
+ seen_usr_bin = false
+
+ paths = ENV['PATH'].split(':').collect{|p| File.expand_path p}
+
+ paths.each do |p|
+ if p == '/usr/bin'
+ seen_usr_bin = true
+ unless seen_prefix_bin
+ puts <<-EOS.undent
+ /usr/bin is in your PATH before Homebrew's bin. This means that system-
+ provided programs will be used before Homebrew-provided ones. This is an
+ issue if you install, for instance, Python.
+
+ Consider editing your .bashrc to put:
+ #{HOMEBREW_PREFIX}/bin
+ ahead of /usr/bin in your $PATH.
+
+ EOS
+ end
+ end
+
+ seen_prefix_bin = true if p == "#{HOMEBREW_PREFIX}/bin"
+ seen_prefix_sbin = true if p == "#{HOMEBREW_PREFIX}/sbin"
+ end
+
+ unless seen_prefix_bin
+ puts <<-EOS.undent
+ Homebrew's bin was not found in your path. Some brews depend
+ on other brews that install tools to bin.
+
+ You should edit your .bashrc to add:
+ #{HOMEBREW_PREFIX}/bin
+ to $PATH.
+
+ EOS
+ end
+
+ unless seen_prefix_sbin
+ puts <<-EOS.undent
+ Some brews install binaries to sbin instead of bin, but Homebrew's
+ sbin was not found in your path.
+
+ Consider editing your .bashrc to add:
+ #{HOMEBREW_PREFIX}/sbin
+ to $PATH.
+
+ EOS
+ end
+end
+
+def check_which_pkg_config
+ binary = `/usr/bin/which pkg-config`.chomp
+ return if binary.empty?
+
+ unless binary == "#{HOMEBREW_PREFIX}/bin/pkg-config"
+ puts <<-EOS.undent
+ You have a non-brew 'pkg-config' in your PATH:
+ #{binary}
+
+ `./configure` may have problems finding brew-installed packages using
+ this other pkg-config.
+
+ EOS
+ end
+end
+
+def check_pkg_config_paths
+ binary = `/usr/bin/which pkg-config`.chomp
+ return if binary.empty?
+
+ # Use the debug output to determine which paths are searched
+ pkg_config_paths = []
+
+ debug_output = `pkg-config --debug 2>&1`
+ debug_output.split("\n").each do |line|
+ line =~ /Scanning directory '(.*)'/
+ pkg_config_paths << $1 if $1
+ end
+
+ # Check that all expected paths are being searched
+ unless pkg_config_paths.include? "/usr/X11/lib/pkgconfig"
+ puts <<-EOS.undent
+ Your pkg-config is not checking "/usr/X11/lib/pkgconfig" for packages.
+ Earlier versions of the pkg-config formula did not add this path
+ to the search path, which means that other formula may not be able
+ to find certain dependencies.
+
+ To resolve this issue, re-brew pkg-config with:
+ brew rm pkg-config && brew install pkg-config
+
+ EOS
+ end
+end
+
+def check_for_gettext
+ if %w[lib/libgettextlib.dylib
+ lib/libintl.dylib
+ include/libintl.h ].any? { |f| File.exist? "#{HOMEBREW_PREFIX}/#{f}" }
+ puts <<-EOS.undent
+ gettext was detected in your PREFIX.
+
+ The gettext provided by Homebrew is "keg-only", meaning it does not
+ get linked into your PREFIX by default.
+
+ If you `brew link gettext` then a large number of brews that don't
+ otherwise have a `depends_on 'gettext'` will pick up gettext anyway
+ during the `./configure` step.
+
+ If you have a non-Homebrew provided gettext, other problems will happen
+ especially if it wasn't compiled with the proper architectures.
+
+ EOS
+ end
+end
+
+def check_for_iconv
+ if %w[lib/libiconv.dylib
+ include/iconv.h ].any? { |f| File.exist? "#{HOMEBREW_PREFIX}/#{f}" }
+ puts <<-EOS.undent
+ libiconv was detected in your PREFIX.
+
+ Homebrew doesn't provide a libiconv formula, and expects to link against
+ the system version in /usr/lib.
+
+ If you have a non-Homebrew provided libiconv, many formulae will fail
+ to compile or link, especially if it wasn't compiled with the proper
+ architectures.
+
+ EOS
+ end
+end
+
+def check_for_config_scripts
+ real_cellar = HOMEBREW_CELLAR.realpath
+
+ config_scripts = []
+
+ paths = ENV['PATH'].split(':').collect{|p| File.expand_path p}
+ paths.each do |p|
+ next if ['/usr/bin', '/usr/sbin', '/usr/X11/bin', "#{HOMEBREW_PREFIX}/bin", "#{HOMEBREW_PREFIX}/sbin"].include? p
+ next if p =~ %r[^(#{real_cellar.to_s}|#{HOMEBREW_CELLAR.to_s})]
+
+ configs = Dir["#{p}/*-config"]
+ # puts "#{p}\n #{configs * ' '}" unless configs.empty?
+ config_scripts << [p, configs.collect {|p| File.basename(p)}] unless configs.empty?
+ end
+
+ unless config_scripts.empty?
+ puts <<-EOS.undent
+ Some "config" scripts were found in your path, but not in system or Homebrew folders.
+
+ `./configure` scripts often look for *-config scripts to determine if software packages
+ are installed, and what additional flags to use when compiling and linking.
+
+ Having additional scripts in your path can confuse software installed via Homebrew if
+ the config script overrides a system or Homebrew provided script of the same name.
+
+ EOS
+
+ config_scripts.each do |pair|
+ puts pair[0]
+ puts " " + pair[1] * " "
+ end
+ puts
+ end
+end
+
+def check_for_dyld_vars
+ if ENV['DYLD_LIBRARY_PATH']
+ puts <<-EOS.undent
+ Setting DYLD_LIBARY_PATH can break dynamic linking.
+ You should probably unset it.
+
+ EOS
+ end
+end
+
+def check_for_symlinked_cellar
+ if HOMEBREW_CELLAR.symlink?
+ puts <<-EOS.undent
+ Symlinked Cellars can cause problems.
+ Your Homebrew Cellar is a symlink: #{HOMEBREW_CELLAR}
+ which resolves to: #{HOMEBREW_CELLAR.realpath}
+
+ The recommended Homebrew installations are either:
+ (A) Have Cellar be a real folder inside of your HOMEBREW_PREFIX
+ (B) Symlink "bin/brew" into your prefix, but don't symlink "Cellar".
+
+ Older installations of Homebrew may have created a symlinked Cellar, but this can
+ cause problems when two formula install to locations that are mapped on top of each
+ other during the linking step.
+
+ EOS
+ end
+end
+
+def check_for_multiple_volumes
+ volumes = Volumes.new
+
+ # Find the volumes for the TMP folder & HOMEBREW_CELLAR
+ real_cellar = HOMEBREW_CELLAR.realpath
+
+ tmp_prefix = ENV['HOMEBREW_TEMP'] || '/tmp'
+ tmp=Pathname.new `/usr/bin/mktemp -d #{tmp_prefix}/homebrew-brew-doctor-XXXX`.strip
+ real_temp = tmp.realpath.parent
+
+ where_cellar = volumes.which real_cellar
+ where_temp = volumes.which real_temp
+
+ unless where_cellar == where_temp
+ puts <<-EOS.undent
+ Your Cellar & TEMP folders are on different volumes.
+
+ OS X won't move relative symlinks across volumes unless the target file
+ already exists.
+
+ Brews known to be affected by this are Git and Narwhal.
+
+ You should set the "HOMEBREW_TEMP" environmental variable to a suitable
+ folder on the same volume as your Cellar.
+
+ EOS
+ end
+end
+
+def check_for_git
+ git = `/usr/bin/which git`.chomp
+ if git.empty?
+ puts <<-EOS.undent
+ "Git" was not found in your path.
+
+ Homebrew uses Git for several internal functions, and some formulae
+ use Git checkouts instead of stable tarballs.
+
+ You may want to do:
+ brew install git
+
+ EOS
+ end
+end
+
+def check_for_autoconf
+ which_autoconf = `/usr/bin/which autoconf`.chomp
+ unless (which_autoconf == '/usr/bin/autoconf' or which_autoconf == '/Developer/usr/bin/autoconf')
+ puts <<-EOS.undent
+ You have an "autoconf" in your path blocking the system version at:
+ #{which_autoconf}
+
+ Custom autoconf in general and autoconf 2.66 in particular has issues
+ and will cause some Homebrew formulae to fail.
+
+ EOS
+ end
+end
+
+def __check_linked_brew f
+ links_found = []
+
+ Pathname.new(f.prefix).find do |src|
+ dst=HOMEBREW_PREFIX+src.relative_path_from(f.prefix)
+ next unless dst.symlink?
+
+ dst_points_to = dst.realpath()
+ next unless dst_points_to.to_s == src.to_s
+
+ if src.directory?
+ Find.prune
+ else
+ links_found << dst
+ end
+ end
+
+ return links_found
+end
+
+def check_for_linked_kegonly_brews
+ require 'formula'
+
+ warnings = Hash.new
+
+ Formula.all.each do |f|
+ next unless f.keg_only? and f.installed?
+ links = __check_linked_brew f
+ warnings[f.name] = links unless links.empty?
+ end
+
+ unless warnings.empty?
+ puts <<-EOS.undent
+ Some keg-only formula are linked into the Cellar.
+
+ Linking a keg-only formula, such as gettext, into the cellar with
+ `brew link f` will cause other formulae to detect them during the
+ `./configure` step. This may cause problems when compiling those
+ other formulae.
+
+ Binaries provided by keg-only formulae may override system binaries
+ with other strange results.
+
+ You may wish to `brew unlink` these brews:
+ EOS
+
+ puts *warnings.keys.collect { |f| " #{f}" }
+ end
+end
+
+def check_for_other_vars
+ target_var = ENV['MACOSX_DEPLOYMENT_TARGET']
+ return if target_var.nil? or target_var.empty?
+
+ unless target_var == MACOS_VERSION.to_s
+ puts <<-EOS.undent
+ $MACOSX_DEPLOYMENT_TARGET was set to #{target_var}
+ This is used by Fink, but having it set to a value different from the
+ current system version (#{MACOS_VERSION}) can cause problems, compiling
+ Git for instance, and should probably be removed.
+
+ EOS
+ end
+end
+
+module Homebrew extend self
+def doctor
+ read, write = IO.pipe
+
+ if fork == nil
+ read.close
+ $stdout.reopen write
+
+ check_usr_bin_ruby
+ check_homebrew_prefix
+ check_for_macgpg2
+ check_for_stray_dylibs
+ check_gcc_versions
+ check_cc_symlink
+ check_for_other_package_managers
+ check_for_x11
+ check_for_nonstandard_x11
+ check_access_share_locale
+ check_access_share_man
+ check_access_include
+ check_access_etc
+ check_user_path
+ check_which_pkg_config
+ check_pkg_config_paths
+ check_access_pkgconfig
+ check_for_gettext
+ check_for_config_scripts
+ check_for_dyld_vars
+ check_for_other_vars
+ check_for_symlinked_cellar
+ check_for_multiple_volumes
+ check_for_git
+ check_for_autoconf
+ check_for_linked_kegonly_brews
+
+ exit! 0
+ else
+ write.close
+
+ unless (out = read.read).chomp.empty?
+ puts out
+ else
+ puts "Your OS X is ripe for brewing."
+ puts "Any troubles you may be experiencing are likely purely psychosomatic."
+ end
+ end
+end
+end