Module: SharedEnvExtension

Includes:
CompilerConstants
Included in:
Stdenv, Superenv
Defined in:
Library/Homebrew/extend/ENV/shared.rb,
Library/Homebrew/extend/os/mac/extend/ENV/shared.rb

Overview

Homebrew extends Ruby's `ENV` to make our code more readable. Implemented in SharedEnvExtension and either Superenv or Stdenv (depending on the build mode).

Constant Summary collapse

CC_FLAG_VARS =
%w[CFLAGS CXXFLAGS OBJCFLAGS OBJCXXFLAGS].freeze
FC_FLAG_VARS =
%w[FCFLAGS FFLAGS].freeze
SANITIZED_VARS =
%w[
  CDPATH CLICOLOR_FORCE
  CPATH C_INCLUDE_PATH CPLUS_INCLUDE_PATH OBJC_INCLUDE_PATH
  CC CXX OBJC OBJCXX CPP MAKE LD LDSHARED
  CFLAGS CXXFLAGS OBJCFLAGS OBJCXXFLAGS LDFLAGS CPPFLAGS
  MACOSX_DEPLOYMENT_TARGET SDKROOT DEVELOPER_DIR
  CMAKE_PREFIX_PATH CMAKE_INCLUDE_PATH CMAKE_FRAMEWORK_PATH
  GOBIN GOPATH GOROOT PERL_MB_OPT PERL_MM_OPT
  LIBRARY_PATH
].freeze

Constants included from CompilerConstants

CompilerConstants::COMPILERS, CompilerConstants::COMPILER_SYMBOL_MAP, CompilerConstants::GNU_GCC_REGEXP, CompilerConstants::GNU_GCC_VERSIONS

Instance Method Summary collapse

Instance Method Details

#append(keys, value, separator = " ") ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
# File 'Library/Homebrew/extend/ENV/shared.rb', line 59

def append(keys, value, separator = " ")
  value = value.to_s
  Array(keys).each do |key|
    old = self[key]
    if old.nil? || old.empty?
      self[key] = value
    else
      self[key] += separator + value
    end
  end
end

#append_path(key, path) ⇒ Object



83
84
85
# File 'Library/Homebrew/extend/ENV/shared.rb', line 83

def append_path(key, path)
  self[key] = PATH.new(self[key]).append(path)
end

#append_to_cflags(newflags) ⇒ Object



51
52
53
# File 'Library/Homebrew/extend/ENV/shared.rb', line 51

def append_to_cflags(newflags)
  append(CC_FLAG_VARS, newflags)
end

#ccObject



114
115
116
# File 'Library/Homebrew/extend/ENV/shared.rb', line 114

def cc
  self["CC"]
end

#cflagsObject



122
123
124
# File 'Library/Homebrew/extend/ENV/shared.rb', line 122

def cflags
  self["CFLAGS"]
end

#compilerSymbol

Outputs the current compiler. <pre># Do something only for clang if ENV.compiler == :clang

# modify CFLAGS CXXFLAGS OBJCFLAGS OBJCXXFLAGS in one go:
ENV.append_to_cflags "-I ./missing/includes"

end</pre>

Returns:



157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'Library/Homebrew/extend/ENV/shared.rb', line 157

def compiler
  @compiler ||= if (cc = ARGV.cc)
    warn_about_non_apple_gcc($&) if cc =~ GNU_GCC_REGEXP
    fetch_compiler(cc, "--cc")
  elsif (cc = homebrew_cc)
    warn_about_non_apple_gcc($&) if cc =~ GNU_GCC_REGEXP
    compiler = fetch_compiler(cc, "HOMEBREW_CC")

    if @formula
      compilers = [compiler] + CompilerSelector.compilers
      compiler = CompilerSelector.select_for(@formula, compilers)
    end

    compiler
  elsif @formula
    CompilerSelector.select_for(@formula)
  else
    DevelopmentTools.default_compiler
  end
end

#cppflagsObject



130
131
132
# File 'Library/Homebrew/extend/ENV/shared.rb', line 130

def cppflags
  self["CPPFLAGS"]
end

#cxxObject



118
119
120
# File 'Library/Homebrew/extend/ENV/shared.rb', line 118

def cxx
  self["CXX"]
end

#cxxflagsObject



126
127
128
# File 'Library/Homebrew/extend/ENV/shared.rb', line 126

def cxxflags
  self["CXXFLAGS"]
end

#determine_ccObject



179
180
181
# File 'Library/Homebrew/extend/ENV/shared.rb', line 179

def determine_cc
  COMPILER_SYMBOL_MAP.invert.fetch(compiler, compiler)
end

#fcObject



138
139
140
# File 'Library/Homebrew/extend/ENV/shared.rb', line 138

def fc
  self["FC"]
end

#fcflagsObject



146
147
148
# File 'Library/Homebrew/extend/ENV/shared.rb', line 146

def fcflags
  self["FCFLAGS"]
end

#fflagsObject



142
143
144
# File 'Library/Homebrew/extend/ENV/shared.rb', line 142

def fflags
  self["FFLAGS"]
end

#fortranObject



219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
# File 'Library/Homebrew/extend/ENV/shared.rb', line 219

def fortran
  # Ignore repeated calls to this function as it will misleadingly warn about
  # building with an alternative Fortran compiler without optimization flags,
  # despite it often being the Homebrew-provided one set up in the first call.
  return if @fortran_setup_done
  @fortran_setup_done = true

  flags = []

  if fc
    ohai "Building with an alternative Fortran compiler"
    puts "This is unsupported."
    self["F77"] ||= fc

    if ARGV.include? "--default-fortran-flags"
      flags = FC_FLAG_VARS.reject { |key| self[key] }
    elsif values_at(*FC_FLAG_VARS).compact.empty?
      opoo <<~EOS
        No Fortran optimization information was provided.  You may want to consider
        setting FCFLAGS and FFLAGS or pass the `--default-fortran-flags` option to
        `brew install` if your compiler is compatible with GCC.

        If you like the default optimization level of your compiler, ignore this
        warning.
      EOS
    end

  else
    if (gfortran = which("gfortran", (HOMEBREW_PREFIX/"bin").to_s))
      ohai "Using Homebrew-provided fortran compiler."
    elsif (gfortran = which("gfortran", PATH.new(ORIGINAL_PATHS)))
      ohai "Using a fortran compiler found at #{gfortran}."
    end
    if gfortran
      puts "This may be changed by setting the FC environment variable."
      self["FC"] = self["F77"] = gfortran
      flags = FC_FLAG_VARS
    end
  end

  flags.each { |key| self[key] = cflags }
  set_cpu_flags(flags)
end

#gcc_version_formula(name) ⇒ Object



272
273
274
275
276
277
278
279
280
281
282
# File 'Library/Homebrew/extend/ENV/shared.rb', line 272

def gcc_version_formula(name)
  version = name[GNU_GCC_REGEXP, 1]
  gcc_version_name = "gcc@#{version}"

  gcc = Formulary.factory("gcc")
  if gcc.version_suffix == version
    gcc
  else
    Formulary.factory(gcc_version_name)
  end
end

#ld64Object

ld64 is a newer linker provided for Xcode 2.5



265
266
267
268
269
# File 'Library/Homebrew/extend/ENV/shared.rb', line 265

def ld64
  ld64 = Formulary.factory("ld64")
  self["LD"] = ld64.bin/"ld"
  append "LDFLAGS", "-B#{ld64.bin}/"
end

#ldflagsObject



134
135
136
# File 'Library/Homebrew/extend/ENV/shared.rb', line 134

def ldflags
  self["LDFLAGS"]
end

#ncurses_defineObject

Snow Leopard defines an NCURSES value the opposite of most distros. See: bugs.python.org/issue6848 Currently only used by aalib in core.



194
195
196
# File 'Library/Homebrew/extend/ENV/shared.rb', line 194

def ncurses_define
  append "CPPFLAGS", "-DNCURSES_OPAQUE=0"
end

#no_weak_imports_support?Boolean

Returns:

  • (Boolean)


2
3
4
5
6
7
8
9
# File 'Library/Homebrew/extend/os/mac/extend/ENV/shared.rb', line 2

def no_weak_imports_support?
  return false unless compiler == :clang

  return false if MacOS::Xcode.version && MacOS::Xcode.version < "8.0"
  return false if MacOS::CLT.version && MacOS::CLT.version < "8.0"

  true
end

#permit_arch_flagsObject



301
# File 'Library/Homebrew/extend/ENV/shared.rb', line 301

def permit_arch_flags; end

#permit_weak_importsObject

A no-op until we enable this by default again (which we may never do).



304
# File 'Library/Homebrew/extend/ENV/shared.rb', line 304

def permit_weak_imports; end

#prepend(keys, value, separator = " ") ⇒ Object



71
72
73
74
75
76
77
78
79
80
81
# File 'Library/Homebrew/extend/ENV/shared.rb', line 71

def prepend(keys, value, separator = " ")
  value = value.to_s
  Array(keys).each do |key|
    old = self[key]
    if old.nil? || old.empty?
      self[key] = value
    else
      self[key] = value + separator + old
    end
  end
end

#prepend_create_path(key, path) ⇒ Object



99
100
101
102
103
# File 'Library/Homebrew/extend/ENV/shared.rb', line 99

def prepend_create_path(key, path)
  path = Pathname.new(path) unless path.is_a? Pathname
  path.mkpath
  prepend_path key, path
end

#prepend_path(key, path) ⇒ Object

Prepends a directory to `PATH`. Is the formula struggling to find the pkgconfig file? Point it to it. This is done automatically for `keg_only` formulae. <pre>ENV.prepend_path “PKG_CONFIG_PATH”, “#.opt_lib/pkgconfig”</pre> Prepending a system path such as /usr/bin is a no-op so that requirements don't accidentally override superenv shims or formulae's `bin` directories (e.g. <pre>ENV.prepend_path “PATH”, which(“emacs”).dirname</pre>)



94
95
96
97
# File 'Library/Homebrew/extend/ENV/shared.rb', line 94

def prepend_path(key, path)
  return if %w[/usr/bin /bin /usr/sbin /sbin].include? path.to_s
  self[key] = PATH.new(self[key]).prepend(path)
end

#remove(keys, value) ⇒ Object



105
106
107
108
109
110
111
112
# File 'Library/Homebrew/extend/ENV/shared.rb', line 105

def remove(keys, value)
  return if value.nil?
  Array(keys).each do |key|
    next unless self[key]
    self[key] = self[key].sub(value, "")
    delete(key) if self[key].empty?
  end
end

#remove_cc_etcObject



42
43
44
45
46
47
48
49
# File 'Library/Homebrew/extend/ENV/shared.rb', line 42

def remove_cc_etc
  keys = %w[CC CXX OBJC OBJCXX LD CPP CFLAGS CXXFLAGS OBJCFLAGS OBJCXXFLAGS LDFLAGS CPPFLAGS]
  removed = Hash[*keys.flat_map { |key| [key, self[key]] }]
  keys.each do |key|
    delete(key)
  end
  removed
end

#remove_from_cflags(val) ⇒ Object



55
56
57
# File 'Library/Homebrew/extend/ENV/shared.rb', line 55

def remove_from_cflags(val)
  remove CC_FLAG_VARS, val
end

#resetObject



38
39
40
# File 'Library/Homebrew/extend/ENV/shared.rb', line 38

def reset
  SANITIZED_VARS.each { |k| delete(k) }
end

#setup_build_environment(formula = nil) ⇒ Object



32
33
34
35
# File 'Library/Homebrew/extend/ENV/shared.rb', line 32

def setup_build_environment(formula = nil)
  @formula = formula
  reset
end

#userpaths!Object



199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
# File 'Library/Homebrew/extend/ENV/shared.rb', line 199

def userpaths!
  path = PATH.new(self["PATH"]).select do |p|
    # put Superenv.bin and opt path at the first
    p.start_with?("#{HOMEBREW_REPOSITORY}/Library/ENV", "#{HOMEBREW_PREFIX}/opt")
  end
  path.append(HOMEBREW_PREFIX/"bin") # XXX hot fix to prefer brewed stuff (e.g. python) over /usr/bin.
  path.append(self["PATH"]) # reset of self["PATH"]
  path.append(
    # user paths
    ORIGINAL_PATHS.map do |p|
      begin
        p.realpath.to_s
      rescue
        nil
      end
    end - %w[/usr/X11/bin /opt/X11/bin],
  )
  self["PATH"] = path
end

#warn_about_non_apple_gcc(name) ⇒ Object



285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
# File 'Library/Homebrew/extend/ENV/shared.rb', line 285

def warn_about_non_apple_gcc(name)
  begin
    gcc_formula = gcc_version_formula(name)
  rescue FormulaUnavailableError => e
    raise <<~EOS
      Homebrew GCC requested, but formula #{e.name} not found!
    EOS
  end

  return if gcc_formula.opt_prefix.exist?
  raise <<~EOS
    The requested Homebrew GCC was not installed. You must:
      brew install #{gcc_formula.full_name}
  EOS
end