문서의 이전 판입니다!
settings.gradle이 필요하다. 여기서 하위 프로젝트를 include해준다.include "shared", "api", "services:webservice", "services:shared"
build.gradle에 모든 서브 프로젝트에 공통된 설정을 넣는다.subprojects { apply plugin: 'java' apply plugin: 'eclipse-wtp' repositories { mavenCentral() } dependencies { testCompile 'junit:junit:4.8.2' } version = '1.0' jar { manifest.attributes provider: 'gradle' } }
// 어느 서브 프로젝트의 build.gradle dependencies { compile project(':shared') } // shared 서브 프로젝트에 의존하고 있다.
water/ build.gradle settings.gradle bluewhale/
settings.gradle include 'bluewhale'
Closure cl = { task -> println "I'm $task.project.name" } task hello << cl project(':bluewhale') { task hello << cl }
gradle -q hello로 실행하면> gradle -q hello I'm water I'm bluewhale
project()라는 메소드가 있으며, 이는 프로젝트의 경로를 인자로 받아서 해당 경로의 Project 객체를 리턴한다. 이러한 방법을 교차 프로젝트 구성 cross project configuration이라고 부른다.krill 서브 디렉토리를 만들어서 krill 서브 프로젝트를 선언한다. settings.gradle include 'bluewhale', 'krill'
allprojects { task hello << { task -> println "I'm $task.project.name" } }
> gradle -q hello I'm water I'm bluewhale I'm krill
allprojects 프라퍼티는 현재 프로젝트와 그것의 모든 서브 프로젝트를 리턴한다. allprojects에 클로저를 인자로 주면 클로저의 구문이 allprojects의 프로젝트들로 위임된다. allprojects.each로 이터레이션을 도는 것도 가능하다.
Project.subprojects로 서브 프로젝트들만 접근하는 것도 가능하다. allprojects는 부모 프로젝트까지 포함한 것이다.
> gradle -q hello I'm water I'm bluewhale - I depend on water I'm krill - I depend on water
allprojects { task hello << {task -> println "I'm $task.project.name" } } subprojects { hello << {println "- I depend on water"} } project(':bluewhale').hello << { println "- I'm the largest animal that has ever lived on this planet." }
> gradle -q hello I'm water I'm bluewhale - I depend on water - I'm the largest animal that has ever lived on this planet. I'm krill - I depend on water
build.gradle을 두고 거기에 행위를 추가할 수 있다.water/
build.gradle
settings.gradle
bluewhale/
build.gradle
krill/
build.gradle
bluewhale/build.gradle hello.doLast { println "- I'm the largest animal that has ever lived on this planet." }
krill/build.gradle hello.doLast { println "- The weight of my species in summer is twice as heavy as all human beings." }
> gradle -q hello I'm water I'm bluewhale - I depend on water - I'm the largest animal that has ever lived on this planet. I'm krill - I depend on water - The weight of my species in summer is twice as heavy as all human beings.
tropicalFish라는 프로젝트를 추가하고 water 프로젝트 빌드 파일에 행위를 더 추가해보자.
water/
build.gradle
settings.gradle
bluewhale/
build.gradle
krill/
build.gradle
tropicalFish/
settings.gradle include 'bluewhale', 'krill', 'tropicalFish'
build.gradle allprojects { task hello << {task -> println "I'm $task.project.name" } } subprojects { hello << {println "- I depend on water"} } // 이름이 tropicalFish가 아닌 프로젝트만 찾아서 설정 configure(subprojects.findAll { it.name != 'torpicalFish' }) { hello << {println '- I love to spend time in the arctic waters.'} }
> gradle -q hello I'm water I'm bluewhale - I depend on water - I love to spend time in the arctic waters. - I'm the largest animal that has ever lived on this planet. I'm krill - I depend on water - I love to spend time in the arctic waters. - The weight of my species in summer is twice as heavy as all human beings. I'm tropicalFish - I depend on water
ext 프라퍼티를 통해 필터링이 가능하다.
water/
build.gradle
settings.gradle
bluewhale/
build.gradle
krill/
build.gradle
tropicalFish/
build.gradle
tropicalFish/build.gradle ext.arctic = false
> gradle -q hello I'm water I'm bluewhale - I depend on water - I'm the largest animal that has ever lived on this planet. - I love to spend time in the arctic waters. I'm krill - I depend on water - The weight of my species in summer is twice as heavy as all human beings. - I love to spend time in the arctic waters. I'm tropicalFish - I depend on water
afterEvaluate는 서브 프로젝트의 빌드 스크립트를 모두 수행한 뒤에 인자로 넘어온 클로저를 실행하라는 의미이다. arctic 프라퍼티가 서브 프로젝트 빌드 스크립트에 선언 돼 있기 때문이다.hello 태스크를 실행하면 최상위와 그 아래 모든 서브 프로젝트의 hello 태스크가 실행 된다.hello 태스크를 실행하면 bluewhale 프로젝트의 태스크만 실행된다.hello라는 이름의 태스크를 찾고 실행한다.> gradle distanceToIceberg :bluewhale:distanceToIceberg 20 nautical miles :krill:distanceToIceberg 5 nautical miles BUILD SUCCESSFUL Total time: 1 secs
distanceToIceberg 태스크가 없지만 상관없다. 왜냐면 계층 구조를 따라 내려가면서 해당 명칭의 태스크를 실행한다라는 규칙 때문이다.tropicalFish에서 실행한 gradle -q :hello :krill:hello hello > gradle -q :hello :krill:hello hello I'm water I'm krill - I depend on water - The weight of my species in summer is twice as heavy as all human beings. - I love to spend time in the arctic waters. I'm tropicalFish - I depend on water
:bluewhale 은 파일 시스템상에서 water/bluewhale을 뜻한다.:bluewhale:hello는 bluewhale 프로젝트의 hello 태스크의존성과 실행 순서에 대해서 확인해보자.
messages/
settings.gradle
consumer/
build.gradle
producer/
build.gradle
settings.gradle include 'consumer', 'producer'
consumer/build.gradle task action << { println("Consuming message: " + (rootProject.hasProperty('producerMessage') ? rootProject.producerMessage : 'null')) }
producer/build.gradle task action << { println "Producing message:" rootProject.producerMessage = 'Watch the order of execution.' }
> gradle -q action Consuming message: null Producing message:
:consumer:action이 :producer:action 보다 먼저 실행된다.action 태스크를 실행하면 규칙에 따라 :aProducer:action은 실행이 안되므로 null이 찍힌다.consumer/build.gradle task action(dependsOn: ':producer:action') << { println("Consuming message: " + (rootProject.hasProperty('producerMessage') ? rootProject.producerMessage : 'null')) }
> gradle -q action Producing message: Consuming message: Watch the order of execution.
:consumer:action이 :producer:action에 실행시 의존성을 걸고 있기 때문에 항상 :producer:action이 먼저 실행된다.consumer/build.gradle message = rootProject.hasProperty('producerMessage') ? rootProject.producerMessage : 'null' task consume << { println("Consuming message: " + message) }
producer/build.gradle rootProject.producerMessage = 'Watch the order of evaluation.'
> gradle -q consume Consuming message: null
consumer/build.gradle evaluationDependsOn(':producer') message = rootProject.hasProperty('producerMessage') ? rootProject.producerMessage : 'null' task consume << { println("Consuming message: " + message) }
> gradle -q consume Consuming message: Watch the order of evaluation.
evaluationDependsOn은 producer를 consumer보다 먼저 평가하게 만든다.rootProject.producerMessage 값을 바로 읽게 만들기만 해도 된다. consumer/build.gradle task consume << { println("Consuming message: " + (rootProject.hasProperty('producerMessage') ? rootProject.producerMessage : 'null')) }
evaluationDependsOnChildren() 메소드를 사용한다.dependsOn을 사용해 서로 다른 두 프로젝트의 실행시 의존성을 지정할 경우 이 메소드는 기본적으로 두 프로젝트간에 구성 의존성을 생성하는 것이다. 따라서 이 때는 구성 의존성을 명시적으로 지정하지 않아도 된다.두 개의 웹 애플리케이션 서브 프로젝트를 가진 최상위 프로젝트가 웹 애플리케이션 배포본을 생성하는 예를 본다. 예제에서는 단 하나의 교차 프로젝트 구성을 사용한다.
webDist/
settings.gradle
build.gradle
date/
src/main/java/
org/gradle/sample/
DateServlet.java
hello/
src/main/java/
org/gradle/sample/
HelloServlet.java
settings.gradle include 'date', 'hello'
build.gradle allprojects { apply plugin: 'java' group 'org.gradle.sample' version = '1.0' } subprojects { apply plugin: 'war' repositories { mavenCentral() } dependencies { compile "javax.servlet:servlet-api:2.5" } } task explodedDist(dependsOn: assemble) << { File explodedDist = mkdir("$buildDir/explodedDist") subprojects.each { project -> project.tasks.withType(Jar).each { archiveTask -> copy { from archiveTask.archivePath into explodedDist } } } }
gradle -q explodedDist를 실행하면 “$buildDir/explodedDist”에 hello-1.0.jar와 date-1.0.jar 가 생성된다.arhivePath를 알아야만 하기 때문이다. 하지만 태스크를 실행하는 시점에 요청한다. 따라서 순환 의존성은 아니다.한 프로젝트가 다른 프로젝트의 컴파일 결과와 그 의존하는 라이브러리들 모두에 의존하는 경우가 발생한다. 이 때 프로젝트간 의존성을 설정한다.
java/
settings.gradle
build.gradle
api/
src/main/java/
org/gradle/sample/
api/
Person.java
apiImpl/
PersonImpl.java
services/personService/
src/
main/java/
org/gradle/sample/services/
PersonService.java
test/java/
org/gradle/sample/services/
PersonServiceTest.java
shared/
src/main/java/
org/gradle/sample/shared/
Helper.java
settinga.gradle include 'api', 'shared', 'services:personService'
build.gradle subprojects { apply plugin: 'java' group = 'org.gradle.sample' version = '1.0' repositories { mavenCentral() } dependencies { testCompile "junit:junit:4.8.2" } } project(':api') { dependencies { compile project(':shared') } } project(':services:personService') { dependencies { compile project(':shared'), project(':api') } }
gradle compile을 실행하면 shared가 먼저 빌드 되고 그 뒤에 api가 빌드 된다. 프로젝트 의존성은 부분적인 멀티 프로젝트 빌드를 가능케 한다.build.gradle subprojects { apply plugin: 'java' group = 'org.gradle.sample' version = '1.0' } project(':api') { configurations { spi } dependencies { compile project(':shared') } task spiJar(type: Jar) { baseName = 'api-spi' dependsOn classes from sourceSets.main.output include('org/gradle/sample/api/**') } artifacts { spi spiJar } } project(':services:personService') { dependencies { compile project(':shared') compile project(path: ':api', configuration: 'spi') testCompile "junit:junit:4.8.2", project(':api') } }
-a 옵션으로 gradle을 실행하면 된다.