You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何禁用SBT项目中依赖模块的重新编译?

Optimizing SBT Compilation: Avoid Recompiling Core When Only ModuleA Changes

Hey there! I get it—waiting for the core module to recompile every time you tweak ModuleA is a total time drain. Let's fix this so SBT only rebuilds core when its actual code changes, not just because you're starting ModuleA's container.

Why This Happens

By default, SBT treats dependencies as transitive and triggers a full dependency check whenever you run a task like container:start on ModuleA. Even if core's code hasn't changed, SBT might still recompile it if it can't confirm the cached state is valid.

1. Enable Cached Resolution (Easiest & Most Reliable)

SBT has built-in cached resolution that keeps track of when dependencies (like core) were last compiled. Turning this on tells SBT to skip recompiling core unless its source files have actually changed.

Add this setting to your root project or global build settings:

val root: Project = Project(id = "...", settings = Seq(
  updateOptions := updateOptions.value.withCachedResolution(true),
  // Your other root settings here
)).aggregate(moduleA)

How to verify:

  • First, run core/compile to build core once.
  • Modify a file in ModuleA and run moduleA/container:start—core won't recompile.
  • Modify a file in core, then run moduleA/container:start—core will recompile as expected.

2. Export Core's Jar & Adjust Dependency Strategy

If you want more control over how ModuleA uses core, you can configure core to export its compiled jar, then have ModuleA depend on that jar instead of the raw source dependency. This ensures core only rebuilds when its code changes.

Update your project definitions like this:

val core: Project = project.settings(
  exportJars := true, // Tells SBT to package core's classes into a jar
  // Your other core settings here
)

val moduleA: Project = project.settings(
  // Add core's jar as a library dependency
  libraryDependencies += core % "compile" artifacts(Artifact(core.id, "jar", "jar")),
  // Keep test dependencies linked to core's sources for testing
  libraryDependencies += core % "test" artifacts(Artifact(core.id, "jar", "test-jar"))
).dependsOn(core % "test->test") // Only link test sources for ModuleA's tests

This way, ModuleA uses core's pre-compiled jar for main code, so SBT won't recompile core unless the jar is outdated (i.e., core's code changed).

3. Manual Control (For Temporary Workflows)

If you want full manual control (not recommended for long-term use), you can disconnect ModuleA's compile task from core's, and instead add core's compiled class files directly to ModuleA's classpath.

val core: Project = project.settings(/* Your core settings */)

val moduleA: Project = project.settings(
  // Add core's compiled classes to ModuleA's classpath
  unmanagedClasspath in Compile += (classDirectory in core in Compile).value,
  unmanagedClasspath in Test += (classDirectory in core in Test).value,
  // Stop ModuleA's compile from triggering core's compile
  compile in Compile := (compile in Compile).dependsOn().evaluated
).aggregate(core) // Aggregate core so you can still compile it manually

Note: With this approach, you'll need to manually run core/compile whenever you change core's code—SBT won't do it automatically.

Final Tips

  • Always run clean if you start seeing unexpected behavior (it resets cached states).
  • For large projects, combining cached resolution with exportJars gives the best balance of automation and speed.

内容的提问来源于stack exchange,提问作者John Mullins

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:01:49