-
-
Save leahneukirchen/361451 to your computer and use it in GitHub Desktop.
THIS DOCUMENT MOVED TO http://chneukirchen.github.com/rps/ | |
AND http://github.com/chneukirchen/rps | |
= Ruby Packaging Standard | |
The aim of this document is two-fold. First, to specify a common | |
structure of how a Ruby package distributed as source (that is, but | |
not limited to, development directories, version-controlled | |
repositories, .tar.gz, Gems, ...) should conform to. | |
Second, to document common and proven ways to structure Ruby packages, | |
and to point out certain anti-patterns that sneaked into common use. | |
It is by intent not to innovate. | |
(See RFC 2119 for use of MUST, SHOULD, SHALL.) | |
== Library files | |
Library code MUST reside in lib/. | |
Libraries SHOULD use a directory as namespace, e.g. lib/foo.rb and lib/foo/**. | |
Libraries SHOULD NOT require code of the project that are outside of lib/. | |
Libraries MUST not require 'rubygems' or modify the $LOAD_PATH. | |
Ruby library files MUST end with .rb. | |
Library files SHOULD be installed with mode 0644. | |
== Executables | |
Executables MUST reside in bin/. | |
Ruby executables SHOULD have a shebang line using env: | |
#!/usr/bin/env ruby | |
Executables SHOULD NOT require code of the project that are outside of lib/. | |
Executables SHOULD NOT require 'rubygems' or modify the $LOAD_PATH, | |
unless they are specifically made for doing that (e.g. package managers). | |
Executable files SHOULD NOT end with .rb. | |
Executable files SHOULD be installed with mode 0755. | |
== Extensions | |
Extensions are directories which contain a extconf.rb. | |
Extensions SHOULD reside in ext/. | |
Extensions SHOULD be buildable with "ruby extconf.rb; make". | |
XXX How to install, how to find out what was built. | |
== Data files | |
Data files and resources of the project belong to data/. | |
XXX Or data/<projectname>? | |
XXX Where to install to, how to find out that place from the program? | |
== Tests | |
Tests SHOULD reside in test/ or spec/. | |
== History | |
09apr2010: First initial draft. | |
10apr2010: Fix binary permissions. | |
10apr2010: Add data files. |
@postmodern, @sunaku: This is a problem that's very easily solved with aliases. It's not completely transparent, but the disadvantages are outweighed by the fact that your executables aren't making any assumptions about the relative directory structure. When I'm developing, I'm generally executing scripts from the root of the project directory, so I use something like this:
$ alias rb='ruby -rubygems -Ilib:test'
$ rb bin/johnson
It's also pretty darn easy to make a project-specific alias (using absolute paths) for any given executable as well.
@jbarnette I have this in my env
export RUBYOPT="-Ilib:test"
or
export RUBYOPT="-rubygems -Ilib:test"
@josh Absolutely, the only reason I don't have that turned on all the time is because I'm dumb and it's deeply confused me a couple of times when I've been in the root directory of a project that contributes, say, RubyGems plugins via the load path. :)
@jbarnette Aliases seem like a good compromise, but they don't solve the problem completely for me: I like to use the development versions of my projects right from my source area (e.g. I run ~/src/my_project/bin/my_project directly from anywhere in the file system).
I had to write a little wrapper script (could also be a shell function if you prefer) to address this:
> cat ~/bin/rubin
#!/bin/sh -x
dir="$(dirname "$(dirname "$1")")"
ruby -rubygems -I "$dir/lib:$dir/test" "$@"
And then run it this way:
rubin ~/src/my_project/bin/my_project
I guess I can live with this. :-/
@chneukirchen Your ruby-wrapper script is awesome! Totally solves my problem. Thank you.
I've only ever used RubyGems for packaging my projects, so I'm kind of scared of setup.rb's style of separating my project's directories (i.e. lib/ is no longer next to bin/ and so on). In particular, I am confused about the following:
I want to run the man
executable (pointing it to my project's man/ directory) from my project's executable in bin/. With RubyGems, I can rely on bin/ being next to man/. But with setup.rb I don't know how to find my project's man/ directory from my project's executable in bin/!
Any suggestions? Thanks.
Similar to josh and jbarnette, I use this rbdev
shell function to activate bin
, lib
, and ext
dirs when I'm working on a project:
# develop out of the current directory.
rbdev() {
local useful dir
test -d ./bin && {
useful=yes
PATH="$(pwd)/bin:$PATH"
echo "./bin on \$PATH"
}
test -d ./ext && {
useful=yes
for dir in ./ext/*
do
test -d "$dir" || continue
RUBYLIB="$(pwd)/$dir:$RUBYLIB"
export RUBYLIB
echo "$dir on \$RUBYLIB"
done
}
test -d ./lib && {
useful=yes
RUBYLIB="$(pwd)/lib:$RUBYLIB"
export RUBYLIB
echo "./lib on \$RUBYLIB"
}
test -z "$useful" && {
echo "no ./lib or ./bin detected. help me help you."
return 1
}
}
When I'm working on e.g., RDiscount, I do something like:
$ cd ~/git/rdiscount
$ rbdev
./bin on $PATH
./ext on $RUBYLIB
./lib on $RUBYLIB
Not setting up the load path from executables has been a problem, though. People assume everything is broken when they get a LoadError
+ backtrace after checking out a project for the first time and running an executable. I really wish these techniques for setting up development environments would become common practice. I'm thinking a template HACKING
file that explained basic environment prep would probably go a long way.
@chneukirchen Would you mind moving this discussion to ruby-talk? It's hard to quote and inline-reply to the various tangents here. And it's easy for questions to get lost in the noise. Also, I'm sure the vast number of Rubyists on ruby-talk would have valuable feedback on this spec. Thanks.
Please discuss now at:
See ruby-wrapper at http://github.com/chneukirchen/rup