2024 Clojure 状态调查!分享您的看法

欢迎使用!请查看关于页面以了解此工作方式的更多信息。

0
工具构建

在包含多个模块的单一代码库的上下文中,我发现了一个与clojure.tools.build.api/compile-clj相关的问题,这个问题使得在基本项目根不是当前目录时难以编译文件。

以下是一个演示问题的最小场景。

我有一个使用tools.build来准备/包装其模块的顶级单一代码库deps.edn

 {: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-dirsclass-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,以便正确解析项目中的相对路径以及任何传递性本地依赖项的相对路径。项目根目录的目的是为了这个目的。我认为最好不是将基础放在变量中,而是将其绑定在调用构建任务(如create-basis和compile-clj)之外。

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

我想说的是,这使在monorepo的上下文中处理多项基础变得有些不方便,因为您可以在不同的目录中操作不同的模块,这些目录包含了您想要统一处理的`deps.edn`文件。

一个可以简化事情的建议是,放宽绑定 `*project-root*` 的要求,使其成为对应于构建基础时使用的 `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` 中的一致相对路径解析为绝对路径会完成这项工作,因为它允许额外的相对路径参数仍然根据 `build.clj` 基目录进行解析。

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