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

欢迎!请参阅关于页面获取更多有关此功能的信息。

0
tools.build

在包含多个模块的 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* 并根据模块 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,以便正确解析项目中的相对路径以及任何递归本地依赖项的相对路径。*project-root*就是为了这个目的。我认为最好不要在变量中放置基础,而是在外部绑定,在调用构建任务(如create-basis和compile-clj)之前。

by
是的,我明白*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`的相对路径根据`deps.edn`基本目录设置成绝对路径将完成这项工作,因为它允许额外的相对路径参数根据`build.clj`基本目录进行解析。

这合理吗?
by
是的,我会考虑这个问题的。
...