为什么交叉构建约定将 scala 版本附加到 artifactId? [英] Why does the cross-building convention append the scala version to the artifactId?

查看:17
本文介绍了为什么交叉构建约定将 scala 版本附加到 artifactId?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

<块引用>

用于指示库编译的 Scala 版本的底层机制是附加 _<scala-version>以图书馆的名义.这种相当简单的方法允许与 Maven、Ant 和其他构建工具的用户进行互操作.-- sbt 文档:跨构建发布约定

虽然这是一种简单的方法,但与 Maven 和其他构建工具的互操作性仍有待改进.因为 artifactId 不同(例如 scalatest_2.9.0scalatest_2.10.0),Maven 将它们视为不同的工件.Maven 的依赖解析机制因此受到损害,同一工件的多个版本(针对不同的 scala 版本构建)可能会出现在类路径上.

为什么不把 scala 版本放在分类器中呢?这似乎是分类器的主要预期用例之一:

<块引用>

分类器允许 [Maven] 区分从同一个 POM 构建但内容不同的工件.作为这个元素的动机,例如,考虑一个项目,它提供了一个针对 JRE 1.5 的工件,但同时也提供了一个仍然支持 JRE 1.4 的工件.第一个工件可以配备分类器 jdk15,第二个工件配备 jdk14,以便客户端可以选择使用哪一个.-- Maven 文档:POM 参考

解决方案

将版本附加到名称是很久以前做出的历史决定,因此它可能不会改变,因为许多库已经按照约定发布.

话虽如此,正如 Seth 所指出的,几年前 sbt 0.12 将_2.10.0"后缀缩短为_2.10"以利用 Scala 库的二进制兼容性版本.这是 [0.12] 计划中的标记:

<块引用>

我所说的交叉版本是指在模块 ID 中包含 Scala 版本的某些部分,以区分通过针对不同 Scala 版本编译相同源代码而生成的工件.我并不是说能够使用 +task 针对多个 Scala 版本进行构建,这将保持不变;我只是指跨版本约定.

[剪辑]

以不灵活的 pom.xml 格式对其进行编码一直是一种 hack,我认为对于针对 Scala 2.10 及更高版本构建的项目,最好不要使用它.然而,也许这比任何可能取代它的临时解决方案都要好.我没有看到其他构建工具的用户这样做,所以我希望没有什么可以取代它.

Josh 建议:

<块引用>

(1) Scala 分类器.这些可以是自定义字符串 并且 可以使用依赖项指定.至少,IIRC 这应该可以工作.

这是马克的回复:

<块引用>

可以指定依赖项"是什么意思?所有分类器只有一个 pom,对吧?如何为每个分类器声明不同的依赖关系?

这里有一些来自 Geoff Reedy 的关于分类器的更有趣的评论p><块引用>

我也认为分类器是处理这个问题尤其是鉴于 Maven 文档中的建议分类器 java-1.4java-1.5 用于区分 jars适合各自的平台.致命的缺陷似乎是传递依赖管理.也就是说,没有办法选择基于分类器的传递依赖集模块.当您使用此模块时,我们需要能够说使用 scala-2.10 分类器,它使用scala-2.10 分类器,当与 2.9 分类器一起使用时会引入使用 scala-2.9 分类器的自己的部门.

我认为使用 jvm 版本可以使这项工作成为可能,因为jvm 版本控制在配置文件激活中具有特殊支持,可以可以控制依赖关系.

The underlying mechanism used to indicate which version of Scala a library was compiled against is to append _<scala-version> to the library's name. This fairly simple approach allows interoperability with users of Maven, Ant and other build tools. -- sbt Documentation: Cross-Build Publishing Conventions

While this is a simple approach, the interoperability with Maven and other build tools leaves something to be desired. Because the artifactId is different (e.g. scalatest_2.9.0 and scalatest_2.10.0), Maven treats them as different artifacts. Maven's dependency resolution mechanism is thus compromised and multiple versions of the same artifact (built against different scala versions) can wind up on the classpath.

Why not put the scala version in the classifier? This seems to be one of the primary intended use cases for the classifier:

The classifier allows [Maven] to distinguish artifacts that were built from the same POM but differ in their content. As a motivation for this element, consider for example a project that offers an artifact targeting JRE 1.5 but at the same time also an artifact that still supports JRE 1.4. The first artifact could be equipped with the classifier jdk15 and the second one with jdk14 such that clients can choose which one to use. -- Maven Documentation: POM Reference

解决方案

Appending version to the name is a historical decision that was made long time ago so it'll likely not going to change since many libraries are published with the convention already.

Having said that, as Seth noted, there was a discussion to review this topic a few years ago when sbt 0.12 shortened "_2.10.0" postfix to "_2.10" to take advantage of Scala library's binary compatibility between the minor versions. Here's Mark from [0.12] plan:

By cross versioning, I mean the practice of including some part of the Scala version in the module ID to distinguish an artifact generated by compiling the same source code against different Scala versions. I do not mean the ability to build against multiple Scala versions using +task, which will stay; I am just referring to the cross version convention.

[snip]

It has always been a hack to encode this in the inflexible pom.xml format and I think it may be best to move away from this for projects built against Scala 2.10 and later. However, perhaps this is better than any ad hoc solutions that might take its place. I don't see users of other build tools doing this, so I expect nothing would replace it.

Somewhere down the thread Josh suggested:

(1) Scala classifiers. These can be custom strings and can be specified with dependencies. At least, IIRC this should work.

Here's Mark's response:

What do mean by "can be specified with dependencies"? There is only one pom for all of the classifiers, right? How can you declare different dependencies for each classifier?

Here are some more interesting remark on classifiers from Geoff Reedy

I too thought that classifiers would be the perfect way to deal with this issue especially in light of the suggestion in the maven docs that classifiers java-1.4 and java-1.5 be used to distiguish between jars appropriate for the respective platform. The fatal flaw seems to be transitive dependency management. That is, there's no way to choose the transitive dependency set based on the classifier used to require the module. We'd need to be able to say that when you're using this module with the scala-2.10 classifier it brings its own dependencies using the scala-2.10 classifier and when used with the 2.9 classifier brings in its own deps with the scala-2.9 classifier.

I think with the jvm versions it's possible to make this work because jvm versioning has special support in the profile activation which can can control dependencies.

这篇关于为什么交叉构建约定将 scala 版本附加到 artifactId?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆