Leiningen

简介:

1 What's Leiningen

Leiningen is a tool for automating Clojure projects without setting your hair on fire.

If you come from the Java world, Leiningen is "Maven meets Ant without the pain". For Ruby and Python folks, Leiningen combines RubyGems/Bundler/Rake and pip/Fabric in a single tool.

Clojure项目自动化创建, 编译, 打包和部署的工具集. 
具体可以提供如下功能,

It manages various project-related tasks, and can:

  • create new projects
  • manage dependencies for your project
  • run tests
  • run a REPL (without you having to worry about adding dependencies to the classpath)
  • compile Java sources (if any)
  • run the project (if the project is an app)
  • generate a maven-style "pom" file for the project
  • compile and package projects for deployment
  • publish libraries to maven artifact repositories such as Clojars
  • run custom automation tasks written in Clojure (leiningen plug-ins)

 

2 Basic Usage

help, 帮助手册

Use lein help to see a complete list. lein help $TASK shows the usage for a specific task.

new, 创建新项目

$ lein new [TEMPLATE] NAME # generate a new project skeleton

run, 执行, 以-main函数会入口函数

$ lein run -m my.namespace # run the -main function of a namespace 

test, 执行test namespace目录里面的所有testcase

$ lein test [TESTS] # run the tests in the TESTS namespaces, or all tests

repl, launch repl

$ lein repl # launch an interactive REPL session

uberjar, 将project打包成jar

$ lein uberjar # package the project and dependencies as standalone jar

串联执行

You can also chain tasks together in a single command by using the do task with comma-separated tasks:

$ lein do clean, test foo.test-core, jar

 

在project directory内执行命令

Most tasks need to be run from somewhere inside a project directory to work, but some (newhelpsearchversion, andrepl) may run from anywhere.

 

 

3 Create Project

使用lein new来创建新的clojure项目, 会在当前目录创建项目目录my-stuff.

$ lein new my-stuff

Generating a project called my-stuff based on the 'default' template.
$ cd my-stuff
$ find .
.
./.gitignore
./doc
./doc/intro.md
./project.clj
./README.md
./src
./src/my_stuff
./src/my_stuff/core.clj
./test
./test/my_stuff
./test/my_stuff/core_test.clj

Namespace Mapping Convention

创建project时, 会自动创建namespace my-stuff.core 
my-stuff.core instead of just my-stuff since single-segment namespaces are discouraged in Clojure. 
Namespace在FP里面比较重要, 比在OO里面重要, 因为对于OO还有class, 其实就是做了一层的namespace封装, 有效的避免冲突 
但是对于FP, 直接就是function, 如果不加合理的namespace, 那就太容易冲突了 
所以这儿使用my-stuff.core, 在project内部需要namespace的分层, 除了core, 肯定应该有其他的子namespace……

 

4 Project.clj, Configuration

首先可以看出data=code, 配置文件一样可以用clojure文件来写, 只要实现macro, 配置文件直接就可以run, 很牛!


Default自动生成的project.clj的模板如下:

(defproject my-stuff "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.4.0"]])

一个简单的例子,

(defproject myproject "0.5.0-SNAPSHOT"
  :description "A project for doing things."
  :license "Eclipse Public License 1.0"
  :url "http://github.com/technomancy/myproject"
  :dependencies [[org.clojure/clojure "1.4.0"]]
  :plugins [[lein-ring "0.4.5"]])

实际使用的会比这个复杂很多, 参考下面的sample.project.clj

See the sample.project.clj file (also available via lein help sample) for a detailed listing of configuration options.

通过profiles可以根据不同的情况设定不同的configuration

The project.clj file can be customized further with the use of profiles.

 

Dependencies

Overview

Clojure is a hosted language and Clojure libraries are distributed the same way as in other JVM languages: as JARs.

JARs (.jar files) are basically just .zip files with a little extra JVM-specific metadata. They usually contain .class files (JVM bytecode) and .clj source files, but they can also contain other things like config files, JavaScript files or text files with static data.

必须要指明, project和其他包的依赖关系, 这样leiningen才能自动的下载配置相关包, 以保证project可以被正常的编译和运行.

 

Artifact IDs, Groups, and Versions

Artifact IDs, 包的名字, 如clojure, hibernate 
Groups, 一般是reversed域名, 如com.cedarsoft.utils.legacy 
Versions, 版本号, 1.3.4 
[com.cedarsoft.utils.legacy/hibernate "1.3.4"]

Clojure libraries often use the same group-id and artifact-id (as with clj-http), in which case you can omit the group-id.

[clj-http "0.5.5"]

 

Snapshot Versions

Sometimes versions will end in "-SNAPSHOT". This means that it is not an official release but a development build.

所以自动生成的project.clj的版本是带"-SNAPSHOT": my-stuff "0.1.0-SNAPSHOT"

当然尽量不要在dependency里面加snapshot的版本, 除了你知道你在干吗, 并确实需要这样... 
另外的原因是对于snapshot version, leiningen每天都会去更新最新版, 所以有效率问题...

Adding a snapshot dependency to your project will cause Leiningen to actively go seek out the latest version of the dependency daily (whereas normal release versions are cached in the local repository) so if you have a lot of snapshots it will slow things down.

Artifact IDs, Groups和Namespace的关系

Note that some libraries make their group-id and artifact-id correspond with the namespace they provide inside the jar, but this is just a convention. There is no guarantee they will match up at all.

Repositories

Dependencies are stored in a maven repository (类似PyPi)

There are several popular open source repositories. Leiningen by default will use two of them: clojars.org and Maven Central.

leiningen需要根据配置的dependency, 来自动的找到这些包, 去哪儿找, 默认是clojars.org and Maven Central

可以自行增加third-party repositories 
You can add third-party repositories by setting the :repositories key in project.clj. See the sample.project.clj.

 

5 Running Code

Lein REPL

The REPL is an interactive prompt where you can enter arbitrary code to run in the context of your project.

lein repl和一般的repl相比, 最大的优势是, project context awareness 
对于一般的repl, 能够被require的包都必须要在classpath底下能够找到, 如果没有, 你需要自己去download并配置到classpath里面去 
而lein会自动的管理dependency, 只需要在project.clj里面把需要的denpendency写清楚, lein会自动完成download和classpath配置 
所以只需要在project目录下执行lein repl, 即可以require当前project namespace的所有代码, 以及所有denpendency的库 
这个相当方便, 尤其在测试的时候

需要注意的是, lein repl其实是可以在任何目录下执行的, 但是如果不是project目录, 那就和普通repl没有任何区别.

 

Lein REPL还有命令提示, 主要有如下命令

函数执行
user=> (require 'my-stuff.core)
nil
user=> (my-stuff.core/foo “me”)
me Hello, World!
nil

如果在denpendency中加了[clj-http "0.5.5"]

user=> (require '[clj-http.client :as http])
nil
user=> (def response (http/get "http://leiningen.org"))
#'user/response
帮助文档, doc, javadoc, clojuredocs

doc, find-doc显示帮助文档 
javadoc, 显示java的帮助文档

clojuredocs offers more thorough examples from the ClojureDocs site.

ClojureDocs is a community-powered documentation and examples repository for the Clojure programming language.

clojuredocs这个挺管用, 比如你不知道reduce怎么用

user=> (user/clojuredocs reduce)

就会给出很多例子, 也可以直接去网站查, 更好看些, http://clojuredocs.org/clojure_core/clojure.core/reduce

查看源代码, source
user=> (source my-stuff.core/foo)
(defn foo
  "I don't do a whole lot."
  [x]
  (println x "Hello, World!"))
nil

Lein Run

如果要使用lein run去运行namespace, 必须先实现-main函数, 因为lein run -m会在namespace里面找-main, 如果没有, 会报错

(defn -main
  "I don't do a whole lot."
  [& args]
  (println "Hello, World!"))
 
$ lein run -m my-stuff.core
Hello, World!

Providing an alternate -m argument will tell Leiningen to look for the -main function in another namespace. 
Setting a default :main in project.clj lets you omit -m
比如加上如下配置,

:main my-stuff.core
可以直接运行, 不用-m 

$ lein run 
Hello, World!

 

6 Tests

We haven't written any tests yet, but we can run the failing tests included from the project template:

$ lein test

lein test my.test.stuff

FAIL in (a-test) (stuff.clj:7)
FIXME, I fail.
expected: (= 0 1)
  actual: (not (= 0 1))

Ran 1 tests containing 1 assertions.
1 failures, 0 errors.

Once we fill it in the test suite will become more useful. Sometimes if you've got a large test suite you'll want to run just one or two namespaces at a time; lein test my.test.stuff will do that. You also might want to break up your tests using test selectors; see lein help test for more details.

 

7 Make Jar

Generally speaking, there are three different goals that are typical of Leiningen projects:

  • An application you can distribute to end-users
  • A library for other Clojure projects to consume
  • A server-side application

Uberjar

The simplest thing to do is to distribute an uberjar. This is a single standalone executable jar file most suitable for giving to nontechnical users. 
最简单的方式, 直接打包成可执行的jar

1. 在project.clj加上:main, 配置-main存在的namespace

2. 在namespace声明中, 加上:gen-class. 不加会报错(Error: Could not find or load main class my_stuff.core)

(ns my-stuff.core
  (:gen-class))
$ lein uberjar
Compiling my.stuff
Compilation succeeded.
Created /home/phil/src/leiningen/my-stuff/target/my-stuff-0.1.0-SNAPSHOT.jar
Including my-stuff-0.1.0-SNAPSHOT.jar
Including clj-http-0.4.1.jar
Including clojure-1.3.0.jar
Including lucene-core-3.0.2.jar
Created /home/phil/src/leiningen/my-stuff/target/my-stuff-0.1.0-SNAPSHOT-standalone.jar

4. 象普通jar一样的执行

$ java -jar my-stuff-0.1.0-standalone.jar Hello world.
Welcome to my project! These are your args: (Hello world.)
 

Framework (Uber)jars

看下面的例子, 对于hadoop这样framework的包, 无法也无需打包到jar里面 
因为必须实际的运行环境里面有hadoop集群否则, 根本运行不了 
所以使用:provided, 表示需要, 但是不包含在jar里面, 需要使用者保证运行环境符合.

(project example.hadoop "0.1.0"
  ...
  :profiles {:provided
             {:dependencies
              [[org.apache.hadoop/hadoop-core "0.20.2-dev"]]}}
  :main example.hadoop)
 

Server-side Projects

There are many ways to get your project deployed as a server-side application. Aside from the obvious uberjar approach, simple programs can be packaged up as tarballs with accompanied shell scripts using the lein-tar plugin and then deployed using palletchef, or other mechanisms.

 

Publishing Libraries

If your project is a library and you would like others to be able to use it as a dependency in their projects, you will need to get it into a public repository.

可以将生成的jar发布到public库里面

$ lein deploy clojars

 

8 Getting Started with Eclipse and Counterclockwise

Eclipse的leiningen插件, 使用更方便

http://dev.clojure.org/display/doc/Getting+Started+with+Eclipse+and+Counterclockwise

ctrl+alt+s, 执行当前cljr文件, 并启动repl



本文章摘自博客园,原文发布日期:2013-03-07

目录
相关文章
|
算法 Java 决策智能
运筹优化工具库介绍(一)
运筹优化问题有时候极其复杂,我们可以使用运筹优化工具库帮助数学建模,解决复杂的最优化问题,本文介绍几个常见的运筹优化工具库。
1029 0
|
Ubuntu Shell 开发工具
Ubuntu 20.04 安装nvm
Ubuntu 20.04 安装nvm
5950 0
|
4月前
|
JavaScript 前端开发 NoSQL
技术好文:Redash(开源轻量级智能)生产环境部署及实践(withoutdocker)
Redash(开源轻量级智能)生产环境部署及实践(withoutdocker)
290 0
|
XML 存储 Java
Neo4j的springboot的简单实现
# 引言 今天带来通过springboot来操作neo4j的教程。 # pom.xml的依赖 ``` <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.
Neo4j的springboot的简单实现
|
算法 调度
关于OptaPlanner的使用(一)——简介
关于OptaPlanner的使用(一)——简介
916 0
|
存储 Kubernetes 数据安全/隐私保护
影片自由,丝滑流畅,Docker容器基于WebDav协议通过Alist挂载(百度网盘/阿里云盘)Python3.10接入
使用过NAS(Network Attached Storage)的朋友都知道,它可以通过局域网将本地硬盘转换为局域网内的“网盘”,简单理解就是搭建自己的“私有云”,但是硬件和网络成本都太高了,有点可望而不可及的意思。Alist开源库则可以满足我们,它能将公共网盘反过来变成一种联网的本地硬盘,使用Web页面来统一挂载和管理,网盘类型包含但不限于:百度网盘、阿里云盘、迅雷网盘等等。
影片自由,丝滑流畅,Docker容器基于WebDav协议通过Alist挂载(百度网盘/阿里云盘)Python3.10接入
|
缓存 应用服务中间件 Linux
局域网自建YUM仓库
在公司的局域网内自建一个yum仓库,对于不能连外网的环境非常有用。同时也提高了内网服务器的下载速度。
459 0
|
缓存 监控 网络协议
代理和中继的区别
代理和中继的区别
229 0
|
缓存 NoSQL 关系型数据库
实现高并发,高可用,分布式支付系统
实现高并发,高可用,分布式支付系统
695 1
实现高并发,高可用,分布式支付系统
|
JavaScript 前端开发
WebStorm配置【设置左侧及其代码编辑区最舒服的字体】
WebStorm配置【设置左侧及其代码编辑区最舒服的字体】
695 0
WebStorm配置【设置左侧及其代码编辑区最舒服的字体】