davidB / scala-maven-plugin

The scala-maven-plugin (previously maven-scala-plugin) is used for compiling/testing/running/documenting scala code in maven.
https://davidb.github.io/scala-maven-plugin/
The Unlicense
560 stars 151 forks source link

Best way to cross compile #177

Closed jodersky closed 2 years ago

jodersky commented 8 years ago

Hi,

What is the best way to cross-compile a project for various scala versions? I came across the FAQ, mentioning to use a property-dependant artifactId, i.e.

<artifactId>scala-maven-plugin_${scalaVersion}</artifactId>

However maven 3.3 complains that it requires a stable artifact.

[WARNING] 'artifactId' contains an expression but should be a constant

Is there a workaround for cross-compiling?

davidB commented 8 years ago

Hi,

scala-maven-plugin doesn't exist with suffix '_X.Y.Z'. I guess it's a bad example and you ask about dependencies and not plugin.

  1. prefer to use the property "scala.compat.version". that doesn't include patch/bugfix in the version, eg 2.11. And this property is also used by check multi scala version (see checkMultipleScalaVersions
  2. I'm not aware of an other way to "simulate" cross-compile, that using profile + property (scala.version and scala.compat.version) + shell script
jodersky commented 8 years ago

Actually I did mean the artifactId of the the POMs, parent and child.

I know I can use a system property (scala binary version in this case) to append to any dependencies and, with the help of profiles, mimic dependencies on scala libraries.

The issue however is that I want my project to be publishable for multiple Scala versions, thus I need to be able to append a "_${scala.compat.version}" to the artifactId of projects.

Another option I thought of would be to keep the artifactIds without the "_xx" part, but generate and publish jars containing the binary dependency. Is it possible to have different artifactIds and generated artifact names in maven?

thanks for your help

lefou commented 8 years ago

@jodersky If you use the Scala-Extension to Maven, than you write your pom in Scala. This way, it is possible to feed the artifactId from a varible. That way, it is at least possible, to read the target Scala-Version e.g. from the system environment and use it in the artifactId as in the following snippet:

implicit val scalaVersion = System.getenv("SCALA_VERSION") match {
  case null => ScalaVersion("2.11.7")
  case v => ScalaVersion(v)
}
println("Using Scala version: " + scalaVersion.version)

ScalaModel(
  gav = "com.github.domino-osgi" %% "domino" % dominoVersion,
  modelVersion = "4.0.0",
// ...

For an example, have a look at https://github.com/domino-osgi/domino/blob/master/pom.scala

Of course, it is still not possible to build multiple target versions in one go, but at least, you can invoke maven multiple times like so:

SCALA_VERSION=2.10.5 mvn clean package
lefou commented 8 years ago

You need at least Maven 3.3.1 to use the Scala Extension. To enable it, add the following file:

".mvn/extensions.xml"

<extensions xmlns="http://maven.apache.org/EXTENSIONS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/EXTENSIONS/1.0.0 http://maven.apache.org/xsd/core-extensions-1.0.0.xsd">
  <extension>
    <groupId>io.takari.polyglot</groupId>
    <artifactId>polyglot-scala</artifactId>
    <version>0.1.11</version>
  </extension>
</extensions>
davidB commented 8 years ago

@lefou I don't see the gain to use Scala Extension. With profile and/or properties you can do the same. I remember when I build Scala-IDE for scala 2.7 and scala 2.8. I call a script that do something like

mvn clean package -Dscala.version=2.10.5
or 
mvn clean package -Pscala_210
lefou commented 8 years ago

The OP itention was to modify the artifactId of the local project. AFAIK you can not use variables in the project artifactId, at least not in the XML-based pom. That's where the Scala-based pom steps in.

jodersky commented 8 years ago

@davidB, I originally also had profiles or -D settings in mind however maven does not allow properties to be used in the artifactId (hence the warning message generated above)

@lefou Thanks for the tip on scala-extension, I would however rather not have to define my pom in scala (in this case I would just resort to sbt, which, as a side note, I would do anyway but is not under my control).

I asked the same question on StackOverflow and just received a possible answer. I'll let you know if it works and update the issue accordingly

lefou commented 6 years ago

@jodersky Did you found a stable solution which also produces stable pom's when installing/deploying to the repository?

davidB commented 6 years ago

the scalor plugin seems to use modules for cross compile: https://github.com/random-maven/scalor-maven-plugin/tree/master/src/it/test-cross

jodersky commented 6 years ago

@lefou I haven't used maven recently and unfortunately don't have a follow-up.

slandelle commented 5 years ago

IMHO, cross compiling is out of scope here. That's something you should achieve with sbt, not maven.

niebloomj commented 5 years ago

@slandelle why should we have to use sbt if we want to cross compile? I don't see why using maven must been we only have one version to compile against.

lefou commented 5 years ago

Look at my older comments above, if you want a cross-compile solution for Maven (using Polyglot Scala Extension). It is well-tried, I gave an open source project as example. Any other solution saying "don't use Maven" should be out-of-scope for a Maven plugin project. But if you want to try/use another build system, please don't only look at sbt. There are many other tools that can do the cross-compile job. If you have no experience with any other scala build tool yet, I can really recommend mill.

blast-hardcheese commented 4 years ago

Internally, I've been maintaining a patchset to https://www.mojohaus.org/flatten-maven-plugin/ that enables <activation>-Pscala-2.10</activation>, <activation>-Pscala-2.11</activation>, etc in <profile>s to be translated into arguments to activeProfileIds in the flattened POM. This has permitted relatively stable cross-publishing, albeit with the caveat that passing profile activation by JVM property (a la mvn -D-Pscala-2.11) trips up new users, so I don't consider this to be a more broadly useful technique.

The problem comes from the inability to inspect the ruleset used to determine which profiles were intentionally activated when the flatten-maven-plugin was called, as that information has already been interpolated to the runtime and lost (at least, as far as I could find).

This approach, combined with sed, is what we've been using to work around this.

rdesgroppes commented 3 years ago

Internally, I've been maintaining a patchset to https://www.mojohaus.org/flatten-maven-plugin/ that enables <activation>-Pscala-2.10</activation>, <activation>-Pscala-2.11</activation>, etc in <profile>s to be translated into arguments to activeProfileIds in the flattened POM. This has permitted relatively stable cross-publishing, albeit with the caveat that passing profile activation by JVM property (a la mvn -D-Pscala-2.11) trips up new users, so I don't consider this to be a more broadly useful technique.

@blast-hardcheese Is it something you could share?

slandelle commented 2 years ago

Closing as stale.