mirror of
https://github.com/Homebrew/brew.git
synced 2025-07-14 16:09:03 +08:00
Cross-platform diagnostics.
This commit is contained in:
parent
4ebccf79a8
commit
e5435dfeb7
@ -480,60 +480,6 @@ module Homebrew
|
||||
EOS
|
||||
end
|
||||
|
||||
def check_for_gettext
|
||||
find_relative_paths("lib/libgettextlib.dylib",
|
||||
"lib/libintl.dylib",
|
||||
"include/libintl.h")
|
||||
return if @found.empty?
|
||||
|
||||
# Our gettext formula will be caught by check_linked_keg_only_brews
|
||||
gettext = begin
|
||||
Formulary.factory("gettext")
|
||||
rescue
|
||||
nil
|
||||
end
|
||||
homebrew_owned = @found.all? do |path|
|
||||
Pathname.new(path).realpath.to_s.start_with? "#{HOMEBREW_CELLAR}/gettext"
|
||||
end
|
||||
return if gettext&.linked_keg&.directory? && homebrew_owned
|
||||
|
||||
inject_file_list @found, <<~EOS
|
||||
gettext files detected at a system prefix.
|
||||
These files can cause compilation and link failures, especially if they
|
||||
are compiled with improper architectures. Consider removing these files:
|
||||
EOS
|
||||
end
|
||||
|
||||
def check_for_iconv
|
||||
find_relative_paths("lib/libiconv.dylib", "include/iconv.h")
|
||||
return if @found.empty?
|
||||
|
||||
libiconv = begin
|
||||
Formulary.factory("libiconv")
|
||||
rescue
|
||||
nil
|
||||
end
|
||||
if libiconv&.linked_keg&.directory?
|
||||
unless libiconv.keg_only?
|
||||
<<~EOS
|
||||
A libiconv formula is installed and linked.
|
||||
This will break stuff. For serious. Unlink it.
|
||||
EOS
|
||||
end
|
||||
else
|
||||
inject_file_list @found, <<~EOS
|
||||
libiconv files detected at a system prefix other than /usr.
|
||||
Homebrew doesn't provide a libiconv formula, and expects to link against
|
||||
the system version in /usr. libiconv in other prefixes can cause
|
||||
compile or link failure, especially if compiled with improper
|
||||
architectures. macOS itself never installs anything to /usr/local so
|
||||
it was either installed by a user or some other third party software.
|
||||
|
||||
tl;dr: delete these files:
|
||||
EOS
|
||||
end
|
||||
end
|
||||
|
||||
def check_for_config_scripts
|
||||
return unless HOMEBREW_CELLAR.exist?
|
||||
real_cellar = HOMEBREW_CELLAR.realpath
|
||||
@ -571,17 +517,17 @@ module Homebrew
|
||||
EOS
|
||||
end
|
||||
|
||||
def check_dyld_vars
|
||||
dyld_vars = ENV.keys.grep(/^DYLD_/)
|
||||
return if dyld_vars.empty?
|
||||
def check_ld_vars
|
||||
ld_vars = ENV.keys.grep(/^(|DY)LD_/)
|
||||
return if ld_vars.empty?
|
||||
|
||||
values = dyld_vars.map { |var| "#{var}: #{ENV.fetch(var)}" }
|
||||
values = ld_vars.map { |var| "#{var}: #{ENV.fetch(var)}" }
|
||||
message = inject_file_list values, <<~EOS
|
||||
Setting DYLD_* vars can break dynamic linking.
|
||||
Setting DYLD_* or LD_* variables can break dynamic linking.
|
||||
Set variables:
|
||||
EOS
|
||||
|
||||
if dyld_vars.include? "DYLD_INSERT_LIBRARIES"
|
||||
if ld_vars.include? "DYLD_INSERT_LIBRARIES"
|
||||
message += <<~EOS
|
||||
|
||||
Setting DYLD_INSERT_LIBRARIES can cause Go builds to fail.
|
||||
@ -612,38 +558,6 @@ module Homebrew
|
||||
EOS
|
||||
end
|
||||
|
||||
def check_for_multiple_volumes
|
||||
return unless HOMEBREW_CELLAR.exist?
|
||||
volumes = Volumes.new
|
||||
|
||||
# Find the volumes for the TMP folder & HOMEBREW_CELLAR
|
||||
real_cellar = HOMEBREW_CELLAR.realpath
|
||||
where_cellar = volumes.which real_cellar
|
||||
|
||||
begin
|
||||
tmp = Pathname.new(Dir.mktmpdir("doctor", HOMEBREW_TEMP))
|
||||
begin
|
||||
real_tmp = tmp.realpath.parent
|
||||
where_tmp = volumes.which real_tmp
|
||||
ensure
|
||||
Dir.delete tmp
|
||||
end
|
||||
rescue
|
||||
return
|
||||
end
|
||||
|
||||
return if where_cellar == where_tmp
|
||||
|
||||
<<~EOS
|
||||
Your Cellar and TEMP directories are on different volumes.
|
||||
macOS 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
|
||||
directory on the same volume as your Cellar.
|
||||
EOS
|
||||
end
|
||||
|
||||
def check_git_version
|
||||
# https://help.github.com/articles/https-cloning-errors
|
||||
return unless Utils.git_available?
|
||||
@ -859,21 +773,6 @@ module Homebrew
|
||||
nil
|
||||
end
|
||||
|
||||
def check_for_non_prefixed_findutils
|
||||
findutils = Formula["findutils"]
|
||||
return unless findutils.any_version_installed?
|
||||
|
||||
gnubin = %W[#{findutils.opt_libexec}/gnubin #{findutils.libexec}/gnubin]
|
||||
default_names = Tab.for_name("findutils").with? "default-names"
|
||||
return if !default_names && (paths & gnubin).empty?
|
||||
|
||||
<<~EOS
|
||||
Putting non-prefixed findutils in your path can cause python builds to fail.
|
||||
EOS
|
||||
rescue FormulaUnavailableError
|
||||
nil
|
||||
end
|
||||
|
||||
def check_for_pydistutils_cfg_in_home
|
||||
return unless File.exist? "#{ENV["HOME"]}/.pydistutils.cfg"
|
||||
|
||||
|
@ -1 +1,5 @@
|
||||
require "extend/os/mac/diagnostic" if OS.mac?
|
||||
if OS.mac?
|
||||
require "extend/os/mac/diagnostic"
|
||||
elsif OS.linux?
|
||||
require "extend/os/linux/diagnostic"
|
||||
end
|
||||
|
33
Library/Homebrew/extend/os/linux/diagnostic.rb
Normal file
33
Library/Homebrew/extend/os/linux/diagnostic.rb
Normal file
@ -0,0 +1,33 @@
|
||||
require "tempfile"
|
||||
require "utils/shell"
|
||||
require "os/linux/diagnostic"
|
||||
|
||||
module Homebrew
|
||||
module Diagnostic
|
||||
class Checks
|
||||
def check_tmpdir_sticky_bit
|
||||
message = generic_check_tmpdir_sticky_bit
|
||||
return if message.nil?
|
||||
message + <<~EOS
|
||||
If you don't have administrative privileges on this machine,
|
||||
create a directory and set the HOMEBREW_TEMP environment variable,
|
||||
for example:
|
||||
install -d -m 1755 ~/tmp
|
||||
#{Utils::Shell.set_variable_in_profile("HOMEBREW_TEMP", "~/tmp")}
|
||||
EOS
|
||||
end
|
||||
|
||||
def check_xdg_data_dirs
|
||||
return if ENV["XDG_DATA_DIRS"].to_s.empty?
|
||||
return if ENV["XDG_DATA_DIRS"].split("/").include?(HOMEBREW_PREFIX/"share")
|
||||
<<~EOS
|
||||
Homebrew's share was not found in your XDG_DATA_DIRS but you have
|
||||
this variable set to include other locations.
|
||||
Some programs like `vapigen` may not work correctly.
|
||||
Consider adding Homebrew's share directory to XDG_DATA_DIRS like so:
|
||||
#{Utils::Shell.prepend_variable_in_profile("XDG_DATA_DIRS", HOMEBREW_PREFIX/"share")}
|
||||
EOS
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -29,6 +29,21 @@ module Homebrew
|
||||
]).freeze
|
||||
end
|
||||
|
||||
def check_for_non_prefixed_findutils
|
||||
findutils = Formula["findutils"]
|
||||
return unless findutils.any_version_installed?
|
||||
|
||||
gnubin = %W[#{findutils.opt_libexec}/gnubin #{findutils.libexec}/gnubin]
|
||||
default_names = Tab.for_name("findutils").with? "default-names"
|
||||
return if !default_names && (paths & gnubin).empty?
|
||||
|
||||
<<~EOS
|
||||
Putting non-prefixed findutils in your path can cause python builds to fail.
|
||||
EOS
|
||||
rescue FormulaUnavailableError
|
||||
nil
|
||||
end
|
||||
|
||||
def check_for_unsupported_macos
|
||||
return if ARGV.homebrew_developer?
|
||||
|
||||
@ -275,6 +290,95 @@ module Homebrew
|
||||
may not build correctly with a non-/usr/local prefix.
|
||||
EOS
|
||||
end
|
||||
|
||||
def check_for_gettext
|
||||
find_relative_paths("lib/libgettextlib.dylib",
|
||||
"lib/libintl.dylib",
|
||||
"include/libintl.h")
|
||||
return if @found.empty?
|
||||
|
||||
# Our gettext formula will be caught by check_linked_keg_only_brews
|
||||
gettext = begin
|
||||
Formulary.factory("gettext")
|
||||
rescue
|
||||
nil
|
||||
end
|
||||
|
||||
if gettext&.linked_keg&.directory?
|
||||
homebrew_owned = @found.all? do |path|
|
||||
Pathname.new(path).realpath.to_s.start_with? "#{HOMEBREW_CELLAR}/gettext"
|
||||
end
|
||||
return if homebrew_owned
|
||||
end
|
||||
|
||||
inject_file_list @found, <<~EOS
|
||||
gettext files detected at a system prefix.
|
||||
These files can cause compilation and link failures, especially if they
|
||||
are compiled with improper architectures. Consider removing these files:
|
||||
EOS
|
||||
end
|
||||
|
||||
def check_for_iconv
|
||||
find_relative_paths("lib/libiconv.dylib", "include/iconv.h")
|
||||
return if @found.empty?
|
||||
|
||||
libiconv = begin
|
||||
Formulary.factory("libiconv")
|
||||
rescue
|
||||
nil
|
||||
end
|
||||
if libiconv&.linked_keg&.directory?
|
||||
unless libiconv.keg_only?
|
||||
<<~EOS
|
||||
A libiconv formula is installed and linked.
|
||||
This will break stuff. For serious. Unlink it.
|
||||
EOS
|
||||
end
|
||||
else
|
||||
inject_file_list @found, <<~EOS
|
||||
libiconv files detected at a system prefix other than /usr.
|
||||
Homebrew doesn't provide a libiconv formula, and expects to link against
|
||||
the system version in /usr. libiconv in other prefixes can cause
|
||||
compile or link failure, especially if compiled with improper
|
||||
architectures. macOS itself never installs anything to /usr/local so
|
||||
it was either installed by a user or some other third party software.
|
||||
|
||||
tl;dr: delete these files:
|
||||
EOS
|
||||
end
|
||||
end
|
||||
|
||||
def check_for_multiple_volumes
|
||||
return unless HOMEBREW_CELLAR.exist?
|
||||
volumes = Volumes.new
|
||||
|
||||
# Find the volumes for the TMP folder & HOMEBREW_CELLAR
|
||||
real_cellar = HOMEBREW_CELLAR.realpath
|
||||
where_cellar = volumes.which real_cellar
|
||||
|
||||
begin
|
||||
tmp = Pathname.new(Dir.mktmpdir("doctor", HOMEBREW_TEMP))
|
||||
begin
|
||||
real_tmp = tmp.realpath.parent
|
||||
where_tmp = volumes.which real_tmp
|
||||
ensure
|
||||
Dir.delete tmp
|
||||
end
|
||||
rescue
|
||||
return
|
||||
end
|
||||
|
||||
return if where_cellar == where_tmp
|
||||
|
||||
<<~EOS
|
||||
Your Cellar and TEMP directories are on different volumes.
|
||||
macOS 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
|
||||
directory on the same volume as your Cellar.
|
||||
EOS
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
7
Library/Homebrew/os/linux/diagnostic.rb
Normal file
7
Library/Homebrew/os/linux/diagnostic.rb
Normal file
@ -0,0 +1,7 @@
|
||||
module Homebrew
|
||||
module Diagnostic
|
||||
class Checks
|
||||
alias generic_check_tmpdir_sticky_bit check_tmpdir_sticky_bit
|
||||
end
|
||||
end
|
||||
end
|
@ -145,11 +145,6 @@ describe Homebrew::Diagnostic::Checks do
|
||||
end
|
||||
end
|
||||
|
||||
specify "#check_dyld_vars" do
|
||||
ENV["DYLD_INSERT_LIBRARIES"] = "foo"
|
||||
expect(subject.check_dyld_vars).to match("Setting DYLD_INSERT_LIBRARIES")
|
||||
end
|
||||
|
||||
specify "#check_for_symlinked_cellar" do
|
||||
begin
|
||||
HOMEBREW_CELLAR.rmtree
|
||||
@ -165,6 +160,26 @@ describe Homebrew::Diagnostic::Checks do
|
||||
end
|
||||
end
|
||||
|
||||
specify "#check_ld_vars catches LD vars" do
|
||||
ENV["LD_LIBRARY_PATH"] = "foo"
|
||||
expect(subject.check_ld_vars).to match("Setting DYLD_\\* or LD_\\* variables")
|
||||
end
|
||||
|
||||
specify "#check_ld_vars catches DYLD vars" do
|
||||
ENV["DYLD_LIBRARY_PATH"] = "foo"
|
||||
expect(subject.check_ld_vars).to match("Setting DYLD_\\* or LD_\\* variables")
|
||||
end
|
||||
|
||||
specify "#check_ld_vars catches LD and DYLD vars" do
|
||||
ENV["LD_LIBRARY_PATH"] = "foo"
|
||||
ENV["DYLD_LIBRARY_PATH"] = "foo"
|
||||
expect(subject.check_ld_vars).to match("Setting DYLD_\\* or LD_\\* variables")
|
||||
end
|
||||
|
||||
specify "#check_ld_vars returns success when neither LD nor DYLD vars are set" do
|
||||
expect(subject.check_ld_vars).to be nil
|
||||
end
|
||||
|
||||
specify "#check_tmpdir" do
|
||||
ENV["TMPDIR"] = "/i/don/t/exis/t"
|
||||
expect(subject.check_tmpdir).to match("doesn't exist")
|
||||
|
@ -45,4 +45,9 @@ describe Homebrew::Diagnostic::Checks do
|
||||
expect(subject.check_ruby_version)
|
||||
.to match "Ruby version 1.8.6 is unsupported on 10.12"
|
||||
end
|
||||
|
||||
specify "#check_dyld_insert" do
|
||||
ENV["DYLD_INSERT_LIBRARIES"] = "foo"
|
||||
expect(subject.check_ld_vars).to match("Setting DYLD_INSERT_LIBRARIES")
|
||||
end
|
||||
end
|
||||
|
@ -75,19 +75,20 @@ describe Utils::Shell do
|
||||
it "supports Tcsh" do
|
||||
ENV["SHELL"] = "/bin/tcsh"
|
||||
expect(subject.prepend_path_in_profile(path))
|
||||
.to start_with("echo 'setenv PATH #{path}:$")
|
||||
.to eq("echo 'setenv PATH #{path}:$PATH' >> #{shell_profile}")
|
||||
end
|
||||
|
||||
it "supports Bash" do
|
||||
ENV["SHELL"] = "/bin/bash"
|
||||
expect(subject.prepend_path_in_profile(path))
|
||||
.to start_with("echo 'export PATH=\"#{path}:$")
|
||||
.to eq("echo 'export PATH=\"#{path}:$PATH\"' >> #{shell_profile}")
|
||||
end
|
||||
|
||||
it "supports Fish" do
|
||||
ENV["SHELL"] = "/usr/local/bin/fish"
|
||||
ENV["fish_user_paths"] = "/some/path"
|
||||
expect(subject.prepend_path_in_profile(path))
|
||||
.to start_with("echo 'set -g fish_user_paths \"#{path}\" $fish_user_paths' >>")
|
||||
.to eq("echo 'set -g fish_user_paths \"#{path}\" $fish_user_paths' >> #{shell_profile}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -40,6 +40,17 @@ module Utils
|
||||
SHELL_PROFILE_MAP.fetch(preferred, "~/.bash_profile")
|
||||
end
|
||||
|
||||
def set_variable_in_profile(variable, value)
|
||||
case preferred
|
||||
when :bash, :ksh, :sh, :zsh, nil
|
||||
"echo 'export #{variable}=#{sh_quote(value)}' >> #{profile}"
|
||||
when :csh, :tcsh
|
||||
"echo 'setenv #{variable} #{csh_quote(value)}' >> #{profile}"
|
||||
when :fish
|
||||
"echo 'set -gx #{variable} #{sh_quote(value)}' >> #{profile}"
|
||||
end
|
||||
end
|
||||
|
||||
def prepend_path_in_profile(path)
|
||||
case preferred
|
||||
when :bash, :ksh, :sh, :zsh, nil
|
||||
|
Loading…
x
Reference in New Issue
Block a user