SBT多模块项目中模块与源码目录的映射方法咨询
如何实现scala/scala项目中SBT模块与源码路径的映射
问题背景
我正在尝试查找SBT构建项目中各模块对应的源码路径,以GitHub上的scala/scala项目为例,执行依赖树命令后得到一级模块列表,同时项目的src和test目录结构也已明确,但无法直接将模块与目录一一对应,需要实现模块到源码路径的映射(例如org.scala-lang:scala-reflect对应/path/src/reflect/,org.scala-lang:scalacheck对应/path/test/scalacheck/)。之前在Apache Pekko项目中使用的工件名拼接逻辑不适用于此项目,特此咨询可行方案。
现有信息
执行SBT依赖树命令得到的一级模块列表
[info] org.scala-lang:root_2.13:2.13.11-bin-SNAPSHOT [S] [info] org.scala-lang:scala-reflect:2.13.11-bin-SNAPSHOT [S] [info] org.scala-lang:scala-compiler:2.13.11-bin-SNAPSHOT [S] [info] org.scala-lang:scalap:2.13.11-bin-SNAPSHOT [info] org.scala-lang:scala-compiler-doc:2.13.11-bin-SNAPSHOT [info] org.scala-lang:scala-compiler-interactive:2.13.11-bin-SNAPSHOT [info] org.scala-lang:scala-tastytest:2.13.11-bin-SNAPSHOT [S] [info] org.scala-lang:scala-testkit:2.13.11-bin-SNAPSHOT [info] org.scala-lang:repl:2.13.11-bin-SNAPSHOT [info] org.scala-lang:scala-dist:2.13.11-bin-SNAPSHOT [S] [info] org.scala-lang:tasty:2.13.11-bin-SNAPSHOT [info] org.scala-lang:scalacheck:2.13.11-bin-SNAPSHOT [S] [info] org.scala-lang:scala-repl-frontend:2.13.11-bin-SNAPSHOT [info] org.scala-lang:junit:2.13.11-bin-SNAPSHOT [info] org.scala-lang:scala-partest:2.13.11-bin-SNAPSHOT [S]
项目src和test目录结构
├── src │ ├── compiler │ ├── intellij │ ├── interactive │ ├── library │ ├── library-aux │ ├── manual │ ├── partest │ ├── partest-javaagent │ ├── reflect │ ├── repl │ ├── repl-frontend │ ├── scaladoc │ ├── scalap │ ├── tastytest │ └── testkit ├── test │ ├── async │ ├── benchmarks │ ├── files │ ├── instrumented │ ├── jcstress │ ├── junit │ ├── macro-annot │ ├── osgi │ ├── scalacheck │ ├── scaladoc │ ├── script-tests │ └── tasty
原有方案(不适用于scala/scala项目)
之前在Apache Pekko项目中使用的代码逻辑:
String gavid = line.substring(startIndex, line.lastIndexOf(":")); System.out.println("GAV id: " + gavid); String[] parts1 = gavid.split(":"); String[] parts2 = parts1[1].split("_"); int hyphenIndex = parts2[0].indexOf('-'); String directory = parts2[0].substring(hyphenIndex + 1); new_module.setSrcCodePath(object.getSrcCodePath() + directory + '/');
可行的映射方案
针对scala/scala项目的模块命名规则和目录结构,可采用以下逻辑实现映射:
1. 提取模块核心名称
从GAV字符串中提取工件名(即:分隔的第二部分,去掉后缀的_2.13这类Scala版本标识):
- 对于
org.scala-lang:scala-reflect:2.13.11-bin-SNAPSHOT,提取scala-reflect - 对于
org.scala-lang:repl:2.13.11-bin-SNAPSHOT,提取repl
2. 定义名称转换规则
scala/scala项目的模块名和目录名存在固定的简化对应关系,可通过**移除前缀scala-(如果存在)**来匹配目录:
| 模块工件名 | 转换后目录名 |
|---|---|
| scala-reflect | reflect |
| scala-compiler | compiler |
| scala-tastytest | tastytest |
| scala-testkit | testkit |
| scala-compiler-interactive | interactive |
| scala-repl-frontend | repl-frontend |
| scala-partest | partest |
| scalap | scalap |
| repl | repl |
| tasty | tasty |
| scalacheck | scalacheck |
| junit | junit |
3. 区分src/test目录
- 大部分核心模块(如reflect、compiler、repl等)对应的源码在
src/目录下 - 测试相关模块(如scalacheck、junit、tasty测试部分)对应的源码在
test/目录下 - 可通过预先定义的列表判断归属:
- 归属
test/的模块:scalacheck、junit、tasty - 其余核心模块归属
src/
- 归属
4. 特殊模块单独处理
root_2.13:聚合根模块,无单独源码目录,可跳过或标记为特殊模块scala-dist:分发聚合模块,无对应源码目录,需特殊处理scala-compiler-doc:对应src/scaladoc目录,需单独映射
5. 示例代码实现(Java)
import java.util.Arrays; import java.util.List; public class ModulePathMapper { public static void main(String[] args) { // 示例模块行 String line = "[info] org.scala-lang:scala-reflect:2.13.11-bin-SNAPSHOT [S]"; mapModuleToPath(line); } public static void mapModuleToPath(String moduleLine) { // 提取GAV核心部分 String gavPart = moduleLine.replace("[info] ", "").split(" ")[0]; String[] gavParts = gavPart.split(":"); String artifactName = gavParts[1]; // 移除Scala版本后缀(如_2.13) if (artifactName.contains("_")) { artifactName = artifactName.split("_")[0]; } // 转换为目录名 String dirName; if (artifactName.startsWith("scala-")) { dirName = artifactName.substring(6); // 跳过"scala-"前缀(6个字符) } else { dirName = artifactName; } // 特殊模块映射 if ("scala-compiler-doc".equals(artifactName)) { dirName = "scaladoc"; } // 确定基础路径(src/test) String basePath; List<String> testModules = Arrays.asList("scalacheck", "junit", "tasty"); if (testModules.contains(dirName)) { basePath = "/path/test/"; } else { basePath = "/path/src/"; } // 生成最终路径 String finalPath = basePath + dirName + "/"; System.out.println(gavPart + " -> " + finalPath); } }
内容的提问来源于stack exchange,提问作者Sri Shylesh
相关产品推荐
相关产品推荐

