Боитесь ли вы Gradle так как боюсь его я?

    Скажу сразу — в Gradle я совсем новичок.
    Пол рабочего дня, вместо того, чтоб писать код содержащий мою семью, я потратил на то, чтобы узнать что из 150-ти строк конфига, надо было исправить одну, поменяв classpath 'com.jakewharton.sdkmanager:gradle-plugin:+ на com.jakewharton.sdkmanager:gradle-plugin:0.10.1.
    Программа вчера запускалась а сегодня перестала. А знаете что я сегодня сделал не так? А ничего. Абсолютно тот же код и те же конфиги. Ни одного файла не менял.
    Смышленый или опытный программист уже догадался что знак "+" — значит что надо загрузить самую последнюю версию библиотеки и загрузилось что то не то. Да это часть проблемы, но не вся. Сама библиотека ничего не портила. Она просто имела зависимость от другой — которая портила.
    Да и вообще, что за мода выкладывать не оттестированные библиотеки в общий репозиторий? При Мавене такого не было!

    А если интересно, опишу как это выглядело.
    Перестало из IDE запускаться приложение на Андроид. Чтоб понять что виновато не IDE, а Graddle, который собирает приложение ушло время. Кстати компилировалось то все отлично. До самого конца. Но не запускалось.
    Поискал ошибку, в интернете нашол что у плагина android.tools.build в последней версии баг. Надо только вернуть старую, 11-ю и все заработает. Я смотрю в конфиги и вижу что 11я уже стоит. В общем я долго извращался, пока не понял что не смотря на то что прописана 11-я, используется все равно последняя.
    В Gradle не нашел как посмотреть зависимости плагинов (а в Мавене такая возможность есть). Но путем коментирования строчек и перезапускания билда снова и снова я нашол плагин, который в новой версии использует новую версию злосчастного android.tools.build.

    Почему это вообще произошло?
    Произшла эта ситуация изза моей неопытности. Когда я начинал проект, не будучи знатоком Gradle'а, я просто скопировал конфиг выложенный на гит хабе. Да. Я знаю что копи-паст — зло, но надо же новичку с чего-то начинать. Признаю что вина лежит полностью на мне, но как бы было приятно, если бы новые пользователи были как-то защищены от таких проблем.

    Чтобы быть не просто плаксой, а эрудированным плаксой, постараюсь сделать свои предложения в пустоту:
    Ну если в конфиге прямо указана версия плагина, то можно как-то информировать пользователя что использоваться будет другая.
    Да, хорошо бы было ввести команду, показывающую дерево зависимости плагинов.
    Не надо выкладывать плохо оттестированные плагины в общий доступ.
    Возможность ставить "+" надо запретить. По крайней мере на самом верхнем уровне. То есть «10.+» еще можно, но просто "+" — АТАТА!

    Вот такое увлекательное приключение на 5 часов в мире Gradle было у меня сегодня.
    В общем, новички Gradle, не наступайте на мои грабли, а старожилы — ругайте меня во всю, за мою некомпетентность.

    Similar posts

    Ads
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More

    Comments 27

      +8
      Dear diary,…
        +7
        Если вы хотели выплеснуть эмоции, то у вас получилось.
        А если хотели предостеречь других от своих ошибок, на каком-то примере, то не очень.
        Люди с опытом, понимают о чем вы и без этой кучи слов.
        А те, кто с Gradle не знаком, из этой мешанины слов все равно не поймут о чем вы.
        Хоть бы пример конфигов привели что ли… как было и как надо.
          0
          Да конфиг приводить особого смысла не имеет. Из 150ти строк конфига надо было поменять classpath 'com.jakewharton.sdkmanager:gradle-plugin:+' на classpath 'com.jakewharton.sdkmanager:gradle-plugin:0.10.1'
            0
            Вот эту строку и надо было в статью внести.
              0
              Поправил, следуя вашему совету.
              0
              150 строк конфига? Да вышутите наверное? Что вы туда засунули то?
                +2
                // Top-level build file where you can add configuration options common to all sub-projects/modules.
                
                buildscript {
                    repositories {
                        mavenCentral()
                        // gradle versions
                        maven { url "https://github.com/ben-manes/gradle-versions-plugin/raw/mvnrepo" }
                        // crashlytics
                        maven { url 'http://download.crashlytics.com/maven' }
                        maven { url 'https://www.testfairy.com/maven' }
                    }
                
                    dependencies {
                        // android plugin
                        classpath 'com.android.tools.build:gradle:0.11.+'
                        // configuration for codegen dependencies (dagger-compiler)
                        classpath 'com.neenbedankt.gradle.plugins:android-apt:+'
                        // use Java 8 lambdas on android
                        classpath 'me.tatarka:gradle-retrolambda:1.3.3'
                        // gradle robolectric plugin
                //        classpath 'org.robolectric:robolectric-gradle-plugin:0.11+'
                        // downloading deps for CI
                        classpath 'com.jakewharton.sdkmanager:gradle-plugin:0.10.1'
                        // versions plugin
                        classpath 'com.github.ben-manes:gradle-versions-plugin:0.5-beta-5'
                        // crashlytics
                        classpath 'com.crashlytics.tools.gradle:crashlytics-gradle:1.+'
                
                        classpath 'com.testfairy.plugins.gradle:testfairy:1.+'
                    }
                }
                
                allprojects {
                    repositories {
                        mavenCentral()
                    }
                }
                
                task wrapper(type: Wrapper) {
                    gradleVersion = '1.11'
                }
                configurations {
                    all*.exclude group: 'com.android.support', module: 'support-</code>v4'
                }
                
                
                
                apply plugin: 'android-sdk-manager'
                apply plugin: 'android'
                apply plugin: 'retrolambda'
                apply plugin: 'crashlytics'
                apply plugin: 'android-apt'
                //apply plugin: 'robolectric'
                apply plugin: 'testfairy'
                apply plugin: 'versions'
                
                android {
                    final APPLICATION_ID = "mercurievv.driftingjury.androidapp"
                
                    compileSdkVersion 19
                    buildToolsVersion '19.1'
                
                    defaultConfig {
                        minSdkVersion 14
                        targetSdkVersion 19
                
                //        applicationId APPLICATION_ID
                        versionCode 1
                        versionName '0.1.0'
                
                        testInstrumentationRunner "com.google.android.apps.common.testing.testrunner.GoogleInstrumentationTestRunner"
                    }
                
                    productFlavors {
                        staging {
                            buildConfigField "String", "API_URL", "\"https://example-staging.com\""
                //            applicationId "${APPLICATION_ID}.staging"
                        }
                
                        production {
                            buildConfigField "String", "API_URL", "\"https://example.com\""
                        }
                    }
                
                    compileOptions {
                        sourceCompatibility JavaVersion.VERSION_1_8
                        targetCompatibility JavaVersion.VERSION_1_8
                    }
                
                    final IS_TRAVIS = "true".equals(System.getenv("TRAVIS"))
                    final PRE_DEX_ENABLED = "true".equals(System.getProperty("pre-dex", "true"))
                
                    dexOptions {
                        preDexLibraries = PRE_DEX_ENABLED && !IS_TRAVIS
                    }
                
                    packagingOptions {
                        exclude 'LICENSE.txt'
                        exclude 'META-INF/LICENSE'
                        exclude 'META-INF/NOTICE'
                        exclude 'META-INF/services/javax.annotation.processing.Processor'
                    }
                
                    lintOptions {
                        enable 'IconExpectedSize', 'EasterEgg', 'SelectableText', 'StopShip', 'TypographyQuotes', 'UnusedIds'
                        disable 'InvalidPackage'
                        warningsAsErrors true
                        lintConfig file("$projectDir/lint.xml")
                        abortOnError false
                
                    }
                
                    sourceSets {
                        main {
                            androidTest.setRoot('src/test')
                        }
                    }
                    testfairyConfig {
                      apiKey "0_o"
                    }
                
                }
                
                retrolambda {
                    jdk System.getenv("JAVA8_HOME")
                    oldJdk System.getenv("JAVA7_HOME")
                    javaVersion JavaVersion.VERSION_1_7
                }
                
                repositories {
                    // crashlytics
                    maven { url 'http://download.crashlytics.com/maven' }
                }
                
                final DAGGER_VERSION = '1.2.1'
                //final ESPERANDRO_VERSION = '2.0.0'
                
                dependencies {
                    androidTestCompile 'junit:junit:4.11'
                    compile fileTree(dir: 'libs', include: ['*.jar'])
                    compile 'com.android.support:appcompat-v7:19.+'
                    compile 'org.roboguice:roboguice:2.0'
                    compile 'com.google.code.gson:gson:2.2.4'
                    compile 'com.j256.ormlite:ormlite-android:4.42'
                    compile 'javax.persistence:persistence-api:1.0.2'
                
                    retrolambdaConfig 'net.orfjackal.retrolambda:retrolambda:1.3.0'
                    compile 'com.crashlytics.android:crashlytics:1.+'
                
                    compile "com.mixpanel.android:mixpanel-android:4.2.1@aar"
                
                    compile 'com.netflix.rxjava:rxjava-android:0.19.0' // FRP
                
                    compile 'com.jakewharton:butterknife:5.1.0' // view injection
                    compile 'com.jakewharton.timber:timber:2.4.0' // logging
                
                    compile 'com.squareup.retrofit:retrofit:1.6.0'
                    compile 'com.intellij:annotations:12.0' // @Nullable NotNull
                
                
                //???    compile 'com.github.mttkay.memento:memento:0.2' // retaining objects in activity
                    androidTestCompile 'org.mockito:mockito-core:1.9.5'
                    androidTestCompile 'org.robolectric:robolectric:2.3'
                    androidTestCompile 'com.squareup:fest-android:1.0.8'
                
                /*
                
                    androidTestCompile('com.jakewharton.espresso:espresso:1.1-r3') {
                        // TODO workaround for http://b.android.com/65445
                        exclude group:'com.google.guava', module:'guava'
                    }
                    androidTestCompile('com.jakewharton.espresso:espresso-support-v4:1.1-r3') {
                        // TODO workaround for http://b.android.com/65445
                        exclude group:'com.android.support', module:'support-v4'
                        exclude group:'com.google.guava', module:'guava'
                    }
                */
                }
                configurations {
                    all*.exclude group: 'com.android.support', module: 'support-v4'
                    all*.exclude group: 'org.apache.maven', module: 'maven-ant-tasks'
                    all*.exclude group: 'org.hamcrest', module: 'hamcrest-core'
                }
                
                  0
                  Ух я смотрю у вас тут полный фарш, если вы это все осилили, почему тогда про + столько вопросов то?
                  У вас даже уже gradle-versions-plugin стоит, и все равно куча библиотек с + в версиях, почему?
                    0
                    Я писал что я взял готовый конфиг. И да, не стоит доверять всему что написано, но вчера же он работал.
                      0
                      Что то не пойму, то есть вы и половины не используете из того что там написано?

                      В общем, что вам нужно:
                      1. указать конкретные версии для всех зависимостей (без +). Что бы избежать эти проблемы в будущем.
                      2. у вас уже стоит плагин gradle-versions-plugin. Поэтому что бы проверить на наличие новых версий, нужно запустить: gradlew dependencyUpdates
                      3. Обновить конкретные версии плагинов
                        0
                        Ну я бы не сказал что половину не использую. 1/4. Но планирую.
                        1. Да теперь это понятно. Просто наверняка не я один такой. Вот и хочется либо таких же как я предупредить либо чтоб это как-то побезопасней было реализовано.
                        2. Спасибо. Я так понял что это команда обнавления всех зависимостей проекта. В данном случае она бы проблему не решила т.к. баг был как раз в последней версии зависимости.

                        Ну в общем да. Наука — не ставить плюсы. Но я доверился :)
                          0
                          gradlew dependencyUpdates — вроверяет и показывает какие зависимости могут быть обновлены, эта команда больше ничего не делает. Дальше вам руками нужно обновить. То есть вы бы уже точно знали какие библиотеки были обновлены.

                          Например:
                          The following dependencies have later milestone versions:
                          — com.android.support:support-annotations [19.1.0 -> 21.0.0-rc1]
                          — com.android.support:support-v4 [19.1.0 -> 21.0.0-rc1]
                          — com.fasterxml.jackson.core:jackson-annotations [2.3.3 -> 2.4.1]
                          — com.fasterxml.jackson.core:jackson-core [2.3.3 -> 2.4.1.1]

                            0
                            Спасибо. Полезно.
              0
              Я с грейдлом не работал, но по аналогии с мавеном — вполне осилил…

              PS чтобы два раза не вставать 2 MercurieVV вы таки нихреново хитрите — в мавене dependency:tree — плагин, который был принят в основной инструментарий сборщика и только. Ни о какой «встроенной команде» речи не идёт — так почему же вы в этом обвиняете грейдл (и искали ли вы соответствующий плагин?)?
                0
                Да я не скажу что я прям не осиливаю Градл, но шишку сегодня набил здоровенную. В мавене даже вначале такого не было, но там и версии зависимостей все всегда прописывают. Вроде можно их размазано ставить, но я ни разу такого не встречал и у самого мысли не возникало так написать.

                Что насчет зависимостей. плагинов. По чесноку, я этим в мавене ни разу не пользовался т.к. небыло необходимости. Но, столкнувшись с проблемой я поискал и нашел maven.apache.org/plugins/maven-dependency-plugin/resolve-plugins-mojo.html
                Для Градла же я искал и не нашел. Так же предполагал что простой gradle dependecies поможет, но запуская его в корневой проекта мне не вывело вообще ни одной зависимости, запуская в модуле выдало только обычные зависимости (не плагины).

                Еще мне очень нравится связка Idea с мавен. Шустро работает, подсказки где надо. Ну, надеюсь, со временем и с Градлом все устаканится.
                  0
                  В мавене при сборке dependencyManagment имеет более высокий приоритет, чем зависимости… зависимостей (мда… ну и фраза), думаю и в gradle есть что-то похожее. А вот если нет прямой отсылки к версии зависимости и в dM не прописано — тогда какая-нибудь зависимость может протащить другую версию… И кстати — не всегда рабочую (в рамках проекта, разумеется)…

                  Idea + maven? Мне не очень… — чуть поменяешь чуть-чуть (например версию) тут же начинается побочный процесс анализа и загрузки и идеей пользоваться уже невозможно.
              –2
              > Пол рабочего дня, вместо того, чтоб писать код содержащий мою семью, я потратил на то, чтоб узнать что в одном месте вместо '+' надо поставить '0.10.1'.
              Вот мне интересно, если разработка так важна для вас, что вы делали последние полтора года тогда?
                0
                Как что? Кодировал.
                  +3
                  минусующим, грэдл и новая сборка появилась не вчера, а уже достаточно давно. Потратив 10-20 минут в неделю на чтение и тесты помогли бы избежать проблем выше.
                  Так же копипаста 150+ строк конфига, в котором половина не понятно всегда плохая идея.
                  А теперь люди перескакивающие с эклипса просто в ужасе, сколько им теперь нужно учить и разбираться, а ведь можно было бы это все избежать, времени было и есть достаточно.
                  0
                  А что значит «перестало запускаться»? Какая-то ошибка была, или молча?
                    0
                    Ошибка была. Но я не сразу понял что дело действительно в Gradle т.к. собиралось все нормально. Не проходил именно запуск приложения на девайс.
                    UnsupportedMethodException
                    Unsupported method: AndroidArtifact.getOutputFile().
                      0
                      У меня сейчас используется 0.12+ и пока что проблем нет.

                      Пробовали:
                      1. пересобирать проект?
                      2. пересобрать из командной строки или запуском соотвествующего таска из Android Studio?
                      3. перезапустить демон: gradlew --stop?
                        0
                        1 и 2 пробовал. На это и потратил столько времени. Я еще пробовал менять 11ю и 12ю версию Градла, Пробовал стирать весь кэш зависимостей.
                        Вот тут этот баг описывается: code.google.com/p/android/issues/detail?id=72374 Видать он возникает в каких-то специфических случаях.
                        О «gradlew --stop» не знал, но я убивал в таск менеджере все java процессы и пару раз рестартил комп.
                    –1
                    Может есть смысл вначале прочитать основы?

                    Chapter 8. Dependency Management Basics
                    www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html

                    Первый же пример:

                    dependencies {
                        compile group: 'org.hibernate', name: 'hibernate-core', version: '3.6.7.Final'
                        testCompile group: 'junit', name: 'junit', version: '4.+'
                    }
                    

                    The build script also states that any junit >= 4.0 is required to compile the project's tests.
                      –1
                      Я понимал что значит '4.+'. Дело в том, что увидев что такой конфиг выложен в публичный доступ, я и подумать не мог что с этим может быть что-то плохое. Раз человек выкладывал, а другие качали — он знал что делал.
                      Но как я в кратце описал проблема была не только в этом.
                      –2
                      Сам себе злой буратино.

                      Я так понимаю, вы используете AndroidStudio. У нее не было еще ни одного стабильного релиза. Она в бету-то вышла месяц назад. Вполне ожидаемо, что при ее обновлениях или обновлениях android-gradle плагина, могут возникнуть проблемы и несовместимости. Хотите стабильности — используйте эклипс и ант. Хотите быть на острие — смиритесь с нестабильностью не-релизных версий.
                        0
                        А у меня javafx плугин обновился и иконки пропали.
                        Хотите стабильности — управляйте версиями вручную. А репозитории в основном maven`овские, между делом.
                        Градл мне нравится, но уж очень медленный.

                        Only users with full accounts can post comments. Log in, please.