The LFE rebar3 Plugin Command Reference






by Duncan McGreggor











publisher logo

Published by Cowboys 'N' Beans Books

https://github.com/cnbbookshttp://cnbb.pub/info@cnbb.pub




First electronic edition published: 2020




© 2020, Duncan McGreggor

This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License

Creative Commons License




Cover art: Original version from 1968 DEC FOCAL Programming Manual with stylised PDP-8 as the dominant cover graphic. Adaptation of the original as a spoof and homage was made in 2015 by Duncan McGreggor.

Introduction

The rebar3_lfe project is a rebar3 plugin for the LFE language. It provides many of the conveniences one has come to expext of a programming language's build tool:

  • Project Creation
  • A REPL
  • Compilation
  • Maintenane Tasks (e.g., file cleanup)
  • Metadata

Features

  • Create new LFE projects:
    • rebar3 new lfe-lib
    • rebar3 new lfe-main
    • rebar3 new lfe-escript
    • rebar3 new lfe-app
    • rebar3 new lfe-release
  • Start up an LFE REPL:
    • rebar3 lfe repl
  • Compile LFE source code:
    • rebar3 lfe compile
  • Run eunit tests
    • rebar3 eunit
  • Run an LFE project's main/1 function as an lfescript (run rebar3 new lfe-main to see an example):
    • rebar3 lfe run
    • rebar3 lfe run -- 1 2 5
    • rebar3 lfe run -main some/path/main.lfe
  • Escriptize an LFE escript project:
    • rebar3 ecsriptize
  • Run an escriptized LFE escript project:
    • rebar3 lfe run-ecsript
  • Generate an LFE/OTP release
    • rebar3 release
  • Run an LFE/OTP release project's release script (COMMAND can be start , stop , status, ping, etc.):
    • rebar3 lfe run-release COMMAND
  • Cleanup
    • rebar3 lfe clean
    • rebar3 lfe clean-build
    • rebar3 lfe clean-cache
    • rebar3 lfe clean-all
  • Metadata
    • rebar3 lfe versions

More coming soon!

Background

This plugin originally started life as a shell script (lfetool -- there's even a T-shirt for it!), then it toyed with integrating with rebar (the original). Around that time, though, rebar3 was under initial development, and LFE took a chance on it as an early adopter. This lead to a whole series of LFE plugins, but after a few years momentum was lost.

Those early rebar3 efforts have been combined into a single plugin in this project, with many updates and using all the latest approaches developed in rebar3's now mature ecosystem.

Previous Releases

This is the documentation for rebar3_lfe v0.3.0-dev (unreleased).

Previous versions of the documentation:

Related

There is also the LFE Quick Start with rebar3 which you may be interested in.

Setup

Dependencies

In order to use the LFE rebar3 plugin, you need to have the following installed on your system:

  • Erlang (only tested with versions 19 and above)
  • rebar3 (tested with 3.10 and 3.12)

You don't need to download LFE; the plugin will do that for you.

Using the Plugin

After installing rebar3, the only thing you need to do in order to take full advantage of the LFE rebar3 plugin is add it to the plugins in your global rebar.config file.

Stable

To use the latest stable release, update your `rebar.config` to:

{plugins, [
  {rebar3_lfe,
    {git, "https://github.com/lfe-rebar3/rebar3_lfe.git", {tag, "0.2.0"}}}
]}.

Unstable

If you want to use the current development branch (unstable):

{plugins, [
  {rebar3_lfe,
    {git, "https://github.com/lfe-rebar3/rebar3_lfe.git", {branch, "release/0.3.x"}}}
]}.

Command Reference

The following sections detail actual usage of the suite of rebar3 lfe commands.

Compiling

The single most imporant convenience provided by the LFE rebar3 plugin is arguably the compiler. This allows any LFE project to be downloaded, compile, and used by any BEAM language that is also using rebar3 to manage its dependencies, etc.

To compile an LFE project:

rebar3 lfe compile

If you are publishing your LFE code, or using it in another project, you'll want to update your rebar.config file so that it is compile when a user (or script) executes the regular rebar3 compile command.

To ensure your LFE code will compile in other projects, add the following to your project's rebar.config:

{provider_hooks, [
  {pre, [{compile, {lfe, compile}}]}
  ]}.

Package Support

The LFE rebar3 plugin provides support for pseudo-packages. There is no such thing as a pckage in Erlang, but using this plugin, you can emulate some of the behaviours of packages.

This is accomplished by traversing top-level source directories for any subdirectories: if the plugin finds any .lfe or .erl files in subdirectories under configured source directories, it will create a dotted module name composed of the relative path to that file, and write that name to the ebin directory after successful compilation.

Here are some examples of how combinations of subdirectories and files will be transformed in their final form as .beam files:

./src/my.package1.lfe                      -> ebin/my.package1.beam
./src/my/package2.lfe                      -> ebin/my.package2.beam
./src/my/other/package.lfe                 -> ebin/my.other.package.beam
./src/my/really/deeply/nested/package1.lfe -> ebin/my.really.deeply.nested.package1.beam
./src/my/really/deeply/nested.package2.lfe -> ebin/my.really.deeply.nested.package2.beam
./src/my/really.deeply.nested.package3.lfe -> ebin/my.really.deeply.nested.package3.beam
./src/my.really.deeply.nested.package4.lfe -> ebin/my.really.deeply.nested.package4.beam

Running the REPL

An LFE project and all of its dependencies may be interacted with via a REPL that is started with the LFE rebar3 plguin, as rebar3 sets all of the correct library locations for use by shells and REPLs.

To start up a REPL:

rebar3 lfe repl

Testing

[In progress]

eunit

If you have written eunit tests in Erlang or LFE, they will be compiled by either the rebar3 compile or rebar3 lfe compile command and thus be available and ready to run using rebar3 as-is.

Run compiled eunit tests:

rebar3 eunit

ltest

[In progress]

Common Test

[In progress]

Creating Projects

The rebar3_lfe plugin is capable of creating several common project layouts. This and following sections provide details on those that are currently supported.

Creating LFE Libraries

Library projects are those with no running applications or scripts; they simply provide some core bit of functionality intended for use by applications, scripts, or other libraries.

To create a library project with the default name:

rebar3 new lfe-lib

This will generate the following output:

===> Writing my-lfe-lib/README.md
===> Writing my-lfe-lib/LICENSE
===> Writing my-lfe-lib/rebar.config
===> Writing my-lfe-lib/.gitignore
===> Writing my-lfe-lib/src/my-lfe-lib.lfe
===> Writing my-lfe-lib/src/my-lfe-lib.app.src

You can also explicitely name your project:

rebar3 new lfe-lib forty-two

Which will produce the following:

===> Writing forty-two/README.md
===> Writing forty-two/LICENSE
===> Writing forty-two/rebar.config
===> Writing forty-two/.gitignore
===> Writing forty-two/src/forty-two.lfe
===> Writing forty-two/src/forty-two.app.src

As mentioned abouve, the REPL offers a nice way to quickly interact your new project.

Start the REPL:

cd forty-two
rebar3 lfe repl

Call the generated/sample LFE function:

lfe> (mything:my-fun)
hello-world

Creating main Scripts

LFE supports the creation of scripts, and these can be integrated with libraries, allowing for the best of both worlds: a simple collection of useful functions (library) and a means of running them from the command line.

Create a library that also has a script with a main function:

rebar3 new lfe-main special-proj

Which generates:

===> Writing special-proj/README.md
===> Writing special-proj/LICENSE
===> Writing special-proj/rebar.config
===> Writing special-proj/.gitignore
===> Writing special-proj/src/special-proj.lfe
===> Writing special-proj/scripts/main.lfe
===> Writing special-proj/src/special-proj.app.src

The generated project's main script + function may then be run with:

cd mymain
rebar3 lfe run -- 42

Which will produce the following output:

Running script '/usr/local/bin/rebar3' with args [<<"42">>] ...
'hello-worl

Creating escripts

The LFE rebar3 plugin also supports generating escript-based projects in LFE. This is similar in nature to the main-based project, but is more standard in the BEAM family of languages.

To create an escript-based project:

rebar3 new lfe-escript myapp
===> Writing myapp/README.md
===> Writing myapp/LICENSE
===> Writing myapp/rebar.config
===> Writing myapp/.gitignore
===> Writing myapp/src/myapp.lfe
===> Writing myapp/src/myapp.app.src

Compile the LFE and then bundle all the code up by "escriptizing" it:

cd myapp
rebar3 lfe compile
rebar3 escriptize

Run the newly-created escript:

rebar3 lfe run-escript 1 2 5 no '3!'

Which will display the following:

Got args: ("1" "2" "5" "no" "3!")
Answer: 42

Creating OTP Applications

In the wider Erlang community, it is very common to see applications that run one or more gen_servers (or other server behaviours) managed by a supervision tree (with the appropriate restart strategy defined). The LFE rebar3 plugin provides the ability to generate OTP gen_server applications with the server managed in a supervision tree.

To create an LFE/OTP application:

rebar3 new lfe-app otp-lfe
===> Writing otp-lfe/README.md
===> Writing otp-lfe/LICENSE
===> Writing otp-lfe/rebar.config
===> Writing otp-lfe/.gitignore
===> Writing otp-lfe/src/otp-lfe.lfe
===> Writing otp-lfe/src/otp-lfe-app.lfe
===> Writing otp-lfe/src/otp-lfe-sup.lfe
===> Writing otp-lfe/src/otp-lfe.app.src

We can use the plugin's REPL command to demonstrate usage.

Start the REPL:

cd otp-lfe
rebar3 lfe repl

Start the app:

lfe> (application:ensure_all_started 'otp-lfe)
#(ok (otp-lfe))

Make sure the supervisor is running:

lfe> (erlang:whereis 'otp-lfe-sup)
#Pid<0.205.0>

Make an API call to the gen_server:

lfe> (otp-lfe:echo "testing the supervised gen_server ...")
"testing the supervised gen_server ..."

Creating OTP Releases

If you're going to be running an LFE application in production, you will very likely want to do so using the "release" functionality provided by OTP.

Create a release-based project with:

rebar3 new lfe-release prod-lfe
===> Writing prod-lfe/README.md
===> Writing prod-lfe/LICENSE
===> Writing prod-lfe/rebar.config
===> Writing prod-lfe/.gitignore
===> Writing prod-lfe/apps/prod-lfe/src/prod-lfe.lfe
===> Writing prod-lfe/apps/prod-lfe/src/prod-lfe-app.lfe
===> Writing prod-lfe/apps/prod-lfe/src/prod-lfe-sup.lfe
===> Writing prod-lfe/apps/prod-lfe/src/prod-lfe.app.src
===> Writing prod-lfe/config/sys.config
===> Writing prod-lfe/config/vm.args

Start up the application:

rebar3 lfe run-release start

Check the status of the application:

rebar3 lfe run-release ping
pong

Known Issue!

If your ping doesn't get a pong after starting the release, this is a known issue that is being investigated in the following ticket:

https://github.com/lfe-rebar3/rebar3_lfe/issues/33

Workaround

The current workaround for a relese that doesn't start is simply to run the following again:

rebar3 release
rebar3 lfe run-release start
rebar3 lfe run-release ping

In addition to using the LFE rebar3 commands to start the application, you can start up a release console and then switch to the LFE REPL.

Start the console:

./_build/default/rel/prod-lfe/bin/prod-lfe console
Eshell V11.0  (abort with ^G)
(prod-app@spacemac)1> lfe_shell:start().
(prod-app@spacemac)lfe> (erlang:whereis 'prod-lfe-sup)
#Pid<0.351.0>
(prod-app@spacemac)lfe> (prod-lfe:echo "testing from production!")
"testing from production!"

Running Code

The LFE rebar3 plugin provides developers the ability to run LFE code directly, taking advantage of rebar3's setting of library paths for dependencies, etc.

run

To run an LFE project that was generated with rebar3 new lfe-main:

rebar3 lfe run

run-escript

To run an LFE project that was generated with rebar3 new lfe-escript:

rebar3 lfe run-escript

run-release

To run an LFE project that was generated with rebar3 new lfe-release and has been compiled with rebar3 release:

rebar3 lfe run-release COMMAND

Where COMMAND is one of the non-interactive commands supported by the release script:

  • start
  • stop
  • restart
  • reboot
  • pid
  • ping

Others non-interactive commands not listed may also work, but they have not been tested.

Known Issue!

If your release doesn't start (e.g., running rebar3 lfe run-release ping doesn't return pong), this is a known issue that is being investigated in the following ticket:

https://github.com/lfe-rebar3/rebar3_lfe/issues/33

Workaround

The current workaround for a relese that doesn't start is simply to re-run rebar3 release and rebar3 lfe run-release start.

Cleanup Commands

There are a handful of tasks the author of the plugin has found useful when debugging LFE applications, rebar3 plugins, etc. These include various "cleanup" tasks that are not currently supported by rebar3 (or whose support is problematic).

clean

Remove the apps' ebin/* files:

rebar3 lfe clean

clean-build

Remove the _build directory:

rebar3 lfe clean-build

clean-cache

Remove the the cached directories for the app and the rebar3_lfe plugin, both global and local:

rebar3 lfe clean-cache

clean-all

Perform all clean tasks as well as remove the files erl_crash.dump, rebar3.crashdump, and rebar.lock:

rebar3 lfe clean-all

Versions

It can be very useful to obtain all the important version info for a project: your project, LFE, the LFE rebar3 plugin, and the Erlang release installed/active on your machine. When submiting a bug or asking for help on the LFE Slack, you might very well be asked for this information.

Get a project's versions:

rebar3 lfe versions
(#(apps
   (#(prod-lfe git)))
 #(languages
   (#(lfe "1.3-dev")
    #(erlang "23")
    #(emulator "11.0")
    #(driver_version "3.3")))
 #(tooling
   (#(rebar "3.10.0")
    #(rebar3_lfe "0.2.0"))))

Feedback and Docs Bugs

If you would like to provide feedback about this guide, we would welcome the chance to improve the experience for everyone. Please create a ticket in the Github issue tracker. Be sure to give a full description so that we can best help you!