LoginSignup
11
10

More than 5 years have passed since last update.

ClojureのAhead-of-timeコンパイルについて

Last updated at Posted at 2013-07-15

-main中からgen-classで定義したクラスを呼びだす以下のコードをlein runで実行しようとするとエラーが発生する.

src/class-ns-test/core.clj
(ns class-ns-test.core)
(gen-class :name "Hello")
;; クラスを作るにはgen-class関数を使うほか, nsの中に:gen-class symbolをkeyとするmappingの形で定義することもできる.

(defn -main [& args]
  (println (Class/forName "Hello")))
$ lein run
Exception in thread main java.lang.ClassNotFoundException: Hello

project.cljに:aotオプションを加えるとうまくいく.

project.clj
(defproject class-ns-test "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.5.1"]]
  :aot [class-ns-test.core]  ;; <==== 追加
  :main class-ns-test.core)
$ lein run
Hello

:aot とは何か.

Ahead-of-time Compilation

aot = ahead-of-time compilationについての公式ドキュメント によると

  • Clojureはon-the-fly(実行中?)にコードをJVMバイトコードにコンパイルする.
  • しかし, 以下の様なケースでは事前に(ahead-of-time)コンパイルしておきたい.
    • ソースコードなしでアプリケーションを配布したい
    • アプリケーションの起動を速くしたい
    • Javaの名前ありクラスを使いたい
    • アプリケーションに実行時バイトコード変換が必要ない

aotは以下の様な方針/仕様となっている.

  • Clojureの動的性質を出来るだけ失わないように設計されている
  • ソースコードと生成される.classパスはJavaのclasspath規約に従う
  • コンパイルはnamespace単位で指定
  • fnおよびgen-classが, それぞれ1個ずつの.classファイルを生成する

また, compile関数を使うことでコード中の任意の位置でコンパイルすることも出来る. つまりproject.cljに:aotを追加する代わりに, 以下のようにも書ける.

src/class-ns-test/core.clj
(defn -main [& args]
  (compile 'class-ns-test.core)  ;; <==== 追加
  (println (Class/forName "Hello")))
11
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
10