diff options
| author | Samuel John | 2013-03-18 16:25:35 +0100 |
|---|---|---|
| committer | Samuel John | 2013-08-20 15:20:45 +0200 |
| commit | 78d436c68e4257d0750e25dc4675be3b00fd12f6 (patch) | |
| tree | ca5105bbd30cfeabc121789106618ebf7ef7fc97 | |
| parent | 865b68de103ccd4a0386dbd127db1827105aae4d (diff) | |
| download | brew-78d436c68e4257d0750e25dc4675be3b00fd12f6.tar.bz2 | |
Adding an example-formula.rb to show all features
A huge cheat sheet. Kind of.
| -rw-r--r-- | Library/Contributions/example-formula.rb | 442 |
1 files changed, 442 insertions, 0 deletions
diff --git a/Library/Contributions/example-formula.rb b/Library/Contributions/example-formula.rb new file mode 100644 index 000000000..8376e2713 --- /dev/null +++ b/Library/Contributions/example-formula.rb @@ -0,0 +1,442 @@ +require 'formula' + +# This is a non-functional example formula to showcase all features and +# therefore, its overly complex and dupes stuff just to comment on it. +# You may want to use `brew create` to start your own new formula! +# Documentation: https://github.com/mxcl/homebrew/wiki/Formula-Cookbook + + +## Naming -- Every Homebrew formula is a class of the type `Formula`. +# Ruby classes have to start Upper case and dashes are not allowed. +# So we transform: `example-formula.rb` into `ExampleFormula`. Further, +# Homebrew does enforce that the name of the file and the class correspond. +# Check with `brew search` that the name is free. A file may contain multiple +# classes (we call them sub-formulae) but the main one is the class that +# corresponds to the filename. +class ExampleFormula < Formula + + homepage 'http://www.example.com' # used by `brew home example-formula`. + + # The url of the archive. Prefer https (security and proxy issues): + url 'https://packed.sources.and.we.prefer.https.example.com/archive-1.2.3.tar.bz2' + mirror 'https://in.case.the.host.is.down.example.com' # `mirror` is optional. + + # Optionally specify the download strategy `:using => ...` + # `:git`, `:hg`, `:svn`, `:bzr`, `:cvs`, + # `:curl` (normal file download. Will also extract.) + # `:nounzip` (without extracting) + # `:post` (download via an HTTP POST) + # `UnsafeSubversionDownloadStrategy` (svn with invalid certs) + url 'https://some.dont.provide.archives.example.com', :using => :git, :tag => '1.2.3' + + # version is seldom needed, because its usually autodetected from the URL/tag. + version '1.2-final' + + # For integrity and security, we verify the hash (`openssl dgst -sha1 <FILE>`) + # You may also use sha256 if the software uses sha256 on their homepage. + # Leave it empty at first and `brew install` will tell you the expected. + sha1 'cafebabe78901234567890123456789012345678' + + # Optionally, specify a repository to be used. Brew then generates a + # `--HEAD` option. Remember to also test it. + # The download strategies (:using =>) are the same as for `url`. + head 'https://we.prefer.https.over.git.example.com/.git' + head 'https://example.com/.git', :branch => 'name_of_branch', :revision => 'abc123' + head 'https://hg.is.awesome.but.git.has.won.example.com/', :using => :hg # If autodetect fails. + + # The optional devel block is only executed if the user passes `--devel`. + # Use this to specify a not-yet-released version of a software. + devel do + url 'https://example.com/archive-2.0-beta.tar.gz' + sha1 '1234567890123456789012345678901234567890' + end + + + ## Options + + # Options can be used as arguemnts to `brew install`. + # To switch features on/off: `'enable-something'` or `'disable-otherthing'`. + # To use another software: `'with-other-software'` or `'without-foo'` + # Note, that for dependencies that are `:optional` or `:recommended`, options + # are generated automatically. + # Build a universal (On newer intel Macs this means a combined 32bit and + # 64bit binary/library). Todo: better explain what this means for PPC. + option :universal + option 'enable-spam', 'The description goes here without a dot at the end' + option 'with-qt', 'Text here overwrites the autogenerated one from `depends_on "qt"`' + # Only show an option if the Command Line Tools are installed: + option 'with-dtrace', 'Experimental DTrace support' if MacOS::CLT.installed? + + ## Bottles + + # Bottles are pre-built and added by the Homebrew maintainers for you. + # If you maintain your own repository, you can add your own bottle links. + # Read in the wiki about how to provide bottles: + # <https://github.com/mxcl/homebrew/wiki/Bottles> + 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 of the formula. + sha1 'd3d13fe6f42416765207503a946db01378131d7b' => :mountain_lion + sha1 'cdc48e79de2dee796bb4ba1ad987f6b35ce1c1ee' => :lion + sha1 'a19b544c8c645d7daad1d39a070a0eb86dfe9b9c' => :snow_leopard + sha1 '583dc9d98604c56983e17d66cfca2076fc56312b' => :snow_leopard_32 + end + + def pour_bottle? + # Only needed if this formula has to check if using the pre-built + # bottle is fine. (For example boost bottled with system python breaks + # if the user has a brewed python) + true + end + + ## keg_only + + # Software that will not be sym-linked into the `brew --prefix` will only + # live in it's 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. + keg_only :provided_by_osx + keg_only "because I want it so" + + + ## Dependencies + + # 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.) + + # `:build` means this dep is only needed during build. + depends_on 'cmake' => :build + # Explictly name formulae in other taps. + depends_on 'homebrew/dupes/tcl-tk' + # `:recommended` dependencies are built by default. But a `--without-...` + # option is generated to opt-out. + depends_on 'readline' => :recommended + # `:optional` dependencies are NOT built by default but a `--with-...` + # options is generated. + depends_on 'glib' => :optional + # 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. + # Optional and enforce that boost is built with `--with-c++11`. + depends_on 'boost' => [:optional, 'with-c++11'] + # 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 :clt # If the formula really needs the CLTs for 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 :arch => :intel # If this formula only builds on intel architecture. + depends_on :arch => :x86_64 # If this formula only build on intel x86 64bit. + 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. + depends_on :libpng # Often, not all of X11 is needed. + depends_on :fontconfig + # autoconf/automake is sometimes needed for --HEAD checkouts: + depends_on :autoconf if build.head? + depends_on :automake if build.head? + depends_on :bsdmake + depends_on :libtool + depends_on :libltdl + depends_on :mysql => :recommended + depends_on :cairo if build.devel? + depends_on :pixman if build.devel? + # 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 + + # The formula needs python or needs certain Python modules that + # should be installed via pip? + # If any Python >= 2.6 < 3.x is okay (either from OS X or brewed): + depends_on :python + depends_on :python2 # this is a synonym + # Specify the minimum version, for example 2.6 is too old: + depends_on :python => "2.7" + # Any Python 2.x but with the modules 'numpy' and 'docutils' importable. + depends_on :python => ['numpy', 'docutils'] + # Python 3.x if the `--with-python3` is given to `brew install example` + depends_on :python3 => :optional + # A python module with a different name on PyPi than on import: + depends_on :python2 => ['enchant' => 'pyenchant'] # 'import_name' => 'pip_install_name' + # All in one. The version - if specified - has to come first + depends_on :python => ['2.7.4', 'numpy', {'yaml' =>'PyYAML'}, 'twisted', :optional ] + + # Modules/Packages from other languages, such as :chicken, :jruby, :lua, + # :node, :ocaml, :perl, :rbx, :ruby, can be specified by + depends_on 'some_module' => :lua + + ## Conflicts + + # If this formula conflicts with another one: + conflicts_with 'imagemagick', :because => 'because this is just a stupid example' + + + ## Failing with a certain compiler? + + # If it is failing for certain compiler: + fails_with :llvm do # :llvm is really llvm-gcc + build 2334 + cause "Segmentation fault during linking." + end + + fails_with :clang do + build 425 + cause 'multiple configure and compile errors' + end + + + ## Patches + + # Optionally define a `patches` method returning `DATA` and/or a string with + # the url to a patch or a list thereof. + def patches + # DATA is the embedded diff that comes after __END__ in this file! + # In this example we only need the patch for older clang than 425: + DATA unless MacOS.clang_build_version >= 425 + end + + # More than the one embedded patch? Use a dict with keys :p0, :p1 and/or + # p2: as you need, for example: + def patches + {:p0 => [ + 'https://trac.macports.org/export/yeah/we/often/steal/a/patch.diff', + 'https://github.com/example/foobar/commit/d46a8c6265c4c741aaae2b807a41ea31bc097052.diff', + DATA ], + # For gists, please use the link to a specific hash, so nobody can change it unnoticed. + :p2 => ['https://raw.github.com/gist/4010022/ab0697dc87a40e65011e2192439609c17578c5be/tags.patch'] + } + end + + + ## The install method. + + def install + # Now the sources (from `url`) are downloaded, hash-checked and + # Homebrew has changed into a temporary directory where the + # archive has been unpacked or the repository has benn cloned. + + # Print a warning (do this rarely) + opoo 'Dtrace features are experimental!' if build.with? 'dtrace' + + # 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 reg. exes. + inreplace 'somefile.cfg', /look[for]what?/, "replace by #{bin}/tool" + + # 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. + system "./bootstrap.sh", "--arg1", "--prefix=#{prefix}" + + # For Cmake, we have some necessary defaults in `std_cmake_args`: + system "cmake", ".", *std_cmake_args + + # 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: + args = ["--option1", "--option2"] + args << "--i-want-spam" if build.include? "enable-spam" + args << "--qt-gui" if build.with? "qt" # "--with-qt" ==> build.with? "qt" + args << "--some-new-stuff" if build.head? # if head is used instead of url. + args << "--universal-binray" if build.universal? + + # The `build.with?` and `build.without?` are smart enough to do the + # right thing™ with respect to defaults defined via `:optional` and + # `:recommended` dependencies. + + # If you need to give the path to lib/include of another brewed formula + # please use the `opt_prefix` instead of the `prefix` of that other + # formula. The reasoning behind this is that `prefix` has the exact + # version number and if you update that other formula, things might + # break if they remember that exact path. In contrast to that, the + # `$(brew --prefix)/opt/formula` is the same path for all future + # versions of the formula! + args << "--with-readline=#{Formula.factory('readline').opt_prefix}/lib" if build.with? "readline" + + # Most software still uses `configure` and `make`. + # Check with `./configure --help` what our options are. + system "./configure", "--disable-debug", "--disable-dependency-tracking", + "--prefix=#{prefix}", + *args # our custom arg list (needs `*` to unpack) + + # Calling a setup.py as provided by (many) python based projects: + # The `python do ... end` block sets up PYTHONPATH, PYTHON and other + # vars so that distutils are happy to install into the Cellar. This + # allows brewed python modules to be un/installed and updated properly. + # https://github.com/mxcl/homebrew/wiki/Homebrew-and-Python + python do + # If you `depend_on :python` and `depend_on :python3`, this block + # will be run twice - for each Python version one pass! + # `python` points to the corresponding Python binary (e.g. `python3`) + system python, "setup.py", "install", "--prefix=#{prefix}" + + # Sometimes, for old setup.py files, you'll get a warning that + # your formula cannot be linked because easy-install.pth would be + # overwritten. In this case, please add these two flags: + system python, "setup.py", "install", "--prefix=#{prefix}", + "--single-version-externally-managed", + "--record=installed.txt" + end + + # If your formula's build system is not thread safe: + ENV.deparallelize + + # A general note: The commands here are executed line by line, so if + # you change some variable or call a method like ENV.deparallelize, it + # only affects the lines after that command. + + # 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 + + # This is in general not necessary, but to show how to find the path to + # the Mac OS X SDK: + ENV.append 'CPPFLAGS', "-I#{MacOS.sdk_path}/usr/include" unless MacOS::CLT.installed? + + # Overwriting any env var: + ENV['LDFLAGS'] = '--tag CC' + + system "make", "install" + + # We are in a temporary directory and don't have to care about cleanup. + + # Instead of `system "cp"` or something, call `install` on the Pathname + # objects as they are smarter with respect to correcting access rights. + # (`install` is a Homebrew mixin into Ruby's Pathname) + + # The pathnames defined in the formula + prefix # == HOMEBREW_PREFIX+'Cellar'+name+version + bin # == prefix+'bin' + doc # == share+'doc'+name + include # == prefix+'include' + info # == share+'info' + lib # == prefix+'lib' + libexec # == prefix+'libexec' + + man # share+'man' + man1 # man+'man1' + man2 # man+'man2' + man3 # man+'man3' + man4 # man+'man4' + man5 # man+'man5' + man6 # man+'man6' + man7 # man+'man7' + man8 # man+'man8' + sbin # prefix+'sbin' + share # prefix+'share' + frameworks # prefix+'Frameworks' + kext_prefix # prefix+'Library/Extensions' + # Configuration stuff that will survive formula updates + etc # HOMEBREW_PREFIX+'etc' + # Generally we don't want var stuff inside the keg + var # HOMEBREW_PREFIX+'var' + bash_completion # prefix+'etc/bash_completion.d' + zsh_completion # share+'zsh/site-functions' + # Further possibilities with the pathnames: + # http://www.ruby-doc.org/stdlib-1.8.7/libdoc/pathname/rdoc/Pathname.html + + # Sometime you will see that instead of `+` we build up a path with `/` + # because it looks nicer (but you can't nest more than two `/`): + (var/'foo').mkpath + # Copy `./example_code/simple/ones` to share/demos/examples + (share/'demos').install "example_code/simple/ones" + # Copy `./example_code/simple/ones` to share/demos/examples + (share/'demos').install "example_code/simple/ones" => 'examples' + + # Additional stuff can be defined in a sub-formula (see below) and + # with a block like this, it will be extracted into its own temporary + # dir. We can install into the Cellar of the main formula easily, + # because `prefix`, `bin` and all the other pre-defined variables are + # from the main formula. + AdditionalStuff.new.brew { bin.install 'my/extra/tool' } + + # `name` and `version` are accessible too, if you need them. + end + + + ## Caveats + + def caveats + "Are optional. Something the user should know?" + end + + 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 += python.standard_caveats if python + s += "Some issue only on older systems" if MacOS.version < :mountain_lion + s + end + + + ## Test (is optional but makes us happy) + + test do + # `test do` 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. + system bin/'foobar', '--version' + + (testpath/'Test.file').write <<-EOS.undent + writing some test file, if you need to + EOS + # To capture the output of a command, we use backtics: + assert_equal 'OK', ` test.file`.strip + + # Need complete control over stdin, stdout? + require 'open3' + Open3.popen3("#{bin}/example", "big5:utf-8") do |stdin, stdout, _| + stdin.write("\263\134\245\134\273\134") + stdin.close + assert_equal "許功蓋", stdout.read + end + + # If an exception is raised (e.g. by assert), or if we return false, or if + # the command run by `system` prints to stderr, we consider the test failed. + end + + + ## Plist handling + + # Define this method to provide a plist. + # Todo: Expand this example with a little demo plist? I dunno. + # There is more to startup plists. Help, I suck a plists! + def plist; nil; end +end + +class AdditionalStuff < Formula + # Often, a second formula is used to download some resource + # NOTE: This is going to change when https://github.com/mxcl/homebrew/pull/21714 happens. + url 'https://example.com/additional-stuff.tar.gz' + sha1 'deadbeef7890123456789012345678901234567890' +end + +__END__ +# Room for a patch after the `__END__` +# Read in the wiki about how to get a patch in here: +# https://github.com/mxcl/homebrew/wiki/Formula-Cookbook +# In short, `brew install --interactive --git <formula>` and make your edits. +# Then `git diff >> path/to/your/formula.rb` +# Note, that HOMEBREW_PREFIX will be replaced in the path before it is +# applied. A patch can consit of several hunks. |
