Clojure用のLeiningenの紹介
1. 序章
Leiningenは、Clojureプロジェクト用の最新のビルドシステムです。また、完全にClojureで作成および構成されています。
これはMavenと同様に機能し、実行する正確なステップを構成する必要なしに、プロジェクトを説明する宣言型の構成を提供します。
さあ、Clojureプロジェクトを構築するためにLeiningenを使い始める方法を見てみましょう。
2. Leiningenのインストール
Leiningenは、スタンドアロンのダウンロードとしてだけでなく、さまざまなシステムの多数のパッケージマネージャーから入手できます。
スタンドアロンのダウンロードは、 Windows だけでなく、LinuxおよびMacでも利用できます。 いずれの場合も、ファイルをダウンロードし、必要に応じて実行可能にすると、使用できるようになります。
スクリプトが最初に実行されると、残りのLeiningenアプリケーションがダウンロードされ、この時点から次のようにキャッシュされます。
$ ./lein
Downloading Leiningen to /Users/user/.lein/self-installs/leiningen-2.8.3-standalone.jar now...
.....
Leiningen is a tool for working with Clojure projects.
Several tasks are available:
.....
Run `lein help $TASK` for details.
.....
3. 新しいプロジェクトの作成
Leiningenをインストールしたら、それを使用して leinnewを呼び出すことで新しいプロジェクトを作成できます。
これにより、一連のオプションから特定のテンプレートを使用してプロジェクトが作成されます。
- app –アプリケーションの作成に使用されます
- default –通常はライブラリ用の一般的なプロジェクト構造を作成するために使用されます
- plugin –Leiningenプラグインの作成に使用されます
- template –将来のプロジェクト用の新しいLeiningenテンプレートを作成するために使用されます
たとえば、「my-project」という新しいアプリケーションを作成するには、次のように実行します。
$ ./lein new app my-project
Generating a project called my-project based on the 'app' template.
これにより、以下を含むプロジェクトが得られます。
- ビルド定義– project.clj
- ソースディレクトリ– src –初期ソースファイルを含む– src / my_project / core.clj
- テストディレクトリ– test –初期テストファイルを含む– test / my_project / core_test.clj
- いくつかの追加のドキュメントファイル– README.md、LICENSE、CHANGELOG.mdおよびdoc / intro.md
ビルド定義の内部を見ると、ビルドするものは示されていますが、ビルド方法は示されていません。
(defproject my-project "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0"
:url "https://www.eclipse.org/legal/epl-2.0/"}
:dependencies [[org.clojure/clojure "1.9.0"]]
:main ^:skip-aot my-project.core
:target-path "target/%s"
:profiles {:uberjar {:aot :all}})
これは私たちに教えてくれます:
- プロジェクト名、バージョン、説明、ホームページ、ライセンスの詳細で構成されるプロジェクトの詳細。
- アプリケーションの実行時に使用するメインの名前空間
- 依存関係のリスト
- 出力を組み込むためのターゲットパス
- uberjarを構築するためのプロファイル
メインのソース名前空間は my-project.core 、およびファイルにあります
さらに、JVMにはファイル名のハイフンに関する問題があるため、ファイル名はハイフンではなくアンダースコアで生成されます。
生成されたコードは非常に単純です。
(ns my-project.core
(:gen-class))
(defn -main
"I don't do a whole lot ... yet."
[& args]
(println "Hello, World!"))
この依存関係を変更すると、代わりに代替バージョンが取得されます。
4. 構築と実行
私たちのプロジェクトは、それを構築し、実行し、配布用にパッケージ化することができなければ、あまり価値がないので、次にそれを見てみましょう。
4.1. REPLの起動
プロジェクトができたら、leinreplを使用してプロジェクト内でREPLを起動できます。 これにより、すべてのプロジェクトファイルとすべての依存関係を含め、プロジェクト内のすべてがクラスパスですでに利用可能なREPLが得られます。
また、プロジェクトに定義されたメイン名前空間で開始します。
$ lein repl
nREPL server started on port 62856 on host 127.0.0.1 - nrepl://127.0.0.1:62856
[]REPL-y 0.4.3, nREPL 0.5.3
Clojure 1.9.0
Java HotSpot(TM) 64-Bit Server VM 1.8.0_77-b03
Docs: (doc function-name-here)
(find-doc "part-of-name-here")
Source: (source function-name-here)
Javadoc: (javadoc java-object-or-class-here)
Exit: Control+D or (exit) or (quit)
Results: Stored in vars *1, *2, *3, an exception in *e
my-project.core=> (-main)
Hello, World!
nil
これにより、上記で見た現在の名前空間で関数-mainが実行されます。
4.2. アプリケーションの実行
アプリケーションプロジェクトに取り組んでいる場合–を使用して作成 lein新しいアプリ – それから
$ lein run
Hello, World!
これにより、 project.clj ファイルで:mainとして定義された名前空間で-mainという関数が実行されます。
4.3. ライブラリの構築
lein new default を使用して作成されたライブラリプロジェクトで作業している場合、ライブラリをJARファイルにビルドして、他のプロジェクトに含めることができます。
これを実現するには、 leinjarまたはleininstallを使用する2つの方法があります。 違いは、出力JARファイルが配置される場所にあります。
lein jarを使用すると、ローカルターゲットディレクトリに配置されます:
$ lein jar
Created /Users/user/source/me/my-library/target/my-library-0.1.0-SNAPSHOT.jar
lein installを使用すると、JARファイルがビルドされ、pom.xmlファイルが生成され、2つがローカルのMavenリポジトリ(通常は .m2 / repository の下)に配置されます。ユーザーのホームディレクトリ)
$ lein install
Created /Users/user/source/me/my-library/target/my-library-0.1.0-SNAPSHOT.jar
Wrote /Users/user/source/me/my-library/pom.xml
Installed jar and pom into local repo.
4.4. Uberjarの構築
アプリケーションプロジェクトに取り組んでいる場合、 Leiningenは、uberjarと呼ばれるものを構築する機能を提供します。 これは、プロジェクト自体とすべての依存関係を含み、そのまま実行できるように設定されたJARファイルです。
$ lein uberjar
Compiling my-project.core
Created /Users/user/source/me/my-project/target/uberjar/my-project-0.1.0-SNAPSHOT.jar
Created /Users/user/source/me/my-project/target/uberjar/my-project-0.1.0-SNAPSHOT-standalone.jar
ファイルmy-project-0.1.0-SNAPSHOT.jarは、ローカルプロジェクトを正確に含むJARファイルであり、ファイル
$ java -jar target/uberjar/my-project-0.1.0-SNAPSHOT-standalone.jar
Hello, World!
5. 依存関係
プロジェクトに必要なすべてのものを自分で作成することはできますが、一般的に、他の人が私たちに代わって行った作業を再利用する方がはるかに優れています。 これを行うには、プロジェクトをこれらの他のライブラリに依存させます。
5.1. プロジェクトに依存関係を追加する
プロジェクトに依存関係を追加するには、それらをproject.cljファイルに正しく追加する必要があります。
依存関係は、問題の依存関係の名前とバージョンで構成されるベクトルとして表されます。 Clojure自体が依存関係として追加され、 [org.clojure / clojure“ 1.9.0”]の形式で記述されていることはすでに見てきました。
他の依存関係を追加する場合は、:dependenciesキーワードの横のベクトルに追加することで追加できます。 たとえば、 clj-json に依存する場合は、ファイルを更新します。
:dependencies [[org.clojure/clojure "1.9.0"] [clj-json "0.5.3"]]
完了したら、REPLを開始するか、プロジェクトをビルドまたは実行する他の方法を使用すると、Leiningenは依存関係がダウンロードされ、クラスパスで利用できるようになります:
$ lein repl
Retrieving clj-json/clj-json/0.5.3/clj-json-0.5.3.pom from clojars
Retrieving clj-json/clj-json/0.5.3/clj-json-0.5.3.jar from clojars
nREPL server started on port 62146 on host 127.0.0.1 - nrepl://127.0.0.1:62146
REPL-y 0.4.3, nREPL 0.5.3
Clojure 1.9.0
Java HotSpot(TM) 64-Bit Server VM 1.8.0_77-b03
Docs: (doc function-name-here)
(find-doc "part-of-name-here")
Source: (source function-name-here)
Javadoc: (javadoc java-object-or-class-here)
Exit: Control+D or (exit) or (quit)
Results: Stored in vars *1, *2, *3, an exception in *e
my-project.core=> (require '(clj-json [core :as json]))
nil
my-project.core=> (json/generate-string {"foo" "bar"})
"{\"foo\":\"bar\"}"
my-project.core=>
プロジェクト内からも使用できます。 たとえば、生成された src / my_project /core.cljファイルを次のように更新できます。
(ns my-project.core
(:gen-class))
(require '(clj-json [core :as json]))
(defn -main
"I don't do a whole lot ... yet."
[& args]
(println (json/generate-string {"foo" "bar"})))
そして、それを実行すると、期待どおりに実行されます。
$ lein run
{"foo":"bar"}
5.2. 依存関係の検索
多くの場合、プロジェクトで使用する依存関係を見つけるのは難しい場合があります。 Leiningenには、これを簡単にするための検索機能が組み込まれています。 これは、ライン検索を使用して行われます。
たとえば、JSONライブラリは次のようになります。
$ lein search json
Searching central ...
[com.jwebmp/json "0.63.0.60"]
[com.ufoscout.coreutils/json "3.7.4"]
[com.github.iarellano/json "20190129"]
.....
Searching clojars ...
[cheshire "5.8.1"]
JSON and JSON SMILE encoding, fast.
[json-html "0.4.4"]
Provide JSON and get a DOM node with a human representation of that JSON
[ring/ring-json "0.5.0-beta1"]
Ring middleware for handling JSON
[clj-json "0.5.3"]
Fast JSON encoding and decoding for Clojure via the Jackson library.
.....
これは、プロジェクトが使用しているすべてのリポジトリを検索します。この場合、MavenCentralとClojarsです。 次に、 project.clj ファイルに入れる正確な文字列と、可能な場合はライブラリの説明を返します。
6. プロジェクトのテスト
Clojureには、アプリケーションの単体テストのサポートが組み込まれており、Leiningenはこれをプロジェクトに利用できます。
生成されたプロジェクトには、 test ディレクトリのテストコードと、srcディレクトリのソースコードが含まれています。 また、デフォルトで失敗する単一のテストも含まれています– test / my_project /core-test.cljにあります。
(ns my-project.core-test
(:require [clojure.test :refer :all]
[my-project.core :refer :all]))
(deftest a-test
(testing "FIXME, I fail."
(is (= 0 1))))
これにより、プロジェクトから my-project.core 名前空間がインポートされ、コアClojure言語からclojure.test名前空間がインポートされます。 次に、deftestおよびtesting呼び出しを使用してテストを定義します。
テストの名前と、意図的に失敗するように記述されているという事実をすぐに確認できます。これは、 0 ==1であることを示しています。
lein testコマンドを使用してこれを実行し、実行中のテストと失敗したテストをすぐに確認しましょう。
$ lein test
lein test my-project.core-test
lein test :only my-project.core-test/a-test
FAIL in (a-test) (core_test.clj:7)
FIXME, I fail.
expected: (= 0 1)
actual: (not (= 0 1))
Ran 1 tests containing 1 assertions.
1 failures, 0 errors.
Tests failed.
代わりにテストを修正し、代わりに 1 == 1 と主張するように変更すると、代わりに合格メッセージが表示されます。
$ lein test
lein test my-project.core-test
Ran 1 tests containing 1 assertions.
0 failures, 0 errors.
これははるかに簡潔な出力であり、私たちが知る必要があることだけを示しています。 これは、障害が発生すると、すぐに目立つことを意味します。
必要に応じて、テストの特定のサブセットを実行することもできます。 コマンドラインでは名前空間を指定でき、その名前空間のテストのみが実行されます。
$ lein test my-project.core-test
lein test my-project.core-test
Ran 1 tests containing 1 assertions.
0 failures, 0 errors.
$ lein test my-project.unknown
lein test my-project.unknown
Ran 0 tests containing 0 assertions.
0 failures, 0 errors.
7. 概要
この記事では、Leiningenビルドツールの使用を開始する方法と、それを使用して実行可能アプリケーションと共有ライブラリの両方であるClojureベースのプロジェクトを管理する方法について説明しました。
次のプロジェクトで試してみて、どれだけうまく機能するか見てみませんか。