2024 State of Clojure 调查!中分享你的想法。

欢迎!请在关于页面了解更多关于这个功能的信息。

0
tools.build

在一个包含多个模块的单项目管理器中,我注意到代码片段 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"})))

然而,我认为如果基础中计算出的类路径完全展开,转换相对路径为绝对路径以避免这种额外的仪式会更好。

你有什么看法?
为什么目前保留相对源路径目录为相对的有什么原因吗?

1 个答案

0

您应该将 *project-root 绑定,以确保遍历路径正确解析,无论是项目中的相对路径还是任何过渡的本地依赖。由于此目的,存在 project-root。我认为最好不在变量中放置基础,而是在调用构建任务(如 create-basis 和 compile-clj)之外进行绑定。

是的,我理解当前 *tools.build* 在调用任何依赖路径解析的构建任务时,需要绑定 `*project-root*`。

我想说的是,这使在单仓库环境中进行些事情变得有点不便,在该环境中你可以操作多个模块的基础,这些基础引用位于不同目录的 `deps.edn` 文件,而您希望对这些文件进行统一处理。

一个可以简化这些操作的提议是,放宽绑定 `*project-root*` 的要求,并使其成为对应于构建基础时使用的 `deps.edn` 文件基础目录的 `deps.edn` 文件基础的静态属性。

    (binding [b/*project-root* "modules/a"]
                    %b%{create-basis {:project "deps.edn"}})

可以简单地替换为

    (b/create-basis {:project "modules/a/deps.edn"})

然后调用 `compile-clj` 不再需要设置项目根,因为作为参数传递的基础已经知道了。要实现这种设计,根据 `deps.edn` 基目录使 `deps.edn`的相对路径绝对化将完成这项工作,因为它允许根据 `build.clj` 基目录解析额外的相对路径参数。

这有意义吗?
有道理。我会考虑的。
...