Blawnビルド・実行などメモ

# はじめに

恥ずかしながら、Qiitaの記事を見て初めて知りました、Blawn
https://qiita.com/blackenedgold/items/83526b329fe96ee781f5
いじって見たくなるじゃないですか、当然。その時のメモだと思います。

# 弄るからにはDocker

というわけで、Linuxで動作するものらしいので、環境が必要だよね、といえばDockerに登場して貰おうということです。
結局UbuntuとAlpineで試しました。UbuntuではすでにPull Requestされている通り整理されているので、Alpineでも動きましたという感じでしょうか。誰得

## Dockerfile for ubuntu

```Dockerfile.ubuntu

$ cat ~/dev/Brawn/Dockerfile.ubuntu 
FROM ubuntu:latest

MAINTAINER t.obara

RUN apt -y update
RUN apt -y install llvm clang flex bison make g++ git
WORKDIR /opt
RUN cd /opt && git clone https://github.com/kmizu/Blawn.git
RUN cd Blawn && git checkout -b develop origin/develop && cd src/build && make

ENTRYPOINT ["/opt/Blawn/src/build/bin/blawn"]
```

試す

```/bin/bash
$ docker build -f Dockerfile.ubuntu -t blawn:ubuntu .
$ docker run brawn:ubuntu
no input file!
$ echo 'print("Hello")' > hello.blawn
$ docker run -v `pwd`:/opt/work blawn:ubuntu work/hello.blawn
Hello
```

## Dockerfile for alpine

alpineの場合、何が違うかというと、一番大きな違いはllvmのバージョンです。alpineのDockerイメージで提供されているlatestはAlpine Linux v3.10で、llvmを入れるとllvm8が入るようです。そのあたりの違いを考慮しつつ環境を整えて見ました。

```Dockerfile.alpine
FROM alpine:latest

MAINTAINER t.obara

RUN apk add --update llvm-dev g++ make clang flex-dev flex bison git

WORKDIR /opt
RUN cd /opt && git clone https://github.com/kmizu/Blawn.git
RUN cd Blawn && git checkout -b develop origin/develop
COPY Makefile /opt/Blawn/src/build
RUN cd /opt/Blawn/src/build && make && cp -r bin /opt/Blawn && make clean

ENTRYPOINT ["/opt/Blawn/bin/blawn"]

```

試す

```/bin/bash
$ docker build -f Dockerfile.ubuntu -t blawn:alpine .
$ docker run brawn:alpine
no input file!
$ echo 'print("Hello")' > hello.blawn
$ docker run -v `pwd`:/opt/work blawn:alpine work/hello.blawn
Hello
```

実はMakefileを修正しないとうまくビルドできないので、修正しています。もう少し大きな変更が必要なら、gitに反映しても良かったのですがそこまではという感じです。

修正したMakefileの一部を載せておきます。

```Makefile
修正前
LLVM_LINK_OPTION := `llvm-config --cxxflags --system-libs --ldflags --libs core` -fexceptions -O3 -std=gnu++17 -std=c++17 -lstdc++fs
LLVM_OPTION := -I/usr/lib/llvm-6.0/include
CC := g++ -std=gnu++17 -std=c++17 -lstdc++fs -O3
all: blawn
blawn: builtins.o errors.o main.o compiler.o driver.o node.o parser.o lexer.o ast_generator.o node.o ir_generator.o utils.o blawn_context.o errors.o
        $(CC) -g -o blawn main.o compiler.o driver.o parser.o lexer.o ast_generator.o \
        ./node.o builtins.o ir_generator.o utils.o errors.o blawn_context.o -ll $(LLVM_LINK_OPTION)

--> 修正後
LLVM_LINK_OPTION := `llvm-config --cppflags --system-libs --ldflags --libs core` -fexceptions -O3 -std=gnu++17 -std=c++17 -lstdc++fs
LLVM_OPTION := `llvm-config --cppflags`
CC := g++ -std=gnu++17 -std=c++17 -lstdc++fs -O3
all: blawn
blawn: builtins.o errors.o main.o compiler.o driver.o node.o parser.o lexer.o ast_generator.o node.o ir_generator.o utils.o blawn_context.o errors.o
        $(CC) -g -o blawn main.o compiler.o driver.o parser.o lexer.o ast_generator.o \
        ./node.o builtins.o ir_generator.o utils.o errors.o blawn_context.o $(LLVM_LINK_OPTION)

```

### 修正内容
一行目と二行目ですが、どちらもllvm関連の修正です。一行目はllvmーconfigで指定しているオプションをcxxflagsからcppflagsに変更しました。以下に返却される結果を提示していますが、cppflagsで指定し、追加で個別にした方が良さそうに思いました。ubuntuでは確認していませんが、alpineだと、-fno-exceptionsが悪さをしているようで、ビルド時にエラーになりました。
二行目のLLVM_OPTIONはllvm6固定のパスが指定されているので、llvmーconfigで取得してあげた方が良いと思います。ubuntuだとllvm6が入るので今の所は問題ありませんが。
3つ目は五行目の-llオプションです。このオプションについて理解できていません:sweat:
が、alpine側ではエラーになるので、サクッと外しています。

### ubuntu
```sh
# llvm-config --cppflags
-I/usr/lib/llvm-6.0/include   -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS
# llvm-config --cxxflags
-I/usr/lib/llvm-6.0/include -std=c++0x -fuse-ld=gold -Wl,--no-keep-files-mapped -Wl,--no-map-whole-files -fPIC -fvisibility-inlines-hidden -Werror=date-time -std=c++11 -Wall -W -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wno-missing-field-initializers -pedantic -Wno-long-long -Wno-maybe-uninitialized -Wdelete-non-virtual-dtor -Wno-comment -ffunction-sections -fdata-sections -O2 -DNDEBUG  -fno-exceptions -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS
```

### alpine
```sh

# llvm-config --cxxflags
-I/usr/lib/llvm8/include -std=c++1y  -fno-exceptions -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS
# llvm-config --cppflags
-I/usr/lib/llvm8/include -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS
```


# おまけ
```sh
イメージのシェルに入りたい場合

$ docker run -it -v `pwd`:/opt/work --entrypoint /bin/sh brawn:ubuntu
$ docker run -it -v `pwd`:/opt/work --entrypoint /bin/sh brawn:alpine

気になるサイズ
＄ docker images
REPOSITORY                        TAG                 SIZE
brawn                             alpine              726.3 MB
brawn                             ubuntu              1.056 GB

```