Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move remaining undef use in OS extensions to prepend #18378

Merged
merged 4 commits into from
Oct 5, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Library/Homebrew/development_tools.rb
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,6 @@ def build_system_info
"cpu_family" => Hardware::CPU.family.to_s,
}
end
alias generic_build_system_info build_system_info
end
end

Expand Down
1 change: 0 additions & 1 deletion Library/Homebrew/extend/ENV/std.rb
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_a
gcc_formula = gcc_version_formula(cc)
append_path "PATH", gcc_formula.opt_bin.to_s
end
alias generic_setup_build_environment setup_build_environment

sig { returns(T.nilable(PATH)) }
def determine_pkg_config_libdir
Expand Down
1 change: 0 additions & 1 deletion Library/Homebrew/extend/ENV/super.rb
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,6 @@ def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_a
# These flags will also be present:
# a - apply fix for apr-1-config path
end
alias generic_setup_build_environment setup_build_environment

private

Expand Down
190 changes: 96 additions & 94 deletions Library/Homebrew/extend/os/linux/dependency_collector.rb
Original file line number Diff line number Diff line change
@@ -1,101 +1,103 @@
# typed: true # rubocop:disable Sorbet/StrictSigil
# typed: strict
# frozen_string_literal: true

require "os/linux/glibc"

class DependencyCollector
undef gcc_dep_if_needed
undef glibc_dep_if_needed
undef init_global_dep_tree_if_needed!

sig { params(related_formula_names: T::Set[String]).returns(T.nilable(Dependency)) }
def gcc_dep_if_needed(related_formula_names)
# gcc is required for libgcc_s.so.1 if glibc or gcc are too old
return unless DevelopmentTools.needs_build_formulae?
return if building_global_dep_tree?
return if related_formula_names.include?(GCC)
return if global_dep_tree[GCC]&.intersect?(related_formula_names)
return unless formula_for(GCC)

Dependency.new(GCC, [:implicit])
end

sig { params(related_formula_names: T::Set[String]).returns(T.nilable(Dependency)) }
def glibc_dep_if_needed(related_formula_names)
return unless DevelopmentTools.needs_libc_formula?
return if building_global_dep_tree?
return if related_formula_names.include?(GLIBC)
return if global_dep_tree[GLIBC]&.intersect?(related_formula_names)
return unless formula_for(GLIBC)

Dependency.new(GLIBC, [:implicit])
end

private

GLIBC = "glibc"
GCC = OS::LINUX_PREFERRED_GCC_RUNTIME_FORMULA

sig { void }
def init_global_dep_tree_if_needed!
return unless DevelopmentTools.needs_build_formulae?
return if building_global_dep_tree?
return unless global_dep_tree.empty?

building_global_dep_tree!
global_dep_tree[GLIBC] = Set.new(global_deps_for(GLIBC))
# gcc depends on glibc
global_dep_tree[GCC] = Set.new([*global_deps_for(GCC), GLIBC, *@@global_dep_tree[GLIBC]])
built_global_dep_tree!
end

sig { params(name: String).returns(T.nilable(Formula)) }
def formula_for(name)
@formula_for ||= {}
@formula_for[name] ||= Formula[name]
rescue FormulaUnavailableError
nil
end

sig { params(name: String).returns(T::Array[String]) }
def global_deps_for(name)
@global_deps_for ||= {}
# Always strip out glibc and gcc from all parts of dependency tree when
# we're calculating their dependency trees. Other parts of Homebrew will
# catch any circular dependencies.
@global_deps_for[name] ||= if (formula = formula_for(name))
formula.deps.map(&:name).flat_map do |dep|
[dep, *global_deps_for(dep)].compact
end.uniq
else
[]
module OS
module Linux
module DependencyCollector
sig { params(related_formula_names: T::Set[String]).returns(T.nilable(Dependency)) }
def gcc_dep_if_needed(related_formula_names)
# gcc is required for libgcc_s.so.1 if glibc or gcc are too old
return unless ::DevelopmentTools.needs_build_formulae?
return if building_global_dep_tree?
return if related_formula_names.include?(GCC)
return if global_dep_tree[GCC]&.intersect?(related_formula_names)
return unless formula_for(GCC)

Dependency.new(GCC, [:implicit])
end

sig { params(related_formula_names: T::Set[String]).returns(T.nilable(Dependency)) }
def glibc_dep_if_needed(related_formula_names)
return unless ::DevelopmentTools.needs_libc_formula?
return if building_global_dep_tree?
return if related_formula_names.include?(GLIBC)
return if global_dep_tree[GLIBC]&.intersect?(related_formula_names)
return unless formula_for(GLIBC)

Dependency.new(GLIBC, [:implicit])
end

private

GLIBC = "glibc"
GCC = OS::LINUX_PREFERRED_GCC_RUNTIME_FORMULA

sig { void }
def init_global_dep_tree_if_needed!
return unless ::DevelopmentTools.needs_build_formulae?
return if building_global_dep_tree?
return unless global_dep_tree.empty?

building_global_dep_tree!
global_dep_tree[GLIBC] = Set.new(global_deps_for(GLIBC))
# gcc depends on glibc
global_dep_tree[GCC] = Set.new([*global_deps_for(GCC), GLIBC, *@@global_dep_tree[GLIBC]])
built_global_dep_tree!
end

sig { params(name: String).returns(T.nilable(Formula)) }
def formula_for(name)
@formula_for ||= T.let({}, T.nilable(T::Hash[String, Formula]))
@formula_for[name] ||= ::Formula[name]
rescue FormulaUnavailableError
nil
end

sig { params(name: String).returns(T::Array[String]) }
def global_deps_for(name)
@global_deps_for ||= T.let({}, T.nilable(T::Hash[String, T::Array[String]]))
# Always strip out glibc and gcc from all parts of dependency tree when
# we're calculating their dependency trees. Other parts of Homebrew will
# catch any circular dependencies.
@global_deps_for[name] ||= if (formula = formula_for(name))
formula.deps.map(&:name).flat_map do |dep|
[dep, *global_deps_for(dep)].compact

Check warning on line 66 in Library/Homebrew/extend/os/linux/dependency_collector.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/extend/os/linux/dependency_collector.rb#L66

Added line #L66 was not covered by tests
end.uniq
else
[]
end
end

# Use class variables to avoid this expensive logic needing to be done more
# than once.
# rubocop:disable Style/ClassVars
@@global_dep_tree = T.let({}, T::Hash[String, T::Set[String]])
@@building_global_dep_tree = T.let(false, T::Boolean)

sig { returns(T::Hash[String, T::Set[String]]) }
def global_dep_tree
@@global_dep_tree
end

sig { void }
def building_global_dep_tree!
@@building_global_dep_tree = true
end

sig { void }
def built_global_dep_tree!
@@building_global_dep_tree = false
end

sig { returns(T::Boolean) }
def building_global_dep_tree?
@@building_global_dep_tree.present?
end
# rubocop:enable Style/ClassVars
end
end

# Use class variables to avoid this expensive logic needing to be done more
# than once.
# rubocop:disable Style/ClassVars
@@global_dep_tree = {}
@@building_global_dep_tree = false

sig { returns(T::Hash[String, T::Set[String]]) }
def global_dep_tree
@@global_dep_tree
end

sig { void }
def building_global_dep_tree!
@@building_global_dep_tree = true
end

sig { void }
def built_global_dep_tree!
@@building_global_dep_tree = false
end

sig { returns(T::Boolean) }
def building_global_dep_tree?
@@building_global_dep_tree.present?
end
# rubocop:enable Style/ClassVars
end

DependencyCollector.prepend(OS::Linux::DependencyCollector)
90 changes: 50 additions & 40 deletions Library/Homebrew/extend/os/linux/development_tools.rb
Original file line number Diff line number Diff line change
@@ -1,54 +1,64 @@
# typed: true # rubocop:todo Sorbet/StrictSigil
# typed: strict
# frozen_string_literal: true

class DevelopmentTools
class << self
sig { params(tool: T.any(String, Symbol)).returns(T.nilable(Pathname)) }
def locate(tool)
(@locate ||= {}).fetch(tool) do |key|
@locate[key] = if needs_build_formulae? &&
(binutils_path = HOMEBREW_PREFIX/"opt/binutils/bin/#{tool}").executable?
binutils_path
elsif needs_build_formulae? && (glibc_path = HOMEBREW_PREFIX/"opt/glibc/bin/#{tool}").executable?
glibc_path
elsif (homebrew_path = HOMEBREW_PREFIX/"bin/#{tool}").executable?
homebrew_path
elsif File.executable?((system_path = "/usr/bin/#{tool}"))
Pathname.new system_path
module OS
module Linux
module DevelopmentTools
extend T::Helpers

requires_ancestor { ::DevelopmentTools }

sig { params(tool: T.any(String, Symbol)).returns(T.nilable(Pathname)) }
def locate(tool)
@locate ||= T.let({}, T.nilable(T::Hash[T.any(String, Symbol), Pathname]))
@locate.fetch(tool) do |key|
@locate[key] = if ::DevelopmentTools.needs_build_formulae? &&
(binutils_path = HOMEBREW_PREFIX/"opt/binutils/bin/#{tool}").executable?
binutils_path
elsif ::DevelopmentTools.needs_build_formulae? &&
(glibc_path = HOMEBREW_PREFIX/"opt/glibc/bin/#{tool}").executable?
glibc_path
elsif (homebrew_path = HOMEBREW_PREFIX/"bin/#{tool}").executable?
homebrew_path
elsif File.executable?((system_path = "/usr/bin/#{tool}"))
Pathname.new system_path
end
end
end
end

sig { returns(Symbol) }
def default_compiler
:gcc
end
sig { returns(Symbol) }
def default_compiler = :gcc

sig { returns(T::Boolean) }
def needs_libc_formula?
return @needs_libc_formula if defined? @needs_libc_formula
sig { returns(T::Boolean) }
def needs_libc_formula?
return @needs_libc_formula unless @needs_libc_formula.nil?

@needs_libc_formula = OS::Linux::Glibc.below_ci_version?
end
@needs_libc_formula = T.let(OS::Linux::Glibc.below_ci_version?, T.nilable(T::Boolean))
@needs_libc_formula = !!@needs_libc_formula
end

sig { returns(T::Boolean) }
def needs_compiler_formula?
return @needs_compiler_formula if defined? @needs_compiler_formula
sig { returns(T::Boolean) }
def needs_compiler_formula?
return @needs_compiler_formula unless @needs_compiler_formula.nil?

gcc = "/usr/bin/gcc"
@needs_compiler_formula = if File.exist?(gcc)
gcc_version(gcc) < OS::LINUX_GCC_CI_VERSION
else
true
gcc = "/usr/bin/gcc"
@needs_compiler_formula = T.let(if File.exist?(gcc)
::DevelopmentTools.gcc_version(gcc) < OS::LINUX_GCC_CI_VERSION
else
true
end, T.nilable(T::Boolean))
!!@needs_compiler_formula
end
end

sig { returns(T::Hash[String, T.nilable(String)]) }
def build_system_info
generic_build_system_info.merge({
"glibc_version" => OS::Linux::Glibc.version.to_s.presence,
"oldest_cpu_family" => Hardware.oldest_cpu.to_s,
})
sig { returns(T::Hash[String, T.nilable(String)]) }
def build_system_info
super.merge({
"glibc_version" => OS::Linux::Glibc.version.to_s.presence,
"oldest_cpu_family" => Hardware.oldest_cpu.to_s,
})
end
end
end
end

DevelopmentTools.singleton_class.prepend(OS::Linux::DevelopmentTools)
Loading
Loading