Getting started with Erlang and Cowboy on Windows (rebar3 edition)

This is a follow-up to my previous post about Erlang and Cowboy, except this time covering it with the rebar3 build tool.

First, let me predicate this a little bit. rebar3 is a cool build tool, and I like it because it’s pure Erlang (no special build environment needed on Windows) and because it supports hex.pm, the new package index for Erlang and Elixir. As I come from a heavy Python background, I love Python’s PyPI, and having something similar in Erlang seems like The Way To Go™. However, if your goal is simply to get up with Erlang and Cowboy in the quickest way possible, read my other post. Cowboy is set up to work with Erlang.mk and will require less set up in that environment (especially the Cowboy-specific templates) compared to the rebar3 approach.

Also be aware that there seem to be some intermittent certificate errors with hex.pm’s package server which causes TLS-related errors and may prevent you from pulling from the package manager server via rebar3. Hopefully this will be resolved soon…

So, for those who are still here, here’s how you get up and running with rebar3.

Prerequisites

  • Erlang installed and on your PATH.
  • Git installed and on your PATH.

For those behind proxy servers

First, for the people out there who have to work from behind a proxy server: at the time of writing, the docs for rebar3 don’t appear to mention how to set up your proxy. I had to read the sources of the bootstrap file (used for “building” rebar3) to figure this step out. Skip this if you don’t have to worry about a proxy server:

  • Create the directory %USERPROFILE%\.config\rebar3.
  • Create the file %USERPROFILE%\.config\rebar3\rebar.config.
  • Add the following to the config file, replacing the fake servers with your real proxy servers:
    {http_proxy, "http://proxy.my-company.com:123"}.
    {https_proxy, "https://proxy.my-company.com:456"}.
    

Note: if the above does not work, it’s possible that Erlang may think your home directory is somewhere else (although I haven’t personally seen this). Check what Erlang returns for the command init:get_argument(home)., and replace %USERPROFILE% with the directory it specifies. This is the same command that rebar3’s bootstrap uses under the hood.

Finally: this isn’t really rebar3-specific, but for other tools (e.g. git), you will likely also want to set the http_proxy and https_proxy environment variables to the same values you used above. If you set your proxy info both in the config file above and in your environment variables, you should be golden.

Building rebar3

For this step, I’m basically just following the official docs.

Building rebar3 on Windows can be done as so:

git clone https://github.com/rebar/rebar3.git
cd rebar3
bootstrap.bat

Assuming everything goes smoothly, you should end up with two new files: rebar3 and rebar3.cmd. rebar3 is the guts, rebar3.cmd is the shim needed for Windows.

Move rebar3 and rebar3.cmd into a directory on your PATH. My personal preference is to have a scripts directory on the PATH, e.g. c:\scripts, and place rebar3 into there.

Troubleshooting: rebar_fetch errors

There is a chance that when you run bootstrap.bat, rather than building successfully, you’ll be met with an error like this:

===> Fetching eunit_formatters ({pkg,<<"eunit_formatters">>,<<"0.3.1">>})
escript: exception error: no match of right hand side value
                 {error,
                     {rebar_fetch,
                         {fetch_fail,<<"eunit_formatters">>,<<"0.3.1">>}}}

Without going too deep into details, this seems to be an intermittent certificate issue with the hex.pm package server. At the time of writing, it seems that there is an open issue with regards to this.

While this is an upstream problem that needs to be fixed, it can be worked around.

While I haven’t tested this, here is a possible solution that may make things work::

  • If not already done, create the directory %USERPROFILE%\.config\rebar3.
  • If not already done, create the file %USERPROFILE%\.config\rebar3\rebar.config.
  • Add this line to the config file:
    {ssl_verify, false}.
    

Thanks to Juggalocialist for suggesting this as a possible work-around.

Alternatively, although much more cumbersome, you can also grab the dependencies manually. For each failed dependency:

In my particular case, I had to do this for about 4 packages, but then I could successfully run bootstrap.cmd.

Creating a new rebar3 project

First, create a new project. My advice is to create a new “release”, per the docs:

rebar3 new release hello_erlang

The project generated here seems to follow the expectations of the Cowboy docs somewhat closer; my uneducated assumption is that the templates here are closer to the normal expectation for an Erlang app, whereas erlang.mk’s generated files are slightly different for some reason (perhaps a good one) that I don’t know.

Before going further, I advise making a few tweaks to the generated rebar.config file; the defaults seem fine for Linux users but not for Windows users. I suspect a few sharp edges still remain (and have been cut by them during previous experimentation).

Here’s what I suggest:

  • Set include_erts to true. This slows down the build a bit, but with it set to false, it tries to use the installed Erlang environment. The problem is that it seems to have a problem if there are spaces in the path to Erlang, which there are by default in Windows. (Forgive the Japanese Windows error message here; nonetheless, you can see that ” Files” is missing in the path.)
    ファイル c:\Program\erts-6.2\bin\werl.exe が見つかりません。
    
  • Set dev_mode to false. dev_mode makes rebar3 create symlinks to files, and it technically does create Windows-compatible symlinks. However, you’ll likely run into these issues:
    • If you run rebar3 release, normally you can run your app via _build\default\rel\hello_erlang\bin\hello_erlang.cmd console. However, this seems to fail silently when dev_mode is true on Windows.
    • Changing dev_mode to false after running a release with it set to true seems to cause errors, and I have not yet figured out how to resolve those errors short of deleting and re-creating the project; simply removing the _build directory does not resolve the problem.

    With this set up, you can test that you have a working app via running:

    rebar3 release
    _build\default\rel\hello_erlang\bin\hello_erlang.cmd console
    

    Using rebar3 with Cowboy

    Okay, now that you’ve gotten this far, here’s how to work with Cowboy.

    First, let’s add Cowboy as a dependency.

    In your rebar.config, change your deps line to look like this:

    {deps, [
            {cowboy, "1.0.4"}
           ]}.
    

    This should pull Cowboy from hex.pm, the Erlang/Elixir package directory. Run rebar3 compile to make sure the dependency is pullable. If it isn’t, substitute the cowboy clause above with {cowboy, {git, "git://github.com/ninenines/cowboy.git", {tag, "1.0.4"}}} and try again.

    The next step is editing the apps\hello_erlang\src\hello_erlang.app.src file. This follows the ninenines docs exactly: in the applications section, after stdlib, add cowboy. e.g.:

    {application, hello_erlang,
     [{description, "An OTP application"},
      {vsn, "0.1.0"},
      {registered, []},
      {mod, { hello_erlang_app, []}},
      {applications,
       [kernel,
        stdlib,
        cowboy
       ]},
      {env,[]},
      {modules, []},
    
      {maintainers, []},
      {licenses, []},
      {links, []}
     ]}.
    

    Note that, different from the ninenines guide, rather than files being at src\<file>, they are at apps\<project>\src\<file>.

    Next, following the above-mentioned guide, edit apps\hello_erlang\src\hello_erlang_app.erl. Just follow the guide verbatim with regards to the changes to the file’s contents.

    Again, to test the app, use the following:

    rebar3 release
    _build\default\rel\hello_erlang\bin\hello_erlang.cmd console
    

    Now, the final bit I want to cover is the Cowboy-specific templates. The templates are baked into Cowboy’s erlang.mk file and depend on using the erlang.mk-generated Makefile. rebar3 provides a templating mechanism, but we’ll need to extract the Cowboy templates and convert them into rebar templates.

    Under _build\default\lib\cowboy\erlang.mk, if you open the file, you can find the templates by searching for “define tpl_cowboy” (without the quotes). At the time of writing, I see four cowboy-specific templates. The actual template is everything between the “define tpl_cowboy” and the following “endef”. I will show how to convert the cowboy_http template; converting the others is an exercise for the reader.

    Here’s the quick-and-dirty procedure for converting cowboy_http:

    • Create the directory %USERPROFILE%\.config\rebar3\templates.
    • Create the .template file, %USERPROFILE%\.config\rebar3\templates\cowboy_http.template:
      {description, "Direct port of cowboy_http to rebar3"}.
      {variables, [
          {n, "http_handler", "Name of the module to create."},
          {project, "delete_me", "Name of the project."}
      ]}.
      {template, "cowboy_http.erl", "apps/{{project}}/src/{{n}}.erl"}.
      
    • Create the .erl file, %USERPROFILE%\.config\rebar3\templates\cowboy_http.erl. This is done by copying the body of the original template from the erlang.mk file and replacing $(n) with {{n}}.

    The one “wart” I see is that I don’t see a clear way to refer to the project name implicitly; thus I had to create the extra “project” variable in the cowboy_http.template file above. This causes the command for instantiating the cowboy_http template a little more verbose in rebar3 compared to erlang.mk.

    Anyway, once the template is created, you should be able to create modules based upon the template like so:

    rebar3 new cowboy_http project=hello_erlang n=hello_handler
    

    From here, you should be able to follow the rest of the Cowboy “Getting Started” guide without problems.

    Summary

    So, with this procedure, it should be possible to get up and running with rebar3.

    In summary, the procedure for working with rebar3 on Windows is:

    1. Set up proxy, if needed (environment and rebar.config)
    2. Build rebar3
    3. Tweak your project’s rebar.config so your project will build and run on Windows successfully.
    4. Extract any needed templates from Cowboy’s erlang.mk into rebar templates.

    The unexpected certificate errors when downloading from hex.pm via the rebar3 bootstrap script made things a bit more painful than I would have liked. Hopefully this will be resolved soon, but at least there is a workaround for those who are particularly determined.

    Thanks for reading!

Leave a Reply

Your email address will not be published. Required fields are marked *