Въведение в Gradle

Тази статия е част от поредица: • Въведение в Gradle (текуща статия) • Ant срещу Maven срещу Gradle

• Писане на потребителски приставки Gradle

• Създаване на дебел буркан в Gradle

1. Общ преглед

Gradle е Groovy-базирана система за управление на изграждането, създадена специално за изграждане на Java-базирани проекти.

Инструкции за инсталиране можете да намерите тук.

2. Строителни блокове - проекти и задачи

В Gradle Сградите се състоят от един или повече проекти и всеки проект се състои от една или повече задачи.

Проект в Gradle може да бъде сглобяване на буркан , война или дори zip файл.

Задачата е отделна работа. Това може да включва компилиране на класове или създаване и публикуване на Java / уеб архиви.

Една проста задача може да бъде определена като:

task hello { doLast { println 'Baeldung' } }

Ако изпълним горната задача, използвайки командата gradle -q hello от същото място, където се намира build.gradle , трябва да видим изхода в конзолата.

2.1. Задачи

Сценариите за изграждане на Gradle не са нищо друго освен Groovy:

task toLower { doLast { String someString = 'HELLO FROM BAELDUNG' println "Original: "+ someString println "Lower case: " + someString.toLowerCase() } }

Можем да дефинираме задачи, които зависят от други задачи. Зависимостта на задачата може да бъде дефинирана чрез предаване на аргумента dependOn: taskName в дефиниция на задача:

task helloGradle { doLast { println 'Hello Gradle!' } } task fromBaeldung(dependsOn: helloGradle) { doLast { println "I'm from Baeldung" } }

2.2. Добавяне на поведение към задача

Можем да определим задача и да я подобрим с допълнително поведение:

task helloBaeldung { doLast { println 'I will be executed second' } } helloBaeldung.doFirst { println 'I will be executed first' } helloBaeldung.doLast { println 'I will be executed third' } helloBaeldung { doLast { println 'I will be executed fourth' } }

doFirst и doLast добавят действия съответно отгоре и отдолу на списъка с действия и могат да бъдат дефинирани няколко пъти в една задача .

2.3. Добавяне на свойства на задачата

Можем също да дефинираме свойства:

task ourTask { ext.theProperty = "theValue" } 

Тук задаваме “theValue” като свойство на задачата ourTask .

3. Управление на приставки

В Gradle има два типа приставки - скрипт и двоични.

За да се възползвате от допълнителна функционалност, всеки плъгин трябва да премине през две фази: разрешаване и прилагане.

Разрешаването означава да се намери правилната версия на приставката и да се добави към пътя на класа на проекта.

Прилагането на приставки е изпълнение на Plugin.apply (T) върху проекта .

3.1. Прилагане на приставки за скриптове

В aplugin.gradle можем да дефинираме задача:

task fromPlugin { doLast { println "I'm from plugin" } }

Ако искаме да приложим този плъгин към нашия файл build.gradle на проекта , всичко, което трябва да направим, е да добавим този ред към нашия build.gradle :

apply from: 'aplugin.gradle' 

Сега изпълнението на командата gradle задачи трябва да покаже задачата fromPlugin в списъка със задачи.

3.2. Прилагане на двоични приставки с помощта на приставки DSL

В случай на добавяне на основна двоична приставка, можем да добавим кратки имена или идентификатор на приставка:

plugins { id 'application' }

Сега тече задача от приложение плъгин трябва да бъде на разположение в един проект, за да изпълнят всяка изпълнима буркан. За да приложим приставка за общност, трябва да споменем напълно квалифициран идентификатор на приставка:

plugins { id "org.shipkit.bintray" version "0.9.116" }

Сега задачите на Shipkit трябва да са достъпни в списъка със задачи gradle .

Ограниченията на приставките DSL са:

  • Той не поддържа Groovy код в блока на приставките
  • блокът plugins трябва да бъде оператор от най-високо ниво в скриптовете за изграждане на проекта ( преди него е разрешен само блокът buildscripts {} )
  • Приставки DSL не може да се пише в плъгин за скриптове, файл settings.gradle или в init скриптове

Приставките DSL все още се инкубира. DSL и другата конфигурация може да се променят в по-новите версии на Gradle.

3.3. Наследена процедура за прилагане на приставки

Също така можем да приложим плъгини, като използваме “apply plugin” :

apply plugin: 'war'

Ако трябва да добавим приставка за общност, трябва да добавим външния буркан към пътя на класа на изграждане, като използвам блока buildscript {} .

Then, we can apply the plugin in the build scripts butonly after any existing plugins{} block:

buildscript { repositories { maven { url "//plugins.gradle.org/m2/" } } dependencies { classpath "org.shipkit:shipkit:0.9.117" } } apply plugin: "org.shipkit.bintray-release"

4. Dependency Management

Gradle supports very flexible dependency management system, it's compatible with the wide variety of available approaches.

Best practices for dependency management in Gradle are versioning, dynamic versioning, resolving version conflicts and managing transitive dependencies.

4.1. Dependency Configuration

Dependencies are grouped into different configurations. A configuration has a name and they can extend each other.

If we apply the Java plugin, we'll have compile, testCompile, runtime configurations available for grouping our dependencies. The default configuration extends “runtime”.

4.2. Declaring Dependencies

Let's look at an example of adding some dependencies (Spring and Hibernate) using several different ways:

dependencies { compile group: 'org.springframework', name: 'spring-core', version: '4.3.5.RELEASE' compile 'org.springframework:spring-core:4.3.5.RELEASE', 'org.springframework:spring-aop:4.3.5.RELEASE' compile( [group: 'org.springframework', name: 'spring-core', version: '4.3.5.RELEASE'], [group: 'org.springframework', name: 'spring-aop', version: '4.3.5.RELEASE'] ) testCompile('org.hibernate:hibernate-core:5.2.12.Final') { transitive = true } runtime(group: 'org.hibernate', name: 'hibernate-core', version: '5.2.12.Final') { transitive = false } }

We're declaring dependencies in various configurations: compile, testCompile, and runtime in various formats.

Sometimes we need dependencies that have multiple artifacts. In such cases, we can add an artifact-only notations @extensionName (or ext in the expanded form) to download the desired artifact:

runtime "org.codehaus.groovy:groovy-all:[email protected]" runtime group: 'org.codehaus.groovy', name: 'groovy-all', version: '2.4.11', ext: 'jar'

Here, we added the @jar notation to download only the jar artifact without the dependencies.

To add dependencies to any local files, we can use something like this:

compile files('libs/joda-time-2.2.jar', 'libs/junit-4.12.jar') compile fileTree(dir: 'libs', include: '*.jar')

When we want to avoid transitive dependencies,we can do it on configuration level or on dependency level:

configurations { testCompile.exclude module: 'junit' } testCompile("org.springframework.batch:spring-batch-test:3.0.7.RELEASE"){ exclude module: 'junit' }

5. Multi-Project Builds

5.1. Build Lifecycle

In the initialization phase, Gradle determines which projects are going to take part in a multi-project build.

This is usually mentioned in settings.gradle file, which is located in the project root. Gradle also creates instances of the participating projects.

In the configuration phase, all created projects instances are configured based on Gradle feature configuration on demand.

In this feature, only required projects are configured for a specific task execution. This way, configuration time is highly reduced for a large multi-project build. This feature is still incubating.

Finally, in the execution phase, a subset of tasks, created and configured are executed. We can include code in the settings.gradle and build.gradle files to perceive these three phases.

In settings.gradle :

println 'At initialization phase.'

In build.gradle :

println 'At configuration phase.' task configured { println 'Also at the configuration phase.' } task execFirstTest { doLast { println 'During the execution phase.' } } task execSecondTest { doFirst { println 'At first during the execution phase.' } doLast { println 'At last during the execution phase.' } println 'At configuration phase.' }

5.2. Creating Multi-Project Build

We can execute the gradle init command in the root folder to create a skeleton for both settings.gradle and build.gradle file.

All common configuration will be kept in the root build script:

allprojects { repositories { mavenCentral() } } subprojects { version = '1.0' }

The setting file needs to include root project name and subproject name:

rootProject.name = 'multi-project-builds' include 'greeting-library','greeter'

Now we need to have a couple of subproject folders named greeting-library and greeter to have a demo of a multi-project build. Each subproject needs to have an individual build script to configure their individual dependencies and other necessary configurations.

If we'd like to have our greeter project dependent on the greeting-library, we need to include the dependency in the build script of greeter:

dependencies { compile project(':greeting-library') }

6. Using Gradle Wrapper

If a Gradle project has gradlew file for Linux and gradlew.bat file for Windows, we don't need to install Gradle to build the project.

If we execute gradlew build in Windows and ./gradlew build in Linux, a Gradle distribution specified in gradlew file will be downloaded automatically.

If we'd like to add the Gradle wrapper to our project:

gradle wrapper --gradle-version 4.2.1

The command needs to be executed from the root of the project. This will create all necessary files and folders to tie Gradle wrapper to the project. The other way to do the same is to add the wrapper task to the build script:

task wrapper(type: Wrapper) { gradleVersion = '4.2.1' }

Сега трябва да изпълним задачата на обвивката и тя ще обвърже нашия проект с обвивката. Освен файловете gradlew , в папката gradle се генерира папка с обвивка, съдържаща буркан и файл със свойства.

Ако искаме да се премине към нова версия на Gradle, ние само трябва да се промени за влизане в gradle- wrapper.properties .

7. Заключение

В тази статия разгледахме Gradle и видяхме, че той има по-голяма гъвкавост в сравнение с други съществуващи инструменти за изграждане по отношение на разрешаване на конфликти на версии и управление на преходни зависимости.

Изходният код за тази статия е достъпен в GitHub.

Следваща » Ant срещу Maven срещу Gradle