There is now an AOT compiler that can compile .clj files to .class
files on disk. This can be used to save startup time, deliver
applications without source, interop with bytecode-based tools etc.
The main structural change related to AOT is that the mapping between
a Clojure namespace and a Java package has changed. Where it was ns
maps to package:
my.fancy.lib ==> my/fancy/lib/lib.clj
it is now ns maps to class:
my.fancy.lib ==> my/fancy/lib.clj, when compiled, my/fancy/lib.class
Just lift your files up a directory to accommodate this change. Note
that this implies that all namespaces should have at least 2 segments,
and following the Java package name guidelines, e.g.
com.mydomain.mylib, is recommended.
Accordingly, the clojure ns has been renamed clojure.core. Any
explicitly qualified references will need to be changed. boot.clj has
been renamed core.clj.
The only other source-level change here was a small one to load - you
no longer should supply the .clj extension, in keeping with load's new
ability to load from .class files.
The latter is the only functional difference AOT brings to existing
code - load will load from a .class file if it is newer than the .clj.
Both files need to be in the classpath, using a directory structure
corresponding the the Java package as per above. Once compiled, .clj
files need not be present at all if .class files are supplied.
The unit of compilation is the lib. To compile a lib, simple say:
(compile 'my.fancy.lib)
The source must be in the classpath, in my/fancy/lib.clj Compilation
output will go under the path designated by *compile-path*, which
defaults to the "classes" directory under cwd. Output will go to
*compile-path*/my/fancy/lib.class, and the subdirectories will be
created if needed. *compile-path* is bound in the repl and can be set!
or bound with binding. The *compile-path* directory must also be in
the classpath.
Compilation occurs under a same-world model, i.e. compiling a file has
the effect of loading it as well. As each file/fn is compiled, it is
loaded using the standard class lookup (thus the *compile-path* in
classpath requirement above). This is so that definitions can see and
utilize the definitions and macros that preceded them. While
compiling, a *compile-files* flag is set. This will cause nested load/
require/uses to compile as well, if needed. If your file has some def
initializers you don't want to run at compile-time, you can
conditionalize them like this:
A .class file will be produced for every file loaded. This file
defines a class called my.fancy.lib, which will have a static void load
() method (this name is likely to change). Calling this method has the
same effect as loading the original .clj would.
Namespaces defined in multiple files are supported. Simply (load "lib-
helper-file") for any helper files at the bottom of your ns-
defining .clj file. Note that classes will be created for these files
as well, even though they are not namespaces, and are not intended for
standalone use
In addition to the class file per .clj file, there will be a .class
file for every function. These will be named my/fancy/lib
$myfun__xxxx.class. They too are not intended for standalone use.
There will be many of these, so please use jar files for distribution.
The clojure.contrib and tools folks are working on getting in sync
with these changes. For minimal disruption, please stick with the SVN
rev they support (say, 1088), or lend a hand in testing their patches.
Still to come is a folding of genclass functionality into AOT, making
for a much smoother process.
Those of you who've used Clojure for a while know such breaking
changes are few and far between. AOT compilation is an important, non-
trivial, and often requested feature. Please be patient during the
transition.
> The clojure.contrib and tools folks are working on getting in sync > with these changes. For minimal disruption, please stick with the SVN > rev they support (say, 1088), or lend a hand in testing their patches.
I've updated my contribs and others that hadn't yet been updated to minimal compatibility with the AOT compilation change. Minimal compatibility means that they've been updated so they reside at the proper path (pulled up from their individual directories) and that they load into Clojure. Please test any that you use and report any problems.
For the contrib files I updated, I did an "svn cp" so Subversion history should be preserved over the transition. I also left the old versions at the old locations (appropriate for Clojure SVN 1088 and below) in place for a transitional period. I plan to delete my contribs at their old locations in a couple of days. I recommend other contrib authors do the same. Folks who want to have clojure-contrib as it was for Clojure SVN 1088 should use clojure-contrib SVN 235.
The new changes to Clojure look great! I look forward to exploring them.
On Nov 13, 1:43 pm, Rich Hickey <richhic...@gmail.com> wrote:
> We're coming around the other side of the few breaking changes I
> wanted to get done before release 1.0.
> New regex format:
> Uniform binding syntax using vectors:
> And ahead-of-time (AOT) compilation (SVN 1094+)
Wow, cool! I haven't had a lot of time to follow the list lately, but
I'm excited by these developments.
> There is now an AOT compiler that can compile .clj files to .class
> files on disk. This can be used to save startup time, deliver
> applications without source, interop with bytecode-based tools etc.
> The main structural change related to AOT is that the mapping between
> a Clojure namespace and a Java package has changed. Where it was ns
> maps to package:
> my.fancy.lib ==> my/fancy/lib/lib.clj
> it is now ns maps to class:
> my.fancy.lib ==> my/fancy/lib.clj, when compiled, my/fancy/lib.class
> Just lift your files up a directory to accommodate this change. Note
> that this implies that all namespaces should have at least 2 segments,
> and following the Java package name guidelines, e.g.
> com.mydomain.mylib, is recommended.
> Accordingly, the clojure ns has been renamed clojure.core. Any
> explicitly qualified references will need to be changed. boot.clj has
> been renamed core.clj.
> The only other source-level change here was a small one to load - you
> no longer should supply the .clj extension, in keeping with load's new
> ability to load from .class files.
> The latter is the only functional difference AOT brings to existing
> code - load will load from a .class file if it is newer than the .clj.
> Both files need to be in the classpath, using a directory structure
> corresponding the the Java package as per above. Once compiled, .clj
> files need not be present at all if .class files are supplied.
> The unit of compilation is the lib. To compile a lib, simple say:
> (compile 'my.fancy.lib)
> The source must be in the classpath, in my/fancy/lib.clj Compilation
> output will go under the path designated by *compile-path*, which
> defaults to the "classes" directory under cwd. Output will go to
> *compile-path*/my/fancy/lib.class, and the subdirectories will be
> created if needed. *compile-path* is bound in the repl and can be set!
> or bound with binding. The *compile-path* directory must also be in
> the classpath.
> Compilation occurs under a same-world model, i.e. compiling a file has
> the effect of loading it as well. As each file/fn is compiled, it is
> loaded using the standard class lookup (thus the *compile-path* in
> classpath requirement above). This is so that definitions can see and
> utilize the definitions and macros that preceded them. While
> compiling, a *compile-files* flag is set. This will cause nested load/
> require/uses to compile as well, if needed. If your file has some def
> initializers you don't want to run at compile-time, you can
> conditionalize them like this:
> A .class file will be produced for every file loaded. This file
> defines a class called my.fancy.lib, which will have a static void load
> () method (this name is likely to change). Calling this method has the
> same effect as loading the original .clj would.
> Namespaces defined in multiple files are supported. Simply (load "lib-
> helper-file") for any helper files at the bottom of your ns-
> defining .clj file. Note that classes will be created for these files
> as well, even though they are not namespaces, and are not intended for
> standalone use
> In addition to the class file per .clj file, there will be a .class
> file for every function. These will be named my/fancy/lib
> $myfun__xxxx.class. They too are not intended for standalone use.
> There will be many of these, so please use jar files for distribution.
> The clojure.contrib and tools folks are working on getting in sync
> with these changes. For minimal disruption, please stick with the SVN
> rev they support (say, 1088), or lend a hand in testing their patches.
> Still to come is a folding of genclass functionality into AOT, making
> for a much smoother process.
> Those of you who've used Clojure for a while know such breaking
> changes are few and far between. AOT compilation is an important, non-
> trivial, and often requested feature. Please be patient during the
> transition.
Thanks very much Rich. All these changes are very exciting.
I look forward to using them.
Does this mean that at some point clojure.jar would
contain precompiled class files for clojure code?
I suppose that would mean faster startup of the
repl.
> There is now an AOT compiler that can compile .clj files to .class
> files on disk. This can be used to save startup time, deliver
> applications without source, interop with bytecode-based tools etc.
> The main structural change related to AOT is that the mapping between
> a Clojure namespace and a Java package has changed. Where it was ns
> maps to package:
> my.fancy.lib ==> my/fancy/lib/lib.clj
> it is now ns maps to class:
> my.fancy.lib ==> my/fancy/lib.clj, when compiled, my/fancy/lib.class
> Just lift your files up a directory to accommodate this change. Note
> that this implies that all namespaces should have at least 2 segments,
> and following the Java package name guidelines, e.g.
> com.mydomain.mylib, is recommended.
> Accordingly, the clojure ns has been renamed clojure.core. Any
> explicitly qualified references will need to be changed. boot.clj has
> been renamed core.clj.
> The only other source-level change here was a small one to load - you
> no longer should supply the .clj extension, in keeping with load's new
> ability to load from .class files.
> The latter is the only functional difference AOT brings to existing
> code - load will load from a .class file if it is newer than the .clj.
> Both files need to be in the classpath, using a directory structure
> corresponding the the Java package as per above. Once compiled, .clj
> files need not be present at all if .class files are supplied.
> The unit of compilation is the lib. To compile a lib, simple say:
> (compile 'my.fancy.lib)
> The source must be in the classpath, in my/fancy/lib.clj Compilation
> output will go under the path designated by *compile-path*, which
> defaults to the "classes" directory under cwd. Output will go to
> *compile-path*/my/fancy/lib.class, and the subdirectories will be
> created if needed. *compile-path* is bound in the repl and can be set!
> or bound with binding. The *compile-path* directory must also be in
> the classpath.
> Compilation occurs under a same-world model, i.e. compiling a file has
> the effect of loading it as well. As each file/fn is compiled, it is
> loaded using the standard class lookup (thus the *compile-path* in
> classpath requirement above). This is so that definitions can see and
> utilize the definitions and macros that preceded them. While
> compiling, a *compile-files* flag is set. This will cause nested load/
> require/uses to compile as well, if needed. If your file has some def
> initializers you don't want to run at compile-time, you can
> conditionalize them like this:
> A .class file will be produced for every file loaded. This file
> defines a class called my.fancy.lib, which will have a static void load
> () method (this name is likely to change). Calling this method has the
> same effect as loading the original .clj would.
> Namespaces defined in multiple files are supported. Simply (load "lib-
> helper-file") for any helper files at the bottom of your ns-
> defining .clj file. Note that classes will be created for these files
> as well, even though they are not namespaces, and are not intended for
> standalone use
> In addition to the class file per .clj file, there will be a .class
> file for every function. These will be named my/fancy/lib
> $myfun__xxxx.class. They too are not intended for standalone use.
> There will be many of these, so please use jar files for distribution.
> The clojure.contrib and tools folks are working on getting in sync
> with these changes. For minimal disruption, please stick with the SVN
> rev they support (say, 1088), or lend a hand in testing their patches.
> Still to come is a folding of genclass functionality into AOT, making
> for a much smoother process.
> Those of you who've used Clojure for a while know such breaking
> changes are few and far between. AOT compilation is an important, non-
> trivial, and often requested feature. Please be patient during the
> transition.
It's currently possible to compile the files and rebuild the jar. It
does result in a faster startup time.
There doesn't seem to be a way to generate precompiled class files
with main methods at this point. Is there any reason such
functionality can't be added? Right now, if I want an executable
precompiled jar, I have to make a wrapper with gen-and-save-class or
Java.
> > And ahead-of-time (AOT) compilation (SVN 1094+)
> Thanks very much Rich. All these changes are very exciting.
> I look forward to using them.
> Does this mean that at some point clojure.jar would
> contain precompiled class files for clojure code?
> I suppose that would mean faster startup of the
> repl.
That's just a matter of adding precompiling to the ant script.
On Nov 14, 4:51 am, Zak Wilson <zak.wil...@gmail.com> wrote:
> It's currently possible to compile the files and rebuild the jar. It
> does result in a faster startup time.
> There doesn't seem to be a way to generate precompiled class files
> with main methods at this point. Is there any reason such
> functionality can't be added? Right now, if I want an executable
> precompiled jar, I have to make a wrapper with gen-and-save-class or
> Java.
Support for main (and the other features of genclass) is coming.
> Just lift your files up a directory to accommodate this change. Note
> that this implies that all namespaces should have at least 2 segments,
> and following the Java package name guidelines, e.g.
> com.mydomain.mylib, is recommended.
I notice that the user namespace is still one segment "user". Will
this remain a one-segment namespace or be changed to two segments at
some point?
> > Just lift your files up a directory to accommodate this change. Note
> > that this implies that all namespaces should have at least 2 segments,
> > and following the Java package name guidelines, e.g.
> > com.mydomain.mylib, is recommended.
> I notice that the user namespace is still one segment "user". Will
> this remain a one-segment namespace or be changed to two segments at
> some point?