t100のプログラミング脱出作戦

自分のプログラミング脳をプログラムにして、いつかプログラミングから脱出してやるぞっ!とか夢見ながら、日々プログラム作っていく 百野 貴博 の日記です!今は、屋号『百蔵。』として、Silverlight・WPFを追跡中です! (2007/09/30)
スポンサーサイト
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
【--/--/-- --:--】 | スポンサー広告 | トラックバック(-) | コメント(-) top↑
ClojureのビルドツールLeiningenのチュートリアルを訳しました
Leiningenのチュートリアルを訳してみました。

Leiningenを使って開発を始めるのに、いい感じの足がかりに、、、なったらいいな!
無いよりはマシだと思います!たぶん!
(`・ω・´)9m ビシ

しかし、、、予想以上のボリュームだったので、めっちゃ時間かかってしまいました。

さらに、相変わらず直訳です。すみません。(´・ω・`)
改めて読み返したら、死ぬほど読みづらい・・・。


いつもは訳しながら自分でも実行してみるんですが、今回は訳すので精一杯だったので
コマンドやサンプルコードは、原文のものをそのままコピペしています。

前回まで、使っていたLeiningenとバージョンが違うみたいなので、若干実行結果が違うかもしれません。
ご注意くださいませ。


---

この翻訳にあたって、私の他の仕事のスケジュールも押してきたので、後半翻訳をお願いしてしまった奥さんに感謝を捧げます。
(昔、翻訳の勉強をしていたので、私の5000倍英語ができるのです)

#オライリー本のまえがき風に


このくらいの量を2,3時間で訳し切れるようになれたらな・・・
■Leiningen Tutorial

AntやMaven に怒って触ったことの無い皆さんへ、JVMに新しいものがあります。パニックにならないで下さい。
Leiningen は、あなたに心地よくデザインされています。このチュートリアルでは、あなたのスタートを助け、Leiningen のプロジェクトをビルドして、JVM上の依存関係を管理する方法を示します。


■Create Project

README に従って、Leiningenがインストールされているという前提で進みます。
新しいプロジェクトを作成するのは、簡単です。


$ lein new myproject

Created new project in: myproject

$ cd myproject
$ tree
.
|-- project.clj
|-- README
|-- src
|  `-- myproject
|    `-- core.clj
`-- test
  `-- myproject
    `-- core_test.clj



プロジェクトの README, 実装のコードを含んだ src ディレクトリ, test ディレクトリ, そして、Leiningen にプロジェクトを説明する為の project.clj ファイルが作成されます。
(訳者中:※ Leiningen 1.0 で実行したので、Leiningen のページにある出力結果と、ちょっと違うみたいです。 )

src/myproject/core.clj ファイルは、myproject.core 名前空間に対応します。

シングルセグメントの名前空間はClojureでは推奨されていないので、myprojectのみの変わりに、この名前空間を使っていることに注意してください。
同じく、test/myproject/core_test.clj は、myproject.core-test 名前空間に対応しています。
JVMは、ハイフン(-)のあるファイル名のロードに問題があるので、名前空間の名前に含まれるハイフンは、ディスク上のアンダースコアを持ったファイル名に置き換えられることを忘れないようにする必要があります。

■Packaging

今のところかなり役に立たないのですが、プロジェクトが一区切りしたタイミングで、パッケージングすることができます。

$ lein jar

Created ~/src/myproject/myproject-1.0.0-SNAPSHOT.jar


JVM 向けのライブラリは、JVM仕様のメタデータを含んだZipファイルである jar ファイルとしてパッケージ化されます。
それらは大抵、.class ファイル(JVMバイトコード)と、.clj ソースファイルを含みますが、config ファイルのような他のものも含むことができます。
Leiningen は、それらをリモートリポジトリからダウンロードします。

■ project.clj


$ cat project.clj

(defproject myproject "1.0.0-SNAPSHOT"
:description "FIXME: write"
:dependencies [[org.clojure/clojure "1.1.0"]
[org.clojure/clojure-contrib "1.1.0"]])



Clojarsにアップロード(後で解説します)した後に、あなたのプロジェクトが検索結果で見つけられるように :description に短い文を含めてください。
何らかのポイントでREADMEも更新する必要があるでしょう。しかし、今のところは :dependencies の設定のみで飛ばしておきましょう。
Clojure は、ここが標準的な依存関係であることに注意してください。他の言語と違って、どのClojureのバージョンとの切り替えが簡単です。
Clojure Contrib を使っているなら、Clojure バージョンとマッチするかを確認できます。

単純な ピュア Clojure プロジェクトの場合なら、デフォルトの依存関係はClojure と Contrib のみですが、そうでない場合、dependencies のリストを編集する必要があります。

■依存関係

Clojars は、Clojureコミュニティの中央 jar リポジトリで、あなたがプロジェクトに必要なClojureの依存関係を見つけることができる場所です。
どの依存関係も、それを使うために project.clj に同様に記述する必要があります。
Robert Hookeというライブラリの追加する方法を見てみましょう。

以下に示す記述で、Clojures上の依存関係はLeiningen を使って有効になります。

[robert/hooke "1.0.1"]



・"robert" は group-id と呼びます。
・"hooke" はartifact-id と呼びます。
・"1.0.1" は、必要とする jar のバージョンです。

Clojars上のプロジェクトでは、しばしば group-id と artifact-id は同じです。その場合、Leiningenの依存関係の記述方法からそれを省くことが出来ます。
Javaライブラリでは、しばしばドメイン名が group-id として使われます。
project.cljのdefprojectフォーオムの先頭にあるgroup名、artifact名と、バージョンは同じルールに従います。

Javaライブラリは Javana 検索で見つけることができます。しかし、Maven XML からLeiningen の書き方に変更する必要があります。
Lucene の基本的な書き方は以下です。

<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-core</artifactId>
<version>3.0.2</version>
</dependency>


こうなります。

[org.apache.lucene/lucene-core "3.0.2"]


時々、バージョンが"-SNAPSHOT" で終わることがあります。これは、オフィシャルなリリースでく開発ビルドであるという意味です。
スナップショットの依存関係に頼るとガッカリさせられるでしょうが、バグFixが必要な場合など時々必要になる場合があります。
まだ、それらを使ってリリースに進むべきではありません。
プロジェクトにスナップショットの依存関係を追加することは、あなたが lein deps を実行したときに、Leiningenが一日に一度依存関係の最新バージョンを検索に出て行く要因になります。
(通常リリースバージョンであれば、ローカルリポジトリにキャッシュされるのに対して)
ですから、スナップショットをたくさん追加すると、処理を遅くする可能性があります。


ローカルリポジトリに関しても説明しましょう。Leiningenがカバーする下でMaven APIを使うので、LeiningenかMavenを使って取得した全ての依存関係は、$HOME/.m2/repository にキャッシュされます。
次のコマンドで現在のプロジェクトをローカルリポジトリにインストールできます。


$ lein install

Wrote pom.xml
[INFO] Installing myproject-1.0.0-SNAPSHOT.jar to ~/.m2/repository/myproject/myproject/1.0.0-SNAPSHOT/myproject-1.0.0-SNAPSHOT.jar



通常は、Leiningenは、依存関係を必要に応じて取得(fetch)します。しかし、新しい依存を追加して、直ちに取得して適用したい場合も次のように実行できます。

$ lein deps

Copying 4 files to ~/src/myproject/lib
Copied :dependencies into ~/src/myproject/lib.


依存関係は、Clojures、中央Maven(Java)リポジトリ、オフィシャル Clojure ビルドサーバー、その他、project.clj ファイルに追加した全てのリポジトリからダウンロードされます。
sample.project.clj ファイルの :repositories を見てください。

もし、あなたのプロジェクトが異なるバージョンの依存関係でも動作することが確認できているなら、単一のバージョンの代わりに範囲を指定できます。

[org.clojure/clojure "[1.1,1.2]"] ; <= will match 1.1.0 through 1.2.0.



詳細は Maven's version range specification を見てください。


■開発の依存関係

時々、開発の利便性の為だけに依存関係を取得したい場合があります。それらは厳密にはプロジェクトの機能に必要ないものです。
Leiningen は、それらを:dev-dependencies と呼びます。

これらを project.clj の標準の dependencies と並べて記述して、lein deps を実行するとダウンロードされます。
しかし、それらは他のプロジェクトがあなたのプロジェクトに依存した場合には、持っていきません。
swank-clojure for Emacs support を使うことは、典型的な例でしょう。
それらをランタイムに含めたいとは思わないでしょうが、プロジェクトのハッキングの際には使っていたいでしょう。

■コードを書く

ここは、Leiningenがあなたを助けることができない章です。ここでは、あなたは一人です。
しかし、これは完全ではありません。Leiningen は、あなたのテストを実行することを助けることができます。


$ lein test

Testing myproject.core-test
FAIL in (replace-me) (core_test.clj:6)
No tests have been written.
expected: false
actual: false
Ran 1 tests containing 1 assertions.
1 failures, 0 errors.



もちろん、私たちはまだ何もテストを書いていません。だから、Leiningen が lein new で私たちのために作成したスケルトンが失敗します。
しかし、いったんテスト一式を書いたなら、より役立つようになります。時々、大きなテスト一式がある場合に、ひとつか二つの名前空間だけをテストしたい時があるでしょう。

$ lein test myproject.parser-test

Testing myproject.parser-test
Ran 2 tests containing 10 assertions.
0 failures, 0 errors.


新しいプロセスを開始する必要があるので、lein test はしばしばテストの実行が必須の開発サイクルにとっては、良いソリューションではありません。
この為、より良いエディタ統合(clojure-test-mode for Emacs を見てください)を調べるか、repl を開いた状態を保って、そこから run-tests を実行するかのどちらかでしょう。

■コンパイル

あなたがラッキーなら、どんなAOT(ahead-of-time)コンパイルなしに逃れられるでしょう。 しかし、AOTコンパイルが必須のJava互換機能があるので、もしあなたがそれらを使う必要があるなら、あなたのproject.clj ファイルに :aot オプションを追加する必要があります。
そのオプションは、AOT-コンパイルしたい名前空間のリストになるはずです。
sample.project.clj にはサンプルの使い方があります。


依存関係と同様に、コンパイルは自動で実行されますが、必要があれば手動で実行することができます。

$ lein compile

Compiling myproject.core



あなたのコードのコンパイルの為に、それは実行されます。これは、副作用のあるコードをトップレベルに置くべきではないことを意味します。
スタートアップで実行されるべきコードがあるなら、以下の"Uberjar"で解説しているように -main 関数に置いてください。

■ What to do with it/Leiningenを使って何をするか

一般的に言えば、典型的なLeiningenプロジェクトには3つの異なるゴール(目的)があります。

・エンドユーザーへ配布可能なアプリケーション
・ライブラリ
・サーバーサイドアプリケーション

エンドユーザーへ配布可能なアプリケーションとして使用する場合には、uberjarを構築することも可能ですし、またshell-wrapperを使用することもできます。
ライブラリとして使う場合には、Clojarsのような repositoryへpublish したいと思うでしょう。
サーバーサイドアプリケーションとして使う場合には、以下の記述の通り、さまざまな
使用方法があります。

■Uberjar

最もシンプルなのは、uberjar を配布することです。これは、単体で実行可能な jar ファイルです。
動かすためには、あなたの project.clj の :main に namespace を指定する必要があります。
今の時点で、私たちの project.clj は、これに似ているはずです。

(defproject myproject "1.0.0-SNAPSHOT"
:description "This project is MINE."
:dependencies [[org.clojure/clojure "1.1.0"]
[org.clojure/clojure-contrib "1.1.0"]
[org.apache.lucene/lucene-core "3.0.2"]
[robert/hooke "1.0.1"]]
:main myproject.core)




名前空間には、スタンドアロンのjarが実行される際に呼ばれる -main 関数が含まれていなければなりません。
この名前空間には、トップにある ns フォーム に :gen-class の記述が書かれていなければなりません。
-main 関数は、コマンドライン引数を通過させます。
ここで、src/myproject/core.clj の簡単なサンプルを試してみましょう。

(ns myproject.core
(:gen-class))

(defn -main [& args]
(println "Welcome to my project! These are your args:" args))



さあ、ここでuberjarを生成する準備が整いました。

$ lein uberjar
Cleaning up
Copying 4 files to /home/phil/src/leiningen/myproject/lib
Created ~/src/myproject/myproject-1.0.0.jar
Including myproject-1.0.0-SNAPSHOT.jar
Including clojure-contrib-1.1.0.jar
Including hooke-1.0.1.jar
Including clojure-1.1.0.jar
Including lucene-core-3.0.2.jar
Created myproject-1.0.0-standalone.jar


uberjar は、全ての依存関係のコンテンツを含む一つの jar ファイルを作ります。
ユーザーは単純なJavaの起動か、幾つかのシステムでは jar ファイルのダブルクリックで、それを実行することが出来ます。

$ java -jar myproject-1.0.0-standalone.jar Hello world.
Welcome to my project! These are your args: (Hello world.)



java コマンドラインツールで、通常の(uber ではない)jar を実行することも出来ますが、クラスパスを自分自身で構成する必要があるので、エンドユーザーにとっては適したソリューションではありません。


■Shell Wrappers

uberjar には、幾つかのデメリットもあります。他のコマンドラインツールに比べて、やや実行しづらい面があります。
どのようにJVMを起動するのかコントロールをすることも出来ません。
この問題を解決する為に、プロジェクトを開始しようとしている jar ファイルが使うことの出来る Shell Script を加えることが出来ます。
Leiningen は、インストール時にこのシェルスクリプトを ~/.lein/bin ディレクトリに置いています。

単純に、project.clj に :shell-wrapper true のみを含めれば、Leiningenは自動的に簡単なshell script wrapper をjarファイルを作成するときに自動生成します。
しかしながら、さらにコントロールが必要な場合に、map を提供することもできます。

:shell-wrapper {:main myproject.core
:bin "bin/myproject"}





通常、shell wrapperは、projectの :main namespaceの -main 関数を実行しますが、このオプションを指定することが uberjarの為のAOTのトリガーとなるので、これを避けるか、uberjarとは異なるシェルラッパーの為の:main を使いたいと望む場合、:main ns に :shell-wrapper マップを含むことができます。
resources ディレクトリにあるファイルを、デフォルトのshell wrapperの代わりのテンプレートとして使うファイルを指すために、:bin キーを指定することができます。
format 関数は、このファイルの内容と、必要なクラスパス、メインの名前空間と共に呼ばれます。そのため、%s を正しい位置に置いてください。
サンプルとして the default wrapper を見てください。

■Publishing

プロジェクトがlibraryで、ほかの人達もプロジェクト内で依存関係として使用できる様にすることを希望するのであれば、共有リポジトリへ入る必要があるでしょう。
自分のリポジトリを保持したり、Maven centralへ入ることも可能ではありますが、一番簡単な方法は、Clojarsで発行することです。
一旦、アカウントを発行してしまえば、発行は簡単です。

$ lein jar && lein pom
$ scp pom.xml myproject-1.0.0.jar clojars@clojars.org:


いったん、うまく実行できれば、依存する他のプロジェクトにおいてもパッケージとして利用できるようになるでしょう。
Clojars にプロジェクトのgroup-idを発行するための許可をもらう必要がありますが、group-idがまだ存在しない場合でもClojarsは自動的にgroup-idを作って許可を与えてくれます。


時々、オリジナルのメンテナーがそれを発行していないか、まだ適用されていないバグ修正が必要な場合などに、あなたが直接メンテナンスしていないライブラリを発行する必要が発生します。
このような場合には、オリジナルの group-idで発行することは避けたいでしょう。なぜならそうすることによって本当のメンテナーが一旦発行したgroup-idを使用することを防げるからです。
その group-idの代わりに "org.clojars.$USERNAME" を使うべきです。


■Server-side Projects

プロジェクトをサーバー側のアプリケーションとしてデプロイする方法はたくさんあります。
シンプルなプログラムは、lein-release pluginを利用し、さらにchefpallet、あるいは他の機能を使ってデプロイする shell scriptを付属させた tarballとしてまとめることができます。
Web applicationでもlein-war pluginを使ってデプロイすることができます。
Hadoop projectでさえ構築することができます。
こうした配置(展開)は幾通りもあるので、Leiningen本体にbuilt-inされているタスクよりも、pluginを使用する方がより扱いやすいでしょう。


■That's IT!

図解の方がよいのであれば、project management上の Full Disclojure screencastを試してみてください。
さあ!次のプロジェクトへ向けてコードを書いてみましょう!

テーマ: プログラミング - ジャンル: コンピュータ

komagata
非常に参考になり助かりました!
お金払いたいくらいです!
ありがとうございました。
2011/06/24(金) 18:34:01 | URL | [ 編集]
t100
komagata さん
大変ありがたいコメントありがとうございます!
返信が遅くなってしまって、すみません・・・。

これからも、面白そうな情報があればドンドン紹介していきたいと思います!宜しくお願い致しますー。
2011/07/25(月) 00:43:45 | URL | [ 編集]












管理者にだけ表示を許可する


トラックバックURL:
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。