普段、次のコマンドを通じてxmonad.hsを「コンパイル」し、その設定内容を反映させていることと思いますし、 ほとんどの方がxmonad.hsの中身がhaskellのプログラムであることを知っていると思います。
$ xmonad --recompile
しかし、xmonad使いだけれど、haskell使いでない場合、 普通のhaskellのプログラムをどうやってコンパイルするのか知らない人も多いのでは無いでしょうか?
今回のノートでは、 一般のhaskellプログラム開発で、今、 最も利用されているであろう「stack」というものを紹介します。 stackが使えるようになると、xmonad.hsをxmonadコマンドを使わず、自分でコンパイル出来るようになります。 そして、xmonadだけじゃない、一般的なhaskellのプログラムの作り方を覚えられれば、 この先、xmonadの設定をする場合に、xmonad-contrib等のxmonad関連のモジュールに縛られること無く、 世界に無数にあるhaskellのライブラリから好きなものを組み込んで、より自由なカスタマイズが可能となるのです。
さて、実際そこまで、おおげさな夢を広げなくても、stackを使えば、 AarchLinuxの場合、xmonad、haskell関連のパッケージアップデートがあった時(頻繁に有りますよね)、 xmonadのリコンパイルを忘れて、xmonadが立ち上がらず、twitterで悪口をいうという 「xmonadあるある」から、開放されるでしょう。
haskell開発の準備は思ったほど難しくない
さて、まずは一度くらい、ArchLinuxのhaskellのページを見てみましょう。
haskellのコンパイルについて、動的にリンクするのか、静的にリンクするのかだとか、 haskellのパッケージを公式パッケージで管理するのか、別のリポジトリを使うのかとか、 stackだとかcabalだと、普通のxmonad使いにとっては、 話がとても複雑で難しく読むのに飽きてしまう人もいると思います。 なので、私自身も、haskellの開発環境に足をつけるのがとても億劫なのでした。
しかし、xmonadでより自由にカスタマイズを楽しむためには、いずれ通らなければならない道です。 そこで、意を決して「stack-static」をインストールして使い始めることにしてみました。
まず、使い始めの心配事としては、xmonadを使っている場合、既にグローバルの環境に、 archlinuxの公式パッケージ管理に属する
xmonadを初めとしたghcやhaskellに関するarchlinucパッケージがあるが、
これをどうすればよいのか?
という事だったのです。しかし、 結論としては、
ほっておいて大丈夫そうだ!
と、いうことでした。 stackは、そもそも、「他の環境から独立したパッケージ毎の環境を作ってくれる」と、本家のページには書いてあったのですが、 一方で、archlinuxのページでは、「ghcやhaskell関連パッケージは削除しましょう」という意味の記述がありました。 そこで、一応、archlinuxの指示道理に関連パッケージを削除しようとしたら、 実際にはxmonadを使っている場合、依存関係的にそれらは削除できませんでした。 結果、指示通りにできていない部分があるので、何かトラブルになるのかぁ、、と、懸念していたのですが、 特に今の所不都合はおこっていません。
ですから、結局のところ、あまり悩まずに、AURの「stack-static」をインストールするだけで夢のhaskell開発環境は簡単に手に入るのです。
もし、知らないうちに公式パッケージのstackをインストールしていた場合には、
stack-staticをインストールする時に、衝突している旨のメッセージがでるので、入れ替える選択を選べばよいですし、
事前にやっておくことは、~/.stack
が、既にあるかを確認して、あったら削除しておくということだけです。(もちろん、普段から何かにstackの何かを使っている場合を除いて)
これで、準備は完了です。
後は、「stack-static」をインストールするだけ!
$ yay stack-static
stackがインストール出来たら、stackにhaskell開発環境を準備してもらいましょう。 stackが使う独立した開発環境として、 ghc等を~/.stack以下にインストールしてくれます。 難しく考えずに、以下のコマンドでOK!
$ stack setup
ここまでやっておけば、あとは、巷の「はじめてstackでなんたらかんたらやってみた」的な記事を適当に試せるようなっています。
xmonad.hsのstackプロジェクト構成
さっそく、やってみましょう。 stackでは、
$ stack new プロジェクト名 テンプレート名
という感じで、コマンドを発行すると、プロジェクト名のディレクトリの中に、テンプレートに従ったプロジェクトを作成してくれます。
テンプレートには色々なものがあるらしいのですが、 ここでは、xmonad.hsの管理用に、ok-xmonad.hsfilesというものを作ってみました。 例えば、このテンプレートを使って、my-xmonadというプロジェクトを作成する場合、次のようになります。 (コピペできるように、プロンプトの飾りは入れていません。)
stack new my-xmonad https://gist.githubusercontent.com/nekolinuxblog/630514e99ddb77d7862d25a543c29509/raw/2a54c8c4907e33a85d10a75346a1c188c43a9c6a/ok-xmonad.hsfiles
コマンドを実行すると、 テンプレートがダウンロードされて、セットアップされます。 my-xmonadディレクトリ以下は、次のような構造になっています。
これらファイルの役割を簡単に把握しましょう。
xmonad.hs
xmonad.hsは、いつもあなたがxmonadの設定を行っているxmonad.hsのサンプルです。 このサンプルでは、xmobar,dmenu,xtermを利用しています、必要に応じてシステムにインストールしておいてください。 基本的で簡単なxmonad.hsのサンプルです。 自分のxmonad.hsが無くても、これを使って、すぐにstackのビルドを試すことが出来ます。
package.yaml
package.yamlは、このsktackパッケージについて、対象となるソースファイルの指定や コンパイル時にどんな依存モジュールが必要で、どんなコンパイルオプションを付けるか等を指定するファイルです。 テンプレートで既に作成されているものは、xmonad.hsというファイル名のファイルをコンパイルするように指定してあります。 サンプルをそのままコンパイルする場合には、このファイルはこのままで大丈夫です。
しかし、このファイルは重要なファイルで、今後、xmonad.hsのカスタマイズを行って行く場合に、 xmonad、xmonad-contrib以外のモジュールを利用するようになると、 「dependencies:」項目に、その必要となるモジュール名を要素として加えていく必要があります。 テンプレートでは、base、xmonad、xmonad-contribが設定されていて、 それ以外のもの(xmonadの設定でよく利用されているもの)はコメントになっているので参考にして下さい。
初めは、xmonad.hsで扱うモジュールをここで書いておかないといけないという認識だけで十分です。 package.yamlのことがもっと知りたくなったら、Hpackというキーワードで調べてみましょう。
my-xmonad.cabal
stack setup
で(プロジェクト作成時にも)、package.yamlに基づいて自動生成されます。
ですから、自分で勝手に書き換えてはいけません。設定は、package.yamlに書いて行いましょう。
libディレクトリ
ここに、xmonad.hsから独立した自作のモジュールを作る場合、このディレクトリの中にファイルを作ります。 今の所、利用しません。
stack.yaml
stack自身の設定で、自動生成されます。 また、stack.yaml.lockも作成されます。 両方共ここでは触る必要はありません。
build
これは、stackとは関係がない、 xmonad自身が使う実行ファイルで、後で詳しく紹介します。
stackでxmonad.hsをコンパイル
サンプルさえあれば、準備は整っています。 初コンパイルしてみましょう!と言いたいのですが、 その前に
xmonad.hsの初めてのコンパイルには
凄く時間がかかります!
うちのセルロンCPUだと、20分くらい掛かりました。 ですから、時間に余裕のある時に、お茶でも飲む準備をしてから、 プロジェクトのディレクトリ(ここではmy-xmonad)の中で、 次のコマンドを発行して下さい。
$ stack build
エラーがなく終了すれば、コンパイルは完了です。
バイナリの出力ファイルは.stack-work
内にちゃんとできています。
普通のアプリならば、このbuildのあと、stack intall
を行って、
出来上がったバイナリファイルを~/.local/bin
にインストールします。
今回もとりあえず、試しにインストールしてみましょう。
$ stack install
stackがバイナリファイルをコピーするメッセージがでたとおもいます。
~/.local/bin
を確認すると、「my-xmonad-exe」というファイルが見つかったと思います。
xmonad起動の秘密
さて、そもそも、xmonadは何をどうやって起動しているのでしょうか? Xをstartxコマンドを使って手動起動しているなら、~/.xinitrc等に、 xmonadというコマンドを書いて起動しているはずです。 ディスプレーマネージャーを使っている場合、/usr/share/xsession/xmonad.desktopというセッションファイルで xmonadコマンドが指定されています。
xmonadコマンドは、archlinuxでは、xmonadパッケージでインストールされ、/usr/bin/xmonadにあります。 xmonadコマンドでxmonadウィンドマネージャが起動されるので、 このxmonadバイナリにxmonad.hsで設定した内容がその都度入っているのか?その都度、xmonadバイナリが置き換わっているのか? 色んな事を想像してしまいますが、実際にはそうではありません。
xmonadバイナリの本物
実際に、自分がカスタマイズしたxmonadの設定が入っている実行ファイルは、
たぶん、みなさんもいつも目にしている
~/.xmonad/xmonad-x86_64-linux
です。
xmonad --recompile
する度に、xmonad.hsがコンパイルされ、
新しい「xmonad-x86_64-linux」に置き換えられているのです。
そして、xmonadが起動するときには、「xmonad-x86_64-linux」が呼び出されているのです。
ここで、私達は、stack build
を使って、
自作の「my-xmonad-exe」というバイナリを手に入れました。
これを「xmonad-x86_64-linux」にリネームして、~/.xmonad/xmonad-x86_64-linux
へ置けば、
xmonadにあなたが作ったxmonadバイナリを強制的に利用させることが出来ます。
buildファイルというxmonadのスマート機能
しかし、上記のように無理やりなことをしなくても、
実は、今までと同じxmonad --recompile
するだけで、
stackでの自作バイナリを使ってくれるようにする方法をxmonad自身が用意してくれています。
最近のxmonadバージョンを使っている場合、xmonad --recompile
をした時、下記のメッセージが出ていることを知っていましたか?
$ xmonad --recompile
XMonad will use ghc to recompile, because "/home/neko/.xmonad/build" does not exist.
xmonadは、「.xmonad/buildが無いから、ghcでリコンパイルするよ」といっています。
つまり、もともと、xmonad --recompile
を発行すると、xmonadは、.xmonad/build
を実行してくれるようになっているのです。
そこで、このbuildファイルの中に、stackでのビルドと出来上がったファイルのインストールをスクリプトで記述しておけば、
今まで通りの操作で、stack産のxmonadを使えるようになるのです。
そして、そのbuildファイルが、今回のテンプレートで用意して、パッケージの中に入っているbuildファイルなのです。
#!/bin/sh
#
# As of 0.13, xmonad --recompile will look for a custom build script.
set -e
stack build :my-xmonad-exe --verbosity error
stack install :my-xmonad-exe --local-bin-path bin/ --verbosity error
mv bin/my-xmonad-exe "$1"
stackでのビルドを行い、インストールは、パッケージ内のbinディレクトリに仮に行った上で、 $1つまり、xmonad側で指定してくれる名前にリネームして、バイナリファイルを配置するだけのスクリプトです。
stackでxmonad.hsを管理
ここまでで、stackの開発環境を手に入れ、 xmonad.hsのためのプロジェクを作り、それをコンパイルしてバイナリファイルを得、 xmonadで、そのコンパイルされたバイナリファイルがどのように呼び出されるのかを把握しました。 その上で、xmonad自身が、ビルドを外部で行う事を許している事もわかりました。
これらの知識を踏まえて、xmonad.hsを具体的にどう管理すればよいのかといえば、
- xmonad.hs用のパッケージをok-xmonad.hsfilesテンプレートで作成
- パッケージのディレクトリを~/.xmonadに変更
- ~/.xmonad/buildに実行権限を与える
これで完了です。
つまりは、~/.xmonad
ディレクトリをパッケージディレクトリにしてしまうのです。
あとは、普通にxmonad.hsを編集して、いつものようにxmonad --recompile
するだけ、
もちろん、「Mod+q」にバインドされているなら、それで普通にリコンパイルアンドリスタートされます。
念の為、言っておきますが、 パッケージディレクトリを.xmonadディレクトリと入れ替える時は、 今まで使ってきた、xmonad.hsをなくさないように注意してくださいね。 また、初めに作るパッケージ名を「.xmonad」という風には出来ません。 自分の好きな名前で作った後に、ディレクトリの名前を変えて下さい。
参考にしたサイト等
もともと、xmonad.hsをstackでコンパイルしようとしたのは、 Haskell-jpのslackでのやりとりのなかで、勧めてもらったのがきっかけでした。 xmonadとstackの関連を勉強してみようと、 ネットで色々とみていて、「I finally set up XMonad to build with Stack!」という記事を見つけました。
特に、stackのプロジェクトを作る時に、テンプレートが使える事と、それ自体にxmonad.hsなんかを入れてしまえることが書かれていて、めちゃめちゃ感動しました。 また、xmonad自体が、buildというファイルでxmonad.hsのバイナリのビルドを制御できることもここに書かれていました。(テンプレートとして)
一方で、stackでのビルドの制御は「cabal」ファイルで記述されるようなしくみになっていたのですが、 最近ではHPackという「package.yaml」を使うほうが便利ということだったので、このページではそれが使えるテンプレートに書き換えてみました。 「package.yaml」については、「これからのHaskellプロジェクトではcabalではなくpackage.yaml(hpack)を使いましょう」を参考にしました。
0 件のコメント:
コメントを投稿