mirror of
https://github.com/Homebrew/brew.git
synced 2025-07-14 16:09:03 +08:00

This is the pattern we've been adopting for a while and it's a bit cleaner. Let's remove all of the existing usage of the existing pattern to avoid confusion when adopting the new one.
192 lines
5.3 KiB
Ruby
192 lines
5.3 KiB
Ruby
# typed: strict
|
|
# frozen_string_literal: true
|
|
|
|
require "hardware"
|
|
require "extend/ENV/shared"
|
|
|
|
module Stdenv
|
|
include SharedEnvExtension
|
|
|
|
SAFE_CFLAGS_FLAGS = "-w -pipe"
|
|
private_constant :SAFE_CFLAGS_FLAGS
|
|
|
|
sig {
|
|
params(
|
|
formula: T.nilable(Formula),
|
|
cc: T.nilable(String),
|
|
build_bottle: T.nilable(T::Boolean),
|
|
bottle_arch: T.nilable(String),
|
|
testing_formula: T::Boolean,
|
|
debug_symbols: T.nilable(T::Boolean),
|
|
).void
|
|
}
|
|
def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil, testing_formula: false,
|
|
debug_symbols: false)
|
|
super
|
|
|
|
self["HOMEBREW_ENV"] = "std"
|
|
|
|
ORIGINAL_PATHS.reverse_each { |p| prepend_path "PATH", p }
|
|
prepend_path "PATH", HOMEBREW_SHIMS_PATH/"shared"
|
|
|
|
# Set the default pkg-config search path, overriding the built-in paths
|
|
# Anything in PKG_CONFIG_PATH is searched before paths in this variable
|
|
self["PKG_CONFIG_LIBDIR"] = determine_pkg_config_libdir
|
|
|
|
self["MAKEFLAGS"] = "-j#{make_jobs}"
|
|
self["RUSTFLAGS"] = Hardware.rustflags_target_cpu(effective_arch)
|
|
|
|
if HOMEBREW_PREFIX.to_s != "/usr/local"
|
|
# /usr/local is already an -isystem and -L directory so we skip it
|
|
self["CPPFLAGS"] = "-isystem#{HOMEBREW_PREFIX}/include"
|
|
self["LDFLAGS"] = "-L#{HOMEBREW_PREFIX}/lib"
|
|
# CMake ignores the variables above
|
|
self["CMAKE_PREFIX_PATH"] = HOMEBREW_PREFIX.to_s
|
|
end
|
|
|
|
frameworks = HOMEBREW_PREFIX.join("Frameworks")
|
|
if frameworks.directory?
|
|
append "CPPFLAGS", "-F#{frameworks}"
|
|
append "LDFLAGS", "-F#{frameworks}"
|
|
self["CMAKE_FRAMEWORK_PATH"] = frameworks.to_s
|
|
end
|
|
|
|
# Os is the default Apple uses for all its stuff so let's trust them
|
|
define_cflags "-Os #{SAFE_CFLAGS_FLAGS}"
|
|
|
|
begin
|
|
send(compiler)
|
|
rescue CompilerSelectionError
|
|
# We don't care if our compiler fails to build the formula during `brew test`.
|
|
raise unless testing_formula
|
|
|
|
send(DevelopmentTools.default_compiler)
|
|
end
|
|
|
|
return unless cc&.match?(GNU_GCC_REGEXP)
|
|
|
|
gcc_formula = gcc_version_formula(cc)
|
|
append_path "PATH", gcc_formula.opt_bin.to_s
|
|
end
|
|
|
|
sig { returns(T.nilable(PATH)) }
|
|
def determine_pkg_config_libdir
|
|
PATH.new(
|
|
HOMEBREW_PREFIX/"lib/pkgconfig",
|
|
HOMEBREW_PREFIX/"share/pkgconfig",
|
|
homebrew_extra_pkg_config_paths,
|
|
"/usr/lib/pkgconfig",
|
|
).existing
|
|
end
|
|
|
|
# Removes the MAKEFLAGS environment variable, causing make to use a single job.
|
|
# This is useful for makefiles with race conditions.
|
|
# When passed a block, MAKEFLAGS is removed only for the duration of the block and is restored after its completion.
|
|
sig { params(block: T.proc.returns(T.untyped)).returns(T.untyped) }
|
|
def deparallelize(&block)
|
|
old = self["MAKEFLAGS"]
|
|
remove "MAKEFLAGS", /-j\d+/
|
|
if block
|
|
begin
|
|
yield
|
|
ensure
|
|
self["MAKEFLAGS"] = old
|
|
end
|
|
end
|
|
|
|
old
|
|
end
|
|
|
|
%w[O1 O0].each do |opt|
|
|
define_method opt do
|
|
send(:remove_from_cflags, /-O./)
|
|
send(:append_to_cflags, "-#{opt}")
|
|
end
|
|
end
|
|
|
|
sig { returns(T.any(String, Pathname)) }
|
|
def determine_cc
|
|
s = super
|
|
DevelopmentTools.locate(s) || Pathname(s)
|
|
end
|
|
private :determine_cc
|
|
|
|
sig { returns(Pathname) }
|
|
def determine_cxx
|
|
dir, base = Pathname(determine_cc).split
|
|
dir/base.to_s.sub("gcc", "g++").sub("clang", "clang++")
|
|
end
|
|
private :determine_cxx
|
|
|
|
GNU_GCC_VERSIONS.each do |n|
|
|
define_method(:"gcc-#{n}") do
|
|
super()
|
|
send(:set_cpu_cflags)
|
|
end
|
|
end
|
|
|
|
sig { void }
|
|
def clang
|
|
super
|
|
replace_in_cflags(/-Xarch_#{Hardware::CPU.arch_32_bit} (-march=\S*)/, '\1')
|
|
map = Hardware::CPU.optimization_flags.dup
|
|
if DevelopmentTools.clang_build_version < 700
|
|
# Clang mistakenly enables AES-NI on plain Nehalem
|
|
map[:nehalem] = "-march=nehalem -Xclang -target-feature -Xclang -aes"
|
|
end
|
|
set_cpu_cflags(map)
|
|
end
|
|
|
|
sig { void }
|
|
def cxx11
|
|
append "CXX", "-std=c++11"
|
|
libcxx
|
|
end
|
|
|
|
sig { void }
|
|
def libcxx
|
|
append "CXX", "-stdlib=libc++" if compiler == :clang
|
|
end
|
|
|
|
private
|
|
|
|
sig { params(before: Regexp, after: String).void }
|
|
def replace_in_cflags(before, after)
|
|
CC_FLAG_VARS.each do |key|
|
|
self[key] = fetch(key).sub(before, after) if key?(key)
|
|
end
|
|
end
|
|
|
|
# Convenience method to set all C compiler flags in one shot.
|
|
sig { params(val: String).void }
|
|
def define_cflags(val)
|
|
CC_FLAG_VARS.each { |key| self[key] = val }
|
|
end
|
|
|
|
# Sets architecture-specific flags for every environment variable
|
|
# given in the list `flags`.
|
|
sig { params(flags: T::Array[String], map: T::Hash[Symbol, String]).void }
|
|
def set_cpu_flags(flags, map = Hardware::CPU.optimization_flags)
|
|
cflags =~ /(-Xarch_#{Hardware::CPU.arch_32_bit} )-march=/
|
|
xarch = Regexp.last_match(1).to_s
|
|
remove flags, /(-Xarch_#{Hardware::CPU.arch_32_bit} )?-march=\S*/
|
|
remove flags, /( -Xclang \S+)+/
|
|
remove flags, /-mssse3/
|
|
remove flags, /-msse4(\.\d)?/
|
|
append flags, xarch unless xarch.empty?
|
|
append flags, map.fetch(effective_arch)
|
|
end
|
|
|
|
sig { returns(T::Array[Pathname]) }
|
|
def homebrew_extra_pkg_config_paths
|
|
[]
|
|
end
|
|
|
|
sig { params(map: T::Hash[Symbol, String]).void }
|
|
def set_cpu_cflags(map = Hardware::CPU.optimization_flags)
|
|
set_cpu_flags(CC_FLAG_VARS, map)
|
|
end
|
|
end
|
|
|
|
require "extend/os/extend/ENV/std"
|