File Manager
Viewing File: README.md
# MiniPortile
This documents versions 2 and up, for which the require file was
renamed to `mini_portile2`. For mini_portile versions 0.6.x and
previous, please visit
[the v0.6.x branch](https://github.com/flavorjones/mini_portile/tree/v0.6.x).
[](https://travis-ci.org/flavorjones/mini_portile?branch=master)
[](https://ci.appveyor.com/project/flavorjones/mini-portile/branch/master)
* Documentation: http://www.rubydoc.info/github/flavorjones/mini_portile
* Source Code: https://github.com/flavorjones/mini_portile
* Bug Reports: https://github.com/flavorjones/mini_portile/issues
This project is a minimalistic implementation of a port/recipe system
**for developers**.
Because _"Works on my machine"_ is unacceptable for a library maintainer.
## Not Another Package Management System
`mini_portile2` is not a general package management system. It is not
aimed to replace apt, macports or homebrew.
It's intended primarily to make sure that you, as the developer of a
library, can reproduce a user's dependencies and environment by
specifying a specific version of an underlying dependency that you'd
like to use.
So, if a user says, "This bug happens on my system that uses libiconv
1.13.1", `mini_portile2` should make it easy for you to download,
compile and link against libiconv 1.13.1; and run your test suite
against it.
This scenario might be simplified with something like this:
```
rake compile LIBICONV_VERSION=1.13.1
```
(For your homework, you can make libiconv version be taken from the
appropriate `ENV` variables.)
## Sounds easy, but where's the catch?
At this time (and highly likely will be always) `mini_portile2` is
only compatible with **GCC compilers** and **autoconf**- or
**configure**-based projects.
That is, it assumes the library you want to build contains a
`configure` script, which all the autoconf-based libraries do.
### How to use
Now that you know the catch, and you're still reading this, here is a
quick example:
```ruby
gem "mini_portile2", "~> 2.0.0" # NECESSARY if used in extconf.rb. see below.
require "mini_portile2"
recipe = MiniPortile.new("libiconv", "1.13.1")
recipe.files = ["http://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.13.1.tar.gz"]
recipe.cook
recipe.activate
```
The gem version constraint makes sure that your extconf.rb is
protected against possible backwards-incompatible changes to
`mini_portile2`. This constraint is REQUIRED if you're using
`mini_portile2` within a gem installation process (e.g., extconf.rb),
because Bundler doesn't enforce gem version constraints at
install-time (only at run-time.
`#cook` will download, extract, patch, configure and compile the
library into a namespaced structure.
`#activate` ensures GCC will find this library and prefer it over a
system-wide installation.
### Directory Structure Conventions
`mini_portile2` follows the principle of **convention over configuration** and
established a folder structure where is going to place files and perform work.
Take the above example, and let's draw some picture:
```
mylib
|-- ports
| |-- archives
| | `-- libiconv-1.13.1.tar.gz
| `-- <platform>
| `-- libiconv
| `-- 1.13.1
| |-- bin
| |-- include
| `-- lib
`-- tmp
`-- <platform>
`-- ports
```
In above structure, `<platform>` refers to the architecture that
represents the operating system you're using (e.g. i686-linux,
i386-mingw32, etc).
Inside the platform folder, `mini_portile2` will store the artifacts
that result from the compilation process. The library is versioned so
you can keep multiple versions around on disk without clobbering
anything.
`archives` is where downloaded source files are cached. It is
recommended you avoid trashing that folder to avoid downloading the
same file multiple times (save bandwidth, save the world).
`tmp` is where compilation is performed and can be safely discarded.
Use the recipe's `#path` to obtain the full path to the installation
directory:
```ruby
recipe.cook
recipe.path # => /home/luis/projects/myapp/ports/i686-linux/libiconv/1.13.1
```
### How can I combine this with my compilation task?
In the simplest case, your rake `compile` task will depend on
`mini_portile2` compilation and most important, activation.
Example:
```ruby
task :libiconv do
recipe = MiniPortile.new("libiconv", "1.13.1")
recipe.files << {
url: "http://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.13.1.tar.gz"],
md5: "7ab33ebd26687c744a37264a330bbe9a"
}
checkpoint = ".#{recipe.name}-#{recipe.version}.installed"
unless File.exist?(checkpoint)
recipe.cook
touch checkpoint
end
recipe.activate
end
task :compile => [:libiconv] do
# ... your library's compilation task ...
end
```
The above example will:
* **download** and verify integrity the sources only once
* **compile** the library only once (using a timestamp file)
* ensure compiled library is **activated**
* make the compile task depend upon compiled library activation
As an exercise for the reader, you could specify the libiconv version
in an environment variable or a configuration file.
### Native and/or Cross Compilation
The above example covers the normal use case: compiling dependencies
natively.
`MiniPortile` also covers another use case, which is the
cross-compilation of the dependencies to be used as part of a binary
gem compilation.
It is the perfect complementary tool for
[`rake-compiler`](https://github.com/rake-compiler/rake-compiler) and
its `cross` rake task.
Depending on your usage of `rake-compiler`, you will need to use
`host` to match the installed cross-compiler toolchain.
Please refer to the examples directory for simplified and practical usage.
### Supported Scenarios
As mentioned before, `MiniPortile` requires a GCC compiler
toolchain. This has been tested against Ubuntu, OSX and even Windows
(RubyInstaller with DevKit)
## License
This library is licensed under MIT license. Please see LICENSE.txt for details.