Projmake-mode: Flymake Replacement

There is a great new Emacs plugin from Eric Merritt that like FlyMake builds your code and highlights within Emacs any errors or warnings, but unlike FlyMake builds across the whole project. You can clone the mode from here projmake-mode

After cloning the repo to your desired location add this bit to your dot emacs file, replacing <PATH> with the path to where you cloned the repo.

This Emacs code also uses add-hook to set projmake-mode to start for erlang-mode is loaded. Projmake by default knows how to handle rebar and Make based builds so there is no setup after this, assuming your project is built this way.

Here is my Makefile for building Erlang projects with rebar, replace PROJECT with the name of your project:

Now you can load Emacs and a file from your project and if it is an Erlang file due to the add-hook function in our dot emacs file it will automatically load projmake-mode. You can add hooks for other modes or simply run M-x projmake-mode.

For more documentation and how to extend to other types of projects check out the documentation.

Sinan Releases and Being Right

Fred, of Learn You Some Erlang for Great Good, today posted on his blog about the problems around how rebar handles releases, Rebar Releases and Being Wrong. The problems he mentions and a few others are why, despite giving it a legitimate shot, I have found rebar unusable for my workflow to be efficient and stable while adhering to OTP standards at the same time.

I suggest first reading his post, if you already use rebar, and then continuing on with the rest of this.

I’ll start with an example on the generation of a project containing two applications and a dependency from one of those applications of cowboy. Next, I’ll create a release (and in the process a deployable target system) to show the difference in how sinan handles this process.

TL;DR Sinan does OTP the right way, rebar does not.

First, you can download the latest version sinan from this link, it is simply an executable escript, so ‘chmod +x sinan‘ and put it in your PATH and you are good to go.

Sinan provides a ‘gen’ command to create your project. I include the output of the steps I took to build this project. Sinan assumes this is a multiple application project, but if you give “y” instead it will create a directory structure similar to rebars default structure with a src/ directory instead of a lib/ directory.

$ sinan gen
Please specify your name 
your name> Tristan Sloughter
Please specify your email address 
your email> tristan@mashape.com
Please specify the copyright holder 
copyright holder ("Tristan Sloughter")> 
Please specify name of your project
project name> rel_example
Please specify version of your project
project version> 0.0.1
Please specify the ERTS version ("5.9")> 
Is this a single application project ("n")> 
Please specify the names of the OTP apps that will be developed under this project. One application to a line. Finish with a blank line.
app> app_1
app ("")> app_2
app ("")> 
Would you like a build config? ("y")> y
Project was created, you should be good to go!

We now have a project named rel_example and can see the generated contents.

$ cd rel_example/
$ ls
config  doc  lib  sinan.config

Before going further I add the line {include_erts, true}. to sinan.config so that a generated tarball of the release contains erts and can be booted on a machine without Erlang installed.

$ cat sinan.config
{project_name, rel_example}.
{project_vsn, "0.0.1"}.

{build_dir,  "_build"}.

{ignore_dirs, ["_", "."]}.

{ignore_apps, []}.

{include_erts, true}.

A tree structure view of the generated project is below:

.
├── config
│   └── sys.config
├── doc
├── lib
│   ├── app_1
│   │   ├── doc
│   │   ├── ebin
│   │   │   └── overview.edoc
│   │   ├── include
│   │   └── src
│   │       ├── app_1_app.erl
│   │       ├── app_1.app.src
│   │       └── app_1_sup.erl
│   └── app_2
│       ├── doc
│       ├── ebin
│       │   └── overview.edoc
│       ├── include
│       └── src
│           ├── app_2_app.erl
│           ├── app_2.app.src
│           └── app_2_sup.erl
└── sinan.config

You’ll see we have a lib directory with two applications containing their source files under a src directory. Now in order to boot the release we’ll create, we need to remove a couple tings from each supervisor. Instead of creating something for them to supervise just remove the variable AChild and replace [AChild] with [].

Next, so we have a third party dependency in the example, add cowboy to the applications in nano lib/app_1/src/app_1.app.src:

{applications, [kernel, stdlib, cowboy]},

Sinan provides a depends command to show the depenedencies of the project and where they are located:

$ sinan depends -v
starting: depends
Using the following lib directories to show resolved dependencies and where it found them:

    /home/tristan/.kerl/installs/r15b/lib
    /home/tristan/Devel/rel_example/_build/rel_example/lib

compile time dependencies:

runtime dependencies:

    kernel                    2.15       : /home/tristan/.kerl/installs/r15b/lib/kernel-2.15
    stdlib                    1.18       : /home/tristan/.kerl/installs/r15b/lib/stdlib-1.18
    cowboy                    0.5.0      : /home/tristan/.kerl/installs/r15b/lib/cowboy-0.5.0

project applications:

    app_1                     0.1.0      : /home/tristan/Devel/rel_example/_build/rel_example/lib/app_1-0.1.0
    app_2                     0.1.0      : /home/tristan/Devel/rel_example/_build/rel_example/lib/app_2-0.1.0

Now lets build a release and target system.

$ sinan dist

After running the dist command we have a _build directory that we find the following structure. I removed the files/dirs under each app to shorten the listing.

_build/
├── rel_example
│   ├── bin
│   │   ├── rel_example
│   │   └── rel_example-0.0.1
│   ├── erts-5.9
│   │   ├── 
│   ├── lib
│   │   ├── app_1-0.1.0
│   │   │   ├── 
│   │   ├── app_2-0.1.0
│   │   │   ├── 
│   │   ├── cowboy-0.5.0
│   │   │   ├── 
│   │   ├── kernel-2.15
│   │   │   ├── 
│   │   └── stdlib-1.18
│   │       ├── 
│   └── releases
│       └── 0.0.1
│           ├── rel_example.boot
│           ├── rel_example.rel
│           ├── rel_example.script
│           └── sys.config
└── tar
    └── rel_example-0.0.1.tar.gz

Sinan has created a lib directory containing all necessary applications for our release as well as the needed files for booting the release. Additionally the dist command creates a tar.gz for easy deployment. But if we simply want to run our release where we are we can:

$ _build/rel_example/bin/rel_example
Erlang R15B (erts-5.9)

[64-bit] [smp:4:4] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.9  (abort with ^G)
1>

This is only the tip of the iceberg of what sinan is capable of. I can’t go into all of it here but I’ll mention that you are able to define multiple releases for a project to generate and which of your project apps to include in each. Additionally you are able to provide a custom rel file if you require tweaks.

The important part to take away from this post is the structure of what you are working with when using sinan and how it is based on OTP standards, both for the source you work on and the results of the build process under _build/.