Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Clojure today exists at a balance point between performance and dynamic flexibility. Some users would be willing to sacrifice dynamic features to gain more performance. Other users would be willing to sacrifice performance to gain better development error messages or debugging. The problem we aim to solve is to alter the Clojure build such that we can produce alternate versions of Clojure that are useful to smaller audiences while retaining Clojure as it is today.

Example builds we may want to produce (examples):

  • Direct linking
    • Off - allows redefs, good for interactive dev tooling or modifying Clojure internals
    • On - better performance and optimization for long-running more static programs
  • Lazy vars
    • On - faster bootstrap for scripts or dev reloading
    • Off - faster var invocation for long-running programs
  • Metadata (:doc, :file, :line, :added) - removing metadata makes .class files smaller and faster to load, but removes metadata for doc
    • Full - :doc, :file, :line, :added
    • Intermediate - :file, :line
    • Minimal - none
  • Dev assistance
    • Validation and error messages that can guide development at the expense of runtime performance

 

VariantDescriptionDirect linkingLazy varsMetadataDev assistance
devFor developmentOffOnFullOn
dynamicFor dynamic production useOffOnIntermediateOff
staticFor static production useOffOffMinimalOff
experimentalExperimental compiler features????

Constraints 

Clojure users:

  • Clojure users Build profile artifacts should be able to depend on and use special builds in a way that is natural for their environment available in public Maven repositories for use with existing build systems (Leiningen, Maven, etc) 

Build:

  • Specialized Clojure builds Boot), alternatives include:
    • Different artifacts:  [org.clojure/clojure-foo "1.8.0"]
    • Different qualifiers: [org.clojure/clojure "1.8.0-foo"]
    • Different classifiers: [org.clojure/clojure "1.8.0" :classifier "foo"]
  • Some features may require further compiler flags or metadata to activate even if using the specialized build
    • For example, you may need to supply special var metadata on a function to get access to a feature
    • Ideally, use of the special feature should be simply ignored if not using the specialized build (or a warning should direct you)

Build:

  • Produce multiple output jars each time we build a version (snapshot or release)
  • The jars will contain different versions of the classes
  • Specialized build flags or env variables will need to be set during the build for each variant
  • Testing should occur for each variant
Integration / release infrastructure:
  • CI must be able to build and test custom builds as part of the dependency matrix
  • CI must be able to perform releases for all of the variants
  • CI must be able to test contribs against custom builds

Compiler:

  • The compiler will need a standard way to determine which variant is active to make decisions during compilation

External builds

Builds that

...

Compiler:

use Clojure may also need to make these kinds of compiler choices to produce their own build profiles. 

It would be useful to produce a guide on how to enable combinations of compiler options to produce builds of different flavors for libraries with the common build tools.

Research

Maven coordinate options

  • Different artifactId
    • Releasing different artifacts would probably require running the build multiple times - there are probably some complexities in the CI and release process as a result.
    • NOT recommended
  • Different qualifier
    • Qualifiers are really designed to give you more information about the purpose of a released version (alpha, beta, GA, build number), so this would be departing from standard Maven expectations.
    • NOT recommended
  • Different classifier
    • Classifiers are designed for this use case - they allow you to create variants of the same group/artifact/version specialized for a particular environment (JDK variants is one example given)
    • Lein and Maven can both specify a classifier - in lein with [org.clojure/clojure "1.6.0" :classifier "foo"]
    • It seems good that the main build and variant share Maven co-ords - there is then a standard way to get from main artifact to (for example) the dev variant for tooling.
    • How-to in Maven
    • How-to in Ant
      • Define property that can be set to activate a particular variant
      • Set that property when running the build
    • Hardest part of this is getting the build to sign and release all of the artifacts together

Maven custom assembly

  • The Maven assembly plugin allows for arbitrary customization of the artifacts created by the build. However, creating multiple artifacts with different Maven coordinates will likely require multiple builds to produce each artifact for deployment. This has issues with signing and release.

Boot

  • Boot provides a great deal of customization capability and might also be a good option for this level of customization
  • Unknown: signed deployment to Maven central repos?

Custom script (ant, make, etc)

  • Would prefer something with greater familiarity to Clojure devs as patch developers need to run the build too