-
-
Notifications
You must be signed in to change notification settings - Fork 9.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #18378 from Homebrew/no-undefs
Move remaining `undef` use in OS extensions to `prepend`
- Loading branch information
Showing
25 changed files
with
1,156 additions
and
1,099 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
190 changes: 96 additions & 94 deletions
190
Library/Homebrew/extend/os/linux/dependency_collector.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
Oops, something went wrong.