在一个包含多个模块的单项目管理器中,我注意到代码片段 clojure.tools.build.api/compile-clj 存在问题,使得在基础上不是当前目录的根目录时编译文件变得困难。
以下是一个展示该问题的最小场景。
我有一个顶层单项目管理器 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* 和根据模块 A 的根目录调整 :src-dirs 和 class-dir 来解决这个问题。
(defn compile-a [_]
(binding [b/*project-root* "modules/a"]
(b/compile-clj
{:basis module-a
:src-dirs ["src"]
:class-dir "../../target/module-a/classes"})))
然而,我认为如果基础中计算出的类路径完全展开,转换相对路径为绝对路径以避免这种额外的仪式会更好。
你有什么看法?
为什么目前保留相对源路径目录为相对的有什么原因吗?