2012-05-25 01:26:46 +00:00
|
|
|
# Profiles
|
|
|
|
|
2014-04-22 21:44:21 +00:00
|
|
|
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.
|
2012-05-25 01:26:46 +00:00
|
|
|
|
2013-08-13 00:15:40 +00:00
|
|
|
By default the `:dev`, `:provided`, `:user`, `:system`, and `:base`
|
|
|
|
profiles are activated for each task, but their settings are not
|
|
|
|
propagated downstream to projects that depend upon yours. Each profile
|
|
|
|
is defined as a map which gets merged into your project map.
|
2012-05-25 01:26:46 +00:00
|
|
|
|
2014-04-22 21:44:21 +00:00
|
|
|
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.
|
2012-07-01 02:43:39 +00:00
|
|
|
|
2012-05-25 01:26:46 +00:00
|
|
|
The example below adds a "dummy-data" resources directory during
|
2013-10-30 18:38:05 +00:00
|
|
|
development and a dependency upon "expectations" that's only used for tests.
|
2012-05-25 01:26:46 +00:00
|
|
|
|
|
|
|
```clj
|
|
|
|
(defproject myproject "0.5.0-SNAPSHOT"
|
|
|
|
:description "A project for doing things."
|
|
|
|
:dependencies [[org.clojure/clojure "1.4.0"]]
|
2012-10-23 22:56:07 +00:00
|
|
|
:profiles {:dev {:resource-paths ["dummy-data"]
|
2013-07-26 20:25:18 +00:00
|
|
|
:dependencies [[expectations "1.4.41"]]}})
|
2012-05-25 01:26:46 +00:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## Declaring Profiles
|
|
|
|
|
2012-07-18 22:51:49 +00:00
|
|
|
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.
|
|
|
|
|
2014-04-22 21:44:21 +00:00
|
|
|
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.
|
2013-03-30 03:15:52 +00:00
|
|
|
|
2013-07-26 20:25:18 +00:00
|
|
|
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.
|
2012-07-18 22:51:49 +00:00
|
|
|
|
2013-07-26 20:25:18 +00:00
|
|
|
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. Use the `show-profiles` task to list them.
|
2012-05-25 01:26:46 +00:00
|
|
|
|
|
|
|
If you want to access dependencies during development time for any
|
2012-06-14 02:37:29 +00:00
|
|
|
project place them in your `:user` profile. Your
|
|
|
|
`~/.lein/profiles.clj` file could look something like this:
|
2012-05-25 01:26:46 +00:00
|
|
|
|
|
|
|
```clj
|
2013-01-22 04:41:14 +00:00
|
|
|
{:user {:plugins [[lein-pprint "1.1.1"]]
|
|
|
|
:dependencies [[slamhound "1.3.1"]]}}
|
2012-05-25 01:26:46 +00:00
|
|
|
```
|
|
|
|
|
2013-07-26 20:25:18 +00:00
|
|
|
## Merging
|
|
|
|
|
2012-07-12 05:07:08 +00:00
|
|
|
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
|
2013-07-26 20:25:18 +00:00
|
|
|
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:
|
2012-05-25 01:26:46 +00:00
|
|
|
|
|
|
|
```clj
|
|
|
|
{:profiles {:dev {:prep-tasks ^:replace ["clean" "compile"]
|
|
|
|
:aliases ^:displace {"launch" "run"}}}}
|
|
|
|
```
|
|
|
|
|
2013-07-26 20:25:18 +00:00
|
|
|
The exception to this merge logic is that `:plugins` and `:dependencies`
|
2012-05-25 01:26:46 +00:00
|
|
|
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.
|
|
|
|
|
2014-04-23 08:28:30 +00:00
|
|
|
Remember that if a profile with the same name is specified at multiple places,
|
|
|
|
the last one will *replace* the previous ones, no merging. Only profiles of
|
|
|
|
different names are merged onto the project map.
|
|
|
|
|
2012-05-25 01:26:46 +00:00
|
|
|
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"]]}})
|
|
|
|
```
|
|
|
|
|
2013-07-26 20:25:18 +00:00
|
|
|
## Activating Profiles
|
|
|
|
|
|
|
|
To activate a different set of profiles for a given task, use the
|
|
|
|
`with-profile` higher-order task:
|
2012-05-25 01:26:46 +00:00
|
|
|
|
|
|
|
$ 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
|
|
|
|
|
2013-07-26 20:25:18 +00:00
|
|
|
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.
|
|
|
|
|
2014-04-22 21:44:21 +00:00
|
|
|
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.
|
2013-07-26 20:25:18 +00:00
|
|
|
|
2012-07-19 00:20:18 +00:00
|
|
|
## 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\"]}]}
|
|
|
|
```
|
|
|
|
|
2012-08-24 12:34:22 +00:00
|
|
|
Composite profiles are used by Leiningen internally for the `:default`
|
|
|
|
profile, which is the profile used if you don't change it using
|
|
|
|
`with-profile`. The `:default` profile is defined to be a composite of
|
2013-07-26 20:25:18 +00:00
|
|
|
`[:base :system :user :provided :dev]`, but you can change this in your
|
2012-08-24 12:34:22 +00:00
|
|
|
`project.clj` just like any other profile.
|
2012-07-19 00:20:18 +00:00
|
|
|
|
2012-05-25 01:26:46 +00:00
|
|
|
## Debugging
|
|
|
|
|
|
|
|
To see how a given profile affects your project map, use the
|
2013-01-20 04:39:43 +00:00
|
|
|
[lein-pprint](https://github.com/technomancy/leiningen/tree/stable/lein-pprint)
|
2012-05-25 01:26:46 +00:00
|
|
|
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
|
2013-07-26 20:25:18 +00:00
|
|
|
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.
|