CLOVER🍀

That was when it all began.

Leiningenことはじめ

そろそろ、Clojureでもビルド・依存関係管理ツールを触ってみようかと思います。Clojure界隈ですと、間違いなくLeiningenが候補となるので例に漏れずこちらで。

Leiningenとは?

Clojureでのビルド・依存関係管理ツールで、プラグインなども豊富にあるようです。JavaでいうMavenやScalaでいうsbtの位置付けにあると思います。

Leiningenのオフィシャルは、Githubと合わせて2つあります?
http://leiningen.org/
https://github.com/technomancy/leiningen/

なお、今回使用するLeiningenのバージョンは

2.0.0-preview7

となります。安定版ではないようですが、1.x系からは移行が進んでいるようですのでまあいいでしょ。

それにしても、バナーのおじさんが渋すぎる…

まずはインストール

以下から、leinスクリプトをダウンロードします。
https://raw.github.com/technomancy/leiningen/preview/bin/lein

これを適当な場所に配置します。自分は、以下に配置しました。まあお好みですよね。

/usr/local/leiningen/lein

続いて、PATHと通します。

export LEININGEN_HOME=/usr/local/leiningen
PATH=${LEININGEN_HOME}:${PATH}

最後、権限変更です。

$ sudo chmod 755 lein

確認。ヘルプを見てみましょう。

$ lein help
Downloading Leiningen now...
--2012-07-08 16:14:08--  https://github.com/downloads/technomancy/leiningen/leiningen-2.0.0-preview7-standalone.jar
github.com (github.com) をDNSに問いあわせています... 207.97.227.239
github.com (github.com)|207.97.227.239|:443 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 302 Found
場所: http://cloud.github.com/downloads/technomancy/leiningen/leiningen-2.0.0-preview7-standalone.jar [続く]
--2012-07-08 16:14:09--  http://cloud.github.com/downloads/technomancy/leiningen/leiningen-2.0.0-preview7-standalone.jar
cloud.github.com (cloud.github.com) をDNSに問いあわせています... 54.240.164.106, 54.240.164.139, 54.240.164.140, ...
cloud.github.com (cloud.github.com)|54.240.164.106|:80 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 200 OK

 〜省略〜

Leiningen is a tool for working with Clojure projects.

Several tasks are available:
check        Check syntax and warn on reflection.
classpath    Write the classpath of the current project to output-file.
clean        Remove all files from project's target-path.
compile      Compile Clojure source into .class files.
deploy       Build jar and deploy to remote repository.
deps         Show details about dependencies.
do           Higher-order task to perform other tasks in succession.
help         Display a list of tasks or help for a given task.
install      Install current project to the local repository.
jar          Package up all the project's files into a jar file.
javac        Compile Java source files.
new          Generate project scaffolding based on a template.
plugin       DEPRECATED. Please use the :user profile instead.
pom          Write a pom.xml file to disk for Maven interoperability.
repl         Start a repl session either with the current project or standalone.
retest       Run only the test namespaces which failed last time around.
run          Run the project's -main function.
search       Search remote maven repositories for matching jars.
show-profilesList all available profiles or display one if given an argument.
test         Run the project's tests.
trampoline   Run a task without nesting the project's JVM inside Leiningen's.
uberjar      Package up the project files and all dependencies into a jar file.
upgrade      Upgrade Leiningen to specified version or latest stable.
version      Print version for Leiningen and the current JVM.
with-profile Apply the given task with the profile(s) specified.

Run lein help $TASK for details.

See also: readme, faq, tutorial, news, sample, profiles,
deploying and copying.

とまあ、なんかいろいろとダウンロードしてきた後に、ヘルプが表示されます。ここでLeiningen本体をダウンロードしているみたいですね。もちろん、2回目以降は「lein help」を入力してもダウンロード処理は行われません。

Leiningenは、最初にインストールしたBashスクリプトに引数を与えることで、いろんなタスクを実行できるみたいです。以下、Githubより。

$ lein new [TEMPLATE] NAME # generate a new project skeleton

$ lein test [TESTS] # run the tests in the TESTS namespaces, or all tests

$ lein repl # launch an interactive REPL session

$ lein run -m my.namespace # run the -main function of a namespace

$ lein uberjar # package the project and dependencies as standalone jar

なんとなく意味はわかりそうです。

プロジェクトを作成してみる

では、プロジェクトを作成してみましょう。ここはチュートリアルに沿って。
https://github.com/technomancy/leiningen/blob/preview/doc/TUTORIAL.md

プロジェクトの作成は、「lein new」で行います。

$ lein new hello-lein
Generating a project called hello-lein based on the 'default' template.
To see other templates (app, lein plugin, etc), try `lein help new`.

プロジェクト名は、「hello-lein」としました。

hello-leinディレクトリが作成されるので、移動してファイルを見てみます。

$ cd hello-lein/
$ find
.
./src
./src/hello_lein
./src/hello_lein/core.clj
./.gitignore
./doc
./doc/intro.md
./README.md
./project.clj
./test
./test/hello_lein
./test/hello_lein/core_test.clj

いきなり、.gitignoreがある…。あと、Mavenのように「src/main/...」という形式では「src」でいきなり終わりになっています。プロジェクト名は、そのまま名前空間になってそうです。

生成されたファイルで、主要そうなものを見てみましょう。
project.clj

(defproject hello-lein "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.4.0"]])

プロジェクトの定義っぽいですね。Clojure自体がdepencenciesに書いてあるのは、ただのJARとしてしか見てないということなのでしょうか…。

src/hello_lein/core.clj

(ns hello-lein.core)

(defn -main
  "I don't do a whole lot."
  [& args]
  (println "Hello, World!"))

アプリケーションのエントリポイントのようですね。

なんか、このままでも動かせそうなので、「lein run」で動かしてみます。「-m」オプションの後には、-main関数を持った名前空間を指定します。

$ lein run -m hello-lein.core
Retrieving org/clojure/clojure/1.4.0/clojure-1.4.0.pom (5k)
    from http://repo1.maven.org/maven2/
Retrieving org/clojure/clojure/1.4.0/clojure-1.4.0.jar (3341k)
    from http://repo1.maven.org/maven2/
Hello, World!

初回なので、Clojure本体もダウンロードしてますね。無事起動にも成功しています。

また、「lein repl」でREPLも起動できるそうで。

$ lein repl
Retrieving org/clojure/tools.nrepl/0.2.0-beta7/tools.nrepl-0.2.0-beta7.pom (3k)
    from http://repo1.maven.org/maven2/
Retrieving org/clojure/pom.contrib/0.0.25/pom.contrib-0.0.25.pom (5k)
    from http://repo1.maven.org/maven2/
Could not find artifact clojure-complete:clojure-complete:pom:0.2.1 in central (http://repo1.maven.org/maven2)
Retrieving clojure-complete/clojure-complete/0.2.1/clojure-complete-0.2.1.pom (1k)
    from https://clojars.org/repo/
Could not find artifact org.thnetos:cd-client:pom:0.3.4 in central (http://repo1.maven.org/maven2)

 〜省略〜

    from https://clojars.org/repo/
Retrieving cheshire/cheshire/3.1.0/cheshire-3.1.0.jar (8k)
    from https://clojars.org/repo/
nREPL server started on port 54723
REPL-y 0.1.0-beta8
Clojure 1.4.0
    Exit: Control+D or (exit) or (quit)
Commands: (user/help)
    Docs: (doc function-name-here)
          (find-doc "part-of-name-here")
  Source: (source function-name-here)
          (user/sourcery function-name-here)
 Javadoc: (javadoc java-object-or-class-here)
Examples from clojuredocs.org: [clojuredocs or cdoc]
          (user/clojuredocs name-here)
          (user/clojuredocs "ns-here" "name-here")

初回は、ダウンロードがえらい実行されます…。

抜ける時は、(exit)やCtr-D、(quit)で。

user=> (exit)
Bye for now!

では、ちょっとhello_lein/core.cljを修正してみます。
src/hello_lein/core.clj

(ns hello-lein.core)

(defn print-hello
  []
  (println "Hello, Leiningen!!"))

(defn -main
  "I don't do a whole lot."
  [& args]
  (print-hello))

実行。

$ lein run -m hello-lein.core
Hello, Leiningen!!

これは、REPLでも認識することができます。

$ lein repl
nREPL server started on port 49591
REPL-y 0.1.0-beta8
Clojure 1.4.0
    Exit: Control+D or (exit) or (quit)
Commands: (user/help)
    Docs: (doc function-name-here)
          (find-doc "part-of-name-here")
  Source: (source function-name-here)
          (user/sourcery function-name-here)
 Javadoc: (javadoc java-object-or-class-here)
Examples from clojuredocs.org: [clojuredocs or cdoc]
          (user/clojuredocs name-here)
          (user/clojuredocs "ns-here" "name-here")

user=> (require '[hello-lein.core])
nil
user=> (hello-lein.core/print-hello)
Hello, Leiningen!!
nil

なお、project.cljを以下のように:mainキーワードをつけるように変更すると…

(defproject hello-lein "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.4.0"]]
  :main hello-lein.core)

「lein run」で名前空間の指定が不要になります。

$ lein run
All namespaces already :aot compiled.
Hello, Leiningen!!

とっかかりとしては、まずこんな感じで?