aboutsummaryrefslogtreecommitdiffstats
path: root/Library/Homebrew
diff options
context:
space:
mode:
authorMike McQuaid2015-08-29 10:56:24 +0100
committerMike McQuaid2015-08-29 15:43:16 +0100
commit2c959a7d5847094d316278188e816a7dadc1a090 (patch)
tree1788b7791102363b7eab595f1346e3199b4de80a /Library/Homebrew
parent77536e39de0368a0ba3ca2b46f0417abdf75aadf (diff)
downloadbrew-2c959a7d5847094d316278188e816a7dadc1a090.tar.bz2
More API documentation.
And remove the documented stuff from the `example-formula.rb`. Closes Homebrew/homebrew#43241. Signed-off-by: Mike McQuaid <mike@mikemcquaid.com>
Diffstat (limited to 'Library/Homebrew')
-rw-r--r--Library/Homebrew/README.md10
-rw-r--r--Library/Homebrew/build_options.rb39
-rw-r--r--Library/Homebrew/cmd/create.rb2
-rw-r--r--Library/Homebrew/cmd/man.rb8
-rw-r--r--Library/Homebrew/compilers.rb1
-rw-r--r--Library/Homebrew/extend/ENV/shared.rb32
-rw-r--r--Library/Homebrew/extend/ENV/std.rb11
-rw-r--r--Library/Homebrew/extend/ENV/super.rb29
-rw-r--r--Library/Homebrew/extend/fileutils.rb22
-rw-r--r--Library/Homebrew/extend/pathname.rb36
-rw-r--r--Library/Homebrew/formula.rb479
-rw-r--r--Library/Homebrew/mach.rb16
-rw-r--r--Library/Homebrew/manpages/brew.1.md2
-rw-r--r--Library/Homebrew/utils.rb1
-rw-r--r--Library/Homebrew/utils/inreplace.rb7
15 files changed, 633 insertions, 62 deletions
diff --git a/Library/Homebrew/README.md b/Library/Homebrew/README.md
index f154675e2..00036f131 100644
--- a/Library/Homebrew/README.md
+++ b/Library/Homebrew/README.md
@@ -1,4 +1,8 @@
-# Homebrew Public API
-We're (finally) working on a documented public API for Homebrew. It's currently a work in progress; a bunch of public stuff is documented and a bunch of private stuff is undocumented. Sorry about that!
+# Homebrew's Formula API
+This is the (partially) documented public API for Homebrew. It's currently a work in progress. Sorry about that!
-The main class you should look at is {Formula}. Assume everything else is private for now.
+The main class you should look at is the {Formula} class (and classes linked from there). That's the class that's used to create Homebrew formulae (i.e. package descriptions). Assume anything else you stumble upon is private.
+
+You may also find the [Formula Cookbook](Formula-Cookbook.md) and [Ruby Style Guide](https://github.com/styleguide/ruby) helpful in creating formulae.
+
+Good luck!
diff --git a/Library/Homebrew/build_options.rb b/Library/Homebrew/build_options.rb
index 05f8507de..2e8f741d4 100644
--- a/Library/Homebrew/build_options.rb
+++ b/Library/Homebrew/build_options.rb
@@ -1,13 +1,28 @@
class BuildOptions
+ # @private
def initialize(args, options)
@args = args
@options = options
end
+ # True if a {Formula} is being built with a specific option
+ # (which isn't named `with-*` or `without-*`).
+ # @deprecated
def include?(name)
@args.include?("--#{name}")
end
+ # True if a {Formula} is being built with a specific option.
+ # <pre>args << "--i-want-spam" if build.with? "spam"
+ #
+ # args << "--qt-gui" if build.with? "qt" # "--with-qt" ==> build.with? "qt"
+ #
+ # # If a formula presents a user with a choice, but the choice must be fulfilled:
+ # if build.with? "example2"
+ # args << "--with-example2"
+ # else
+ # args << "--with-example1"
+ # end</pre>
def with?(val)
name = val.respond_to?(:option_name) ? val.option_name : val
@@ -20,47 +35,65 @@ class BuildOptions
end
end
+ # True if a {Formula} is being built without a specific option.
+ # <pre>args << "--no-spam-plz" if build.without? "spam"
def without?(name)
!with? name
end
+ # True if a {Formula} is being built as a bottle (i.e. binary package).
def bottle?
include? "build-bottle"
end
+ # True if a {Formula} is being built with {Formula.head} instead of {Formula.stable}.
+ # <pre>args << "--some-new-stuff" if build.head?</pre>
+ # <pre># If there are multiple conditional arguments use a block instead of lines.
+ # if build.head?
+ # args << "--i-want-pizza"
+ # args << "--and-a-cold-beer" if build.with? "cold-beer"
+ # end</pre>
def head?
include? "HEAD"
end
+ # True if a {Formula} is being built with {Formula.devel} instead of {Formula.stable}.
+ # <pre>args << "--some-beta" if build.devel?</pre>
def devel?
include? "devel"
end
+ # True if a {Formula} is being built with {Formula.stable} instead of {Formula.devel} or {Formula.head}. This is the default.
+ # <pre>args << "--some-beta" if build.devel?</pre>
def stable?
!(head? || devel?)
end
- # True if the user requested a universal build.
+ # True if a {Formula} is being built universally.
+ # e.g. on newer Intel Macs this means a combined x86_64/x86 binary/library.
+ # <pre>args << "--universal-binary" if build.universal?</pre>
def universal?
include?("universal") && option_defined?("universal")
end
- # True if the user requested to enable C++11 mode.
+ # True if a {Formula} is being built in C++11 mode.
def cxx11?
include?("c++11") && option_defined?("c++11")
end
- # Request a 32-bit only build.
+ # True if a {Formula} is being built in 32-bit/x86 mode.
# This is needed for some use-cases though we prefer to build Universal
# when a 32-bit version is needed.
def build_32_bit?
include?("32-bit") && option_defined?("32-bit")
end
+ # @private
def used_options
@options & @args
end
+ # @private
def unused_options
@options - @args
end
diff --git a/Library/Homebrew/cmd/create.rb b/Library/Homebrew/cmd/create.rb
index 88b8c0df3..e83c9facd 100644
--- a/Library/Homebrew/cmd/create.rb
+++ b/Library/Homebrew/cmd/create.rb
@@ -118,7 +118,7 @@ class FormulaCreator
def template; <<-EOS.undent
# Documentation: https://github.com/Homebrew/homebrew/blob/master/share/doc/homebrew/Formula-Cookbook.md
- # #{HOMEBREW_CONTRIB}/example-formula.rb
+ # http://www.rubydoc.info/github/Homebrew/homebrew/master/frames
# PLEASE REMOVE ALL GENERATED COMMENTS BEFORE SUBMITTING YOUR PULL REQUEST!
class #{Formulary.class_s(name)} < Formula
diff --git a/Library/Homebrew/cmd/man.rb b/Library/Homebrew/cmd/man.rb
index 5c4abbe39..208c07d47 100644
--- a/Library/Homebrew/cmd/man.rb
+++ b/Library/Homebrew/cmd/man.rb
@@ -3,6 +3,7 @@ require "formula"
module Homebrew
SOURCE_PATH=HOMEBREW_REPOSITORY/"Library/Homebrew/manpages"
TARGET_PATH=HOMEBREW_REPOSITORY/"share/man/man1"
+ DOC_PATH=HOMEBREW_REPOSITORY/"share/doc/homebrew"
LINKED_PATH=HOMEBREW_PREFIX/"share/man/man1"
def man
@@ -21,12 +22,15 @@ module Homebrew
else
Homebrew.install_gem_setup_path! "ronn"
+ puts "Writing HTML fragments to #{DOC_PATH}"
puts "Writing manpages to #{TARGET_PATH}"
target_file = nil
Dir["#{SOURCE_PATH}/*.md"].each do |source_file|
- target_file = TARGET_PATH/File.basename(source_file, ".md")
- safe_system "ronn --roff --pipe --organization='Homebrew' --manual='brew' #{source_file} > #{target_file}"
+ target_html = DOC_PATH/"#{File.basename(source_file, ".md")}.html"
+ safe_system "ronn --fragment --pipe --organization='Homebrew' --manual='brew' #{source_file} > #{target_html}"
+ target_man = TARGET_PATH/File.basename(source_file, ".md")
+ safe_system "ronn --roff --pipe --organization='Homebrew' --manual='brew' #{source_file} > #{target_man}"
end
system "man", target_file if ARGV.flag? "--verbose"
diff --git a/Library/Homebrew/compilers.rb b/Library/Homebrew/compilers.rb
index 4ed8c7f00..ab710a6d0 100644
--- a/Library/Homebrew/compilers.rb
+++ b/Library/Homebrew/compilers.rb
@@ -1,3 +1,4 @@
+# @private
module CompilerConstants
GNU_GCC_VERSIONS = %w[4.3 4.4 4.5 4.6 4.7 4.8 4.9 5]
GNU_GCC_REGEXP = /^gcc-(4\.[3-9]|5)$/
diff --git a/Library/Homebrew/extend/ENV/shared.rb b/Library/Homebrew/extend/ENV/shared.rb
index a85eff305..7553540c9 100644
--- a/Library/Homebrew/extend/ENV/shared.rb
+++ b/Library/Homebrew/extend/ENV/shared.rb
@@ -1,12 +1,20 @@
require "formula"
require "compilers"
+# Homebrew extends Ruby's `ENV` to make our code more readable.
+# Implemented in {SharedEnvExtension} and either {Superenv} or
+# {Stdenv} (depending on the build mode).
+# @see Superenv
+# @see Stdenv
+# @see http://www.rubydoc.info/stdlib/Env Ruby's ENV API
module SharedEnvExtension
include CompilerConstants
+ # @private
CC_FLAG_VARS = %w[CFLAGS CXXFLAGS OBJCFLAGS OBJCXXFLAGS]
+ # @private
FC_FLAG_VARS = %w[FCFLAGS FFLAGS]
-
+ # @private
SANITIZED_VARS = %w[
CDPATH GREP_OPTIONS CLICOLOR_FORCE
CPATH C_INCLUDE_PATH CPLUS_INCLUDE_PATH OBJC_INCLUDE_PATH
@@ -18,11 +26,13 @@ module SharedEnvExtension
LIBRARY_PATH
]
+ # @private
def setup_build_environment(formula = nil)
@formula = formula
reset
end
+ # @private
def reset
SANITIZED_VARS.each { |k| delete(k) }
end
@@ -72,6 +82,10 @@ module SharedEnvExtension
append key, path, File::PATH_SEPARATOR if File.directory? path
end
+ # 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", "#{Formula["glib"].opt_lib}/pkgconfig"</pre>
def prepend_path(key, path)
prepend key, path, File::PATH_SEPARATOR if File.directory? path
end
@@ -126,6 +140,13 @@ module SharedEnvExtension
self["FCFLAGS"]
end
+ # Outputs the current compiler.
+ # @return [Symbol]
+ # <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>
def compiler
@compiler ||= if (cc = ARGV.cc)
warn_about_non_apple_gcc($&) if cc =~ GNU_GCC_REGEXP
@@ -147,6 +168,7 @@ module SharedEnvExtension
end
end
+ # @private
def determine_cc
COMPILER_SYMBOL_MAP.invert.fetch(compiler, compiler)
end
@@ -159,13 +181,14 @@ module SharedEnvExtension
end
end
- # Snow Leopard defines an NCURSES value the opposite of most distros
+ # Snow Leopard defines an NCURSES value the opposite of most distros.
# See: https://bugs.python.org/issue6848
- # Currently only used by aalib in core
+ # Currently only used by aalib in core.
def ncurses_define
append "CPPFLAGS", "-DNCURSES_OPAQUE=0"
end
+ # @private
def userpaths!
paths = ORIGINAL_PATHS.map { |p| p.realpath.to_s rescue nil } - %w[/usr/X11/bin /opt/X11/bin]
self["PATH"] = paths.unshift(*self["PATH"].split(File::PATH_SEPARATOR)).uniq.join(File::PATH_SEPARATOR)
@@ -212,12 +235,14 @@ module SharedEnvExtension
end
# ld64 is a newer linker provided for Xcode 2.5
+ # @private
def ld64
ld64 = Formulary.factory("ld64")
self["LD"] = ld64.bin/"ld"
append "LDFLAGS", "-B#{ld64.bin}/"
end
+ # @private
def gcc_version_formula(name)
version = name[GNU_GCC_REGEXP, 1]
gcc_version_name = "gcc#{version.delete(".")}"
@@ -230,6 +255,7 @@ module SharedEnvExtension
end
end
+ # @private
def warn_about_non_apple_gcc(name)
begin
gcc_formula = gcc_version_formula(name)
diff --git a/Library/Homebrew/extend/ENV/std.rb b/Library/Homebrew/extend/ENV/std.rb
index d05ccf1a3..fef991540 100644
--- a/Library/Homebrew/extend/ENV/std.rb
+++ b/Library/Homebrew/extend/ENV/std.rb
@@ -2,9 +2,11 @@ require "hardware"
require "os/mac"
require "extend/ENV/shared"
+# @deprecated
module Stdenv
include SharedEnvExtension
+ # @private
SAFE_CFLAGS_FLAGS = "-w -pipe"
DEFAULT_FLAGS = "-march=core2 -msse4"
@@ -14,6 +16,7 @@ module Stdenv
end
end
+ # @private
def setup_build_environment(formula = nil)
super
@@ -69,6 +72,7 @@ module Stdenv
end
end
+ # @private
def determine_pkg_config_libdir
paths = []
paths << "#{HOMEBREW_PREFIX}/lib/pkgconfig"
@@ -106,11 +110,13 @@ module Stdenv
end
end
+ # @private
def determine_cc
s = super
MacOS.locate(s) || Pathname.new(s)
end
+ # @private
def determine_cxx
dir, base = determine_cc.split
dir / base.to_s.sub("gcc", "g++").sub("clang", "clang++")
@@ -295,6 +301,7 @@ module Stdenv
end
end
+ # @private
def replace_in_cflags(before, after)
CC_FLAG_VARS.each do |key|
self[key] = self[key].sub(before, after) if key?(key)
@@ -308,6 +315,7 @@ module Stdenv
# Sets architecture-specific flags for every environment variable
# given in the list `flags`.
+ # @private
def set_cpu_flags(flags, default = DEFAULT_FLAGS, map = Hardware::CPU.optimization_flags)
cflags =~ /(-Xarch_#{Hardware::CPU.arch_32_bit} )-march=/
xarch = $1.to_s
@@ -319,6 +327,7 @@ module Stdenv
append flags, map.fetch(effective_arch, default)
end
+ # @private
def effective_arch
if ARGV.build_bottle?
ARGV.bottle_arch || Hardware.oldest_cpu
@@ -332,6 +341,7 @@ module Stdenv
end
end
+ # @private
def set_cpu_cflags(default = DEFAULT_FLAGS, map = Hardware::CPU.optimization_flags)
set_cpu_flags CC_FLAG_VARS, default, map
end
@@ -346,5 +356,6 @@ module Stdenv
end
# This method does nothing in stdenv since there's no arg refurbishment
+ # @private
def refurbish_args; end
end
diff --git a/Library/Homebrew/extend/ENV/super.rb b/Library/Homebrew/extend/ENV/super.rb
index 95a8773cd..5216b579c 100644
--- a/Library/Homebrew/extend/ENV/super.rb
+++ b/Library/Homebrew/extend/ENV/super.rb
@@ -1,20 +1,23 @@
require "os/mac"
require "extend/ENV/shared"
-### Why `superenv`?
-# 1) Only specify the environment we need (NO LDFLAGS for cmake)
-# 2) Only apply compiler specific options when we are calling that compiler
-# 3) Force all incpaths and libpaths into the cc instantiation (less bugs)
-# 4) Cater toolchain usage to specific Xcode versions
-# 5) Remove flags that we don't want or that will break builds
-# 6) Simpler code
-# 7) Simpler formula that *just work*
-# 8) Build-system agnostic configuration of the tool-chain
-
+# ### Why `superenv`?
+#
+# 1. Only specify the environment we need (NO LDFLAGS for cmake)
+# 2. Only apply compiler specific options when we are calling that compiler
+# 3. Force all incpaths and libpaths into the cc instantiation (less bugs)
+# 4. Cater toolchain usage to specific Xcode versions
+# 5. Remove flags that we don't want or that will break builds
+# 6. Simpler code
+# 7. Simpler formula that *just work*
+# 8. Build-system agnostic configuration of the tool-chain
module Superenv
include SharedEnvExtension
- attr_accessor :keg_only_deps, :deps, :x11
+ # @private
+ attr_accessor :keg_only_deps, :deps
+
+ attr_accessor :x11
alias_method :x11?, :x11
def self.extended(base)
@@ -22,6 +25,7 @@ module Superenv
base.deps = []
end
+ # @private
def self.bin
return unless MacOS.has_apple_developer_tools?
@@ -36,6 +40,7 @@ module Superenv
delete("as_nl")
end
+ # @private
def setup_build_environment(formula = nil)
super
send(compiler)
@@ -302,6 +307,7 @@ module Superenv
append "HOMEBREW_CCCFG", "h", "" if compiler == :clang
end
+ # @private
def refurbish_args
append "HOMEBREW_CCCFG", "O", ""
end
@@ -312,6 +318,7 @@ module Superenv
end
end
+ # @private
def noop(*_args); end
noops = []
diff --git a/Library/Homebrew/extend/fileutils.rb b/Library/Homebrew/extend/fileutils.rb
index 741fca57f..a6321931c 100644
--- a/Library/Homebrew/extend/fileutils.rb
+++ b/Library/Homebrew/extend/fileutils.rb
@@ -1,7 +1,8 @@
require "fileutils"
require "tmpdir"
-# We enhance FileUtils to make our Formula code more readable.
+# Homebrew extends Ruby's `FileUtils` to make our code more readable.
+# @see http://ruby-doc.org/stdlib-1.8.7/libdoc/fileutils/rdoc/FileUtils.html Ruby's FileUtils API
module FileUtils
# Create a temporary directory then yield. When the block returns,
# recursively delete the temporary directory.
@@ -23,8 +24,10 @@ module FileUtils
end
module_function :mktemp
- # A version of mkdir that also changes to that folder in a block.
+ # @private
alias_method :old_mkdir, :mkdir
+
+ # A version of mkdir that also changes to that folder in a block.
def mkdir(name, &_block)
old_mkdir(name)
if block_given?
@@ -42,6 +45,7 @@ module FileUtils
# never backported into the 1.9.3 branch. Fixed in 2.0.0.
# The monkey-patched method here is copied directly from upstream fix.
if RUBY_VERSION < "2.0.0"
+ # @private
class Entry_
alias_method :old_copy_metadata, :copy_metadata
def copy_metadata(path)
@@ -82,23 +86,27 @@ module FileUtils
end
end
- private
-
- # Run scons using a Homebrew-installed version, instead of whatever
- # is in the user's PATH
+ # Run `scons` using a Homebrew-installed version rather than whatever is in the `PATH`.
def scons(*args)
system Formulary.factory("scons").opt_bin/"scons", *args
end
+ # Run the `rake` from the `ruby` Homebrew is using rather than whatever is in the `PATH`.
def rake(*args)
system RUBY_BIN/"rake", *args
end
- alias_method :old_ruby, :ruby if method_defined?(:ruby)
+ if method_defined?(:ruby)
+ # @private
+ alias_method :old_ruby, :ruby
+ end
+
+ # Run the `ruby` Homebrew is using rather than whatever is in the `PATH`.
def ruby(*args)
system RUBY_PATH, *args
end
+ # Run `xcodebuild` without Homebrew's compiler environment variables set.
def xcodebuild(*args)
removed = ENV.remove_cc_etc
system "xcodebuild", *args
diff --git a/Library/Homebrew/extend/pathname.rb b/Library/Homebrew/extend/pathname.rb
index c71a636e9..ed831f2cb 100644
--- a/Library/Homebrew/extend/pathname.rb
+++ b/Library/Homebrew/extend/pathname.rb
@@ -3,12 +3,15 @@ require "mach"
require "resource"
require "metafiles"
-# we enhance pathname to make our code more readable
+# Homebrew extends Ruby's `Pathname` to make our code more readable.
+# @see http://ruby-doc.org/stdlib-1.8.7/libdoc/pathname/rdoc/Pathname.html Ruby's Pathname API
class Pathname
include MachO
+ # @private
BOTTLE_EXTNAME_RX = /(\.[a-z0-9_]+\.bottle\.(\d+\.)?tar\.gz)$/
+ # Moves a file from the original location to the {Pathname}'s.
def install(*sources)
sources.each do |src|
case src
@@ -77,8 +80,12 @@ class Pathname
end
private :install_symlink_p
+ if method_defined?(:write)
+ # @private
+ alias_method :old_write, :write
+ end
+
# we assume this pathname object is a file obviously
- alias_method :old_write, :write if method_defined?(:write)
def write(content, *open_args)
raise "Will not overwrite #{self}" if exist?
dirname.mkpath
@@ -131,6 +138,7 @@ class Pathname
end
private :default_stat
+ # @private
def cp(dst)
opoo "Pathname#cp is deprecated, use FileUtils.cp"
if file?
@@ -141,6 +149,7 @@ class Pathname
dst
end
+ # @private
def cp_path_sub(pattern, replacement)
raise "#{self} does not exist" unless self.exist?
@@ -157,8 +166,10 @@ class Pathname
end
end
- # extended to support common double extensions
+ # @private
alias_method :extname_old, :extname
+
+ # extended to support common double extensions
def extname(path = to_s)
BOTTLE_EXTNAME_RX.match(path)
return $1 if $1
@@ -175,6 +186,7 @@ class Pathname
# I don't trust the children.length == 0 check particularly, not to mention
# it is slow to enumerate the whole directory just to see if it is empty,
# instead rely on good ol' libc and the filesystem
+ # @private
def rmdir_if_possible
rmdir
true
@@ -189,17 +201,20 @@ class Pathname
false
end
+ # @private
def chmod_R(perms)
opoo "Pathname#chmod_R is deprecated, use FileUtils.chmod_R"
require "fileutils"
FileUtils.chmod_R perms, to_s
end
+ # @private
def version
require "version"
Version.parse(self)
end
+ # @private
def compression_type
case extname
when ".jar", ".war"
@@ -240,10 +255,12 @@ class Pathname
end
end
+ # @private
def text_executable?
/^#!\s*\S+/ === open("r") { |f| f.read(1024) }
end
+ # @private
def incremental_hash(klass)
digest = klass.new
if digest.respond_to?(:file)
@@ -255,6 +272,7 @@ class Pathname
digest.hexdigest
end
+ # @private
def sha1
require "digest/sha1"
incremental_hash(Digest::SHA1)
@@ -282,10 +300,12 @@ class Pathname
children.select(&:directory?)
end
+ # @private
def resolved_path
self.symlink? ? dirname+readlink : self
end
+ # @private
def resolved_path_exists?
link = readlink
rescue ArgumentError
@@ -295,6 +315,7 @@ class Pathname
(dirname+link).exist?
end
+ # @private
def make_relative_symlink(src)
dirname.mkpath
File.symlink(src.relative_path_from(dirname), self)
@@ -308,6 +329,7 @@ class Pathname
self + other.to_s
end unless method_defined?(:/)
+ # @private
def ensure_writable
saved_perms = nil
unless writable_real?
@@ -319,10 +341,12 @@ class Pathname
chmod saved_perms if saved_perms
end
+ # @private
def install_info
quiet_system "/usr/bin/install-info", "--quiet", to_s, "#{dirname}/dir"
end
+ # @private
def uninstall_info
quiet_system "/usr/bin/install-info", "--delete", "--quiet", to_s, "#{dirname}/dir"
end
@@ -389,6 +413,7 @@ class Pathname
end
end
+ # @private
def abv
out = ""
n = Utils.popen_read("find", expand_path.to_s, "-type", "f", "!", "-name", ".DS_Store").split("\n").size
@@ -403,7 +428,9 @@ class Pathname
# the Regexp literals, which forces string interpolation to happen only
# once instead of each time the method is called. This is fixed in 1.9+.
if RUBY_VERSION <= "1.8.7"
+ # @private
alias_method :old_chop_basename, :chop_basename
+
def chop_basename(path)
base = File.basename(path)
if /\A#{Pathname::SEPARATOR_PAT}?\z/o =~ base
@@ -414,7 +441,9 @@ class Pathname
end
private :chop_basename
+ # @private
alias_method :old_prepend_prefix, :prepend_prefix
+
def prepend_prefix(prefix, relpath)
if relpath.empty?
File.dirname(prefix)
@@ -437,6 +466,7 @@ class Pathname
end
end
+# @private
module ObserverPathnameExtension
class << self
attr_accessor :n, :d
diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb
index 7ec035dd7..7a9bb0f69 100644
--- a/Library/Homebrew/formula.rb
+++ b/Library/Homebrew/formula.rb
@@ -22,11 +22,38 @@ require "keg"
# correspond.
# Make sure you check with `brew search` that the name is free!
# @abstract
+# @see SharedEnvExtension
+# @see FileUtils
+# @see Pathname
+# @see http://www.rubydoc.info/github/Homebrew/homebrew/file/share/doc/homebrew/Formula-Cookbook.md Formula Cookbook
+# @see https://github.com/styleguide/ruby Ruby Style Guide
+#
+# <pre>class Wget < Formula
+# homepage "https://www.gnu.org/software/wget/"
+# url "https://ftp.gnu.org/gnu/wget/wget-1.15.tar.gz"
+# sha256 "52126be8cf1bddd7536886e74c053ad7d0ed2aa89b4b630f76785bac21695fcd"
+#
+# def install
+# system "./configure", "--prefix=#{prefix}"
+# system "make", "install"
+# end
+# end</pre>
class Formula
include FileUtils
include Utils::Inreplace
extend Enumerable
+ # @!method inreplace(paths, before = nil, after = nil)
+ # Actually implemented in {Utils::Inreplace.inreplace}.
+ # Sometimes we have to change a bit before we install. Mostly we
+ # prefer a patch but if you need the `prefix` of this formula in the
+ # patch you have to resort to `inreplace`, because in the patch
+ # you don't have access to any var defined by the formula. Only
+ # HOMEBREW_PREFIX is available in the embedded patch.
+ # inreplace supports regular expressions.
+ # <pre>inreplace "somefile.cfg", /look[for]what?/, "replace by #{bin}/tool"</pre>
+ # @see Utils::Inreplace.inreplace
+
# The name of this {Formula}.
# e.g. `this-formula`
attr_reader :name
@@ -43,12 +70,15 @@ class Formula
# The stable (and default) {SoftwareSpec} for this {Formula}
# This contains all the attributes (e.g. URL, checksum) that apply to the
# stable version of this formula.
+ # @private
+
attr_reader :stable
# The development {SoftwareSpec} for this {Formula}.
# Installed when using `brew install --devel`
# `nil` if there is no development version.
# @see #stable
+ # @private
attr_reader :devel
# The HEAD {SoftwareSpec} for this {Formula}.
@@ -57,6 +87,7 @@ class Formula
# commit in the version control system.
# `nil` if there is no HEAD version.
# @see #stable
+ # @private
attr_reader :head
# The currently active {SoftwareSpec}.
@@ -67,6 +98,7 @@ class Formula
# A symbol to indicate currently active {SoftwareSpec}.
# It's either :stable, :devel or :head
# @see #active_spec
+ # @private
attr_reader :active_spec_sym
# Used for creating new Homebrew versions of software without new upstream
@@ -84,12 +116,14 @@ class Formula
# When installing a bottle (binary package) from a local path this will be
# set to the full path to the bottle tarball. If not, it will be `nil`.
+ # @private
attr_accessor :local_bottle_path
# The {BuildOptions} for this {Formula}. Lists the arguments passed and any
# {#options} in the {Formula}. Note that these may differ at different times
# during the installation of a {Formula}. This is annoying but the result of
# state that we're trying to eliminate.
+ # @return [BuildOptions]
attr_accessor :build
# @private
@@ -165,16 +199,19 @@ class Formula
public
# Is the currently active {SoftwareSpec} a {#stable} build?
+ # @private
def stable?
active_spec == stable
end
# Is the currently active {SoftwareSpec} a {#devel} build?
+ # @private
def devel?
active_spec == devel
end
# Is the currently active {SoftwareSpec} a {#head} build?
+ # @private
def head?
active_spec == head
end
@@ -221,6 +258,9 @@ class Formula
end
# A named Resource for the currently active {SoftwareSpec}.
+ # Additional downloads can be defined as {#resource}s.
+ # {Resource#stage} will create a temporary directory and yield to a block.
+ # <pre>resource("additional_files").stage { bin.install "my/extra/tool" }</pre>
def resource(name)
active_spec.resource(name)
end
@@ -246,40 +286,49 @@ class Formula
end
# The {Dependency}s for the currently active {SoftwareSpec}.
+ # @private
def deps
active_spec.deps
end
# The {Requirement}s for the currently active {SoftwareSpec}.
+ # @private
def requirements
active_spec.requirements
end
# The cached download for the currently active {SoftwareSpec}.
+ # @private
def cached_download
active_spec.cached_download
end
# Deletes the download for the currently active {SoftwareSpec}.
+ # @private
def clear_cache
active_spec.clear_cache
end
# The list of patches for the currently active {SoftwareSpec}.
+ # @private
def patchlist
active_spec.patches
end
# The options for the currently active {SoftwareSpec}.
+ # @private
def options
active_spec.options
end
# The deprecated options for the currently active {SoftwareSpec}.
+ # @private
def deprecated_options
active_spec.deprecated_options
end
+ # The deprecated option flags for the currently active {SoftwareSpec}.
+ # @private
def deprecated_flags
active_spec.deprecated_flags
end
@@ -290,6 +339,7 @@ class Formula
end
# All the {.fails_with} for the currently active {SoftwareSpec}.
+ # @private
def compiler_failures
active_spec.compiler_failures
end
@@ -297,11 +347,13 @@ class Formula
# If this {Formula} is installed.
# This is actually just a check for if the {#installed_prefix} directory
# exists and is not empty.
+ # @private
def installed?
(dir = installed_prefix).directory? && dir.children.length > 0
end
# If at least one version of {Formula} is installed.
+ # @private
def any_version_installed?
require "tab"
rack.directory? && rack.subdirs.any? { |keg| (keg/Tab::FILENAME).file? }
@@ -316,6 +368,7 @@ class Formula
# The latest prefix for this formula. Checks for {#head}, then {#devel}
# and then {#stable}'s {#prefix}
+ # @private
def installed_prefix
if head && (head_prefix = prefix(PkgVersion.new(head.version, revision))).directory?
head_prefix
@@ -330,6 +383,7 @@ class Formula
# The currently installed version for this formula. Will raise an exception
# if the formula is not installed.
+ # @private
def installed_version
Keg.new(installed_prefix).version
end
@@ -342,6 +396,7 @@ class Formula
# The parent of the prefix; the named directory in the cellar containing all
# installed versions of this software
+ # @private
def rack
prefix.parent
end
@@ -349,6 +404,12 @@ class Formula
# The directory where the formula's binaries should be installed.
# This is symlinked into `HOMEBREW_PREFIX` after installation or with
# `brew link` for formulae that are not keg-only.
+ #
+ # Need to install into the {.bin} but the makefile doesn't mkdir -p prefix/bin?
+ # <pre>bin.mkpath</pre>
+ #
+ # No `make install` available?
+ # <pre>bin.install "binary1"</pre>
def bin
prefix+"bin"
end
@@ -363,6 +424,9 @@ class Formula
# The directory where the formula's headers should be installed.
# This is symlinked into `HOMEBREW_PREFIX` after installation or with
# `brew link` for formulae that are not keg-only.
+ #
+ # No `make install` available?
+ # <pre>include.install "example.h"</pre>
def include
prefix+"include"
end
@@ -377,6 +441,9 @@ class Formula
# The directory where the formula's libraries should be installed.
# This is symlinked into `HOMEBREW_PREFIX` after installation or with
# `brew link` for formulae that are not keg-only.
+ #
+ # No `make install` available?
+ # <pre>lib.install "example.dylib"</pre>
def lib
prefix+"lib"
end
@@ -402,6 +469,9 @@ class Formula
# The directory where the formula's man1 pages should be installed.
# This is symlinked into `HOMEBREW_PREFIX` after installation or with
# `brew link` for formulae that are not keg-only.
+ #
+ # No `make install` available?
+ # <pre>man1.install "example.1"</pre>
def man1
man+"man1"
end
@@ -416,6 +486,9 @@ class Formula
# The directory where the formula's man3 pages should be installed.
# This is symlinked into `HOMEBREW_PREFIX` after installation or with
# `brew link` for formulae that are not keg-only.
+ #
+ # No `make install` available?
+ # <pre>man3.install "man.3"</pre>
def man3
man+"man3"
end
@@ -466,6 +539,18 @@ class Formula
# The directory where the formula's shared files should be installed.
# This is symlinked into `HOMEBREW_PREFIX` after installation or with
# `brew link` for formulae that are not keg-only.
+ #
+ # Need a custom directory?
+ # <pre>(share/"concept").mkpath</pre>
+ #
+ # Installing something into another custom directory?
+ # <pre>(share/"concept2").install "ducks.txt"</pre>
+ #
+ # Install `./example_code/simple/ones` to share/demos
+ # <pre>(share/"demos").install "example_code/simple/ones"</pre>
+ #
+ # Install `./example_code/simple/ones` to share/demos/examples
+ # <pre>(share/"demos").install "example_code/simple/ones" => "examples"</pre>
def share
prefix+"share"
end
@@ -474,6 +559,9 @@ class Formula
# with the name of the formula appended to avoid linking conflicts.
# This is symlinked into `HOMEBREW_PREFIX` after installation or with
# `brew link` for formulae that are not keg-only.
+ #
+ # No `make install` available?
+ # <pre>pkgshare.install "examples"</pre>
def pkgshare
prefix+"share"+name
end
@@ -537,20 +625,49 @@ class Formula
# The directory used for as the prefix for {#etc} and {#var} files on
# installation so, despite not being in `HOMEBREW_CELLAR`, they are installed
# there after pouring a bottle.
+ # @private
def bottle_prefix
prefix+".bottle"
end
+ # The directory where the formula's installation logs will be written.
+ # @private
def logs
HOMEBREW_LOGS+name
end
- # override this to provide a plist
+ # This method can be overridden to provide a plist.
+ # For more examples read Apple's handy manpage:
+ # https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man5/plist.5.html
+ # <pre>def plist; <<-EOS.undent
+ # <?xml version="1.0" encoding="UTF-8"?>
+ # <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+ # <plist version="1.0">
+ # <dict>
+ # <key>Label</key>
+ # <string>#{plist_name}</string>
+ # <key>ProgramArguments</key>
+ # <array>
+ # <string>#{opt_bin}/example</string>
+ # <string>--do-this</string>
+ # </array>
+ # <key>RunAtLoad</key>
+ # <true/>
+ # <key>KeepAlive</key>
+ # <true/>
+ # <key>StandardErrorPath</key>
+ # <string>/dev/null</string>
+ # <key>StandardOutPath</key>
+ # <string>/dev/null</string>
+ # </plist>
+ # EOS
+ #end</pre>
def plist
nil
end
alias_method :startup_plist, :plist
- # plist name, i.e. the name of the launchd service
+
+ # The {.plist} name (the name of the launchd service).
def plist_name
"homebrew.mxcl."+name
end
@@ -559,10 +676,12 @@ class Formula
prefix+(plist_name+".plist")
end
+ # @private
def plist_manual
self.class.plist_manual
end
+ # @private
def plist_startup
self.class.plist_startup
end
@@ -573,6 +692,7 @@ class Formula
#
# This is the prefered way to refer a formula in plists or from another
# formula, as the path is stable even when the software is updated.
+ # <pre>args << "--with-readline=#{Formula["readline"].opt_prefix}" if build.with? "readline"</pre>
def opt_prefix
Pathname.new("#{HOMEBREW_PREFIX}/opt/#{name}")
end
@@ -619,6 +739,7 @@ class Formula
# Can be overridden to run commands on both source and bottle installation.
def post_install; end
+ # @private
def post_install_defined?
method(:post_install).owner == self.class
end
@@ -631,7 +752,23 @@ class Formula
self.build = build
end
- # tell the user about any caveats regarding this package, return a string
+ # Tell the user about any caveats regarding this package.
+ # @return [String]
+ # <pre>def caveats
+ # <<-EOS.undent
+ # Are optional. Something the user should know?
+ # EOS
+ # end</pre>
+ #
+ # <pre>def caveats
+ # s = <<-EOS.undent
+ # Print some important notice to the user when `brew info <formula>` is
+ # called or when brewing a formula.
+ # This is optional. You can use all the vars like #{version} here.
+ # EOS
+ # s += "Some issue only on older systems" if MacOS.version < :mountain_lion
+ # s
+ # end</pre>
def caveats
nil
end
@@ -642,6 +779,7 @@ class Formula
keg_only_reason && keg_only_reason.valid?
end
+ # @private
def keg_only_reason
self.class.keg_only_reason
end
@@ -651,6 +789,7 @@ class Formula
# skip_clean "bin/foo", "lib/bar"
# keep .la files with:
# skip_clean :la
+ # @private
def skip_clean?(path)
return true if path.extname == ".la" && self.class.skip_clean_paths.include?(:la)
to_check = path.relative_path_from(prefix).to_s
@@ -662,6 +801,7 @@ class Formula
# allow overwriting certain files. e.g.
# link_overwrite "bin/foo", "lib/bar"
# link_overwrite "share/man/man1/baz-*"
+ # @private
def link_overwrite?(path)
# Don't overwrite files not created by Homebrew.
return false unless path.stat.uid == File.stat(HOMEBREW_BREW_FILE).uid
@@ -685,10 +825,12 @@ class Formula
false
end
+ # @private
def require_universal_deps?
false
end
+ # @private
def patch
unless patchlist.empty?
ohai "Patching"
@@ -710,6 +852,7 @@ class Formula
end
end
+ # @private
def lock
@lock = FormulaLock.new(name)
@lock.lock
@@ -719,27 +862,33 @@ class Formula
end
end
+ # @private
def unlock
@lock.unlock unless @lock.nil?
@oldname_lock.unlock unless @oldname_lock.nil?
end
+ # @private
def pinnable?
@pin.pinnable?
end
+ # @private
def pinned?
@pin.pinned?
end
+ # @private
def pin
@pin.pin
end
+ # @private
def unpin
@pin.unpin
end
+ # @private
def ==(other)
instance_of?(other.class) &&
name == other.name &&
@@ -747,10 +896,12 @@ class Formula
end
alias_method :eql?, :==
+ # @private
def hash
name.hash
end
+ # @private
def <=>(other)
return unless Formula === other
name <=> other.name
@@ -760,10 +911,12 @@ class Formula
name
end
+ # @private
def inspect
"#<Formula #{name} (#{active_spec_sym}) #{path}>"
end
+ # @private
def file_modified?
git = which("git")
@@ -798,40 +951,48 @@ class Formula
end
# an array of all core {Formula} names
+ # @private
def self.core_names
@core_names ||= Dir["#{HOMEBREW_LIBRARY}/Formula/*.rb"].map { |f| File.basename f, ".rb" }.sort
end
# an array of all core {Formula} files
+ # @private
def self.core_files
@core_files ||= Pathname.glob("#{HOMEBREW_LIBRARY}/Formula/*.rb")
end
# an array of all tap {Formula} names
+ # @private
def self.tap_names
@tap_names ||= Tap.flat_map(&:formula_names).sort
end
# an array of all tap {Formula} files
+ # @private
def self.tap_files
@tap_files ||= Tap.flat_map(&:formula_files)
end
# an array of all {Formula} names
+ # @private
def self.names
@names ||= (core_names + tap_names.map { |name| name.split("/")[-1] }).sort.uniq
end
# an array of all {Formula} files
+ # @private
def self.files
@files ||= core_files + tap_files
end
# an array of all {Formula} names, which the tap formulae have the fully-qualified name
+ # @private
def self.full_names
@full_names ||= core_names + tap_names
end
+ # @private
def self.each
files.each do |file|
begin
@@ -846,6 +1007,7 @@ class Formula
end
# An array of all racks currently installed.
+ # @private
def self.racks
@racks ||= if HOMEBREW_CELLAR.directory?
HOMEBREW_CELLAR.subdirs.reject(&:symlink?)
@@ -855,6 +1017,7 @@ class Formula
end
# An array of all installed {Formula}
+ # @private
def self.installed
@installed ||= racks.map do |rack|
begin
@@ -864,6 +1027,7 @@ class Formula
end.compact
end
+ # @private
def self.aliases
Dir["#{HOMEBREW_LIBRARY}/Aliases/*"].map { |f| File.basename f }.sort
end
@@ -872,10 +1036,12 @@ class Formula
Formulary.factory(name)
end
+ # @private
def tap?
HOMEBREW_TAP_DIR_REGEX === path
end
+ # @private
def tap
if path.to_s =~ HOMEBREW_TAP_DIR_REGEX
"#{$1}/#{$2}"
@@ -884,6 +1050,7 @@ class Formula
end
end
+ # @private
def print_tap_action(options = {})
if tap?
verb = options[:verb] || "Installing"
@@ -892,29 +1059,35 @@ class Formula
end
# True if this formula is provided by Homebrew itself
+ # @private
def core_formula?
path == Formulary.core_path(name)
end
+ # @private
def env
self.class.env
end
+ # @private
def conflicts
self.class.conflicts
end
# Returns a list of Dependency objects in an installable order, which
# means if a depends on b then b will be ordered before a in this list
+ # @private
def recursive_dependencies(&block)
Dependency.expand(self, &block)
end
# The full set of Requirements for this formula's dependency tree.
+ # @private
def recursive_requirements(&block)
Requirement.expand(self, &block)
end
+ # @private
def to_hash
hsh = {
"name" => name,
@@ -969,14 +1142,17 @@ class Formula
hsh
end
+ # @private
def fetch
active_spec.fetch
end
+ # @private
def verify_download_integrity(fn)
active_spec.verify_download_integrity(fn)
end
+ # @private
def run_test
old_home = ENV["HOME"]
build, self.build = self.build, Tab.for_formula(self)
@@ -992,17 +1168,28 @@ class Formula
ENV["HOME"] = old_home
end
+ # @private
def test_defined?
false
end
+ # @private
def test
end
+ # @private
def test_fixtures(file)
HOMEBREW_LIBRARY.join("Homebrew", "test", "fixtures", file)
end
+ # This method is overriden in {Formula} subclasses to provide the installation instructions.
+ # The sources (from {.url}) are downloaded, hash-checked and
+ # Homebrew changes into a temporary directory where the
+ # archive was unpacked or repository cloned.
+ # <pre>def install
+ # system "./configure", "--prefix=#{prefix}"
+ # system "make", "install"
+ # end</pre>
def install
end
@@ -1018,8 +1205,29 @@ class Formula
EOS
end
- # Pretty titles the command and buffers stdout/stderr
- # Throws if there's an error
+ public
+
+ # To call out to the system, we use the `system` method and we prefer
+ # you give the args separately as in the line below, otherwise a subshell
+ # has to be opened first.
+ # <pre>system "./bootstrap.sh", "--arg1", "--prefix=#{prefix}"</pre>
+ #
+ # For CMake we have some necessary defaults in {#std_cmake_args}:
+ # <pre>system "cmake", ".", *std_cmake_args</pre>
+ #
+ # If the arguments given to configure (or make or cmake) are depending
+ # on options defined above, we usually make a list first and then
+ # use the `args << if <condition>` to append to:
+ # <pre>args = ["--with-option1", "--with-option2"]
+ #
+ # # Most software still uses `configure` and `make`.
+ # # Check with `./configure --help` what our options are.
+ # system "./configure", "--disable-debug", "--disable-dependency-tracking",
+ # "--disable-silent-rules", "--prefix=#{prefix}",
+ # *args # our custom arg list (needs `*` to unpack)
+ #
+ # # If there is a "make", "install" available, please use it!
+ # system "make", "install"</pre>
def system(cmd, *args)
verbose = ARGV.verbose?
# remove "boring" arguments so that the important ones are more likely to
@@ -1178,13 +1386,17 @@ class Formula
# A one-line description of the software. Used by users to get an overview
# of the software and Homebrew maintainers.
# Shows when running `brew info`.
+ #
+ # <pre>desc "Example formula"</pre>
attr_rw :desc
- # @!attribute [w]
+ # @!attribute [w] homepage
# The homepage for the software. Used by users to get more information
# about the software and Homebrew maintainers as a point of contact for
# e.g. submitting patches.
# Can be opened with running `brew home`.
+ #
+ # <pre>homepage "https://www.example.com"</pre>
attr_rw :homepage
# The `:startup` attribute set by {.plist_options}.
@@ -1195,12 +1407,14 @@ class Formula
# @private
attr_reader :plist_manual
- # @!attribute [w]
+ # @!attribute [w] revision
# Used for creating new Homebrew versions of software without new upstream
# versions. For example, if we bump the major version of a library this
# {Formula} {.depends_on} then we may need to update the `revision` of this
# {Formula} to install a new version linked against the new library version.
# `0` if unset.
+ #
+ # <pre>revision 1</pre>
attr_rw :revision
# A list of the {.stable}, {.devel} and {.head} {SoftwareSpec}s.
@@ -1212,6 +1426,15 @@ class Formula
# @!attribute [w] url
# The URL used to download the source for the {#stable} version of the formula.
# We prefer `https` for security and proxy reasons.
+ # Optionally specify the download strategy with `:using => ...`
+ # `:git`, `:hg`, `:svn`, `:bzr`, `:cvs`,
+ # `:curl` (normal file download. Will also extract.)
+ # `:nounzip` (without extracting)
+ # `:post` (download via an HTTP POST)
+ # `S3DownloadStrategy` (download from S3 using signed request)
+ #
+ # <pre>url "https://packed.sources.and.we.prefer.https.example.com/archive-1.2.3.tar.bz2"</pre>
+ # <pre>url "https://some.dont.provide.archives.example.com", :using => :git, :tag => "1.2.3"</pre>
def url(val, specs = {})
stable.url(val, specs)
end
@@ -1220,6 +1443,8 @@ class Formula
# The version string for the {#stable} version of the formula.
# The version is autodetected from the URL and/or tag so only needs to be
# declared if it cannot be autodetected correctly.
+ #
+ # <pre>version "1.2-final"</pre>
def version(val = nil)
stable.version(val)
end
@@ -1230,45 +1455,100 @@ class Formula
# there can be more than one. Generally we add them when the main {.url}
# is unreliable. If {.url} is really unreliable then we may swap the
# {.mirror} and {.url}.
+ #
+ # <pre>mirror "https://in.case.the.host.is.down.example.com"
+ # mirror "https://in.case.the.mirror.is.down.example.com</pre>
def mirror(val)
stable.mirror(val)
end
- # @!attribute [w] sha1
+ # @!attribute [w] sha256
# @scope class
# To verify the {#cached_download}'s integrity and security we verify the
- # SHA-1 hash matches what we've declared in the {Formula}. To quickly fill
+ # SHA-256 hash matches what we've declared in the {Formula}. To quickly fill
# this value you can leave it blank and run `brew fetch --force` and it'll
# tell you the currently valid value.
-
- # @!attribute [w] sha256
- # @scope class
- # Similar to {.sha1} but using a SHA-256 hash instead.
-
+ #
+ # <pre>sha256 "2a2ba417eebaadcb4418ee7b12fe2998f26d6e6f7fda7983412ff66a741ab6f7"</pre>
Checksum::TYPES.each do |type|
define_method(type) { |val| stable.send(type, val) }
end
+ # @!attribute [w] bottle
+ # Adds a {.bottle} {SoftwareSpec}.
+ # This provides a pre-built binary package built by the Homebrew maintainers for you.
+ # It will be installed automatically if there is a binary package for your platform and you haven't passed or previously used any options on this formula.
+ # If you maintain your own repository, you can add your own bottle links.
+ # https://github.com/Homebrew/homebrew/blob/master/share/doc/homebrew/Bottles.md
+ # You can ignore this block entirely if submitting to Homebrew/Homebrew, It'll be
+ # handled for you by the Brew Test Bot.
+ #
+ # <pre>bottle do
+ # root_url "http://mikemcquaid.com" # Optional root to calculate bottle URLs
+ # prefix "/opt/homebrew" # Optional HOMEBREW_PREFIX in which the bottles were built.
+ # cellar "/opt/homebrew/Cellar" # Optional HOMEBREW_CELLAR in which the bottles were built.
+ # revision 1 # Making the old bottle outdated without bumping the version/revision of the formula.
+ # sha256 "4355a46b19d348dc2f57c046f8ef63d4538ebb936000f3c9ee954a27460dd865" => :yosemite
+ # sha256 "53c234e5e8472b6ac51c1ae1cab3fe06fad053beb8ebfd8977b010655bfdd3c3" => :mavericks
+ # sha256 "1121cfccd5913f0a63fec40a6ffd44ea64f9dc135c66634ba001d10bcf4302a2" => :mountain_lion
+ # end</pre>
def bottle(*, &block)
stable.bottle(&block)
end
+ # @private
def build
stable.build
end
+ # @!attribute [w] stable
+ # Allows adding {.depends_on} and {#patch}es just to the {.stable} {SoftwareSpec}.
+ # This is required instead of using a conditional.
+ # It is preferrable to also pull the {url} and {.sha256} into the block if one is added.
+ #
+ # <pre>stable do
+ # url "https://example.com/foo-1.0.tar.gz"
+ # sha256 "2a2ba417eebaadcb4418ee7b12fe2998f26d6e6f7fda7983412ff66a741ab6f7"
+ #
+ # depends_on "libxml2"
+ # depends_on "libffi"
+ # end</pre>
def stable(&block)
@stable ||= SoftwareSpec.new
return @stable unless block_given?
@stable.instance_eval(&block)
end
+ # @!attribute [w] devel
+ # Adds a {.devel} {SoftwareSpec}.
+ # This can be installed by passing the `--devel` option to allow
+ # installing non-stable (e.g. beta) versions of software.
+ #
+ # <pre>devel do
+ # url "https://example.com/archive-2.0-beta.tar.gz"
+ # sha256 "2a2ba417eebaadcb4418ee7b12fe2998f26d6e6f7fda7983412ff66a741ab6f7"
+ #
+ # depends_on "cairo"
+ # depends_on "pixman"
+ # end</pre>
def devel(&block)
@devel ||= SoftwareSpec.new
return @devel unless block_given?
@devel.instance_eval(&block)
end
+ # @!attribute [w] head
+ # Adds a {.head} {SoftwareSpec}.
+ # This can be installed by passing the `--HEAD` option to allow
+ # installing software directly from a branch of a version-control repository.
+ # If called as a method this provides just the {url} for the {SoftwareSpec}.
+ # If a block is provided you can also add {.depends_on} and {#patch}es just to the {.head} {SoftwareSpec}.
+ # The download strategies (e.g. `:using =>`) are the same as for {url}.
+ # `master` is the default branch and doesn't need stating with a `:branch` parameter.
+ # <pre>head "https://we.prefer.https.over.git.example.com/.git"</pre>
+ # <pre>head "https://example.com/.git", :branch => "name_of_branch", :revision => "abc123"</pre>
+ # or (if autodetect fails):
+ # <pre>head "https://hg.is.awesome.but.git.has.won.example.com/", :using => :hg</pre>
def head(val = nil, specs = {}, &block)
@head ||= HeadSoftwareSpec.new
if block_given?
@@ -1280,7 +1560,13 @@ class Formula
end
end
- # Define a named resource using a {SoftwareSpec} style block
+ # Additional downloads can be defined as resources and accessed in the
+ # install method. Resources can also be defined inside a stable, devel, or
+ # head block. This mechanism replaces ad-hoc "subformula" classes.
+ # <pre>resource "additional_files" do
+ # url "https://example.com/additional-stuff.tar.gz"
+ # sha256 "c6bc3f48ce8e797854c4b865f6a8ff969867bbcaebd648ae6fd825683e59fef2"
+ # end</pre>
def resource(name, klass = Resource, &block)
specs.each do |spec|
spec.resource(name, klass, &block) unless spec.resource_defined?(name)
@@ -1291,10 +1577,71 @@ class Formula
specs.each { |spec| spec.go_resource(name, &block) }
end
+ # The dependencies for this formula. Use strings for the names of other
+ # formulae. Homebrew provides some :special dependencies for stuff that
+ # requires certain extra handling (often changing some ENV vars or
+ # deciding if to use the system provided version or not.)
+ # <pre># `:build` means this dep is only needed during build.
+ # depends_on "cmake" => :build</pre>
+ # <pre>depends_on "homebrew/dupes/tcl-tk" => :optional</pre>
+ # <pre># `:recommended` dependencies are built by default.
+ # # But a `--without-...` option is generated to opt-out.
+ # depends_on "readline" => :recommended</pre>
+ # <pre># `:optional` dependencies are NOT built by default.
+ # # But a `--with-...` options is generated.
+ # depends_on "glib" => :optional</pre>
+ # <pre># If you need to specify that another formula has to be built with/out
+ # # certain options (note, no `--` needed before the option):
+ # depends_on "zeromq" => "with-pgm"
+ # depends_on "qt" => ["with-qtdbus", "developer"] # Multiple options.</pre>
+ # <pre># Optional and enforce that boost is built with `--with-c++11`.
+ # depends_on "boost" => [:optional, "with-c++11"]</pre>
+ # <pre># If a dependency is only needed in certain cases:
+ # depends_on "sqlite" if MacOS.version == :leopard
+ # depends_on :xcode # If the formula really needs full Xcode.
+ # depends_on :tex # Homebrew does not provide a Tex Distribution.
+ # depends_on :fortran # Checks that `gfortran` is available or `FC` is set.
+ # depends_on :mpi => :cc # Needs MPI with `cc`
+ # depends_on :mpi => [:cc, :cxx, :optional] # Is optional. MPI with `cc` and `cxx`.
+ # depends_on :macos => :lion # Needs at least Mac OS X "Lion" aka. 10.7.
+ # depends_on :apr # If a formula requires the CLT-provided apr library to exist.
+ # depends_on :arch => :intel # If this formula only builds on Intel architecture.
+ # depends_on :arch => :x86_64 # If this formula only builds on Intel x86 64-bit.
+ # depends_on :arch => :ppc # Only builds on PowerPC?
+ # depends_on :ld64 # Sometimes ld fails on `MacOS.version < :leopard`. Then use this.
+ # depends_on :x11 # X11/XQuartz components. Non-optional X11 deps should go in Homebrew/Homebrew-x11
+ # depends_on :osxfuse # Permits the use of the upstream signed binary or our source package.
+ # depends_on :tuntap # Does the same thing as above. This is vital for Yosemite and above.
+ # depends_on :mysql => :recommended</pre>
+ # <pre># It is possible to only depend on something if
+ # # `build.with?` or `build.without? "another_formula"`:
+ # depends_on :mysql # allows brewed or external mysql to be used
+ # depends_on :postgresql if build.without? "sqlite"
+ # depends_on :hg # Mercurial (external or brewed) is needed</pre>
+ #
+ # <pre># If any Python >= 2.7 < 3.x is okay (either from OS X or brewed):
+ # depends_on :python</pre>
+ # <pre># to depend on Python >= 2.7 but use system Python where possible
+ # depends_on :python if MacOS.version <= :snow_leopard</pre>
+ # <pre># Python 3.x if the `--with-python3` is given to `brew install example`
+ # depends_on :python3 => :optional</pre>
def depends_on(dep)
specs.each { |spec| spec.depends_on(dep) }
end
+ # @!attribute [w] option
+ # Options can be used as arguments to `brew install`.
+ # To switch features on/off: `"with-something"` or `"with-otherthing"`.
+ # To use other software: `"with-other-software"` or `"without-foo"`
+ # Note, that for {.depends_on} that are `:optional` or `:recommended`, options
+ # are generated automatically.
+ #
+ # There are also some special options:
+ # - `:universal`: build a universal binary/library (e.g. on newer Intel Macs
+ # this means a combined x86_64/x86 binary/library).
+ # <pre>option "with-spam", "The description goes here without a dot at the end"</pre>
+ # <pre>option "with-qt", "Text here overwrites the autogenerated one from 'depends_on "qt" => :optional'"</pre>
+ # <pre>option :universal</pre>
def option(name, description = "")
specs.each { |spec| spec.option(name, description) }
end
@@ -1303,19 +1650,62 @@ class Formula
specs.each { |spec| spec.deprecated_option(hash) }
end
+ # External patches can be declared using resource-style blocks.
+ # <pre>patch do
+ # url "https://example.com/example_patch.diff"
+ # sha256 "c6bc3f48ce8e797854c4b865f6a8ff969867bbcaebd648ae6fd825683e59fef2"
+ # end</pre>
+ #
+ # A strip level of `-p1` is assumed. It can be overridden using a symbol
+ # argument:
+ # <pre>patch :p0 do
+ # url "https://example.com/example_patch.diff"
+ # sha256 "c6bc3f48ce8e797854c4b865f6a8ff969867bbcaebd648ae6fd825683e59fef2"
+ # end</pre>
+ #
+ # Patches can be declared in stable, devel, and head blocks. This form is
+ # preferred over using conditionals.
+ # <pre>stable do
+ # patch do
+ # url "https://example.com/example_patch.diff"
+ # sha256 "c6bc3f48ce8e797854c4b865f6a8ff969867bbcaebd648ae6fd825683e59fef2"
+ # end
+ # end</pre>
+ #
+ # Embedded (`__END__`) patches are declared like so:
+ # <pre>patch :DATA
+ # patch :p0, :DATA</pre>
+ #
+ # Patches can also be embedded by passing a string. This makes it possible
+ # to provide multiple embedded patches while making only some of them
+ # conditional.
+ # <pre>patch :p0, "..."</pre>
def patch(strip = :p1, src = nil, &block)
specs.each { |spec| spec.patch(strip, src, &block) }
end
+ # Defines launchd plist handling.
+ #
+ # Does your plist need to be loaded at startup?
+ # <pre>plist_options :startup => true</pre>
+ #
+ # Or only when necessary or desired by the user?
+ # <pre>plist_options :manual => "foo"</pre>
+ #
+ # Or perhaps you'd like to give the user a choice? Ooh fancy.
+ # <pre>plist_options :startup => "true", :manual => "foo start"</pre>
def plist_options(options)
@plist_startup = options[:startup]
@plist_manual = options[:manual]
end
+ # @private
def conflicts
@conflicts ||= []
end
+ # If this formula conflicts with another one.
+ # <pre>conflicts_with "imagemagick", :because => "because this is just a stupid example"</pre>
def conflicts_with(*names)
opts = Hash === names.last ? names.pop : {}
names.each { |name| conflicts << FormulaConflict.new(name, opts[:because]) }
@@ -1327,10 +1717,19 @@ class Formula
skip_clean_paths.merge(paths)
end
+ # @private
def skip_clean_paths
@skip_clean_paths ||= Set.new
end
+ # Software that will not be sym-linked into the `brew --prefix` will only
+ # live in its Cellar. Other formulae can depend on it and then brew will
+ # add the necessary includes and libs (etc.) during the brewing of that
+ # other formula. But generally, keg_only formulae are not in your PATH
+ # and not seen by compilers if you build your own software outside of
+ # Homebrew. This way, we don't shadow software provided by OS X.
+ # <pre>keg_only :provided_by_osx</pre>
+ # <pre>keg_only "because I want it so"</pre>
def keg_only(reason, explanation = "")
@keg_only_reason = KegOnlyReason.new(reason, explanation)
end
@@ -1340,22 +1739,21 @@ class Formula
define_method(:skip_cxxstdlib_check?) { true } if check_type == :skip
end
+ # Marks the {Formula} as failing with a particular compiler so it will fall back to others.
# For Apple compilers, this should be in the format:
- # fails_with compiler do
- # cause "An explanation for why the build doesn't work."
- # build "The Apple build number for the newest incompatible release."
+ # <pre>fails_with :llvm do # :llvm is really llvm-gcc
+ # build 2334
+ # cause "Segmentation fault during linking."
# end
#
+ # fails_with :clang do
+ # build 600
+ # cause "multiple configure and compile errors"
+ # end</pre>
+ #
# The block may be omitted, and if present the build may be omitted;
# if so, then the compiler will be blacklisted for *all* versions.
#
- # For GNU GCC compilers, this should be in the format:
- # fails_with compiler => major_version do
- # cause
- # version "The official release number for the latest incompatible
- # version, for instance 4.8.1"
- # end
- #
# `major_version` should be the major release number only, for instance
# '4.8' for the GCC 4.8 series (4.8.0, 4.8.1, etc.).
# If `version` or the block is omitted, then the compiler will be
@@ -1364,9 +1762,9 @@ class Formula
# For example, if a bug is only triggered on GCC 4.8.1 but is not
# encountered on 4.8.2:
#
- # fails_with :gcc => '4.8' do
+ # <pre>fails_with :gcc => '4.8' do
# version '4.8.1'
- # end
+ # end</pre>
def fails_with(compiler, &block)
specs.each { |spec| spec.fails_with(compiler, &block) }
end
@@ -1375,15 +1773,42 @@ class Formula
specs.each { |spec| spec.needs(*standards) }
end
+ # Test (is required for new formula and makes us happy).
+ # @return [Boolean]
+ #
+ # The block will create, run in and delete a temporary directory.
+ #
+ # We are fine if the executable does not error out, so we know linking
+ # and building the software was ok.
+ # <pre>system bin/"foobar", "--version"</pre>
+ #
+ # <pre>(testpath/"test.file").write <<-EOS.undent
+ # writing some test file, if you need to
+ # EOS
+ # assert_equal "OK", shell_output("test_command test.file").strip</pre>
+ #
+ # Need complete control over stdin, stdout?
+ # <pre>require "open3"
+ # Open3.popen3("#{bin}/example", "argument") do |stdin, stdout, _|
+ # stdin.write("some text")
+ # stdin.close
+ # assert_equal "result", stdout.read
+ # end</pre>
+ #
+ # The test will fail if it returns false, or if an exception is raised.
+ # Failed assertions and failed `system` commands will raise exceptions.
+
def test(&block)
define_method(:test, &block)
end
+ # @private
def link_overwrite(*paths)
paths.flatten!
link_overwrite_paths.merge(paths)
end
+ # @private
def link_overwrite_paths
@link_overwrite_paths ||= Set.new
end
diff --git a/Library/Homebrew/mach.rb b/Library/Homebrew/mach.rb
index f7ca428e6..49382291c 100644
--- a/Library/Homebrew/mach.rb
+++ b/Library/Homebrew/mach.rb
@@ -1,21 +1,26 @@
module ArchitectureListExtension
+ # @private
def fat?
length > 1
end
+ # @private
def intel_universal?
intersects_all?(Hardware::CPU::INTEL_32BIT_ARCHS, Hardware::CPU::INTEL_64BIT_ARCHS)
end
+ # @private
def ppc_universal?
intersects_all?(Hardware::CPU::PPC_32BIT_ARCHS, Hardware::CPU::PPC_64BIT_ARCHS)
end
# Old-style 32-bit PPC/Intel universal, e.g. ppc7400 and i386
+ # @private
def cross_universal?
intersects_all?(Hardware::CPU::PPC_32BIT_ARCHS, Hardware::CPU::INTEL_32BIT_ARCHS)
end
+ # @private
def universal?
intel_universal? || ppc_universal? || cross_universal?
end
@@ -24,6 +29,7 @@ module ArchitectureListExtension
(Hardware::CPU::PPC_32BIT_ARCHS+Hardware::CPU::PPC_64BIT_ARCHS).any? { |a| self.include? a }
end
+ # @private
def remove_ppc!
(Hardware::CPU::PPC_32BIT_ARCHS+Hardware::CPU::PPC_64BIT_ARCHS).each { |a| delete a }
end
@@ -46,12 +52,13 @@ module ArchitectureListExtension
end
module MachO
+ # @private
OTOOL_RX = /\t(.*) \(compatibility version (?:\d+\.)*\d+, current version (?:\d+\.)*\d+\)/
# Mach-O binary methods, see:
# /usr/include/mach-o/loader.h
# /usr/include/mach-o/fat.h
-
+ # @private
def mach_data
@mach_data ||= begin
offsets = []
@@ -132,18 +139,22 @@ module MachO
arch == :ppc64
end
+ # @private
def dylib?
mach_data.any? { |m| m.fetch(:type) == :dylib }
end
+ # @private
def mach_o_executable?
mach_data.any? { |m| m.fetch(:type) == :executable }
end
+ # @private
def mach_o_bundle?
mach_data.any? { |m| m.fetch(:type) == :bundle }
end
+ # @private
class Metadata
attr_reader :path, :dylib_id, :dylibs
@@ -171,6 +182,7 @@ module MachO
end
end
+ # @private
def mach_metadata
@mach_metadata ||= Metadata.new(self)
end
@@ -180,10 +192,12 @@ module MachO
# to be absolute paths.
# Returns an empty array both for software that links against no libraries,
# and for non-mach objects.
+ # @private
def dynamically_linked_libraries
mach_metadata.dylibs
end
+ # @private
def dylib_id
mach_metadata.dylib_id
end
diff --git a/Library/Homebrew/manpages/brew.1.md b/Library/Homebrew/manpages/brew.1.md
index 2ef86a169..71b5dc3df 100644
--- a/Library/Homebrew/manpages/brew.1.md
+++ b/Library/Homebrew/manpages/brew.1.md
@@ -92,7 +92,7 @@ Note that these flags should only appear after a command.
and version, but if it fails, you'll have to make your own template. The wget
formula serves as a simple example. For a complete cheat-sheet, have a look at
- `$(brew --repository)/Library/Contributions/example-formula.rb`
+ <http://www.rubydoc.info/github/Homebrew/homebrew/master/frames>
If `--autotools` is passed, create a basic template for an Autotools-style build.
If `--cmake` is passed, create a basic template for a CMake-style build.
diff --git a/Library/Homebrew/utils.rb b/Library/Homebrew/utils.rb
index 63cdaadfa..84e2363ca 100644
--- a/Library/Homebrew/utils.rb
+++ b/Library/Homebrew/utils.rb
@@ -80,6 +80,7 @@ def oh1(title)
puts "#{Tty.green}==>#{Tty.white} #{title}#{Tty.reset}"
end
+# Print a warning (do this rarely)
def opoo(warning)
$stderr.puts "#{Tty.yellow}Warning#{Tty.reset}: #{warning}"
end
diff --git a/Library/Homebrew/utils/inreplace.rb b/Library/Homebrew/utils/inreplace.rb
index 8ed32bc5b..ee47da457 100644
--- a/Library/Homebrew/utils/inreplace.rb
+++ b/Library/Homebrew/utils/inreplace.rb
@@ -8,6 +8,13 @@ module Utils
end
module Inreplace
+ # Sometimes we have to change a bit before we install. Mostly we
+ # prefer a patch but if you need the `prefix` of this formula in the
+ # patch you have to resort to `inreplace`, because in the patch
+ # you don't have access to any var defined by the formula. Only
+ # HOMEBREW_PREFIX is available in the embedded patch.
+ # inreplace supports regular expressions.
+ # <pre>inreplace "somefile.cfg", /look[for]what?/, "replace by #{bin}/tool"</pre>
def inreplace(paths, before = nil, after = nil)
errors = {}