Gradle multiproject optional subproject's transitive dependency should be resolved to an existing subproject

后端 未结 2 900
名媛妹妹
名媛妹妹 2020-12-18 17:06

suppose the following project. the master project is a multi-project, however every part of the larger project can be developed individually or mixed in:

/ma         


        
2条回答
  •  情歌与酒
    2020-12-18 17:13

    Starting with elastic-deps and with the help of this answer (also from Peter) I came up with the trick below.

    In the top-level build.gradle():

    // make sure we've parsed the subproject dependencies
    evaluationDependsOnChildren()
    
    def subprojectsByName = subprojects.collectEntries { it -> [it.name, it] }
    
    subprojects.each { p ->
      def hacks = [] // list of changes we're going to make
      p.configurations.each { c ->
        c.dependencies.each { d ->
          if (d.group.startsWith("my.group.prefix")) {
            def sub = subprojectsByName[d.name]
            if (sub != null) {
              hacks.add({
                // can't do this immediately or we'll get ConcurrentModificationExceptions
                c.dependencies.remove(d)
                p.dependencies.add(c.name, sub)
              })
            }
          }
        }
      }
      // Now we can safely apply the changes
      for (hack in hacks) {
        hack()
      }
    }
    

    The nice thing about this is that unlike elastic-deps you don't have to modify the subprojects.

    This still has the problem that once you hit a binary dependency, any purely transitive dependencies are resolved as binary. E.g., say I have a project cyan which depends directly on green and blue and transitively, through green, on yellow:

    compile - Compile classpath for source set 'main'.
    +--- my.shared:blue:+ -> 2.0-SNAPSHOT
    +--- my.shared:green:+ -> 2.0-SNAPSHOT
    |    +--- my.shared:yellow:+ -> 2.0-SNAPSHOT
    |    \--- my.shared:blue:+ -> 2.0-SNAPSHOT
    

    Now if I add blue and yellow to my multi-module project, but not green, I get:

    compile - Compile classpath for source set 'main'.
    +--- com.iii.shared:green:+ -> 2.0-SNAPSHOT
    |    +--- com.iii.shared:yellow:+ -> 2.0-SNAPSHOT
    |    \--- com.iii.shared:blue:+ -> project :blue
    \--- project :blue
    

    Note that blue is resolved correctly to the project even when it's transitive, but yellow isn't.

    Personally I think this is a feature, not a bug -- it reflects what would actually happen at distribution time. I can make all the changes to yellow I want, but if I don't put a new yellow artifact in my repository and also an updated green with the updated dependency, then the actual release of cyan isn't going to get those changes.

提交回复
热议问题