八 月
5
土曜日

Clojurescriptビルド時の最適化レベルとエントリポイント

Clojurescriptのビルドをcljs.build.apiで行った際に java.lang.AssertionError: Assert failed: No file for namespace foo.bar.core exists でビルドが失敗するので原因を調べた。


事象

Clojurescript 1.9.854を使用。
以下のようなcljsコンパイルオプションでビルドを行ったところ

(cljs.build.api/build
  "src/main/cljs"
  {:main 'foo.bar.core
   :output-dir "target/out"
   :output-to "target/out/main.js"
   :optimizations :simple
   :target :nodejs
   :verbose true})

エラーが発生。

Caused by: java.lang.AssertionError: Assert failed: No file for namespace foo.bar.core exists
  at cljs.closure$build.invokeStatic(closure.clj:2513)
  at cljs.closure$build.invoke(closure.clj:2444)
  at cljs.build.api$build.invokeStatic(api.clj:205)
  at cljs.build.api$build.invoke(api.clj:189)
  at cljs.build.api$build.invokeStatic(api.clj:192)
  at cljs.build.api$build.invoke(api.clj:189)
  at dev.build$eval7832.invokeStatic(build.clj:7)
  at dev.build$eval7832.invoke(build.clj:7)
  at clojure.lang.Compiler.eval(Compiler.java:6927)
  at clojure.lang.Compiler.load(Compiler.java:7379)
  ... 42 more

原因

本来エントリポイント :main は最適化レベル :optimizations の値が:noneの場合にのみ必要になる。

https://clojurescript.org/reference/compiler-options#main

Specifies an entry point namespace. When combined with optimization level :none

:none以外の場合に :main 指定すると件の例外が発生する。
例外内容からは最適化レベルとエントリポイントの設定が関係していると気づきにくい。

ちなみに:none:main が指定されない逆のケースでは以下のように分かり易い例外が飛ぶ。

java.lang.AssertionError: Assert failed: :nodejs target with :none optimizations requires a :main entry