/resources/leiningen/help/profiles
http://github.com/technomancy/leiningen · #! · 295 lines · 229 code · 66 blank · 0 comment · 0 complexity · 4be1e7f295eaa23e9cccf74b13c9abfc MD5 · raw file
- <!-- START doctoc generated TOC please keep comment here to allow auto update -->
- <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
- **Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
- - [Profiles](#profiles)
- - [Declaring Profiles](#declaring-profiles)
- - [Default Profiles](#default-profiles)
- - [Task Specific Profiles](#task-specific-profiles)
- - [Replacing Default Repl Dependencies](#replacing-default-repl-dependencies)
- - [Profile Metadata](#profile-metadata)
- - [Merging](#merging)
- - [Activating Profiles](#activating-profiles)
- - [Composite Profiles](#composite-profiles)
- - [Dynamic Eval](#dynamic-eval)
- - [Debugging](#debugging)
- <!-- END doctoc generated TOC please keep comment here to allow auto update -->
- # Profiles
- You can change the configuration of your project by applying various
- profiles. For instance, you may want to have a few extra test data
- directories on the classpath during development without including them
- in the jar, or you may want to have development tools like
- [Slamhound](https://github.com/technomancy/slamhound) available in
- every project you hack on without modifying every single `project.clj`
- you use.
- You can place any arbitrary key/value pairs supported by `defproject`
- into a given profile and they will be merged into the project map when
- that profile is activated.
- The example below adds a "dummy-data" resources directory during
- development and a dependency upon "expectations" that's only used for
- tests/development.
- ```clj
- (defproject myproject "0.5.0-SNAPSHOT"
- :description "A project for doing things."
- :dependencies [[org.clojure/clojure "1.4.0"]]
- :profiles {:dev {:resource-paths ["dummy-data"]
- :dependencies [[expectations "1.4.41"]]}})
- ```
- Use the `show-profiles` task to list the project's profiles.
- ## Declaring Profiles
- In addition to `project.clj`, profiles also can be specified in `profiles.clj`
- within the project root. Profiles specified in `profiles.clj` will override
- profiles in `project.clj`, so this can be used for project-specific overrides
- that you don't want committed in version control.
- User-wide profiles can also be specified in
- `~/.lein/profiles.clj`. These will be available in all projects
- managed by Leiningen, though those profiles will be overridden by
- profiles of the same name specified in the project. System-wide
- profiles can be placed in `/etc/leiningen/profiles.clj`. They are
- treated the same as user profiles, but with lower precedence.
- You can also define user-wide profiles within `clj`-files inside
- `~/.lein/profiles.d`. The semantics within such files differ slightly
- from other profile files: rather than a map of maps, the profile map
- is the top-level within the file, and the name of the profile comes
- from the file itself (without the `.clj` part). Defining the same
- user-wide profile in both `~/.lein/profiles.clj` and in
- `~/.lein/profiles.d` is considered an error.
- ## Default Profiles
- Certain profiles are active by default unless you specify another set
- of profiles using the `with-profiles` task. Each of the default
- profiles have different semantics:
- If you want to access dependencies or plugins during development time
- for any project place them in your `:user` profile. Your
- `~/.lein/profiles.clj` file could look something like this:
- ```clj
- {:user {:plugins [[lein-pprint "1.1.1"]]
- :dependencies [[slamhound "1.3.1"]]}}
- ```
- The `:dev` profile is used to specify project specific development
- tooling. Put things here if they are required for builds or tests,
- rather than just convenience tooling.
- The `:user` profile is separate from `:dev`; the latter is intended to
- be specified in the project itself. In order to avoid collisions, the
- project should never define a `:user` profile, nor should a user-wide
- `:dev` profile be defined. Likewise, system profiles should use the
- `:system` profile, and define neither `:user` nor `:dev` profiles.
- The `:system` profile is similar to `:user`, except it applies
- system-wide instead of merely to a single user.
- The `:base` profile provides dependencies necessary for basic repl
- functionality, adds `dev-resources` to the `:resource-paths`, and sets
- defaults for `:jvm-opts`, `:checkout-deps-share` and
- `:test-selectors`. It is part of Leiningen itself; you shouldn't need
- to change it.
- The profiles listed above are active during development, but they are
- unmerged before the jar and pom files are created, making them
- invisible to code that depends upon your project.
- The `:provided` profile is used to specify dependencies that should be
- available during jar creation, but not propagated to other code that
- depends on your project. These are dependencies that the project
- assumes will be provided by whatever environment the jar is used in,
- but are needed during the development of the project. This is often
- used for frameworks like Hadoop that provide their own copies of
- certain libraries.
- The `:default` profile specifies the profiles that are active by
- default when running lein tasks. If not overridden, this is set to
- `:leiningen/default`, which is a composite profile with
- `[:base :system :user :provided :dev]`.
- ## Task Specific Profiles
- Some tasks automatically merge a profile if specified. Examples of
- these are the `:test` profile, when running the `test` task, and the
- `:repl` profile, when running the `repl` task.
- ### Replacing Default Repl Dependencies
- By default, the repl task will use the version of Clojure, tools.nrepl
- and clojure-complete that ships with the Leiningen. These can be
- overridden in projects, but this doesn't change the repl's behaviour
- outside of those projects. To do that, you should put a `:repl`
- profile in your `~/.lein/profiles.clj` file. For example, to replace
- the default tools.nrepl dependency with version 0.2.12, you can insert
- the following profile:
- ```clj
- {:repl {:dependencies [[org.clojure/tools.nrepl "0.2.12"]]}}
- ```
- Now, all calls to `lein repl` will use version 0.2.12 of tools.nrepl,
- with the exception of the projects that has defined a `:repl` profile
- themselves.
- If you want to specify the default Clojure version outside of
- projects, you can do so by `^:displace`-ing it in the `:repl` profile:
- ```clj
- {:repl {:dependencies [^:displace [org.clojure/clojure "1.8.0-alpha3"]]}}
- ```
- This version will only be used outside of Clojure projects. Note that
- this `^:displace` trick will not work with tools.nrepl or
- clojure-complete.
- ## Profile Metadata
- If you mark your profile with `^:leaky` metadata, then the profile
- will not be stripped out when the pom and jar files are created.
- If you mark a profile with `^{:pom-scope :test}` metadata, then the
- profile's `:dependencies` will be added with a `test` scope in the
- generated pom and jar when active. The `:dev`, `:test`, and `:base`
- profiles have this set automatically.
- If you mark a profile with `^{:pom-scope :provided}` metadata, then
- the profile's `:dependencies` will be added with a `provided` scope in
- the generated pom and jar when active. The `:provided` profile has
- this set automatically.
- ## Merging
- Profiles are merged by taking each key in the project map or profile
- map, combining the value if it's a collection and replacing it if it's
- not. Profiles specified later take precedence when replacing, just
- like the `clojure.core/merge` function. The dev profile takes
- precedence over user by default. Maps are merged recursively, sets are
- combined with `clojure.set/union`, and lists/vectors are
- concatenated. You can add hints via metadata that a given value should
- take precedence (`:replace`) or defer to values from a different
- profile (`:displace`) if you want to override this logic:
- ```clj
- {:profiles {:dev {:prep-tasks ^:replace ["clean" "compile"]
- :aliases ^:displace {"launch" "run"}}}}
- ```
- The exception to this merge logic is that `:plugins` and `:dependencies`
- have custom de-duplication logic since they must be specified as
- vectors even though they behave like maps (because it only makes sense
- to have a single version of a given dependency present at once). The
- replace/displace metadata hints still apply though.
- Remember that if a profile with the same name is specified in multiple
- locations, only the profile with the highest "priority" is picked â no merging
- is done. The "priority" is â from highest to lowest â `profiles.clj`,
- `project.clj`, user-wide profiles, and finally system-wide profiles.
- If you need to enable personal overrides of parts of a profile, you can use a
- composite profile with common and personal parts - something like `:dev
- [:dev-common :dev-overrides]`; you would then have just `:dev-overrides {}` in
- `project.clj` and override it in `profiles.clj`.
- Another use of profiles is to test against various sets of dependencies:
- ```clj
- (defproject swank-clojure "1.5.0-SNAPSHOT"
- :description "Swank server connecting Clojure to Emacs SLIME"
- :dependencies [[org.clojure/clojure "1.2.1"]
- [clj-stacktrace "0.2.4"]
- [cdt "1.2.6.2"]]
- :profiles {:1.3 {:dependencies [[org.clojure/clojure "1.3.0"]]}
- :1.4 {:dependencies [[org.clojure/clojure "1.4.0-beta1"]]}})
- ```
- ## Activating Profiles
- To activate a different set of profiles for a given task, use the
- `with-profile` higher-order task:
- $ lein with-profile 1.3 test :database
- Multiple profiles may be combined with commas:
- $ lein with-profile qa,user test :database
- Multiple profiles may be executed in series with colons:
- $ lein with-profile 1.3:1.4 test :database
- The above invocations activate the given profiles in place of the
- defaults. To activate a profile in addition to the defaults, prepend
- it with a `+`:
- $ lein with-profile +server run
- You can also use `-` to deactivate a profile.
- By default all profiles will share the same `:target-path`, which can
- cause problems if settings from one profile leak over into
- another. It's recommended to set `:target-path` to `"target/%s"`,
- which will isolate each profile set and prevent anything from bleeding over.
- ## Composite Profiles
- Sometimes it is useful to define a profile as a combination of other
- profiles. To do this, just use a vector instead of a map as the profile value.
- This can be used to avoid duplication:
- ```clj
- {:shared {:port 9229, :protocol "https"}
- :qa [:shared {:servers ["qa.mycorp.com"]}]
- :stage [:shared {:servers ["stage.mycorp.com"]}]
- :production [:shared {:servers ["prod1.mycorp.com", "prod1.mycorp.com"]}]}
- ```
- ## Dynamic Eval
- Often you want to read an environment variable or execute a function to capture
- a value to use in your profiles. In order to do such a thing with the profiles.clj
- you'll need to use the read-eval syntax.
- Here is an example of such a case:
- ```clj
- {:user {:compile-path #=(eval (System/getenv "ci.compile-path")),
- :target-path #=(eval (System/getenv "ci.target-path"))}}
- ```
- ## Debugging
- To see how a given profile affects your project map, use the
- [lein-pprint](https://github.com/technomancy/leiningen/tree/stable/lein-pprint)
- plugin:
- $ lein with-profile 1.4 pprint
- {:compile-path "/home/phil/src/leiningen/lein-pprint/classes",
- :group "lein-pprint",
- :source-path ("/home/phil/src/leiningen/lein-pprint/src"),
- :dependencies
- ([org.clojure/tools.nrepl "0.0.5" :exclusions [org.clojure/clojure]]
- [clojure-complete "0.1.4" :exclusions [org.clojure/clojure]]
- [org.thnetos/cd-client "0.3.3" :exclusions [org.clojure/clojure]]),
- :target-path "/home/phil/src/leiningen/lein-pprint/target",
- :name "lein-pprint",
- [...]
- :description "Pretty-print a representation of the project map."}
- In order to prevent profile settings from being propagated to other
- projects that depend upon yours, the `:default` profiles are removed
- from your project when generating the pom, jar, and uberjar, and an
- `:uberjar` profile, if present, is included when creating
- uberjars. (This can be useful if you want to specify a `:main`
- namespace for uberjar use without triggering AOT during regular
- development.) Profiles activated through an explicit `with-profile`
- invocation will be preserved.