インタプリタ言語開発環境をDockerで構築する[Windows]
長期休みだし、Rubyみたいな解析木実行型のインタプリタ言語をのぞいてみたいと思ったのでそのための環境構築をしました。
Windows環境なので、Dockerでlinux環境を作り処理を実行できるようにします。
作業場所
C:\Users\{user_name}\Documents\docker_environment\workspace\sunaba
で作業を行い、Dockerfile等はここに置くことで実際のコードと分けて管理しようと思います。
コードはC:\Users\{user_name}\Documents\docker_environment\workspace\sunaba\work
に置き、ここをホストとコンテナとの共有フォルダとしようと思います。
C:.
├─Documents
│ ├─docker_environment
│ │ └─workspace
│ │ └─sunaba
│ │ ├─docker_build.bat
│ │ ├─docker_start.bat
│ │ ├─docker_stop.bat
│ │ ├─Dockerfile
│ │ └─work
│ │ ├─.gitignore
│ │ ├─Makefile
│ │ ├─sunaba.c
│ │ └─test.sh
参考リンク
違いは上記の内容にyaccとlexをインストールしてbatchファイルを追加しているだけです
Dockerのインストール
Docker Desktop for WindowsをDocker Hubからダウンロードしてインストールしてください。
起動してチュートリアルをポチポチできればDockerのインストールができていることを確認できるので楽です
Dockerfileの作成
Dockerfileを以下のように作成し、C:\Users\{user_name}\Documents\docker_environment\workspace\sunaba'に'Dockerfile
という名前で保存してください。
FROM ubuntu:latest
RUN apt update
RUN DEBIAN_FRONTEND=noninteractive apt install -y gcc make git binutils libc6-dev gdb sudo bison flex
RUN adduser --disabled-password --gecos '' user
RUN echo 'user ALL=(root) NOPASSWD:ALL' > /etc/sudoers.d/user
RUN mkdir /work
USER user
WORKDIR /home/user
Dockerイメージの作成
'make_compilerという名前でDockerイメージを作成するバッチファイルを作成します。 以下の内容を
C:\Users{user_name}\Documents\docker_environment\workspace\sunaba'に'docker_build.bat`という名前で保存してください。
@REM docker初回起動時
docker build -t make_compiler C:/Users/{user_name}/Documents/docker_environment/workspace/sunaba/
@REMはコメントです。@REMがある行は削除しても処理に変化はありません。
コンテナ作成用バッチ
compile_test
という名前でコンテナを作成するバッチファイルを作成します。
作成するファイル名はdocker_start.bat
としてC:\Users\{user_name}\Documents\docker_environment\workspace\sunaba
に保存してください
@REM インタラクティブに使用したい場合
@REM docker run --rm -it -v C:/Users/202169/{user_name}/docker_environment/workspace/sunaba/work:/work -w /work --name compile_test make_compiler
@REM コンテナの中でmakeを実行してソースファイルtestをコンパイル
docker run --rm -v C:/Users/{user_name}/Documents/docker_environment/workspace/sunaba/work:/work -w /work --name compile_test make_compiler make test
docker run --rm -v C:/Users/{user_name}/Documents/docker_environment/workspace/sunaba/work:/work -w /work --name compile_test make_compiler make clean
僕はコンテナを使用するたびに新しく作成したい派なので、--rm
オプションでコマンドが終了するとコンテナも終了するようになっています。
また、-v <source>:<dest>
オプションでホストの環境のパス<source>を、Dockerの中で<dest>として共有するようにしています。
最後にmake test
として、後述するテスト処理をするようにしています。
コンテナをインタラクティブに使用した時のコンテナ停止バッチ
コンテナをインタラクティブに使用して作業したい場合のためにコンテナ停止バッチもついでなので作っておきます。
作成するファイル名はdocker_stop.bat
としてC:\Users\{user_name}\Documents\docker_environment\workspace\sunaba
に保存してください
compile_test
という名前でコンテナが作成されていると想定しています。
@REM dockerを止める時
docker stop compile_test
docker rm compile_test
環境構築できたかの確認
ここまでを行い、docker_build.bat
を実行すれば、環境構築は完了しているので
動作確認を行いたいと思います。
実行する処理は低レイヤを知りたい人のためのCコンパイラ作成入門: ステップ1:整数1個をコンパイルする言語の作成 コンパイラ本体の作成の内容です。
処理ファイルの作成
sunnaba.c
という名前でC:\Users\{user_name}\Documents\docker_environment\workspace\sunaba\work
に以下の内容を保存してください
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
if (argc != 2) {
fprintf(stderr, "引数の個数が正しくありません\n");
return 1;
}
printf(".intel_syntax noprefix\n");
printf(".global main\n");
printf("main:\n");
printf(" mov rax, %d\n", atoi(argv[1]));
printf(" ret\n");
return 0;
}
テスト処理用のシェルスクリプト
自動テスト用のシェルスクリプトをtest.sh
という名前でC:\Users\{user_name}\Documents\docker_environment\workspace\sunaba\work
に以下の内容を保存してください
#!/bin/bash
assert() {
expected="$1"
input="$2"
./sunaba "$input" > tmp.s
cc -o tmp tmp.s
./tmp
actual="$?"
if [ "$actual" = "$expected" ]; then
echo "$input => $actual"
else
echo "$input => $expected expected, but got $actual"
exit 1
fi
}
assert 0 0
assert 42 42
echo OK
Makefileの作成
ここまでの処理を自動実行するMakefileをMakefile
という名前でC:\Users\{user_name}\Documents\docker_environment\workspace\sunaba\work
に以下の内容を保存してください
CFLAFS=-std=c11 -g -static
mcc:sunaba.c
test:sunaba
./test.sh
clean:
rm -f sunaba *.o *~ tmp*
.PHONY: test clean
gitで管理することを考え、.gitignore
をC:\Users\{user_name}\Documents\docker_environment\workspace\sunaba\work
に作成します。
*~
*.o
tmp*
a.out
sunaba
最後に、docker_start.bat
を実行して
0 => 0
42 => 42
OK
と表示されたら完了です。
-
{user_name}はそれぞれのPC環境の設定によって変わります。 ↩︎
Discussion