Domanda

I am trying to generate some boilerplate with SBT (tool which is totally new to me). I am using shapeless sbt files as my main reference for the task. I have seen that this project uses code generation from scratch, but my case is slightly different, since I would like to generate some classes from another ones. I pretend to use the new Scala 2.10.0-M4 reflection capabilities for doing so. What basic configuration is needed to have reflection available from a SBT build?

By now, the sbt is unable to find the scala.reflect.runtime.universe package, and I do not know if the problem comes either from the new Scala jar division or from a bad configuration. Besides, my sbt about says:

[info] This is sbt 0.13.0-20120530-052139
[info] The current project is {file:/home/jlg/sandbox/abc/}abc
[info] The current project is built against Scala 2.10.0-SNAPSHOT
[info] 
[info] sbt, sbt plugins, and build definitions are using Scala 2.9.2

By the way, does anybody know other projects using SBT to generate source code?

È stato utile?

Soluzione

Current SBT releases are based on Scala 2.9, and source code generation runs together with SBT with the same libraries. There are basically two choices:

  • be extremely bleeding-edge: get an SBT release running on Scala 2.10 (not even the 0.13 branch does), or waiting for it. The biggest problem is not just that you'd have to recompile SBT yourself, it's recompiling every single SBT plugin you'll need for Scala 2.10. In the long-term, this is maybe the best strategy to do what you ask, but it might be a lot of effort for now. However, beware that you cannot use reflection on your compiled code without evil tricks, since code generation is supposed to happen before compilation. If you need to do that, consider instead generating code at compile-time within the program using macros. This excludes SBT and is much more standard, but I'm not sure if you can generate complete classes in this release (this is I think planned for the future).
  • go with the old: stick with Scala 2.9 and use scalap's capabilities (ScalaSigParser) for compile-time reflection. The problem is that the API is different (not sure how deeply) and not really supported for public use, although various people have been using it for ages. For a project I'm running, a colleague implemented approach and I integrated it within SBT for my project (https://github.com/ps-mr/LinqOnSteroids/); on top of that, I use Scalate to write the templates to use for code generation, which is quite powerful. See in particular build.sbt, which invokes project/Generator.scala and project/src/main/scala/ivm/generation/ScalaSigHelpers.scala (some non-fully-generic wrappers for ScalaSigParser). Scalate Templates for generated code are in src/main/resources, the most relevant here is src/main/resources/WrappedClassInlined.ssp. Even more stuff is involved, I fear you'll pratically need a checkout and playing with it to see what it does exactly—but feel free to ask questions.

Please note that the code is protected by a BSD license, so you need to keep the original copyright if you copy the code.

Note: all the links (except the license) are to the current HEAD for stability, so that they won't disappear so easily even if the files are moved/removed in future versions.

Altri suggerimenti

If you're using 2.10.0-SNAPSHOT, then you should go for scala.reflect.runtime.universe. Take a look at http://dcsobral.blogspot.ch/2012/07/json-serialization-with-reflection-in.html for more information.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top