Multiple settings gradle files for multiple projects building

前端 未结 6 1812
春和景丽
春和景丽 2020-11-29 21:03

I have the following project structure

-->Starnderd Location
        -->Project1 
           -->settings.gradle 
           -->build.gradle
              


        
6条回答
  •  情话喂你
    2020-11-29 21:38

    I was able to solve this problem in a relatively clean way. Improvements are certainly welcome!

    Although Gradle does not support multiple settings.gradle scripts out of the box, it is possible to create individual sub-projects each with their own settings.gradle file. Let's say you have multi-project A that depends on multi-project B, each with their own sub-projects. Your directory structure might look like:

    A
    - settings.gradle
    - foo
    - faz
    \ B
      - settings.gradle
      - bar
      - bap
    

    Out of the box, Gradle expects A/settings.gradle to look something like this:

    include ':foo', ':faz', 'B:bar', 'B:bap'
    

    The problem with this is that every time B adds a new project, A/settings.gradle must also change even if the new project is only used by B. To avoid this situation, you could try to apply B/settings.gradle in A/settings.gradle instead of adding redundant declarations:

    apply from: 'B/settings.gradle'
    include ':foo', ':faz'
    

    If you try this, you'll find that Gradle fails because it generates the wrong projectDir for :bar and :bap. It mistakenly assumes that B's includes are relative to settingsDir which happens to be A/ when Gradle is invoked from that project root. To fix this you can add another script such as B/settings-parent.gradle (the exact name is not significant):

    apply from: 'settings.gradle'
    
    def updateProjectPaths(Set projects) {
        projects.each { ProjectDescriptor project ->
            String relativeProjectPath = project.projectDir.path.replace(settingsDir.path, "")
            project.projectDir = new File("B/$relativeProjectPath")
            // Recursively update paths for all children
            updateProjectPaths(project.children)
        }
    }
    
    updateProjectPaths(rootProject.children)
    

    This strips settingsDir.path and prefixes the path with B/. This can be extended to multiple layers of settings[-parent].gradle files by having each layer add itself onto the path. Now you will apply this script to A/settings.gradle:

    apply from: 'B/settings-parent.gradle'
    include ':foo', ':faz'
    

    With this scheme, new B projects do not unnecessarily break A/settings.gradle and all projects can be used without explicitly referencing the B sub-project. For example, if ':foo' wanted to use 'B:bap', it may simply declare:

    compile project(':bap')
    

提交回复
热议问题