Setup multiple projects in IDEA IntelliJ as separate modules
If you've read through the basic IDEA IntelliJ cookbook, then you already know how to import a Scala CLI
project using BSP
. However, in some cases importing a single project just does not fit the bill.
Here's a walk-through for a slightly more advanced scenario.
Let's say we keep the sources for 2 separate Scala apps in one repository. Each has its own subdirectory, to keep things clean. Additionally, you have another one for scripts alongside them.
It looks somewhat similar to this:
tree -a
.
├── app1
│ ├── src
│ │ └── HelloWorld1.scala
│ └── test
│ └── MyTests1.test.scala
├── app2
│ ├── src
│ │ └── HelloWorld2.scala
│ └── test
│ └── MyTests2.test.scala
└── scripts
├── AnotherScript.sc
└── SomeScript.sc
7 directories, 6 files
@main def hello: Unit = println("hello1")
//> using dep org.scalameta::munit:1.0.0-M7
class MyTests1 extends munit.FunSuite {
test("my test 1") {
assert(2 + 2 == 4)
}
}
@main def hello: Unit = println("hello2")
//> using dep com.lihaoyi::utest::0.8.1
import utest.*
object MessagesTests extends TestSuite {
val tests = Tests {
test("my test 2") {
assert(2 + 2 == 4)
}
}
}
println("some script")
println("another script")
When running these apps, you'd like to run them separately. app1
and app2
may have conflicting dependencies, or it
may just not feel hygienic to share their classpath long term.
However, you keep those in one repository because of business relevance (or whatever other reasons why they are tied together), and so, you'd like to see them all at once in your IDE, with all the syntax coloring, completions and debugging your code straight from the IDE, the whole shebang.
It's tempting to just run:
scala-cli setup-ide .
Unfortunately, in this case that won't really do the trick. Even if you run and package the apps & scripts from the
terminal separately, when importing everything together to your IDE like this, the single BSP
project will make them
share their classpath. This in turn means that things will break.
The only way to solve this is for each to have its own BSP
configuration, really.
And so:
scala-cli setup-ide app1
scala-cli setup-ide app2
scala-cli setup-ide scripts
As a result, a separate .bsp
directory was created in app1
, app2
and scripts
, respectively.
tree -a
.
├── app1
│ ├── .bsp
│ │ └── scala-cli.json
│ ├── .scala-build
│ │ ├── ide-inputs.json
│ │ └── ide-options-v2.json
│ ├── src
│ │ └── HelloWorld1.scala
│ └── test
│ └── MyTests1.test.scala
├── app2
│ ├── .bsp
│ │ └── scala-cli.json
│ ├── .scala-build
│ │ ├── ide-inputs.json
│ │ └── ide-options-v2.json
│ ├── src
│ │ └── HelloWorld2.scala
│ └── test
│ └── MyTests2.test.scala
└── scripts
├── .bsp
│ └── scala-cli.json
├── .scala-build
│ ├── ide-inputs.json
│ └── ide-options-v2.json
├── AnotherScript.sc
└── SomeScript.sc
13 directories, 15 files
After opening the root directory in IntelliJ
(File
-> Open...
), the 3 BSP
setups should be successfully
detected.
However, since there are 3 different setups, IntelliJ
doesn't know what to import. And so, we have to set it up
ourselves.
Right-click on your project root directory in Intellij
and go into Module Settings
.
Then, under Project Structure
-> Modules
press the +
button and then Import Module
.
Navigate to each of the subdirectories from there and add them as a BSP
module (BSP
should be an available choice,
if the setup-ide
was run correctly).
You have to import each of the subdirectories separately (app1
, app2
and scripts
, in the example).
The end result should look like this:
Now each of the subdirectories uses its own BSP
connection, which in turn means a separate classpath. And all of that
in a single IntelliJ
project!
Upon closer inspection, you may notice that IntelliJ
stores this as separate sub-project configurations. Each
subdirectory gets its own .idea
folder with the relevant settings.
tree -a
.
├── .idea
│ ├── .gitignore
│ ├── bsp.xml
│ ├── codeStyles
│ │ ├── Project.xml
│ │ └── codeStyleConfig.xml
│ ├── intellij-multi-bsp.iml
│ ├── misc.xml
│ ├── modules.xml
│ ├── sbt.xml
│ ├── vcs.xml
│ └── workspace.xml
├── app1
│ ├── .bsp
│ │ └── scala-cli.json
│ ├── .idea
│ │ └── modules
│ │ └── app1-root.iml
│ ├── .scala-build
│ │ ├── ide-inputs.json
│ │ └── ide-options-v2.json
│ ├── src
│ │ └── HelloWorld1.scala
│ └── test
│ └── MyTests1.test.scala
├── app2
│ ├── .bsp
│ │ └── scala-cli.json
│ ├── .idea
│ │ └── modules
│ │ └── app2-root.iml
│ ├── .scala-build
│ │ ├── ide-inputs.json
│ │ └── ide-options-v2.json
│ ├── src
│ │ └── HelloWorld2.scala
│ └── test
│ └── MyTests2.test.scala
└── scripts
├── .bsp
│ └── scala-cli.json
├── .idea
│ └── modules
│ └── scripts-root.iml
├── .scala-build
│ ├── ide-inputs.json
│ └── ide-options-v2.json
├── AnotherScript.sc
└── SomeScript.sc
21 directories, 28 files