SBT:遍历项目依赖图

发布于 2024-12-11 12:51:59 字数 815 浏览 0 评论 0原文

我有一个多模块 Web 项目,其依赖关系图与此类似

WAR-project
- A1
-- A2
-- A3
- B1
-- B2
---- B22
-- B3

,即 war 项目依赖于 A1,而后者又依赖于 A2A3等等。

现在,在打包 war 项目之前,我想将一些 Web 资源从其依赖项目复制到 web 应用程序中。所以我的问题是如何以编程方式遍历 SBT 项目的依赖关系图?即在伪代码中

resourcesToCopy = []
visitedProjects = []
traverseProjectDependencies(project) {
  visitedProjects += project
  if(project has resourceFolder) {
    resourcesToCopy += resourceFolder.getPath
  }
  for(projectDependency in project) {
    if(projectDependency is not visited) {
      traverseProjectDependencies(projectDependency)
    }
  }
}

注意 我知道,如果我将资源文件夹添加到每个依赖项的类路径中,那么我可以从 Web 项目中的 fullClasspath 检索它。但我想避免这种解决方案,而且在其他情况下,以编程方式遍历和连接依赖项可能会很有用。

I have a multimodule web project with a dependency graph similar to this

WAR-project
- A1
-- A2
-- A3
- B1
-- B2
---- B22
-- B3

that is the war project depends on A1 which in turn depends on A2 and A3 and so on.

Now prior to the packageing of the war project I want to copy some web resources from its dependent projects into the webapp. So my question is how do I programmatically traverse a SBT project's dependency graph ? i.e. in pseudu code

resourcesToCopy = []
visitedProjects = []
traverseProjectDependencies(project) {
  visitedProjects += project
  if(project has resourceFolder) {
    resourcesToCopy += resourceFolder.getPath
  }
  for(projectDependency in project) {
    if(projectDependency is not visited) {
      traverseProjectDependencies(projectDependency)
    }
  }
}

Note I am aware that if I add the resource folder to the classpath of each of the dependencies then I could retrieve it from the fullClasspath in the web project. But I would like to avoid this solution and also there are other scenarios where programmatically traversing and interfacing with dependencies could be useful.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

凉薄对峙 2024-12-18 12:51:59

以下代码添加了一个aggr-res任务,该任务将聚合依赖项目的所有资源:

val aggrRes= TaskKey[Seq[File]]("aggr-res", "show aggregate resources")

val aggrResTask = aggrRes in Compile <<= {
  (thisProjectRef, buildStructure) flatMap aggrResources(resources in Compile)
}

def aggrResources[T](key: ScopedTask[Seq[T]])(proj: ProjectRef, struct: Load.BuildStructure) = {
  val deps = collectDeps(_.dependencies.map(_.project))(proj, struct)
  deps.flatMap(key in (_, Compile) get struct.data).join.map(_.flatten)
}

def collectDeps(op: ResolvedProject => Seq[ProjectRef])(projRef: ProjectRef, struct: Load.BuildStructure): Seq[ProjectRef] = {
  val deps = Project.getProject(projRef, struct).toSeq.flatMap(op)
  deps.flatMap(ref => ref +: collectDeps(op)(ref, struct)).distinct
}

我已经用一个更完整的示例来说明要点此处

The following code adds a aggr-res task that will aggregate all resources for dependent projects:

val aggrRes= TaskKey[Seq[File]]("aggr-res", "show aggregate resources")

val aggrResTask = aggrRes in Compile <<= {
  (thisProjectRef, buildStructure) flatMap aggrResources(resources in Compile)
}

def aggrResources[T](key: ScopedTask[Seq[T]])(proj: ProjectRef, struct: Load.BuildStructure) = {
  val deps = collectDeps(_.dependencies.map(_.project))(proj, struct)
  deps.flatMap(key in (_, Compile) get struct.data).join.map(_.flatten)
}

def collectDeps(op: ResolvedProject => Seq[ProjectRef])(projRef: ProjectRef, struct: Load.BuildStructure): Seq[ProjectRef] = {
  val deps = Project.getProject(projRef, struct).toSeq.flatMap(op)
  deps.flatMap(ref => ref +: collectDeps(op)(ref, struct)).distinct
}

I have made a gist with a more complete example here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文