LoginSignup
21
5

More than 3 years have passed since last update.

Gleam (Rust + Erlang) 事始め

Last updated at Posted at 2020-10-15

1.はじめに

https://gleam.run/
https://github.com/gleam-lang/gleam

昨年、2019年9月にVer.0.1がリリースされた非常に新しい言語で、Rustで書かれていてErlang VM上で動くコンパイラです。

最近ElixirとRustを勉強していて興味があったので、GleamでHello Worldを表示するまで試してみました。

Gleamのコード例

構文はRustですが、パイプを使って順次処理を流せるところが、Elixirっぽい感じですね~

image.png

2.インストール

実行環境

  • Raspberry Pi 4
  • Raspbian Buster
コマンドライン
$ uname -a
Linux raspi4 5.4.51-v7l+ #1333 SMP Mon Aug 10 16:51:40 BST 2020 armv7l GNU/Linux

(1)Rust

RaspbianのaptでインストールできるRustでは、gleamがコンパイルできないので、最新版(1.47.0)をソースからビルドしました。(後述にエラーの詳細あり)

こちら1を参考にインストール。

コマンドライン
$ cd gitwork/rust
$ curl https://sh.rustup.rs -sSf | sh
info: downloading installer

Welcome to Rust!

This will download and install the official compiler for the Rust
・・・(省略)・・・
Current installation options:


   default host triple: armv7-unknown-linux-gnueabihf
     default toolchain: stable (default)
               profile: default
  modify PATH variable: yes

1) Proceed with installation (default)
2) Customize installation
3) Cancel installation
>1

info: profile set to 'default'
・・・(省略)・・・
コマンドライン
$ source $HOME/.cargo/env
$ rustc --version
rustc 1.47.0 (18bf6b4f0 2020-10-07)
$ cargo --version
cargo 1.47.0 (f3c7e066a 2020-08-28)
$
コマンドライン
$ sudo apt install -y libssl-dev
$
コマンドライン
$ cargo install cargo-edit
    Updating crates.io index
  Downloaded cargo-edit v0.7.0
  Downloaded 1 crate (57.6 KB) in 0.59s
  Installing cargo-edit v0.7.0
・・・(省略)・・・
    Finished release [optimized] target(s) in 15m 21s
  Installing /home/pi/.cargo/bin/cargo-add
  Installing /home/pi/.cargo/bin/cargo-rm
  Installing /home/pi/.cargo/bin/cargo-upgrade
   Installed package `cargo-edit v0.7.0` (executables `cargo-add`, `cargo-rm`, `cargo-upgrade`)
$
コマンドライン
$ git clone https://github.com/sagiegurari/cargo-make.git
Cloning into 'cargo-make'...
remote: Enumerating objects: 559, done.
remote: Counting objects: 100% (559/559), done.
remote: Compressing objects: 100% (348/348), done.
remote: Total 13676 (delta 386), reused 332 (delta 195), pack-reused 13117
Receiving objects: 100% (13676/13676), 6.72 MiB | 3.07 MiB/s, done.
Resolving deltas: 100% (10889/10889), done.


$ cd cargo-make
$ cargo install --force cargo-make
    Updating crates.io index
  Downloaded cargo-make v0.32.7
  Downloaded 1 crate (1.2 MB) in 1.69s
・・・(省略)・・・
   Compiling cargo-make v0.32.7
    Finished release [optimized] target(s) in 9m 41s
  Installing /home/pi/.cargo/bin/cargo-make
  Installing /home/pi/.cargo/bin/makers
   Installed package `cargo-make v0.32.7` (executables `cargo-make`, `makers`)
$
コマンドライン
 $ rustup update
info: syncing channel updates for 'stable-armv7-unknown-linux-gnueabihf'
info: checking for self-updates

  stable-armv7-unknown-linux-gnueabihf unchanged - rustc 1.47.0 (18bf6b4f0 2020-10-07)

info: cleaning up downloads & tmp directories
$

動作確認します。

コマンドライン
$ cd gitwork/rust
$ mkdir ./hello
$ cd hello
$ nano main.rs
$ cat main.rs 

ソースの中身

main.rs
fn main() {
    println!("Hello, world!");
}

コンパイルと実行

コマンドライン
$ rustc main.rs
$ ./main
Hello, world!
$

rustの動作確認ができました。

(2)Erlang

(記述中。基本的にはElixirのインストール時の手順に倣う)

コマンドライン
$ erl
Erlang/OTP 22 [erts-10.5.4] [source] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe]

Eshell V10.5.4  (abort with ^G)
1> 

(3)gleam

公式マニュアル2に従ってインストール。

コマンドライン
$ cd gitwork/rust

$ git clone https://github.com/gleam-lang/gleam.git --branch v0.11.0
Cloning into 'gleam'...
remote: Enumerating objects: 5, done.
・・・(省略)・・・

$ cd gleam
$ make
build                          Build the compiler
install                        Build the Gleam compiler and place it on PATH
test-watch                     Run compiler tests when files change

#ビルド
$ make build
cargo build --release
  Downloaded arrayvec v0.5.1
  Downloaded askama_derive v0.10.3
  Downloaded nix v0.17.0
・・・(省略)・・・
   Compiling askama v0.10.3
   Compiling hyper-tls v0.4.3
   Compiling reqwest v0.10.7
   Compiling gleam v0.11.0 (/home/pi/gitwork/rust/gleam)
    Finished release [optimized] target(s) in 23m 08s

#ビルド
$ make install
cargo install --path . --force --locked
  Installing gleam v0.11.0 (/home/pi/gitwork/rust/gleam)
    Updating crates.io index
    Finished release [optimized] target(s) in 4.08s
  Installing /home/pi/.cargo/bin/gleam
   Installed package `gleam v0.11.0 (/home/pi/gitwork/rust/gleam)` (executable `gleam`)
$

gleamコマンドを実行したところ。

コマンドライン
$ gleam
gleam 0.11.0

USAGE:
    gleam <SUBCOMMAND>

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

SUBCOMMANDS:
    build     Compile a project
    docs      Render HTML documentation for a project
    format    Format source code
    help      Prints this message or the help of the given subcommand(s)
    new       Create a new project
$

(4)rebar3

rebar3は、Erlangのビルドツールです。
公式マニュアル3に従ってインストール。

コマンドライン
$ cd gitwork/

$ git clone https://github.com/erlang/rebar3.git
Cloning into 'rebar3'...
remote: Enumerating objects: 111, done.
remote: Counting objects: 100% (111/111), done.
remote: Compressing objects: 100% (84/84), done.
remote: Total 20765 (delta 57), reused 53 (delta 27), pack-reused 20654
Receiving objects: 100% (20765/20765), 6.23 MiB | 3.30 MiB/s, done.
Resolving deltas: 100% (14204/14204), done.

$ cd rebar3
$ ./bootstrap
===> Verifying dependencies...
===> Fetching bbmustache v1.10.0
===> Fetching cth_readable v1.4.8
・・・(省略)・・・
===> Compiling certifi
===> Analyzing applications...
===> Compiling rebar
===> Building escript for rebar...
$

インストールとコマンドの実行

コマンドライン
$ ./rebar3 local install
===> Extracting rebar3 libs to /home/pi/.cache/rebar3/vsns/3.14.1+build.4800.ref38a3db0e/lib...
===> Writing rebar3 run script /home/pi/.cache/rebar3/bin/rebar3...
===> Add to $PATH for use: export PATH=/home/pi/.cache/rebar3/bin:$PATH

#とりあえずパスを通す
#常用するなら.bashrcに追記のこと
$ export PATH=/home/pi/.cache/rebar3/bin:$PATH

$ rebar3 
Rebar3 is a tool for working with Erlang projects.

Usage: rebar3 [-h] [-v] [<task>]

  -h, --help     Print this help.
  -v, --version  Show version information.
  <task>         Task to run.

  Set the environment variable DEBUG=1 for detailed output.

Several tasks are available:
・・・(省略)・・・
Run 'rebar3 help <TASK>' for details.
$

3.簡単なプログラムを試す

(1)空のプロジェクト

ドキュメント4に従って進めます。

コマンドライン
$ cd gitwork/gleam

#プロジェクトを生成
$ gleam new hello
* creating hello/LICENSE
* creating hello/.gitignore
* creating hello/README.md
* creating hello/gleam.toml
* creating hello/test/hello_test.gleam
* creating hello/src/hello.gleam
* creating hello/.github/workflows/test.yml
* creating hello/rebar.config
* creating hello/src/hello.app.src

Your Gleam project "hello" has been successfully created.
The rebar3 program can be used to compile and test it.

    cd hello
    rebar3 eunit

#ビルド
$ cd hello/
$ rebar3 eunit
===> Fetching rebar_gleam v0.1.0
===> Analyzing applications...
===> Compiling rebar_gleam
===> Verifying dependencies...
===> Fetching gleam_stdlib v0.11.0
Compiling hello
・・・(省略)・・・
===> Performing EUnit tests...
.
Finished in 0.037 seconds
1 tests, 0 failures

続いて、ドキュメント5に従って進めます。

コマンドhello:hello_world().を入力すると、関数を直接実行します。
[Ctrl-C]を二回入力すると、シェルが終了します。

コマンドライン
$ rebar3 shell
===> Verifying dependencies...
Compiling hello
Compiling gleam/option
・・・(省略)・・・
Compiling gleam/uri
Done!
===> Analyzing applications...
===> Compiling hello
Erlang/OTP 22 [erts-10.5.4] [source] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe]

Eshell V10.5.4  (abort with ^G)
1> hello:hello_world().
<<"Hello, from hello!">>
2> 
BREAK: (a)bort (c)ontinue (p)roc info (i)nfo (l)oaded
       (v)ersion (k)ill (D)b-tables (d)istribution
^C
$

Hello, from hello!が表示出来ました。

ソースファイルはこちらに生成されています。
hello/src/hello.gleam
image.png

(2)Webサーバ

Gleamのトップページに紹介されているソースコード、Examples/A basic webserver を試します。

プロジェクトを作成します。

コマンドプロンプト
$ cd gitwork/

#プロジェクトを作成
$ gleam new basicwebserver
* creating basicwebserver/LICENSE
* creating basicwebserver/.gitignore
* creating basicwebserver/README.md
* creating basicwebserver/gleam.toml
* creating basicwebserver/test/basicwebserver_test.gleam
* creating basicwebserver/src/basicwebserver.gleam
* creating basicwebserver/.github/workflows/test.yml
* creating basicwebserver/rebar.config
* creating basicwebserver/src/basicwebserver.app.src

Your Gleam project "basicwebserver" has been successfully created.
The rebar3 program can be used to compile and test it.

    cd basicwebserver
    rebar3 eunit

$ cd basicwebserver/

ソースコードを追記します。

src/basicwebserver.gleam
import gleam/http/elli
import gleam/http
import gleam/bit_builder

pub fn my_service(_req) {
  let body = bit_builder.from_string("Hello, world!")

  http.response(200)
  |> http.set_resp_body(body)
}

pub fn start() {
  elli.start(my_service, on_port: 3000)
}

// ↑ ここまで追記

// ↓ 自動的に生成されている箇所
pub fn hello_world() -> String {
  "Hello, from basicwebserver!"
}

依存関係のあるライブラリを追記します。
Elixirでお馴染みのmix.exsのような書き方ですね。

rebar.config
{erl_opts, [debug_info]}.
{src_dirs, ["src", "gen/src"]}.

{profiles, [
    {test, [{src_dirs, ["src", "test", "gen/src", "gen/test"]}]}
]}.

{project_plugins, [rebar_gleam]}.

{deps, [
    {gleam_stdlib, "~> 0.11"}, //追記
    {gleam_http, "~> 1.1"},    //追記
    {gleam_elli, "~> 0.1"},    //追記
    elli
]}.

実行

コマンドプロンプト
$ rebar3 shell
===> Verifying dependencies...
Compiling gleam/otp/basic_supervisor
Compiling gleam/otp/supervisor
・・・(省略)・・・
===> Analyzing applications...
===> Compiling basicwebserver
Erlang/OTP 22 [erts-10.5.4] [source] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe]

Eshell V10.5.4  (abort with ^G)
1> basicwebserver:start().
{ok,<0.221.0>}
2>

シェルから実行した後、ブラウザでアクセスします。

image.png

(3)マルチスレッド

引き続き、Examples/Multi-threaded hello world を試します。

※プロジェクトの設定が上手くいかずコンパイルできない・・・省略

代わりにこちらを試してみました。
Echo

#ソースをクローン
$ git clone https://github.com/gleam-lang/example-echo-server.git
$ cd example-echo-server/

#コンパイルと実行
$ rebar3 shell
・・・(省略)・・・
===> Analyzing applications...
===> Compiling echo
Erlang/OTP 22 [erts-10.5.4] [source] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe]

Eshell V10.5.4  (abort with ^G)
1> ===> Booted echo

4.まとめ

今回はとりあえず、サンプルのコンパイルまでを試してみました。
まだこれからという所ではあるようですが、今後の成長が楽しみな言語です。

HexやElixirとの連携もできるようなので、引き続き試してみたいと思います)

5.その他

細々とした覚え書き。

(1)古いRustではGleamのビルドができない

Raspbian BusterのaptでインストールできるRustのバージョンは、1.34でした。
こちらのrustcで、gleamをコンパイルしたとき、下記のメッセージが大量にでてしまいました。

image.png

・・・(省略)・・・
'futures_api': futures in libcore are unstable (see issue #50547)
・・・(省略)・・・

この辺、良く解らないので、Rustの最新版(執筆時点は1.47)をソースからビルドし直しました。
これを使うと、Gleamのビルドが通りました。

(2)VS Codeの拡張機能

Gleam Syntaxという拡張機能が、既に用意されてます。(すばらしい!

image.png

コードのハイライト状態

image.png

(3)アップデート

最新版(例ではVer.0.14.0)にアップデートします。

$ cd gitwork/rust/gleam

#ブランチ名を指定してpull
~/gitwork/rust/gleam $ git pull origin v0.14.0

remote: Enumerating objects: 524, done.
remote: Counting objects: 100% (524/524), done.
remote: Total 1598 (delta 524), reused 524 (delta 524), pack-reused 1074
Receiving objects: 100% (1598/1598), 664.41 KiB | 3.10 MiB/s, done.
Resolving deltas: 100% (1131/1131), completed with 82 local objects.
From https://github.com/gleam-lang/gleam
 * tag               v0.14.0    -> FETCH_HEAD
Updating 374e199..3e044d4
Fast-forward
 .gitattributes                                                    |    3 +
 .github/workflows/ci.yaml                                         |   46 +-
(・・・省略・・・)

#ビルド
$ make build && make install
cargo build --release
    Updating crates.io index
(・・・省略・・・)
    Finished release [optimized] target(s) in 34m 17s

#バージョン確認
~/gitwork/rust/gleam $ gleam
gleam 0.14.0

参考資料

21
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
5