Gradle » History » Version 9
Alexey Demakov, 11/30/2015 04:24 PM
1 | 1 | Alexey Demakov | h1. Gradle-based build system. |
---|---|---|---|
2 | |||
3 | h2. История |
||
4 | |||
5 | Предыдущая версия системы сборки использовала Ant для управления сборкой и Ivy для управления зависимостями. |
||
6 | Система сборки представляла собой библиотечный Ant файл, который подключался к проекту и предоставлял |
||
7 | базовую функциональность по сборке Java проектов и управлению выпуском релизов. |
||
8 | Gradle реализует и расширяет эту функциональность, поэтому принято решение использовать этот инструмент для сборки проектов. |
||
9 | |||
10 | h2. Ресурсы |
||
11 | |||
12 | http://gradle.org |
||
13 | |||
14 | h2. Подключение Gradle к проекту |
||
15 | |||
16 | h3. 1. Установить gradle, определить переменную окружения GRADLE_HOME. |
||
17 | |||
18 | h3. 2. В каталоге проекта выполнить команду создания конфигурационных файлов для Java проекта: |
||
19 | |||
20 | @> gradle init --type java-library@ |
||
21 | |||
22 | Другие доступные типы проектов: https://docs.gradle.org/current/userguide/build_init_plugin.html |
||
23 | |||
24 | Также будет создана обертка-запускач gradlew/gradlew.bat, которая избавляет от необходимости вручную |
||
25 | устанавливать gradle для сборки проекта - разработчику достаточно просто выкачать рабочую копию проекта из репозитория, |
||
26 | gradle будет установлен автоматически. |
||
27 | |||
28 | 3 | Alexey Demakov | Имя проекта будет записано в settings.gradle. Gradle предполагает, что имя проекта совпадает с именем каталога проекта. |
29 | Если это не так, необходимо исправить имя проекта в файле settings.gradle. |
||
30 | |||
31 | 1 | Alexey Demakov | Дополнительная информация: |
32 | https://docs.gradle.org/current/userguide/gradle_wrapper.html |
||
33 | https://docs.gradle.org/current/userguide/wrapper_plugin.html |
||
34 | |||
35 | h3. 3. Привести структуру папок в соответствие с соглашениями gradle: |
||
36 | |||
37 | src/main/java - код проекта |
||
38 | src/main/resources - ресурсы проекта |
||
39 | src/test/java - код тестов |
||
40 | |||
41 | Дополнительная информация: |
||
42 | https://docs.gradle.org/current/userguide/java_plugin.html#N12323 |
||
43 | |||
44 | h3. 4. Указать зависимости проекта в build.gradle: |
||
45 | |||
46 | compile - зависимость, необходимая для сборки проекта |
||
47 | testCompile - зависимость, необходимая для сборки тестов |
||
48 | группа:имя:версия - формат зависимости |
||
49 | |||
50 | 2 | Alexey Demakov | <pre> |
51 | 1 | Alexey Demakov | dependencies { |
52 | // The production code uses the SLF4J logging API at compile time |
||
53 | compile ''org.slf4j:slf4j-api:1.7.12'' |
||
54 | |||
55 | // Declare the dependency for your favourite test framework you want to use in your tests. |
||
56 | // TestNG is also supported by the Gradle Test task. Just change the |
||
57 | // testCompile dependency to testCompile ''org.testng:testng:6.8.1'' and add |
||
58 | // ''test.useTestNG()'' to your build script. |
||
59 | testCompile ''junit:junit:4.12'' |
||
60 | } |
||
61 | 2 | Alexey Demakov | </pre> |
62 | 1 | Alexey Demakov | |
63 | Дополнительная информация: https://docs.gradle.org/current/userguide/java_plugin.html#sec:java_plugin_and_dependency_management |
||
64 | |||
65 | 3 | Alexey Demakov | h3. 5. Указать репозитории, в которых ищутся зависимости |
66 | 1 | Alexey Demakov | |
67 | 3 | Alexey Demakov | build.gradle: |
68 | 2 | Alexey Demakov | <pre> |
69 | 1 | Alexey Demakov | repositories { |
70 | // репозиторий ИСП РАН, подключается, если есть зависимости от наших проектов |
||
71 | ivy { |
||
72 | url = ''http://forge.ispras.ru/repo'' |
||
73 | layout ''pattern'', { |
||
74 | artifact ''[organization]/[ext]s/[artifact]-[revision](.[ext])'' |
||
75 | } |
||
76 | } |
||
77 | // Use ''jcenter'' for resolving your dependencies. |
||
78 | // You can declare any Maven/Ivy/file repository here. |
||
79 | jcenter() |
||
80 | } |
||
81 | |||
82 | 2 | Alexey Demakov | </pre> |
83 | 1 | Alexey Demakov | Дополнительная информация: https://docs.gradle.org/current/userguide/dependency_management.html#sec:repositories |
84 | 3 | Alexey Demakov | |
85 | h3. 6. Настроить опции компиляции Java |
||
86 | |||
87 | build.gradle: |
||
88 | <pre> |
||
89 | sourceCompatibility = JavaVersion.VERSION_1_8 |
||
90 | targetCompatibility = JavaVersion.VERSION_1_8 |
||
91 | |||
92 | compileJava { |
||
93 | options.encoding = "UTF-8" |
||
94 | } |
||
95 | </pre> |
||
96 | |||
97 | Команда компилцяии Java файлов: |
||
98 | <pre> |
||
99 | > gradlew compileJava |
||
100 | </pre> |
||
101 | |||
102 | Компиляция и прогон тестов: |
||
103 | <pre> |
||
104 | > gradlew test |
||
105 | </pre> |
||
106 | |||
107 | Дополнительная информация: https://docs.gradle.org/current/userguide/java_plugin.html#N1245A |
||
108 | |||
109 | h3. 7. Подключить плагин для сборки дистрибутива |
||
110 | |||
111 | Для приложений (дистрибутив содержит библиотеки и скрипты для запуска): |
||
112 | |||
113 | build.gradle: |
||
114 | <pre> |
||
115 | apply plugin: ''application'' |
||
116 | ... |
||
117 | mainClassName = "org.gradle.sample.Main" |
||
118 | </pre> |
||
119 | |||
120 | Для библиотек (application plugin подключает это автоматически): |
||
121 | build.gradle: |
||
122 | <pre> |
||
123 | apply plugin: ''distribution'' |
||
124 | </pre> |
||
125 | |||
126 | Команда сборки дистрибутива |
||
127 | <pre> |
||
128 | > gradlew distZip |
||
129 | </pre> |
||
130 | или |
||
131 | <pre> |
||
132 | > gradlew distTar |
||
133 | </pre> |
||
134 | оба сразу: |
||
135 | <pre> |
||
136 | assembleDist |
||
137 | </pre> |
||
138 | |||
139 | Дополнительная информация: |
||
140 | https://docs.gradle.org/current/userguide/distribution_plugin.html |
||
141 | https://docs.gradle.org/current/userguide/application_plugin.html |
||
142 | |||
143 | |||
144 | h3. 8. Подключить плагин для выпуска релизов |
||
145 | |||
146 | build.gradle: |
||
147 | <pre> |
||
148 | // в начало файла |
||
149 | import java.text.SimpleDateFormat |
||
150 | import java.util.regex.Matcher |
||
151 | |||
152 | plugins { |
||
153 | id ''net.researchgate.release'' version ''2.3.4'' |
||
154 | } |
||
155 | |||
156 | ... |
||
157 | |||
158 | // в конец файла |
||
159 | release { |
||
160 | failOnCommitNeeded = false |
||
161 | |||
162 | versionPatterns = [ |
||
163 | // Increments build number: "0.2.5-alpha-150428" => "0.2.6-alpha-150428" |
||
164 | /(^\d+\.\d+\.)(\d+)(-[^-]*)(-[^-]*$)/: |
||
165 | { Matcher m, Project p -> m.replaceAll("${ m[0][1] }${ (m[0][2] as int) + 1 }${ m[0][3] }" ) } |
||
166 | ] |
||
167 | } |
||
168 | 1 | Alexey Demakov | |
169 | 9 | Alexey Demakov | String getCurrentDateString() { |
170 | new SimpleDateFormat( "yyMMdd" ).format( new Date() ) |
||
171 | 1 | Alexey Demakov | } |
172 | |||
173 | 9 | Alexey Demakov | task unSnapshotVersion.doLast { |
174 | def version = project.version.toString() |
||
175 | version += ''-'' + getCurrentDateString() |
||
176 | project.plugins.getPlugin( net.researchgate.release.ReleasePlugin.class ) |
||
177 | .updateVersionProperty( version ) |
||
178 | } |
||
179 | 3 | Alexey Demakov | </pre> |
180 | |||
181 | Готовящаяся к выпуску версия (вместо текущей даты SNAPSHOT) хранится в файле gradle.properties: |
||
182 | <pre> |
||
183 | version=0.1.28-alpha-SNAPSHOT |
||
184 | </pre> |
||
185 | |||
186 | Команда выпуска новой версии: |
||
187 | <pre> |
||
188 | > gradlew release |
||
189 | </pre> |
||
190 | |||
191 | Будет предложено подтвердить или изменить номер выпускаемой версии, а затем номер следующей готовящейся версии. |
||
192 | |||
193 | Дополнительная информация: https://github.com/researchgate/gradle-release |
||
194 | |||
195 | Хорошо бы согласовать систему нумерации версий с "семантическим версионированием":http://semver.org/lang/ru/. |
||
196 | Есть плагин, поддерживающий этот подход: https://plugins.gradle.org/plugin/de.gliderpilot.semantic-release |
||
197 | |||
198 | 6 | Alexey Demakov | h3. 9 Статический анализ кода |
199 | |||
200 | |||
201 | build.gradle: |
||
202 | <pre> |
||
203 | plugins { |
||
204 | id "org.sonarqube" version "1.0" |
||
205 | } |
||
206 | |||
207 | sonarqube { |
||
208 | properties { |
||
209 | property "sonar.host.url", "http://forge.ispras.ru:9000" |
||
210 | property "sonar.jdbc.url", "jdbc:mysql://localhost:3306/sonar" |
||
211 | property "sonar.jdbc.driverClassName", "com.mysql.jdbc.Driver" |
||
212 | property "sonar.jdbc.username", "sonar" |
||
213 | property "sonar.jdbc.password", "sonar" |
||
214 | } |
||
215 | } |
||
216 | |||
217 | </pre> |
||
218 | Дополнительная информация: http://docs.sonarqube.org/display/SONAR/Analyzing+with+SonarQube+Scanner+for+Gradle |
||
219 | 4 | Alexey Demakov | |
220 | 7 | Alexey Demakov | <pre> |
221 | apply plugin: ''checkstyle'' |
||
222 | apply plugin: ''findbugs'' |
||
223 | apply plugin: ''pmd'' |
||
224 | apply plugin: "jacoco" |
||
225 | |||
226 | dependencies { |
||
227 | checkstyle ''com.puppycrawl.tools:checkstyle:6.12.1'' |
||
228 | pmd ''net.sourceforge.pmd:pmd-core:5.4.0'' |
||
229 | pmd ''net.sourceforge.pmd:pmd-java:5.4.0'' |
||
230 | findbugs ''com.google.code.findbugs:findbugs:3.0.1'' |
||
231 | } |
||
232 | |||
233 | checkstyle { |
||
234 | showViolations = false |
||
235 | ignoreFailures = true |
||
236 | } |
||
237 | |||
238 | findbugs { |
||
239 | ignoreFailures = true |
||
240 | } |
||
241 | |||
242 | pmd { |
||
243 | ignoreFailures = true |
||
244 | 8 | Alexey Demakov | ruleSets = [ "java-android,java-basic,java-braces,java-comments,java-clone,java-codesize,java-controversial," |
245 | + "java-coupling,java-design,java-empty,java-finalizers,java-imports,java-j2ee," |
||
246 | + "java-javabeans,java-junit,java-logging-jakarta-commons,java-logging-java," |
||
247 | + "java-migrating,java-migrating_to_13,java-migrating_to_14,java-migrating_to_15," |
||
248 | + "java-migrating_to_junit4,java-naming,java-optimizations,java-strictexception," |
||
249 | + "java-strings,java-sunsecure,java-typeresolution,java-unnecessary,java-unusedcode"] |
||
250 | 7 | Alexey Demakov | } |
251 | |||
252 | jacoco { |
||
253 | toolVersion = "0.7.5.201505241946" |
||
254 | } |
||
255 | |||
256 | jacocoTestReport { |
||
257 | reports { |
||
258 | xml.enabled true |
||
259 | csv.enabled false |
||
260 | } |
||
261 | } |
||
262 | </pre> |
||
263 | |||
264 | 3 | Alexey Demakov | Компиляция, прогон тестов и запуск инструментов статического анализа кода: |
265 | <pre> |
||
266 | > gradlew check</pre> |
||
267 | 4 | Alexey Demakov | |
268 | h3. 10. Копирование зависимостей в подкаталог ''libs'' |
||
269 | |||
270 | gradle скачивает зависимости куда-то в свой кэш. |
||
271 | Это неудобно при использовании eclipse. |
||
272 | Мы привыкли, что библиотеки лежат рядом. |
||
273 | Копировать их в подкаталог ''libs'' проекта можно так: |
||
274 | |||
275 | build.gradle |
||
276 | <pre> |
||
277 | //copying all dependencies attached to ''compile'' into a specific folder |
||
278 | task copylibs(type: Copy) { |
||
279 | //referring to the ''compile'' configuration |
||
280 | from configurations.compile, configurations.testCompile |
||
281 | into ''libs'' |
||
282 | } |
||
283 | </pre> |
||
284 | |||
285 | Запускать при изменении зависимостей: |
||
286 | <pre> |
||
287 | > gradlew copylibs |
||
288 | </pre> |
||
289 | |||
290 | В source code repository не класть! |
||
291 | 5 | Alexey Demakov | |
292 | Альтернатива - "gradle eclipse plugin":https://docs.gradle.org/current/userguide/eclipse_plugin.html |
||
293 | Но .classpath генерируется не переносимый, в source code repository его не положишь. |