PageRenderTime 61ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/Library/Homebrew/extend/ENV.rb

https://github.com/cybertoast/homebrew
Ruby | 449 lines | 331 code | 59 blank | 59 comment | 22 complexity | a3567edd6dbe8fcd6bd901d93601eb62 MD5 | raw file
  1. module HomebrewEnvExtension
  2. # -w: keep signal to noise high
  3. SAFE_CFLAGS_FLAGS = "-w -pipe"
  4. def setup_build_environment
  5. # Clear CDPATH to avoid make issues that depend on changing directories
  6. delete('CDPATH')
  7. delete('GREP_OPTIONS') # can break CMake (lol)
  8. delete('CLICOLOR_FORCE') # autotools doesn't like this
  9. remove_cc_etc
  10. # make any aclocal stuff installed in Homebrew available
  11. self['ACLOCAL_PATH'] = "#{HOMEBREW_PREFIX}/share/aclocal" if MacOS.xcode_version < "4.3"
  12. self['MAKEFLAGS'] = "-j#{self.make_jobs}"
  13. unless HOMEBREW_PREFIX.to_s == '/usr/local'
  14. # /usr/local is already an -isystem and -L directory so we skip it
  15. self['CPPFLAGS'] = "-isystem #{HOMEBREW_PREFIX}/include"
  16. self['LDFLAGS'] = "-L#{HOMEBREW_PREFIX}/lib"
  17. # CMake ignores the variables above
  18. self['CMAKE_PREFIX_PATH'] = "#{HOMEBREW_PREFIX}"
  19. end
  20. # Os is the default Apple uses for all its stuff so let's trust them
  21. set_cflags "-Os #{SAFE_CFLAGS_FLAGS}"
  22. # set us up for the user's compiler choice
  23. self.send self.compiler
  24. # we must have a working compiler!
  25. unless self['CC']
  26. @compiler = MacOS.default_compiler
  27. self.send @compiler
  28. self['CC'] = '/usr/bin/cc'
  29. self['CXX'] = '/usr/bin/c++'
  30. self['OBJC'] = self['CC']
  31. end
  32. # In rare cases this may break your builds, as the tool for some reason wants
  33. # to use a specific linker. However doing this in general causes formula to
  34. # build more successfully because we are changing CC and many build systems
  35. # don't react properly to that.
  36. self['LD'] = self['CC']
  37. end
  38. def deparallelize
  39. remove 'MAKEFLAGS', /-j\d+/
  40. end
  41. alias_method :j1, :deparallelize
  42. # recommended by Apple, but, eg. wget won't compile with this flag, so…
  43. def fast
  44. remove_from_cflags(/-O./)
  45. append_to_cflags '-fast'
  46. end
  47. def O4
  48. # LLVM link-time optimization
  49. remove_from_cflags(/-O./)
  50. append_to_cflags '-O4'
  51. end
  52. def O3
  53. # Sometimes O4 just takes fucking forever
  54. remove_from_cflags(/-O./)
  55. append_to_cflags '-O3'
  56. end
  57. def O2
  58. # Sometimes O3 doesn't work or produces bad binaries
  59. remove_from_cflags(/-O./)
  60. append_to_cflags '-O2'
  61. end
  62. def Os
  63. # Sometimes you just want a small one
  64. remove_from_cflags(/-O./)
  65. append_to_cflags '-Os'
  66. end
  67. def Og
  68. # Sometimes you want a debug build
  69. remove_from_cflags(/-O./)
  70. append_to_cflags '-g -O0'
  71. end
  72. def O1
  73. # Sometimes even O2 doesn't work :(
  74. remove_from_cflags(/-O./)
  75. append_to_cflags '-O1'
  76. end
  77. def gcc_4_0_1
  78. # we don't use xcrun because gcc 4.0 has not been provided since Xcode 4
  79. self['CC'] = "#{MacOS.dev_tools_path}/gcc-4.0"
  80. self['LD'] = self['CC']
  81. self['CXX'] = "#{MacOS.dev_tools_path}/g++-4.0"
  82. self['OBJC'] = self['CC']
  83. replace_in_cflags '-O4', '-O3'
  84. set_cpu_cflags 'nocona -mssse3', :core => 'prescott', :bottle => 'generic'
  85. @compiler = :gcc
  86. end
  87. alias_method :gcc_4_0, :gcc_4_0_1
  88. def xcrun tool
  89. if File.executable? "/usr/bin/#{tool}"
  90. "/usr/bin/#{tool}"
  91. elsif not MacOS.xctools_fucked? and system "/usr/bin/xcrun -find #{tool} 1>/dev/null 2>&1"
  92. # xcrun was provided first with Xcode 4.3 and allows us to proxy
  93. # tool usage thus avoiding various bugs
  94. "/usr/bin/xcrun #{tool}"
  95. else
  96. # otherwise lets try and figure it out ourselves
  97. fn = "#{MacOS.dev_tools_path}/#{tool}"
  98. if File.executable? fn
  99. fn
  100. else
  101. # This is for the use-case where xcode-select is not set up with
  102. # Xcode 4.3. The tools in Xcode 4.3 are split over two locations,
  103. # usually xcrun would figure that out for us, but it won't work if
  104. # xcode-select is not configured properly.
  105. fn = "#{MacOS.xcode_prefix}/Toolchains/XcodeDefault.xctoolchain/usr/bin/#{tool}"
  106. if File.executable? fn
  107. fn
  108. else
  109. nil
  110. end
  111. end
  112. end
  113. end
  114. # if your formula doesn't like CC having spaces use this
  115. def expand_xcrun
  116. self['CC'] =~ %r{/usr/bin/xcrun (.*)}
  117. self['CC'] = `/usr/bin/xcrun -find #{$1}`.chomp if $1
  118. self['CXX'] =~ %r{/usr/bin/xcrun (.*)}
  119. self['CXX'] = `/usr/bin/xcrun -find #{$1}`.chomp if $1
  120. self['LD'] = self['CC']
  121. self['OBJC'] = self['CC']
  122. end
  123. def gcc
  124. # Apple stopped shipping gcc-4.2 with Xcode 4.2
  125. # However they still provide a gcc symlink to llvm
  126. # But we don't want LLVM of course.
  127. self['CC'] = xcrun "gcc-4.2"
  128. self['LD'] = self['CC']
  129. self['CXX'] = xcrun "g++-4.2"
  130. self['OBJC'] = self['CC']
  131. unless self['CC']
  132. self['CC'] = "#{HOMEBREW_PREFIX}/bin/gcc-4.2"
  133. self['LD'] = self['CC']
  134. self['CXX'] = "#{HOMEBREW_PREFIX}/bin/g++-4.2"
  135. self['OBJC'] = self['CC']
  136. raise "GCC could not be found" if not File.exist? self['CC']
  137. end
  138. if not self['CC'] =~ %r{^/usr/bin/xcrun }
  139. raise "GCC could not be found" if Pathname.new(self['CC']).realpath.to_s =~ /llvm/
  140. end
  141. replace_in_cflags '-O4', '-O3'
  142. set_cpu_cflags 'core2 -msse4', :penryn => 'core2 -msse4.1', :core2 => 'core2', :core => 'prescott', :bottle => 'generic'
  143. @compiler = :gcc
  144. end
  145. alias_method :gcc_4_2, :gcc
  146. def llvm
  147. self['CC'] = xcrun "llvm-gcc"
  148. self['LD'] = self['CC']
  149. self['CXX'] = xcrun "llvm-g++"
  150. self['OBJC'] = self['CC']
  151. set_cpu_cflags 'core2 -msse4', :penryn => 'core2 -msse4.1', :core2 => 'core2', :core => 'prescott'
  152. @compiler = :llvm
  153. end
  154. def clang
  155. self['CC'] = xcrun "clang"
  156. self['LD'] = self['CC']
  157. self['CXX'] = xcrun "clang++"
  158. self['OBJC'] = self['CC']
  159. replace_in_cflags(/-Xarch_i386 (-march=\S*)/, '\1')
  160. # Clang mistakenly enables AES-NI on plain Nehalem
  161. set_cpu_cflags 'native', :nehalem => 'native -Xclang -target-feature -Xclang -aes'
  162. append_to_cflags '-Qunused-arguments'
  163. @compiler = :clang
  164. end
  165. def fortran
  166. if self['FC']
  167. ohai "Building with an alternative Fortran compiler. This is unsupported."
  168. self['F77'] = self['FC'] unless self['F77']
  169. if ARGV.include? '--default-fortran-flags'
  170. flags_to_set = []
  171. flags_to_set << 'FCFLAGS' unless self['FCFLAGS']
  172. flags_to_set << 'FFLAGS' unless self['FFLAGS']
  173. flags_to_set.each {|key| self[key] = cflags}
  174. # Ensure we use architecture optimizations for GCC 4.2.x
  175. set_cpu_flags flags_to_set, 'core2 -msse4', :penryn => 'core2 -msse4.1', :core2 => 'core2', :core => 'prescott', :bottle => 'generic'
  176. elsif not self['FCFLAGS'] or self['FFLAGS']
  177. opoo <<-EOS.undent
  178. No Fortran optimization information was provided. You may want to consider
  179. setting FCFLAGS and FFLAGS or pass the `--default-fortran-flags` option to
  180. `brew install` if your compiler is compatible with GCC.
  181. If you like the default optimization level of your compiler, ignore this
  182. warning.
  183. EOS
  184. end
  185. elsif `/usr/bin/which gfortran`.chomp.size > 0
  186. ohai <<-EOS.undent
  187. Using Homebrew-provided fortran compiler.
  188. This may be changed by setting the FC environment variable.
  189. EOS
  190. self['FC'] = `/usr/bin/which gfortran`.chomp
  191. self['F77'] = self['FC']
  192. fc_flag_vars.each {|key| self[key] = cflags}
  193. # Ensure we use architecture optimizations for GCC 4.2.x
  194. set_cpu_flags fc_flag_vars, 'core2 -msse4', :penryn => 'core2 -msse4.1', :core2 => 'core2', :core => 'prescott', :bottle => 'generic'
  195. else
  196. onoe <<-EOS
  197. This formula requires a fortran compiler, but we could not find one by
  198. looking at the FC environment variable or searching your PATH for `gfortran`.
  199. Please take one of the following actions:
  200. - Decide to use the build of gfortran 4.2.x provided by Homebrew using
  201. `brew install gfortran`
  202. - Choose another Fortran compiler by setting the FC environment variable:
  203. export FC=/path/to/some/fortran/compiler
  204. Using an alternative compiler may produce more efficient code, but we will
  205. not be able to provide support for build errors.
  206. EOS
  207. exit 1
  208. end
  209. end
  210. def osx_10_4
  211. self['MACOSX_DEPLOYMENT_TARGET']="10.4"
  212. remove_from_cflags(/ ?-mmacosx-version-min=10\.\d/)
  213. append_to_cflags('-mmacosx-version-min=10.4')
  214. end
  215. def osx_10_5
  216. self['MACOSX_DEPLOYMENT_TARGET']="10.5"
  217. remove_from_cflags(/ ?-mmacosx-version-min=10\.\d/)
  218. append_to_cflags('-mmacosx-version-min=10.5')
  219. end
  220. def minimal_optimization
  221. self['CFLAGS'] = self['CXXFLAGS'] = "-Os #{SAFE_CFLAGS_FLAGS}"
  222. end
  223. def no_optimization
  224. self['CFLAGS'] = self['CXXFLAGS'] = SAFE_CFLAGS_FLAGS
  225. end
  226. # Some configure scripts won't find libxml2 without help
  227. def libxml2
  228. append 'CPPFLAGS', '-I/usr/include/libxml2'
  229. end
  230. def x11
  231. opoo "You do not have X11 installed, this formula may not build." if not MacOS.x11_installed?
  232. # There are some config scripts (e.g. freetype) here that should go in the path
  233. prepend 'PATH', '/usr/X11/bin', ':'
  234. # CPPFLAGS are the C-PreProcessor flags, *not* C++!
  235. append 'CPPFLAGS', '-I/usr/X11/include'
  236. append 'LDFLAGS', '-L/usr/X11/lib'
  237. # CMake ignores the variables above
  238. append 'CMAKE_PREFIX_PATH', '/usr/X11', ':'
  239. end
  240. alias_method :libpng, :x11
  241. # we've seen some packages fail to build when warnings are disabled!
  242. def enable_warnings
  243. remove_from_cflags '-w'
  244. remove_from_cflags '-Qunused-arguments'
  245. end
  246. # Snow Leopard defines an NCURSES value the opposite of most distros
  247. # See: http://bugs.python.org/issue6848
  248. def ncurses_define
  249. append 'CPPFLAGS', "-DNCURSES_OPAQUE=0"
  250. end
  251. # Shortcuts for reading common flags
  252. def cc; self['CC'] or "gcc"; end
  253. def cxx; self['CXX'] or "g++"; end
  254. def cflags; self['CFLAGS']; end
  255. def cxxflags;self['CXXFLAGS']; end
  256. def cppflags;self['CPPFLAGS']; end
  257. def ldflags; self['LDFLAGS']; end
  258. # Shortcuts for lists of common flags
  259. def cc_flag_vars
  260. %w{CFLAGS CXXFLAGS OBJCFLAGS OBJCXXFLAGS}
  261. end
  262. def fc_flag_vars
  263. %w{FCFLAGS FFLAGS}
  264. end
  265. def m64
  266. append_to_cflags '-m64'
  267. append 'LDFLAGS', '-arch x86_64'
  268. end
  269. def m32
  270. append_to_cflags '-m32'
  271. append 'LDFLAGS', '-arch i386'
  272. end
  273. # i386 and x86_64 (no PPC)
  274. def universal_binary
  275. append_to_cflags '-arch i386 -arch x86_64'
  276. replace_in_cflags '-O4', '-O3' # O4 seems to cause the build to fail
  277. append 'LDFLAGS', '-arch i386 -arch x86_64'
  278. unless compiler == :clang
  279. # Can't mix "-march" for a 32-bit CPU with "-arch x86_64"
  280. replace_in_cflags(/-march=\S*/, '-Xarch_i386 \0') if Hardware.is_32_bit?
  281. end
  282. end
  283. def prepend key, value, separator = ' '
  284. # Value should be a string, but if it is a pathname then coerce it.
  285. value = value.to_s
  286. [*key].each do |key|
  287. unless self[key].to_s.empty?
  288. self[key] = value + separator + self[key]
  289. else
  290. self[key] = value
  291. end
  292. end
  293. end
  294. def append key, value, separator = ' '
  295. # Value should be a string, but if it is a pathname then coerce it.
  296. value = value.to_s
  297. [*key].each do |key|
  298. unless self[key].to_s.empty?
  299. self[key] = self[key] + separator + value
  300. else
  301. self[key] = value
  302. end
  303. end
  304. end
  305. def append_to_cflags f
  306. append cc_flag_vars, f
  307. end
  308. def remove key, value
  309. [*key].each do |key|
  310. next if self[key].nil?
  311. self[key] = self[key].sub value, '' # can't use sub! on ENV
  312. self[key] = nil if self[key].empty? # keep things clean
  313. end
  314. end
  315. def remove_from_cflags f
  316. remove cc_flag_vars, f
  317. end
  318. def replace_in_cflags before, after
  319. cc_flag_vars.each do |key|
  320. self[key] = self[key].sub before, after if self[key]
  321. end
  322. end
  323. # Convenience method to set all C compiler flags in one shot.
  324. def set_cflags f
  325. cc_flag_vars.each do |key|
  326. self[key] = f
  327. end
  328. end
  329. # Sets architecture-specific flags for every environment variable
  330. # given in the list `flags`.
  331. def set_cpu_flags flags, default, map = {}
  332. cflags =~ %r{(-Xarch_i386 )-march=}
  333. xarch = $1.to_s
  334. remove flags, %r{(-Xarch_i386 )?-march=\S*}
  335. remove flags, %r{( -Xclang \S+)+}
  336. remove flags, %r{-mssse3}
  337. remove flags, %r{-msse4(\.\d)?}
  338. append flags, xarch unless xarch.empty?
  339. if ARGV.build_bottle?
  340. append flags, '-mtune=' + map.fetch(:bottle) if map.has_key? :bottle
  341. else
  342. # Don't set -msse3 and older flags because -march does that for us
  343. append flags, '-march=' + map.fetch(Hardware.intel_family, default)
  344. end
  345. # not really a 'CPU' cflag, but is only used with clang
  346. remove flags, '-Qunused-arguments'
  347. end
  348. def set_cpu_cflags default, map = {}
  349. set_cpu_flags cc_flag_vars, default, map
  350. end
  351. # actually c-compiler, so cc would be a better name
  352. def compiler
  353. # TODO seems that ENV.clang in a Formula.install should warn when called
  354. # if the user has set something that is tested here
  355. # test for --flags first so that installs can be overridden on a per
  356. # install basis. Then test for ENVs in inverse order to flags, this is
  357. # sensible, trust me
  358. @compiler ||= if ARGV.include? '--use-gcc'
  359. :gcc
  360. elsif ARGV.include? '--use-llvm'
  361. :llvm
  362. elsif ARGV.include? '--use-clang'
  363. :clang
  364. elsif self['HOMEBREW_USE_CLANG']
  365. :clang
  366. elsif self['HOMEBREW_USE_LLVM']
  367. :llvm
  368. elsif self['HOMEBREW_USE_GCC']
  369. :gcc
  370. else
  371. MacOS.default_compiler
  372. end
  373. end
  374. def make_jobs
  375. # '-j' requires a positive integral argument
  376. if self['HOMEBREW_MAKE_JOBS'].to_i > 0
  377. self['HOMEBREW_MAKE_JOBS']
  378. else
  379. Hardware.processor_count
  380. end
  381. end
  382. def remove_cc_etc
  383. keys = %w{CC CXX LD CPP CFLAGS CXXFLAGS OBJCFLAGS OBJCXXFLAGS LDFLAGS CPPFLAGS}
  384. removed = Hash[*keys.map{ |key| [key, self[key]] }.flatten]
  385. keys.each do |key|
  386. self[key] = nil
  387. end
  388. removed
  389. end
  390. end