Project

General

Profile

Actions

Gradle-based build system.

История

Предыдущая версия системы сборки использовала Ant для управления сборкой и Ivy для управления зависимостями.
Система сборки представляла собой библиотечный Ant файл, который подключался к проекту и предоставлял
базовую функциональность по сборке Java проектов и управлению выпуском релизов.
Gradle реализует и расширяет эту функциональность, поэтому принято решение использовать этот инструмент для сборки проектов.

Ресурсы

http://gradle.org

Подключение Gradle к проекту

1. Установить gradle, определить переменную окружения GRADLE_HOME.

2. В каталоге проекта выполнить команду создания конфигурационных файлов для Java проекта:

> gradle init --type java-library

Другие доступные типы проектов: https://docs.gradle.org/current/userguide/build_init_plugin.html

Также будет создана обертка-запускач gradlew/gradlew.bat, которая избавляет от необходимости вручную
устанавливать gradle для сборки проекта - разработчику достаточно просто выкачать рабочую копию проекта из репозитория,
gradle будет установлен автоматически.

Имя проекта будет записано в settings.gradle. Gradle предполагает, что имя проекта совпадает с именем каталога проекта.
Если это не так, необходимо исправить имя проекта в файле settings.gradle.

Дополнительная информация:
https://docs.gradle.org/current/userguide/gradle_wrapper.html
https://docs.gradle.org/current/userguide/wrapper_plugin.html

3. Привести структуру папок в соответствие с соглашениями gradle:

src/main/java - код проекта
src/main/resources - ресурсы проекта
src/test/java - код тестов

Дополнительная информация:
https://docs.gradle.org/current/userguide/java_plugin.html#N12323

4. Указать зависимости проекта в build.gradle:

compile - зависимость, необходимая для сборки проекта
testCompile - зависимость, необходимая для сборки тестов
группа:имя:версия - формат зависимости

dependencies {
    // The production code uses the SLF4J logging API at compile time
    compile 'org.slf4j:slf4j-api:1.7.12'

    // Declare the dependency for your favourite test framework you want to use in your tests.
    // TestNG is also supported by the Gradle Test task. Just change the
    // testCompile dependency to testCompile 'org.testng:testng:6.8.1' and add
    // 'test.useTestNG()' to your build script.
    testCompile 'junit:junit:4.12'
}

Дополнительная информация: https://docs.gradle.org/current/userguide/java_plugin.html#sec:java_plugin_and_dependency_management

5. Указать репозитории, в которых ищутся зависимости

build.gradle:

repositories {
    // репозиторий ИСП РАН, подключается, если есть зависимости от наших проектов
    ivy {
      url = 'http://forge.ispras.ru/repo'
      layout 'pattern', {
        artifact '[organization]/[ext]s/[artifact]-[revision](.[ext])'
      }
    }
    // Use 'jcenter' for resolving your dependencies.
    // You can declare any Maven/Ivy/file repository here.
    jcenter()
}


Дополнительная информация: https://docs.gradle.org/current/userguide/dependency_management.html#sec:repositories

6. Настроить опции компиляции Java

build.gradle:

sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8

compileJava {
  options.encoding = "UTF-8" 
}

Команда компилцяии Java файлов:

> gradlew compileJava

Компиляция и прогон тестов:

> gradlew test

Дополнительная информация: https://docs.gradle.org/current/userguide/java_plugin.html#N1245A

7. Подключить плагин для сборки дистрибутива

Для приложений (дистрибутив содержит библиотеки и скрипты для запуска):

build.gradle:

apply plugin: 'application'
...
mainClassName = "org.gradle.sample.Main" 

Для библиотек (application plugin подключает это автоматически):
build.gradle:

apply plugin: 'distribution'

Команда сборки дистрибутива

> gradlew distZip

или
> gradlew distTar

оба сразу:
assembleDist

Дополнительная информация:
https://docs.gradle.org/current/userguide/distribution_plugin.html
https://docs.gradle.org/current/userguide/application_plugin.html

8. Подключить плагин для выпуска релизов

build.gradle:

// в начало файла
import java.text.SimpleDateFormat
import java.util.regex.Matcher

plugins {
  id 'net.researchgate.release' version '2.3.4'
}

...

// в конец файла
release {
  failOnCommitNeeded = false

  versionPatterns = [
    // Increments build number: "0.2.5-alpha-150428" => "0.2.6-alpha-150428" 
    /(^\d+\.\d+\.)(\d+)(-[^-]*)(-[^-]*$)/: 
    { Matcher m, Project p -> m.replaceAll("${ m[0][1] }${ (m[0][2] as int) + 1 }${ m[0][3] }" ) }
  ]
}

String getCurrentDateString()  {
  new SimpleDateFormat( "yyMMdd" ).format( new Date() )
}

task unSnapshotVersion.doLast {
  def version = project.version.toString()
  version += '-' + getCurrentDateString()
   project.plugins.getPlugin( net.researchgate.release.ReleasePlugin.class )
  .updateVersionProperty( version )
}

Готовящаяся к выпуску версия (вместо текущей даты SNAPSHOT) хранится в файле gradle.properties:

version=0.1.28-alpha-SNAPSHOT

Команда выпуска новой версии:

> gradlew release

Будет предложено подтвердить или изменить номер выпускаемой версии, а затем номер следующей готовящейся версии.

Дополнительная информация: https://github.com/researchgate/gradle-release

Хорошо бы согласовать систему нумерации версий с семантическим версионированием.
Есть плагин, поддерживающий этот подход: https://plugins.gradle.org/plugin/de.gliderpilot.semantic-release

9 Статический анализ кода

build.gradle:

plugins {
  id "org.sonarqube" version "1.0" 
}

sonarqube {
     properties {
        property "sonar.host.url", "http://forge.ispras.ru:9000" 
        property "sonar.jdbc.url", "jdbc:mysql://localhost:3306/sonar" 
        property "sonar.jdbc.driverClassName", "com.mysql.jdbc.Driver" 
        property "sonar.jdbc.username", "sonar" 
        property "sonar.jdbc.password", "sonar" 
    }
}


Дополнительная информация: http://docs.sonarqube.org/display/SONAR/Analyzing+with+SonarQube+Scanner+for+Gradle

apply plugin: 'checkstyle'
apply plugin: 'findbugs'
apply plugin: 'pmd'
apply plugin: "jacoco" 

dependencies {
  checkstyle 'com.puppycrawl.tools:checkstyle:6.12.1'
  pmd 'net.sourceforge.pmd:pmd-core:5.4.0'
  pmd 'net.sourceforge.pmd:pmd-java:5.4.0'
  findbugs 'com.google.code.findbugs:findbugs:3.0.1'
}

checkstyle {
  showViolations = false
  ignoreFailures = true
}

findbugs {
  ignoreFailures = true
}

pmd {
  ignoreFailures = true
  ruleSets = [ "java-android,java-basic,java-braces,java-comments,java-clone,java-codesize,java-controversial," 
             + "java-coupling,java-design,java-empty,java-finalizers,java-imports,java-j2ee," 
             + "java-javabeans,java-junit,java-logging-jakarta-commons,java-logging-java," 
             + "java-migrating,java-migrating_to_13,java-migrating_to_14,java-migrating_to_15," 
             + "java-migrating_to_junit4,java-naming,java-optimizations,java-strictexception," 
             + "java-strings,java-sunsecure,java-typeresolution,java-unnecessary,java-unusedcode"]
}

jacoco {
    toolVersion = "0.7.5.201505241946" 
}

jacocoTestReport {
    reports {
        xml.enabled true
        csv.enabled false
    }
}

Компиляция, прогон тестов и запуск инструментов статического анализа кода:

> gradlew check

10. Копирование зависимостей в подкаталог 'libs'

gradle скачивает зависимости куда-то в свой кэш.
Это неудобно при использовании eclipse.
Мы привыкли, что библиотеки лежат рядом.
Копировать их в подкаталог 'libs' проекта можно так:

build.gradle

//copying all dependencies attached to 'compile' into a specific folder
task copylibs(type: Copy) {
  //referring to the 'compile' configuration
  from configurations.compile, configurations.testCompile
  into 'libs'
}

Запускать при изменении зависимостей:

> gradlew copylibs

В source code repository не класть!

Альтернатива - gradle eclipse plugin
Но .classpath генерируется не переносимый, в source code repository его не положишь.

Updated by Alexey Demakov about 4 years ago · 9 revisions