在一个包含多个模块的 monorepo 环境中,我遇到了一个关于 clojure.tools.build.api/compile-clj 的问题,使得在基础项目根不在当前目录时难以编译文件。
下面是一个演示问题的最小场景。
我有一个顶级 monorepo deps.edn
,使用 tools.build 准备/包装其模块
{:deps {monorepo/module-a {:local/root "modules/a"}}
:aliases {:build {:deps {io.github.clojure/tools.build {:git/tag "v0.8.2"
:git/sha "ba1a2bf"}}
:ns-default build}}}
模块 A 包含一些 Clojure 源文件。这里是 modules/a/deps.edn
{:paths ["src"]}
这些文件需要编译步骤。这里是处理这些文件的最高级 build.clj
文件。
(ns build
(:require [clojure.tools.build.api :as b]))
(def module-a (binding [b/*project-root* "modules/a"]
(b/create-basis {:project "deps.edn"})))
(defn compile-a [_]
(b/compile-clj
{:basis module-a
:src-dirs ["modules/a/src"]
:class-dir "target/module-a/classes"}))
然而,当我从顶级目录调用 clojure -T:build compile-a
时,遇到了以下错误
Execution error (FileNotFoundException) at user/eval136$fn (compile.clj:5).
Could not locate monorepo/module/a__init.class, monorepo/module/a.clj or monorepo/module/a.cljc on classpath.
问题是 "src" 相对目录没有在 :classpath-roots
中展开,导致 compile-clj 在错误的位置搜索源文件。可以通过再次绑定 *project-root* 并将 :src-dirs
和 class-dir
相对于模块 A 的根目录进行调整来解决这个问题。
(defn compile-a [_]
(binding [b/*project-root* "modules/a"]
(b/compile-clj
{:basis module-a
:src-dirs ["src"]
:class-dir "../../target/module-a/classes"})))
然而,在我看来,最好是让 basis 中的计算出的类路径完全展开,将相对路径转换为绝对路径,以避免这种额外的仪式。
您怎么看?
为什么目前保留相对源路径目录为相对路径?