Skip to content


Joshua Nelson edited this page Aug 10, 2019 · 64 revisions

NOTE: If anything on this page doesn't work for you, please file a bug!


You should use Linux to make changes to OSH and test them. One reason for this is that the spec tests run against four other shells (bash/dash/zsh/mksh), and we don't have a way of building the right versions of these shells on other OSes.

When I'm on a Mac, I use Ubuntu on Virtualbox to develop.

(Note that OSH does work on OS X for end users, but development is a different story.)

Quick Start

git clone    # or use your own fork

cd oil                    # or enter the base directory

build/ ubuntu-deps  # Python 2 dev headers, etc.
                          # Uses sudo apt-get, so it's for Ubuntu/Debian.
build/ minimal      # build help, native/libc.c Python extension

bin/osh                   # sanity check to make sure it works. 
                          # Make sure you have Python 2 installed.
                          # Ctrl-D to quit.

test/ unit core/     # Run an individual unit test
test/ all          # run all unit tests, about a second or two

test/ smoke        # run a single file -- see spec tests in parallel
test/ all          # run all spec tests in parallel, ~11 seconds on 
                          # a fast i7 desktop. Should be done in about 30s.

After you've run these tests, you're ready to work on Oil! Details below.

Running Three Kinds of Tests

There are three kinds of tests: unit tests, spec tests, and "wild tests".

Unit tests are in Python:

$ test/ all
$ test/ one osh/

( is a simple wrapper that sets PYTHONPATH)

Spec Tests are written with the framework:

$ test/ install-shells
$ test/ all     # all in parallel
$ test/ smoke   # a single file -- look at the list of functions

Output is in _tmp/spec.

"Wild tests" test the parser against code in the wild. We don't have any golden data to compare against, but whether the parse succeeds or fails is useful for shaking out bugs, sort of like a fuzz test.

$ test/ this-repo

This will run the parser on shell scripts in this repo, and put the output in _tmp/wild/oil-parsed, which you can view with a web browser.

Three Kinds of Builds

(1) What I've documented above, i.e. running bin/osh, can be called the developer build. This builds native/libc.c and uses the system Python interpreter /usr/bin/env python2 to run Oil.

(2) The "production" build is split into two steps: (a) git repo -> release tarball, and (b) release tarball -> Oil app bundle.

2a. Release tarball. This step is architecture-independent and occurs on the developer machine. This process may change, but it's roughly as follows:

# First we need to build a raw Python interpreter, in order to dynamically discover Python dependencies.
build/ ubuntu-deps        # or equivalent for other distros
build/ configure      # configure CPython
build/ build-python   # compile CPython
build/ download-re2c  
build/ install-re2c
build/ all
devtools/ quick-oil-tarball          # build _release/oil.tar with the Makefile and build/*.{sh,py}
build/ oil-tar           # test that you can build the tarball


  • This step is likely to be Linux-centric for awhile. The end-user build, step 2b, should not be Linux-centric. Ideally it would only require a POSIX environment.
  • The full release process is documented at the top of devtools/ Those comments are kept up-to-date.
  • After you've done the steps above, you can also try devtools/ quick-oil-tarball to quickly make tarballs for testing on other machines. (It doesn't run any tests, so make sure the code works on Linux first.)

2b. Oil app bundle build. This step is architecture-dependent and occurs on the machine of the system packager or end user. To perform this step, follow the instructions in the INSTALL.txt file at the root of the tarball.

Tips for Developing

  • Spec Tests are very important! Make sure you know how to run them quickly and maintain a fast, iterative development style.
    • Where Do I Put Spec Tests? If I'm going to change the behavior of the source builtin, I do grep source spec/* and that leads to the spec test that should verify the new behavior.
  • Debugging Completion Scripts -- Use --debug-file!
  • Debugging OSH / OVM / CPython itself
    • make _bin/oil.ovm-dbg and misc/ which creates _bin/osh-dbg may be helpful in debugging... although it's not something I do very often!
  • make clean is meant for the end user source tarball and will just remove the binaries in _bin. make clean-repo is more aggressive and removes the "pre-build" in _devbuild.
  • Make sure to build/ minimal (or all) after you git pull ! The Python extension modules (.so files) that OSH uses may be out of date, and they have to match the Python code.

Pull Requests

Most people have used Github pull requests to send patches. I will use Github's system to make comments. After addressing them, please:

  1. push the commits so I can see them
  2. reply with a message, like "all done", or "I disagree because ..."

If only push commits, I won't look at the PR again, because I'll assume it's in progress.

Code Style

Python code follows Google's Python style guide, which is essentially PEP 8, but with

  • 2 space indents
  • CapWords for function names

There are notable exceptions in the opy/ dir, because I didn't write that code.

The general rule is to follow existing style. (TODO: Should we use an auto-formatter?)

  • For shell code, also follow the existing style. It has 2 space indents, funcs-like-this (unless POSIX shell is required), and vars_like_this.
  • C code generally follows Python style (except 2 space indents?)
  • C++ mostly follows the Google style guide as well (though there currently isn't much of it). TODO: use clang-format.

OPy Compiler and Byterun

See opy/

Clone this wiki locally
You can’t perform that action at this time.