/resources/leiningen/help/profiles

http://github.com/technomancy/leiningen · #! · 295 lines · 229 code · 66 blank · 0 comment · 0 complexity · 4be1e7f295eaa23e9cccf74b13c9abfc MD5 · raw file

  1. <!-- START doctoc generated TOC please keep comment here to allow auto update -->
  2. <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
  3. **Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
  4. - [Profiles](#profiles)
  5. - [Declaring Profiles](#declaring-profiles)
  6. - [Default Profiles](#default-profiles)
  7. - [Task Specific Profiles](#task-specific-profiles)
  8. - [Replacing Default Repl Dependencies](#replacing-default-repl-dependencies)
  9. - [Profile Metadata](#profile-metadata)
  10. - [Merging](#merging)
  11. - [Activating Profiles](#activating-profiles)
  12. - [Composite Profiles](#composite-profiles)
  13. - [Dynamic Eval](#dynamic-eval)
  14. - [Debugging](#debugging)
  15. <!-- END doctoc generated TOC please keep comment here to allow auto update -->
  16. # Profiles
  17. You can change the configuration of your project by applying various
  18. profiles. For instance, you may want to have a few extra test data
  19. directories on the classpath during development without including them
  20. in the jar, or you may want to have development tools like
  21. [Slamhound](https://github.com/technomancy/slamhound) available in
  22. every project you hack on without modifying every single `project.clj`
  23. you use.
  24. You can place any arbitrary key/value pairs supported by `defproject`
  25. into a given profile and they will be merged into the project map when
  26. that profile is activated.
  27. The example below adds a "dummy-data" resources directory during
  28. development and a dependency upon "expectations" that's only used for
  29. tests/development.
  30. ```clj
  31. (defproject myproject "0.5.0-SNAPSHOT"
  32. :description "A project for doing things."
  33. :dependencies [[org.clojure/clojure "1.4.0"]]
  34. :profiles {:dev {:resource-paths ["dummy-data"]
  35. :dependencies [[expectations "1.4.41"]]}})
  36. ```
  37. Use the `show-profiles` task to list the project's profiles.
  38. ## Declaring Profiles
  39. In addition to `project.clj`, profiles also can be specified in `profiles.clj`
  40. within the project root. Profiles specified in `profiles.clj` will override
  41. profiles in `project.clj`, so this can be used for project-specific overrides
  42. that you don't want committed in version control.
  43. User-wide profiles can also be specified in
  44. `~/.lein/profiles.clj`. These will be available in all projects
  45. managed by Leiningen, though those profiles will be overridden by
  46. profiles of the same name specified in the project. System-wide
  47. profiles can be placed in `/etc/leiningen/profiles.clj`. They are
  48. treated the same as user profiles, but with lower precedence.
  49. You can also define user-wide profiles within `clj`-files inside
  50. `~/.lein/profiles.d`. The semantics within such files differ slightly
  51. from other profile files: rather than a map of maps, the profile map
  52. is the top-level within the file, and the name of the profile comes
  53. from the file itself (without the `.clj` part). Defining the same
  54. user-wide profile in both `~/.lein/profiles.clj` and in
  55. `~/.lein/profiles.d` is considered an error.
  56. ## Default Profiles
  57. Certain profiles are active by default unless you specify another set
  58. of profiles using the `with-profiles` task. Each of the default
  59. profiles have different semantics:
  60. If you want to access dependencies or plugins during development time
  61. for any project place them in your `:user` profile. Your
  62. `~/.lein/profiles.clj` file could look something like this:
  63. ```clj
  64. {:user {:plugins [[lein-pprint "1.1.1"]]
  65. :dependencies [[slamhound "1.3.1"]]}}
  66. ```
  67. The `:dev` profile is used to specify project specific development
  68. tooling. Put things here if they are required for builds or tests,
  69. rather than just convenience tooling.
  70. The `:user` profile is separate from `:dev`; the latter is intended to
  71. be specified in the project itself. In order to avoid collisions, the
  72. project should never define a `:user` profile, nor should a user-wide
  73. `:dev` profile be defined. Likewise, system profiles should use the
  74. `:system` profile, and define neither `:user` nor `:dev` profiles.
  75. The `:system` profile is similar to `:user`, except it applies
  76. system-wide instead of merely to a single user.
  77. The `:base` profile provides dependencies necessary for basic repl
  78. functionality, adds `dev-resources` to the `:resource-paths`, and sets
  79. defaults for `:jvm-opts`, `:checkout-deps-share` and
  80. `:test-selectors`. It is part of Leiningen itself; you shouldn't need
  81. to change it.
  82. The profiles listed above are active during development, but they are
  83. unmerged before the jar and pom files are created, making them
  84. invisible to code that depends upon your project.
  85. The `:provided` profile is used to specify dependencies that should be
  86. available during jar creation, but not propagated to other code that
  87. depends on your project. These are dependencies that the project
  88. assumes will be provided by whatever environment the jar is used in,
  89. but are needed during the development of the project. This is often
  90. used for frameworks like Hadoop that provide their own copies of
  91. certain libraries.
  92. The `:default` profile specifies the profiles that are active by
  93. default when running lein tasks. If not overridden, this is set to
  94. `:leiningen/default`, which is a composite profile with
  95. `[:base :system :user :provided :dev]`.
  96. ## Task Specific Profiles
  97. Some tasks automatically merge a profile if specified. Examples of
  98. these are the `:test` profile, when running the `test` task, and the
  99. `:repl` profile, when running the `repl` task.
  100. ### Replacing Default Repl Dependencies
  101. By default, the repl task will use the version of Clojure, tools.nrepl
  102. and clojure-complete that ships with the Leiningen. These can be
  103. overridden in projects, but this doesn't change the repl's behaviour
  104. outside of those projects. To do that, you should put a `:repl`
  105. profile in your `~/.lein/profiles.clj` file. For example, to replace
  106. the default tools.nrepl dependency with version 0.2.12, you can insert
  107. the following profile:
  108. ```clj
  109. {:repl {:dependencies [[org.clojure/tools.nrepl "0.2.12"]]}}
  110. ```
  111. Now, all calls to `lein repl` will use version 0.2.12 of tools.nrepl,
  112. with the exception of the projects that has defined a `:repl` profile
  113. themselves.
  114. If you want to specify the default Clojure version outside of
  115. projects, you can do so by `^:displace`-ing it in the `:repl` profile:
  116. ```clj
  117. {:repl {:dependencies [^:displace [org.clojure/clojure "1.8.0-alpha3"]]}}
  118. ```
  119. This version will only be used outside of Clojure projects. Note that
  120. this `^:displace` trick will not work with tools.nrepl or
  121. clojure-complete.
  122. ## Profile Metadata
  123. If you mark your profile with `^:leaky` metadata, then the profile
  124. will not be stripped out when the pom and jar files are created.
  125. If you mark a profile with `^{:pom-scope :test}` metadata, then the
  126. profile's `:dependencies` will be added with a `test` scope in the
  127. generated pom and jar when active. The `:dev`, `:test`, and `:base`
  128. profiles have this set automatically.
  129. If you mark a profile with `^{:pom-scope :provided}` metadata, then
  130. the profile's `:dependencies` will be added with a `provided` scope in
  131. the generated pom and jar when active. The `:provided` profile has
  132. this set automatically.
  133. ## Merging
  134. Profiles are merged by taking each key in the project map or profile
  135. map, combining the value if it's a collection and replacing it if it's
  136. not. Profiles specified later take precedence when replacing, just
  137. like the `clojure.core/merge` function. The dev profile takes
  138. precedence over user by default. Maps are merged recursively, sets are
  139. combined with `clojure.set/union`, and lists/vectors are
  140. concatenated. You can add hints via metadata that a given value should
  141. take precedence (`:replace`) or defer to values from a different
  142. profile (`:displace`) if you want to override this logic:
  143. ```clj
  144. {:profiles {:dev {:prep-tasks ^:replace ["clean" "compile"]
  145. :aliases ^:displace {"launch" "run"}}}}
  146. ```
  147. The exception to this merge logic is that `:plugins` and `:dependencies`
  148. have custom de-duplication logic since they must be specified as
  149. vectors even though they behave like maps (because it only makes sense
  150. to have a single version of a given dependency present at once). The
  151. replace/displace metadata hints still apply though.
  152. Remember that if a profile with the same name is specified in multiple
  153. locations, only the profile with the highest "priority" is picked – no merging
  154. is done. The "priority" is – from highest to lowest – `profiles.clj`,
  155. `project.clj`, user-wide profiles, and finally system-wide profiles.
  156. If you need to enable personal overrides of parts of a profile, you can use a
  157. composite profile with common and personal parts - something like `:dev
  158. [:dev-common :dev-overrides]`; you would then have just `:dev-overrides {}` in
  159. `project.clj` and override it in `profiles.clj`.
  160. Another use of profiles is to test against various sets of dependencies:
  161. ```clj
  162. (defproject swank-clojure "1.5.0-SNAPSHOT"
  163. :description "Swank server connecting Clojure to Emacs SLIME"
  164. :dependencies [[org.clojure/clojure "1.2.1"]
  165. [clj-stacktrace "0.2.4"]
  166. [cdt "1.2.6.2"]]
  167. :profiles {:1.3 {:dependencies [[org.clojure/clojure "1.3.0"]]}
  168. :1.4 {:dependencies [[org.clojure/clojure "1.4.0-beta1"]]}})
  169. ```
  170. ## Activating Profiles
  171. To activate a different set of profiles for a given task, use the
  172. `with-profile` higher-order task:
  173. $ lein with-profile 1.3 test :database
  174. Multiple profiles may be combined with commas:
  175. $ lein with-profile qa,user test :database
  176. Multiple profiles may be executed in series with colons:
  177. $ lein with-profile 1.3:1.4 test :database
  178. The above invocations activate the given profiles in place of the
  179. defaults. To activate a profile in addition to the defaults, prepend
  180. it with a `+`:
  181. $ lein with-profile +server run
  182. You can also use `-` to deactivate a profile.
  183. By default all profiles will share the same `:target-path`, which can
  184. cause problems if settings from one profile leak over into
  185. another. It's recommended to set `:target-path` to `"target/%s"`,
  186. which will isolate each profile set and prevent anything from bleeding over.
  187. ## Composite Profiles
  188. Sometimes it is useful to define a profile as a combination of other
  189. profiles. To do this, just use a vector instead of a map as the profile value.
  190. This can be used to avoid duplication:
  191. ```clj
  192. {:shared {:port 9229, :protocol "https"}
  193. :qa [:shared {:servers ["qa.mycorp.com"]}]
  194. :stage [:shared {:servers ["stage.mycorp.com"]}]
  195. :production [:shared {:servers ["prod1.mycorp.com", "prod1.mycorp.com"]}]}
  196. ```
  197. ## Dynamic Eval
  198. Often you want to read an environment variable or execute a function to capture
  199. a value to use in your profiles. In order to do such a thing with the profiles.clj
  200. you'll need to use the read-eval syntax.
  201. Here is an example of such a case:
  202. ```clj
  203. {:user {:compile-path #=(eval (System/getenv "ci.compile-path")),
  204. :target-path #=(eval (System/getenv "ci.target-path"))}}
  205. ```
  206. ## Debugging
  207. To see how a given profile affects your project map, use the
  208. [lein-pprint](https://github.com/technomancy/leiningen/tree/stable/lein-pprint)
  209. plugin:
  210. $ lein with-profile 1.4 pprint
  211. {:compile-path "/home/phil/src/leiningen/lein-pprint/classes",
  212. :group "lein-pprint",
  213. :source-path ("/home/phil/src/leiningen/lein-pprint/src"),
  214. :dependencies
  215. ([org.clojure/tools.nrepl "0.0.5" :exclusions [org.clojure/clojure]]
  216. [clojure-complete "0.1.4" :exclusions [org.clojure/clojure]]
  217. [org.thnetos/cd-client "0.3.3" :exclusions [org.clojure/clojure]]),
  218. :target-path "/home/phil/src/leiningen/lein-pprint/target",
  219. :name "lein-pprint",
  220. [...]
  221. :description "Pretty-print a representation of the project map."}
  222. In order to prevent profile settings from being propagated to other
  223. projects that depend upon yours, the `:default` profiles are removed
  224. from your project when generating the pom, jar, and uberjar, and an
  225. `:uberjar` profile, if present, is included when creating
  226. uberjars. (This can be useful if you want to specify a `:main`
  227. namespace for uberjar use without triggering AOT during regular
  228. development.) Profiles activated through an explicit `with-profile`
  229. invocation will be preserved.