Как я могу добавить зависимости проекта Gradle без изменения settings.gradle

Задний план

(Пожалуйста, имейте в виду, что я упростил задачу для целей обсуждения здесь)

  • У меня есть набор приложений и зависимых библиотек, примерно так (каждый с каталогом src/ и build.gradle):

    appa/
    appb/
    libx/
    liby/
    libz/
    
  • В build.gradle зависимости в настоящее время объявлены следующим образом:

    appa/build.gradle:
       compile "com.asdf:libx:1.0"
       compile "com.asdf:liby:1.0"
    appb/build.gradle:
       compile "com.asdf:liby:1.0"
    liby/build.gradle:
       compile "com.asdf:libz:1.0"
    

Какую проблему я пытаюсь решить

  • Say I'm working on appa, and I need to make changes to libx. I need to do multiple steps:
    1. Pull libx from source control and make changes locally
    2. Восстановите и отправьте изменения в какое-то репо (не в прод!)
    3. Rebuild appa (вытаскивание недавно обновленного libx из репо)
  • Если мое тестирование обнаружит ошибку в libx, мне придется повторить это снова.
  • Это очень раздражает при работе в IDE, таких как Eclipse, где, хотя мои проекты логически используют другие проекты, мне все равно приходится использовать артефакты как зависимости.
  • Разве не было бы замечательно, если бы я мог просто вытащить проект локально, и проекты, которые логически зависят от него, будут автоматически использовать исходный проект вместо артефакта для сборки?

Что я сделал до сих пор

  • Я написал небольшой плагин gradle (на который есть ссылка в build.gradle каждого проекта), который определяет com.asdf зависимости и использует подстановка зависимости для замены зависимости артефакта зависимостью проекта, если этот проект существует локально.

    configurations.all {
        resolutionStrategy.dependencySubstitution {
            all { DependencySubstitution dependency ->
                if (dependency.requested instanceof ModuleComponentSelector && dependency.requested.group == 'com.asdf') {
                    def targetProject = findProject(":${dependency.requested.module}")
                    if (targetProject != null) {
                        dependency.useTarget targetProject
                    }
                }
            }
        }
    }
    
  • Ура! С некоторыми изменениями в settings.gradle (см. Ниже) я достиг своей цели ... За исключением ...

Где я застрял

  • Мне нужно изменить settings.gradle, чтобы включить такие строки для каждой зависимости (иначе findProject не разрешит зависимый проект во время сборки):

    include ':libx'
    project(':libx').projectDir = new File(settingsDir, '../libx')
    
  • Хотя возможно просмотреть все settings.gradle файлы и сделать это (я сделал это несколько раз в качестве доказательства концепции), это некрасиво, однообразно и логически является той же информацией, что и передается compile аргументам build.gradle зависимостей.

    • It's also error-prone when someone adds a new dependency but doesn't update settings.gradle, or introduces a typo between them.
  • Я также пробовал сделать settings.gradle просто определять проекты для всех каталогов, которые он находит на этом уровне, но затем сборка любого проекта превращается в мега-сборку всех проектов.
  • (Я пробовал несколько других вещей, но мой вопрос уже давно звучит)

Мой вопрос

Как лучше сделать это, не дублируя информацию между settings.gradle и build.gradle? Я хочу сделать так, чтобы добавление новых зависимостей было таким же простым, как добавление ссылки compile в build.gradle, не касаясь _28 _...

Я все еще новичок в groovy / gradle, так что, может быть, мне не хватает чего-то, что очевидно для более опытного мастера gradle?


person Krease    schedule 04.05.2018    source источник
comment
Похоже, вы ищете составные сборки   -  person mkobit    schedule 05.05.2018
comment
@mkobit - это определенно выглядит многообещающе. После выходных мы рассмотрим подробнее и посмотрим, как это работает.   -  person Krease    schedule 05.05.2018


Ответы (1)


Я считаю, что ваш вариант использования является мотивацией для составных сборок.

У меня есть демонстрация здесь, которая записывает в папку jars как фиктивную публикацию артефактов. Обязательно загляните на README.md, поскольку демонстрация представляет собой мини-лабораторию для опробования сценария использования до и после составных сборок.

В демо mainBuild это appa; utils равно libx. Ключевой синтаксис в mainBuild/settings.gradle (здесь):

includeBuild '../utils'

Это говорит Gradle использовать локальную кодовую базу вместо опубликованного артефакта. Конечно, нельзя передавать эту строку в систему управления версиями.

person Michael Easter    schedule 04.05.2018
comment
Определенно полезно, но, похоже, существуют некоторые ограничения для составных сборок - в зависимости от документа они могут идти только на один уровень (не могут зависеть от другой составной сборки), и по-прежнему требуется дублирование информации в settings.gradle (хотя это выглядит как поменьше гадости, все равно нужно). Определенно область, которую стоит изучить дальше, спасибо :) - person Krease; 07.05.2018