Conditionally compile a piece of code according to the version of scala

226 Aufrufe
Direkt zur ersten ungelesenen Nachricht

Kostas kougios

ungelesen,
16.10.2012, 16:49:2716.10.12
an scala...@googlegroups.com
While developing and compiling a library of mine, I need to distribute it to two versions, one compatible with scala 2.9.2 and one with 2.10.0-M7. But for the 2.10 version, the code has to be slightly different. So I could either do 2 branches and go to the painful process of merging all the time. But I was wondering if there is a conditional compilation command of some sort.

Léonard Schneider

ungelesen,
16.10.2012, 18:18:3516.10.12
an scala...@googlegroups.com
I'm afraid you must have a pre-processing phase, as scala language parser will differ according to the version. You can for example use GNU m4 and include it in your build system, such as SBT (you will have to derive your compile task). If you use SBT and your changes between versions are very limited, you can generate code for both version in an SBT plugin. Look at what Miles Sabin has done with shapeless (https://github.com/milessabin/shapeless/tree/master/project). This is very instructive.

BR

Leo

Kostas kougios

ungelesen,
16.10.2012, 18:28:3716.10.12
an scala...@googlegroups.com
Oh, thats a pity, thanks Leonard.

Miles Sabin

ungelesen,
16.10.2012, 19:40:4916.10.12
an Léonard Schneider, scala...@googlegroups.com
On Tue, Oct 16, 2012 at 11:18 PM, Léonard Schneider
<leonard....@gmail.com> wrote:
> If you use SBT and your changes between versions are very
> limited, you can generate code for both version in an SBT plugin. Look at
> what Miles Sabin has done with shapeless
> (https://github.com/milessabin/shapeless/tree/master/project). This is very
> instructive.

Well, maybe, but it teaches a completely different lesson ;-)

The codegen in shapeless is solely for boilerplate elimination. For
dealing with Scala version differences I branch and merge ... with git
this is relatively painless.

Cheers,


Miles

--
Miles Sabin
tel: +44 7813 944 528
skype: milessabin
gtalk: mi...@milessabin.com
g+: http://www.milessabin.com
http://twitter.com/milessabin

Naftoli Gugenheim

ungelesen,
16.10.2012, 22:04:4616.10.12
an Kostas kougios, scala...@googlegroups.com
You can do something like this: https://github.com/nafg/reactive/blob/master/reactive-core/build.sbt#L5

No plugin required. Now put all cross-version code in src/main/scala, and all per-version code in src/main/scala-<version>. You may want to use scalaVersion instead of scalaBinaryVersion. Personally I have a Compat object with definitions that depend on the version, so there's as little code as possible there.
The advantage of this over branching is mainly simpler cross-building.

Konstantinos Kougios

ungelesen,
17.10.2012, 14:46:5317.10.12
an Naftoli Gugenheim, scala...@googlegroups.com
ok,thanks, so I could have the scala-per-version-specific code on a separate class file. Is there a maven version?

Naftoli Gugenheim

ungelesen,
17.10.2012, 19:10:4017.10.12
an Konstantinos Kougios, scala...@googlegroups.com
Probably whatever the syntax is to add a source directory, with $scalaVersion or whatever the variable is called.

Rafał Krzewski

ungelesen,
17.10.2012, 19:12:1117.10.12
an scala...@googlegroups.com, Naftoli Gugenheim, kostas....@googlemail.com
You can pull that off with Maven profiles, but nowhere near this elegant. You'd need like 20 lines of XML per supported scala version.

Konstantinos Kougios

ungelesen,
19.10.2012, 18:48:1119.10.12
an Rafał Krzewski, scala...@googlegroups.com, Naftoli Gugenheim
Thanks everyone, looks rather non-standard then to do that via maven.

Josh Suereth

ungelesen,
20.10.2012, 07:19:0520.10.12
an Konstantinos Kougios, Rafał Krzewski, Naftoli Gugenheim, scala...@googlegroups.com

I'd go with using git and having a branch for each version you support.   Probably will be easier overall w/ maven.

Or you can make your own tool on top of maven that redoes the model before building.

Rafał Krzewski

ungelesen,
20.10.2012, 11:26:0420.10.12
an scala...@googlegroups.com, Rafał Krzewski, Naftoli Gugenheim, kostas....@googlemail.com
If you would like to try Maven with single branch and multiple source dirs, I have prepared an example project for you: https://github.com/rkrzewski/scala-maven-multiversion 

If your project consists of multiple modules that need such source dir wrangling, most of that logic can be factored out to a common parent project. You just need to move <plugins> to <pluginManagement> and <dependencies> to <dependencyManagement> in the parent module and reference them by groupId/artifactId in child modules.

If you decide to go with multiple branches / single source tree approach, you can also reuse most of the example: just merge <properties> from one profile into main <properties> section and drop buildhelper plugin from POM. Then branch the project and edit <properties> section as necessary. As you develop your POM further, try to limit cross-branch differences in the POM to the <properties> section. This will make maintenance easier.

Cheers,
Rafał

Konstantinos Kougios

ungelesen,
20.10.2012, 16:15:1920.10.12
an Rafał Krzewski, scala...@googlegroups.com, Naftoli Gugenheim
Thanks Rafal, will give it a try

Konstantinos Kougios

ungelesen,
02.11.2012, 20:06:0202.11.12
an Rafał Krzewski, scala...@googlegroups.com, Naftoli Gugenheim
Hi again Rafal, ok had a better look at your project and tried to integrate it into mine. But there is an issue, the main jar is named correctly, i.e.

test-0.0.1-2.9.jar

but the src's are not build into the proper jar file:


mvn package source:jar scala:doc-jar -P2.9

....
target/test-0.0.1-sources.jar
(instead of test-0.0.1-2.9-sources.jar)
target/test-0.0.1-javadoc.jar
(instead of test-0.0.1-2.9-javadoc.jar
I need to deploy to sonatype both jar, sources and scala-docs

Do you know if this can be solved?


On 20/10/12 16:26, Rafał Krzewski wrote:

Rafał Krzewski

ungelesen,
04.11.2012, 19:48:4804.11.12
an scala...@googlegroups.com, Rafał Krzewski, Naftoli Gugenheim, kostas....@googlemail.com
Hi Konstantinos,

I haven't thought of that. It's actually a big problem which makes single branch / multiple profiles approach untenable. Why? I am using classifier dimension of Maven coordinates to store scala version of an artifact. Existing maven tools use the classifier differently. They expect that it has a verbatim value "sources" or "javadoc", hence a whole family of artifacts that differ only in classifier share a single "sources" and "javadoc" artifact.

Since classifier cannot be used to store scala version if one wants to keep m2e "download sources" functionality scala version information needs to be put into another Maven coordinate. Version number looks like the obvious one to use, but in fact it is not: Maven has a notion of dependency range versions (a bit like OSGi) and therefore needs to compare version numbers which in turn requires a rigid format convention, see: http://docs.codehaus.org/display/MAVEN/Dependency+Mediation+and+Conflict+Resolution

This leaves us artifactId as the only place where scala version qualifier may be stored. This poses a problem with single branch / multiple profiles project layout because a profile may not override main Maven coordinate elements (/parent/groupId, /parent/artifactId, /parent/version, /groupId, /artifactId, /version) and variables are not expanded in those - or at lease they haven't been the last time I checked :)

Attaching required scala version number to the end of artifactId, separated by an underscore is a convention used by some projects eg ScalaTest, and I think it's the default convention used by SBT.

It looks like you will need to do the branch juggling after all.

Cheers,
Rafał

Kostas Kougios

ungelesen,
05.11.2012, 17:54:2205.11.12
an Rafał Krzewski, scala...@googlegroups.com, Rafał Krzewski, Naftoli Gugenheim
Ok I see, it's a shame. Probably I will resort to some form of scripting to avoid the branches

Thanks again for the info and effort.

Sent from my self

On 5 Nov 2012, at 00:48, Rafał Krzewski <rafal.k...@gmail.com> wrote:

Hi Konstantinos,

I haven't thought of that. It's actually a big problem which makes single branch / multiple profiles approach untenable. Why? I am using classifier dimension of Maven coordinates to store scala version of an artifact. Existing maven tools use the classifier differently. They expect that it has a verbatim value "sources" or "javadoc", hence a whole family of artifacts that differ only in ipticlassifier share a single "sources" and "javadoc" artifact.

Rafał Krzewski

ungelesen,
05.11.2012, 18:55:1805.11.12
an Kostas Kougios, scala...@googlegroups.com
No problem, it was a fun experiment. :)

Cheers,
Rafał
Allen antworten
Antwort an Autor
Weiterleiten
0 neue Nachrichten