Open22

GHCのJavaScript backendを使ってみる

重城良国重城良国

ghc-9.10.1-src.tar.xzをダウンロード。

https://www.haskell.org/ghc/download_ghc_9_10_1.html#sources

% tar Jxvf ghc-9.10.1-src.tar.xz
% cd ghc-9.10.1
% ./boot.source
% emconfigure ./configure --target=javascript-unknown-ghcjs GHC=/home/.../.stack/.../bin/ghc
% stack install alex
% ./hadrian/build -j12 --flavour=guick --bignum=native --docs=none
% _build/stage1/bin/javascript-unknown-ghcjs-ghc --info | grep Target
% cd ..
% mkdir src
% vi src/hello.hs
% ghc-9.10.1/_build/stage1/bin/javascript-unknown-ghcjs-ghc src/hello.hs
% ./src/hello
% firefox src/hello.jsexe/index.html

重城良国重城良国

実行可能ファイルはghc-9.10.1/_build/bin/javascript-ghcjs-ghcとなっている。が、これだけを/usr/local/binにコピーしても実行できない。_build/stage1/lib以下の、settings, package.conf.d/, ghc-usage.txt, javascript-ghc-js-ghc-9.10.1/もコピーする必要がある。make installとか、そういうやりかたもあるのだと思うのだけど、見つけられなかった。

どうやら

% ./hadrian/build install

みたいにできるようだ。

https://qiita.com/kyamaz/items/4399bb2e8c595a77c1a5

% ./hadrian/build install --prefix=/usr/local/ --docs=none

としたのだけど、コンパイルからまた始まってしまった。--prefixを変えたからか。

もしかすると、--bignum=nativeが必要なのかもしれない。

重城良国重城良国

Stackにあまえていたけど、JavaScriptバックエンドを使うにはGHCの素のパッケージ管理を学ぶ必要があるかもしれない。

重城良国重城良国

./hadrian/build installはうまくいかないな。

sudoでglobalにinstallしようとしていたのが良くなかった。GHCupでローカルにインストールされてたghcやcabalが見つからなかったという話だ。~/.local/以下にインストールすれば大丈夫かもしれない。

command line: sh configure --prefix=/home/foo/.local/
===> Command failed with error code: 1

checking emsdk version... Command failed

となるな。

重城良国重城良国

GHCはHaskellからJavaScriptに変換するときに一度llvmにするのかな。

重城良国重城良国

しばらくはpackageは使わずにall-in-oneでやっていこうかな。
プロジェクトをまたいでの再利用にはコピペを使うという原始的なやりかたでやる。
で、僕のスキルが上がるか、あるいはGHCやCabalやStackの機能が追いつくかしたときにpackageを使うことにしよう。

古のやりかたでSetup.hsをコンパイルして実行するというやりかたならできるかもしれない。

重城良国重城良国

Setup.hsを作ってパッケージを作ろうと思ったが、

% ./Setup configure --with-ghc=javascript-unknown-ghcjs-ghc --with-ghc-pkg=javascript-unknown-ghcjs-ghc-pkg --with-gcc=emcc --with-ld=emcc
% ./Setup build
...
wasm-ld: error: unknown file type: dist/build/Foo.o
...

のようにエラーになってしまう。GHCがJavaScriptを出力するときにどのような動作になっているのかを知る必要があるが、まあ、あとにしよう。

GHCのコードを読まざるを得ないだろうから。

https://gitlab.haskell.org/ghc/ghc/-/wikis/javascript-backend/bug_triage#fooo-file-not-recognized-file-format-not-recognized

重城良国重城良国

たとえばモジュールHelloひとつからなるパッケージを登録するとすると、つぎのようになる。

% javascript-unknown-ghcjs-ghc Hello.hs
% cp Hello.hi /home/foo/tmp/hello-0.1.0.0/
% emar qcls libHShello-0.1.0.0.a Hello.o
% mv libHShello-0.1.0.0.a /home/foo/tmp/hello-0.1.0.0/

以下のような内容のhello.confを作成する。

name:            hello
version:         0.1.0.0
id:              hello-0.1.0.0
key:             hello-0.1.0.0
exposed-modules: Hello
import-dirs:     /home/foo/tmp/hello-0.1.0.0
library-dirs:    /home/foo/tmp/hello-0.1.0.0
hs-libraries:    HShello-0.1.0.0
% javascript-unknown-ghcjs-ghc-pkg register hello.conf
重城良国重城良国

登録したパッケージを使おうとすると

        getDeps: Couldn't find home-module:

Hello

みたいなエラーが出てコンパイルができない

重城良国重城良国

どうやら、idとkeyをhello-0.1.0.0-inplaceのような名前にする必要があったようだ。

name:            hello
version:         0.1.0.0
id:              hello-0.1.0.0-inplace
key:             hello-0.1.0.0-inplace
exposed-modules: Hello
import-dirs:     ${pkgroot}/../lib/javascript-ghcjs-ghc-9.10.1/hello-0.1.0.0
library-dirs:    ${pkgroot}/../lib/javascript-ghcjs-ghc-9.10.1/hello-0.1.0.0
library-dirs-static:    ${pkgroot}/../lib/javascript-ghcjs-ghc-9.10.1/hello-0.1.0.0
hs-libraries:    HShello-0.1.0.0
重城良国重城良国

上の調査でソースコードにderiving Showとかprint文とかを書きまくったので、もう一度ソースコードを入手して、全体をインストールし直そうかな。

他のマシンに何回かインストールしたことで、どこにインストールしたらいいかみたいな話もかたまってきたし。~/.local/ghc/bin/に実行ファイルをコピーして、~/.local/ghc/lib/以下に設定ファイルを置いて、で~/local/bin/にsoft linkを置くのが良さそう。

あと、ソースコードは安定版ではなくて、GitHubから引っ張ってこようかな。進化が速そうなので。

重城良国重城良国

最新のソースで試そうとしたらconfigureの段階でunknown argument: --no-as-neededで失敗したので、大人しく公開されたソースコードを試すことにする。

問題はそこではなくてHappyのバージョンだったようだ。

GitLabから持ってきた最新のソースだと、同様の問題がまた生じる。9.10.1だと平気。

重城良国重城良国

以下のように-inplaceを付ける必要があった様子。GHC.StgToJSあたりが決め打ちで-inplaceの付く名前を使ってるってことなのかな。

name:            hello
version:         0.1.0.0
id:              hello-0.1.0.0-inplace
key:             hello-0.1.0.0-inplace
exposed-modules: Hello
import-dirs:     ${pkgroot}/../lib/javascript-ghcjs-ghc-9.11.20240705/hello-0.1.0.0-inplace
library-dirs:    ${pkgroot}/../lib/javascript-ghcjs-ghc-9.11.20240705/hello-0.1.0.0-inplace
library-dirs-static:    ${pkgroot}/../lib/javascript-ghcjs-ghc-9.11.20240705/hello-0.1.0.0-inplace
hs-libraries:    HShello-0.1.0.0-inplace
重城良国重城良国

あと、書いたかどうか忘れたけど、*.hiファイルとか*.oファイルを作るときには-package-nameオプションが必要。

% javascript-unknown-ghcjs-ghc -package-name hello-0.1.0.0-inplace Hello.hs

みたいにする。

重城良国重城良国

いろいろ覚え書きしたけど、抜けてるところが多い。とくにパッケージ化については、独自のやりかたでインストールできるようにしたので、そのあたりを(まずは)メモりたい。