File: PROFILES.md

package info (click to toggle)
leiningen-clojure 2.9.0-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 2,312 kB
  • sloc: xml: 881; sh: 771; lisp: 46; makefile: 34; java: 16
file content (268 lines) | stat: -rw-r--r-- 11,208 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
<!-- 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)
  - [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` (via [merging](#merging) logic described below), 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-profile` 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. Please note that
putting things in the `:test` profile is strongly advised against as
it can result in tests which can't be run from the repl.

## 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.