Skip to content

Commit 42fe994

Browse files
docs: add cross-building guide for Scala 2/3 setups (#1747)
- Rename file to cross-building.md for URL consistency - Replace 'cross-compilation' with 'cross-building' throughout - Remove speculative/future-looking sections - Add Limitations section explaining no conditional config support - Clarify that scalac/semanticdb flags belong in build tool - Update CLI examples to use defaults from config file - Add sidebar entry under Usage section - Update translations in en.json
1 parent 0dbebb8 commit 42fe994

File tree

3 files changed

+146
-1
lines changed

3 files changed

+146
-1
lines changed

docs/users/cross-building.md

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
---
2+
id: cross-building
3+
title: Cross-building setups
4+
---
5+
6+
Cross-building the same codebase with Scala 2.13 and Scala 3.3+ is common, but
7+
it collides with how Scalafix resolves rules and compiler options. A rule or
8+
build-tool flag that only works on Scala 2 can crash Scalafix when the Scala 3
9+
compilation unit is processed, and vice versa. Split your configuration per
10+
Scala version and let the build tool wire the right file.
11+
12+
## Why separate configs are required today
13+
14+
* Scala 2 only scalac flags such as `-Ywarn-unused-import` or SemanticDB options
15+
using `-P:semanticdb` belong in the build tool. Those settings differ per
16+
target and cannot be inferred by Scalafix.
17+
* Some built-in or community rules rely on compiler symbols present only in a
18+
single Scala major version.
19+
* The CLI currently ingests a single `.scalafix.conf`; there is no per-target
20+
override like sbt’s `CrossVersion`.
21+
22+
## Limitations
23+
24+
Scalafix cannot conditionally toggle rules or scalac options based on the input
25+
Scala version. Provide a separate config file per Scala version and have sbt,
26+
mill, or your CLI invocation choose the right file along with the correct
27+
compiler flags. See [issue #1747](https://github.com/scalacenter/scalafix/issues/1747)
28+
for additional background.
29+
30+
## File layout suggestion
31+
32+
Keep shared defaults in one file and let version-specific files `include` it via
33+
the HOCON `include` syntax. One convenient layout is:
34+
35+
```
36+
.
37+
└── scalafix/
38+
├── common.conf
39+
├── scala2.conf
40+
└── scala3.conf
41+
```
42+
43+
`common.conf`
44+
```scala
45+
rules = [
46+
DisableSyntax,
47+
OrganizeImports
48+
]
49+
50+
DisableSyntax {
51+
noFinalize = true
52+
}
53+
```
54+
55+
`scala2.conf`
56+
```scala
57+
include "common.conf"
58+
59+
rules += RemoveUnused
60+
61+
// Scala 2 only rule settings
62+
RemoveUnused {
63+
imports = true
64+
}
65+
```
66+
67+
`scala3.conf`
68+
```scala
69+
include "common.conf"
70+
71+
rules += LeakingImplicitClassVal
72+
73+
// Scala 3 specific tweaks go here
74+
OrganizeImports {
75+
groupedImports = Keep
76+
}
77+
```
78+
79+
### Multiple include files
80+
81+
You may split out even more granular snippets (for example `linting.conf`,
82+
`rewrites.conf`) and include them from both `scala2.conf` and `scala3.conf`. The
83+
HOCON syntax supports nested includes, so feel free to create the hierarchy that
84+
matches your team conventions.
85+
86+
## Selecting the right config in sbt
87+
88+
Point `scalafixConfig` at the version-specific file, typically inside a helper
89+
setting applied to all cross-built projects:
90+
91+
```scala
92+
import scalafix.sbt.ScalafixPlugin.autoImport._
93+
94+
lazy val commonSettings = Seq(
95+
scalafixConfig := {
96+
val base = (ThisBuild / baseDirectory).value / "scalafix"
97+
val file =
98+
CrossVersion.partialVersion(scalaVersion.value) match {
99+
case Some((3, _)) => base / "scala3.conf"
100+
case _ => base / "scala2.conf"
101+
}
102+
Some(file)
103+
}
104+
)
105+
106+
lazy val core = project
107+
.settings(commonSettings)
108+
.settings(
109+
scalaVersion := "3.3.3",
110+
crossScalaVersions := Seq("2.13.14", "3.3.3")
111+
)
112+
```
113+
114+
For builds that already differentiate per configuration (`Compile`, `Test`,
115+
`IntegrationTest`), you can set `Compile / scalafixConfig` and
116+
`Test / scalafixConfig` separately if the inputs diverge.
117+
118+
## Command-line usage
119+
120+
When invoking the CLI directly, pass the desired config with `--config`:
121+
122+
```
123+
scalafix --config scalafix/scala2.conf
124+
scalafix --config scalafix/scala3.conf
125+
```
126+
127+
Your CI job can loop over each target Scala version, selecting the matching
128+
config before running `scalafix --check`.
129+
130+
## Recommendations
131+
132+
* Keep rules that truly work on both versions inside `common.conf`.
133+
* Manage scalac and SemanticDB flags inside the build tool per target; Scalafix
134+
configs focus solely on rules and rule-specific settings.
135+
* Document in `README.md` or `CONTRIBUTING.md` which rules run on which Scala
136+
version to reduce confusion for new contributors.
137+

website/i18n/en.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@
8282
"users/configuration": {
8383
"title": "Configuration"
8484
},
85+
"users/cross-building": {
86+
"title": "Cross-building setups"
87+
},
8588
"users/installation": {
8689
"title": "Installation"
8790
},

website/sidebars.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
{
22
"users": {
3-
"Usage": ["users/installation", "users/configuration", "users/suppression"],
3+
"Usage": [
4+
"users/installation",
5+
"users/configuration",
6+
"users/cross-building",
7+
"users/suppression"
8+
],
49
"Rules": [
510
"rules/overview",
611
"rules/DisableSyntax",

0 commit comments

Comments
 (0)