Leiningen中文教程

Leiningen用于自动化Clojure项目

它提供各种与项目相关的任务:包括

1. 创建新项目

2. 为项目抓取依赖包

3. 运行测试

4. 运行一个完全可配置的REPL

5. 编译Java源文件

6. 运行项目

7. 为项目生成maven风格的“pom”文件以进行互操作

8. 编译和打包项目

9. 将库发布到Clojars等存储库

10. 运行用Clojure编写的自定义自动化任务(leiningen插件)

获取帮助

lein help

Leiningen项目文件

项目是一个包含一组Clojure(可能还有Java)源文件的目录,以及一些关于它们的元数据。 元数据存储在项目根目录中名为project.clj的文件中,它会告诉你:

1. 项目名字

2. 项目简介

3. 项目依赖关系

4. Clojure的版本

5. 去哪里找到源文件

6. 哪个是app的主命名空间

等等

创建一个项目

Leiningen中文教程_第1张图片

在此示例中,我们使用的是app模板,该模板适用于应用app而非库。 省略app参数将使用适用于库的默认模板。

目录布局

在这里,我们有了项目的README,一个包含代码的src/目录,一个test/目录,以及一个描述Leiningen项目的project.clj文件。 src /my_stuff/core.clj文件对应于my-stuff.core命名空间。

文件名到命名空间映射约定

请注意,我们使用my-stuff.core而不仅仅是my-stuff,因为在Clojure中不鼓励使用单段命名空间。 另请注意,名称中带有破折号的命名空间将具有以下划线命名的相应文件,因为JVM无法在名称中加载带有破折号的文件。 命名空间的复杂性是新手混淆的常见原因,虽然它们大多数超出了本教程的范围,但您可以在其他地方阅读它们。

project.clj

Leiningen中文教程_第2张图片

如果你没有用简短的句子填写 :description,你的项目将很难在搜索结果中找到。 :url也需要天上相应的值。 在某些时候,您还需要充实README.md文件,但是现在让我们跳过设置 :dependencies。 请注意,Clojure在这里只是另一种依赖。 与大多数语言不同,这里可以轻松切换到任何版本的Clojure。

Dependencies依赖

概述

Clojure是一种托管语言,Clojure库的分发方式与其他JVM语言相同,同样是以jar文件的方式。

Jar文件基本上只是.zip文件,带有一些额外的JVM特定元数据。 它们通常包含.class文件(JVM字节码)和.clj源文件,但它们也可以包含其他内容,如配置文件,JavaScript文件或带有静态数据的文本文件。

已发布的JVM库具有identifiers(artifact group,artifact id)和version等属性。

Artifact IDs, Groups, and Versions

你可以使用其网络界面或通过lein search $TERM 搜索Clojars。 在撰写本文时,在clj-http的Clojars页面上显示了以下内容:

[clj-http "2.0.0"]

它还显示了依赖项的Maven和Gradle语法。 您可以将Leiningen版本直接复制到project.clj中的 :dependencies 向量中。 因此,例如,如果您将示例project.clj中的:dependencies行更改为

Leiningen会自动下载clj-http jar并确保它在你的类路径上。 如果你想明确地告诉lein下载新的依赖项,你可以使用lein deps,但如果不这样做,它将按需发生。

在向量内,“clj-http”被称为“artifact id”。 “2.0.0”是版本。 有些库也会有“group id”,显示如下:

[com.cedarsoft.utils.legacy/hibernate "1.3.7"]

group id 是斜杠之前的部分。 特别是对于Java库,它通常是反向域名。 Clojure库通常使用相同的group-id和artifact-id(与clj-http一样),在这种情况下,您可以省略group-id。 如果有一个库是更大的组的一部分(例如ring-jetty-adapter是ring项目的一部分),则group-id在所有子项目中通常是相同的。

Snapshot Versions快照版本

有时版本将以“-SNAPSHOT”结尾。 这意味着它不是正式版本,而是开发版本。 我们不鼓励依赖snapshot依赖包,但如果您需要尚未进入版本化的错误修复等,有时是必要的。 但是,快照版本不会一直使用下去,因此非开发版本永远不会依赖于您无法控制的快照版本。 将快照依赖项添加到项目将导致Leiningen每天主动寻找最新版本的依赖项(而正常发布版本则缓存在本地存储库中),因此如果您有大量快照,它将减慢速度。

请注意,某些库使其group-id和artifact-id与它们在jar中提供的命名空间相对应,但这只是一种约定。 无法保证它们完全匹配,因此在编写 :require和 :import子句之前,请查阅库的文档。

Repositories 库

依赖关系存储在artifact存储库中。 如果您熟悉Perl的CPAN,Python的Cheeseshop(又名PyPi),Ruby的rubygems.org或Node.js的NPM,那就是一样的了。 Leiningen重用现有的JVM存储库基础结构。 有几个流行的开源存储库。 默认情况下,Leiningen将使用其中两个:clojars.org和Maven Central。

Clojars是Clojure社区的集中式maven存储库,而Central则适用于更广泛的JVM社区。

您可以通过在project.clj中设置 :repositories键来添加第三方存储库。 有关如何执行此操作的示例,请参阅sample.project.clj。 此示例使用其他存储库,例如Sonatype存储库,可以访问库的最新SNAPSHOT开发版本(Clojure或Java)。 它还包含有关存储库的其他相关设置,例如更新频率。

Checkout Dependencies 检出依赖项

有时需要并行开发两个项目,但运行lein install并重新启动repl以获取更改非常不方便。 Leiningen提供了一种名为checkout dependencies(或只是checkout)的解决方案。 要使用它,请在项目根目录中创建一个名为checkouts的目录,如下所示:

Leiningen中文教程_第3张图片

然后,在checkouts目录下,创建符号链接到您需要的项目的根目录。 符号链接的名称无关紧要 , Leiningen只关注所有这些文件以查找要使用的project.clj文件。 传统上,它们与它们指向的目录具有相同的名称。

Leiningen中文教程_第4张图片

位于checkouts目录下的库优先于从存储库中提取,但这不能代替在主项目:dependencies依赖项; 它只是为了方便而补充它。 也就是说,给定上面的目录层次结构,project.clj应该包含如下内容:

Leiningen中文教程_第5张图片

请注意,Maven的groupid “com.megacorp”对checkout这种方式没有影响。在checkout中,suchwow和commons链接看起来是一样的,并且groupid层次结构不需要以“commons”实际布局在磁盘上的方式出现。。

在您更新了依赖项之后,lein仍然需要能够在某些存储库(如clojars或〜/ .m2目录)中找到该库。如果lein抱怨像“Could not find artifact suchwow:jar:0.3.9”这样的消息,那么project.clj和suchwow / project.clj可能会使用不同的版本号。您也可能同时处理主项目和suchwow项目,两个项目文件中的版本号已经失效,但仍你然在本地Maven存储库中使用旧版本。在suchwow目录中运行lein install。也就是说:这样的版本号在三个地方必须相同:在howwow的project.clj中,在主项目的project.clj中,以及在主项目使用的某个存储库中。

如果您更改checkout项目的依赖项,您仍然必须运行lein install并重新启动repl;只是源变化会立即被提取。

chekcout是一项可选功能;并非每个正在处理该项目的人都会拥有相同的checkout,因此在推送或合并之前,您的项目应该无需checkout。

确保在使用chekcout时不要覆盖基本配置文件。在实践中,通常意味着使用lein with-profile + foo run而不是lein with-profile foo run。

Search 搜索

Leiningen支持使用命令lein search $TERM 搜索远程Maven存储库以匹配jar。 目前仅支持搜索Central和Clojars。

JVM参数设置

要将额外的参数传递给JVM,请设置 :jvm-opts向量。 这将覆盖Leiningen设置的任何默认JVM选项。

:jvm-opts ["-Xmx1g"]

如果要将编译器参数传递给Clojure编译器,也可以在此处执行此操作。

你还可以在JVM_OPTS环境变量中将选项传递给Leiningen。 如果要为Leiningen JVM提供自定义选项,请将它们设置为LEIN_JVM_OPTS。

运行代码

运行一个REPL(read-eval-print loop):

Leiningen中文教程_第6张图片

REPL是一个交互式提示框,您可以在其中输入任意代码以在项目的上下文中运行。 由于我们已经将clj-http添加到 :dependencies,因此我们可以将它与来自项目自己的src/目录中的my-stuff.core命名空间的代码一起加载:

Leiningen中文教程_第7张图片

对-main的调用同时显示println输出(“Hello,World!”)和返回值(nil)。

内置文档可通过doc获得,您可以使用source检查函数的来源:

Leiningen中文教程_第8张图片

如果已经准备好了-main函数中的代码并且不需要以交互方式输入代码,则运行任务更简单:

提供-m参数将告诉Leiningen在另一个名称空间中查找-main函数。 在project.clj中设置默认值:main可以省略-m。

对于长期运行的lein run进程,您可能希望使用更高阶的trampoline任务来节省内存,这允许Leiningen JVM进程在启动项目的JVM之前退出。

lein trampoline run -m my-stuff.server 5000

如果你要在:java-source-paths或者 :aot中列出的Clojure名称空间中编译任何Java文件,它们将始终通过run,repl等调用在Leiningen运行任何其他代码之前完成此编译。

Tests 测试

Leiningen中文教程_第9张图片

如果我们在test suite 中补充它们将变得更有用。有时,如果你有一个大的test suite,你一次只想运行一个或两个命名空间; lein test my-stuff.core-test可以做到这一点。您也可能想要使用测试选择器来分解测试;请参阅lein help test以获取更多详细信息。

从命令行运行lein test适用于回归测试,对于需要更严格反馈循环的测试模式,JVM过慢的启动时间让它不适合这件事。在这些情况下,要么保持一个打开的repl以运行对 clojure.test/run-tests 的适当调用,要么在编辑器的基础中查看,例如clojure-test-mode。

请记住,虽然保持正在运行的进程很方便,但是该进程很容易进入一个不反映磁盘上的文件的状态 - 加载然后从文件中删除的函数将保留在内存中,使其成为可能很容易错过因缺少功能而导致的问题(通常被称为“getting slimed”)。因此,建议在提交代码之前运行lein test。

Profiles

profiles用于在不同的上下文中将各种内容添加到项目映射中。 例如,在lein测试运行期间,:test profile的内容(如果存在)将合并到项目映射中。 您可以使用此选项来启用仅应在测试运行期间应用的配置,方法是将包含配置文件的目录通过 :resource-paths或其他方式添加到类路径中。 有关详细信息,请参阅lein help profiles

除非另有说明,否则Leiningen会将默认的配置文件集合并到项目地图中。 这包括来自 :user 配置文件,来自project.clj的 :dev配置文件(如果存在),以及内置 :base 配置文件,其中包含nREPL和优化等开发工具,这些工具以运行时性能为代价来加快启动时间。 永远不要使用默认配置文件

用Clojure做什么

一般情况下

1. 分发给终端用户的应用程序

2. 服务器端应用程序

3. 用于其他Clojure项目使用的库

首先,你通常会构建一个uberjar。 对于库,您需要将它们发布到Clojars或私有存储库等存储库。 对于服务器端应用程序, 使用lein new app myapp生成项目将启动一些适用于非库项目的额外默认值,或者您可以浏览Clojars上的可用模板,以获取特定Web技术或其他项目类型等内容。

Uberjar

最简单的方法是分发一个uberjar。 这是一个单独的可执行jar文件,最适合提供给非技术用户。 为此,您需要在project.clj中指定 :main 作为一个主命名空间,并确保它被添加到 :aot中已进行AOT(Ahead Of Time)编译。到目前为止,我们的project.clj文件应如下所示:

Leiningen中文教程_第10张图片

我们还添加了一个dev dependencies,ring-devel。 ring-devel在uberjars中不可用,如果将此项目发布到存储库,则不会将其视为依赖项。

您指定的命名空间需要包含一个-main函数,该函数将在运行standalone jar时调用。 此命名空间应在顶部的ns表单中具有(:gen-class)声明。 -main函数将传递命令行参数。 让我们在src/my_stuff/core.clj中尝试一些简单的方法:

Leiningen中文教程_第11张图片

准备生产uberjar

这将创建一个包含所有依赖项内容的jar包。 用户可以通过简单的java调用来运行它,或者只是通过双击jar文件在某些系统上运行它。

您可以使用java命令行工具运行常规(非超级)jar,但这需要自己构建类路径,因此对于最终用户来说这不是一个好的解决方案。

当然,如果您的用户已经安装了Leiningen,您可以指示他们使用如上所述的lein run。

翻译自:https://github.com/technomancy/leiningen/blob/stable/doc/TUTORIAL.md

翻译者:Eyck Luo

你可能感兴趣的:(Leiningen中文教程)