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
|
|
|
|
|
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
|
2014-09-09 23:04:31 +00:00
|
|
|
|
development and a dependency upon "expectations" that's only used for
|
|
|
|
|
tests/development.
|
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
|
|
|
|
```
|
|
|
|
|
|
2014-09-04 19:20:08 +00:00
|
|
|
|
Use the `show-profiles` task to list the project's profiles.
|
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
|
|
|
|
|
2014-09-06 03:24:29 +00:00
|
|
|
|
## 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:
|
2012-05-25 01:26:46 +00:00
|
|
|
|
|
2014-09-06 03:24:29 +00:00
|
|
|
|
If you want to access dependencies or plugins during development time
|
|
|
|
|
for any project place them in your `:user` profile. Your
|
2012-06-14 02:37:29 +00:00
|
|
|
|
`~/.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
|
|
|
|
```
|
|
|
|
|
|
2014-09-04 19:20:08 +00:00
|
|
|
|
The `:dev` profile is used to specify project specific development
|
2014-09-06 03:24:29 +00:00
|
|
|
|
tooling. Put things here if they are required for builds or tests,
|
|
|
|
|
rather than just convenience tooling.
|
2014-09-04 19:20:08 +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. Likewise, system profiles should use the
|
|
|
|
|
`:system` profile, and define neither `:user` nor `:dev` profiles.
|
|
|
|
|
|
2014-09-09 23:04:31 +00:00
|
|
|
|
The `:system` profile is similar to `:user`, except it applies
|
|
|
|
|
system-wide instead of merely to a single user.
|
|
|
|
|
|
2014-09-06 03:24:29 +00:00
|
|
|
|
The `:base` profile provides dependencies necessary for basic repl
|
|
|
|
|
functionality, adds `dev-resources` to the `:resources-path`, and sets
|
2014-09-04 19:20:08 +00:00
|
|
|
|
defaults for `:jvm-opts`, `:checkout-deps-share` and
|
2014-09-06 03:24:29 +00:00
|
|
|
|
`: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
|
2014-09-09 23:04:31 +00:00
|
|
|
|
invisible to code that depends upon your project.
|
2014-09-06 03:24:29 +00:00
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
2014-09-09 23:04:31 +00:00
|
|
|
|
The `:default` profile specifies the profiles that are active by
|
2014-09-09 17:10:13 +00:00
|
|
|
|
default when running lein tasks. If not overridden, this is set to
|
2014-09-09 23:04:31 +00:00
|
|
|
|
`:leiningen/default`, which is a composite profile with
|
2014-09-09 17:10:13 +00:00
|
|
|
|
`[:base :system :user :provided :dev]`.
|
|
|
|
|
|
2014-09-04 19:20:08 +00:00
|
|
|
|
## 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.
|
|
|
|
|
|
2014-09-09 17:10:13 +00:00
|
|
|
|
## Profile Metadata
|
|
|
|
|
|
|
|
|
|
If you mark your profile with `^:leaky` metadata, then the profile
|
2014-09-09 23:04:31 +00:00
|
|
|
|
will not be stripped out when the pom and jar files are created.
|
2014-09-09 17:10:13 +00:00
|
|
|
|
|
|
|
|
|
If you mark a profile with `^{:pom-scope :test}` metadata, then the
|
|
|
|
|
profile's `:dependencies` will be added with a `test` scope in the
|
2014-09-09 23:04:31 +00:00
|
|
|
|
generated pom and jar when active. The `:dev`, `:test`, and `:base`
|
|
|
|
|
profiles have this set automatically.
|
2014-09-09 17:10:13 +00:00
|
|
|
|
|
2014-09-09 23:04:31 +00:00
|
|
|
|
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.
|
2014-09-09 17:10:13 +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-08-17 21:43:14 +00:00
|
|
|
|
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 – `project.clj`,
|
|
|
|
|
`profiles.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`.
|
2014-04-23 08:28:30 +00:00
|
|
|
|
|
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
|
2014-06-01 17:00:10 +00:00
|
|
|
|
{: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-07-19 00:20:18 +00:00
|
|
|
|
```
|
|
|
|
|
|
2014-09-09 23:04:31 +00:00
|
|
|
|
## Dynamic Eval
|
2014-07-24 19:24:30 +00:00
|
|
|
|
|
|
|
|
|
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"))}}
|
|
|
|
|
```
|
|
|
|
|
|
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.
|