Leiningen

Leiningen - fxjwind - 博客园
http://www.cnblogs.com/fxjwind/archive/2013/03/07/2948005.html

https://github.com/technomancy/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 (new
, help
, search
, version
, andrepl
) may run from anywhere.

3 Create Project
使用lein new来创建新的clojure项目, 会在当前目录创建项目目录my-stuff.
$ lein new my-stuffGenerating 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)niluser=> (my-stuff.core/foo “me”)me Hello, World!nil

如果在denpendency中加了[clj-http "0.5.5"]
user=> (require '[clj-http.client :as http])niluser=> (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.coreHello, 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 testlein test my.test.stuffFAIL 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))3. Generate your uberjar. 会生成两个jar, standalone版本是包含所有依赖包的

$ lein uberjarCompiling my.stuffCompilation succeeded.Created /home/phil/src/leiningen/my-stuff/target/my-stuff-0.1.0-SNAPSHOT.jarIncluding my-stuff-0.1.0-SNAPSHOT.jarIncluding clj-http-0.4.1.jarIncluding clojure-1.3.0.jarIncluding lucene-core-3.0.2.jarCreated /home/phil/src/leiningen/my-stuff/target/my-stuff-0.1.0-SNAPSHOT-standalone.jar

  1. 象普通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 pallet, chef, 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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容