# 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. 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. 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. ```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"]]}}) ``` ## 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. 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. If you want to access dependencies 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"]]}} ``` ## 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 files, the last one will *replace* the previous ones, no merging. (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"]}]} ``` 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 `[:base :system :user :provided :dev]`, but you can change this in your `project.clj` just like any other profile. ## 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.