그래들 (Gradle)
Published by Woong Geun Jang,
레퍼런스
- Gradle User Manual
- Gradle Guides
- Gradle DSL
- Gradle Docs
- Awesome Gradle
그래들 플러그인을 리스팅 해둔 사이트
그래들이 하는 기능 총 3가지
핵심기능
- 의존성 관리
- 빌드
- 퍼블리쉬
추가기능
- Build Scan
- Continuous Build
그래들은 어찌됐든 빌드를 위해서 매번 task 명령을 날려야 하는데, 소스가 변경될 때마다 자동으로 빌드해 주는 기능 - Build Dashboard
그래들 숙련도 테스트
기본
- 그래들 문법: 그래들 파일을 읽어서 프로세스를 설명할 수 있는가?
- 의존성 관리
- 빌드
- Native 라이브러리 그래들을 작성할 수 있는가?
- Native 실행파일 그래들을 작성할 수 있는가?
- Native 프로젝트 테스트를 도입할 수 있는가?
- 멀티 프로젝트를 구성할 수 있는가?
- 퍼블리싱
숙련
궁금증들
- CPP 플러그인을 사용하면, XCode Plugin은 필요한가?
- 플러그인이란 무엇인가?
- Task는 정확히 무엇일까?
- gradle.properties vs gradle.settings
- Build Cache란? incremental build와 차이는?
의존성 관리란?
"...is made up of two pieces. Firstly, Gradle needs to know about the things that your project needs to build or run, in order to find them. We call these incoming files the dependencies of the project. Secondly, Gradle needs to build and upload the things that your project produces. We call these outgoing files the publications of the project." https://docs.gradle.org/current/userguide/artifact_dependencies_tutorial.html
결과적으로 설명하면, 의존성 관리는 크게 2가지 기능을 한다.
- 프로젝트에 필요한 라이브러리 파일들을 빌드해서 필요할 경우 Run
- 프로젝트에서 빌드한 파일들을 업로드
이 2가지 기능을 수행하기 위해서 의존성 관리툴은 다음 2가지 정보가 필요하고 Gradle은 이를 다음과 같은 형태로 지원한다.
- 어떤 라이브러리 파일들(라이브러리명, 버젼, URI 등)이 이 프로젝트에 쓰여졌는지 명시하는 파일 - dependencies
- 빌드해서 밖으로 나가는 파일들 - publications
"Gradle 은 DSL. 즉 Domain Specific Language라고 한다. 이 말이 정확히 뭘 의미하는지 아직 완전히 감은 잡히지 않지만, gradle 의존성 선언 스크립트(build.gradle)을 보면, 어느 정도 이해가 간다. 의존성 선언은 2가지 파트로 나뉘는데, 빌드와 출판이고, 빌드와 출판을 선언할 때 가장 도입부에 선언되는 것이 어떤 플러그인을 사용할 것인가이다. java 플러그인을 사용하면 자바 플러그인에 맞는 의존성 syntax를 써야 하는 것."
gradle은 위에서 얘기했듯이 2가지 기능. 의존성 관리빌드 및 출판을 담당하는데, 그렇다면 좀 더 구체적으로 어떻게 사용하는 것인가~~? 일단 의존성 관리빌드 부분부터 보면, 의존성을 관리하기 위해서는 아래 정보를 명시해야 한다.
- 어떤 플러그인을 사용해서 이 프로젝트가 빌드되어야 하는가?
- 이 프로젝트에 어떤 라이브러리가 쓰이고, 어디서 찾을 수 있는가?
- 어떤 플러그인을 써서 어디로 아티팩트를 출판하는가?
gradle 빌드파일을 보면서 좀 더 알아보자.
build.gradle
// 자바 프로젝트 의존성 관리 및 빌드 명시
apply plugin: ‘java’
// 어떤 레포지터리에서 찾을 것인가?
repositories {
mavenCentral()
}
dependencies {
compile group: 'org.hibernate', name: 'hibernate-core', version: '3.6.7.Final'
testCompile group: 'junit', name: 'junit', version: '4.+'
}
// 출판
apply plugin: 'maven'
uploadArchives {
repositories {
mavenDeployer {
repository(url: "file://localhost/tmp/myRepo/")
}
}
} |
용어들
그래들 래퍼(Gradle Wrapper)
유저 입장에서 gradle로 빌드하기 위해서는 gradle을 설치해야 한다. 만약 유저가 잘못된 버젼의 gradle을 설치한다면, 빌드가 실패할 리스크가 있는데, Wrapper는 그래들 버젼마다 캐싱해 두고 이를 기반으로 빌드를 실행하기 때문에 빌드 툴 버젼에 따른 문제가 발생할 여지를 줄인다.
한 마디로, 프로젝트 유저 입장에서는 이 프로젝트가 gradle wrapper를 사용했다는 점만 인지하면, gradle을 설치할 필요없이 이를 이용해서 gradle 빌드를 실행하면 되는 것
의존성 레졸루션(Dependency Resolution)
거의 대부분의 프로젝트는 외부 라이브러리 파일들에 대한 의존성을 가지고 있고 그래들은 프로젝트의 dependencies를 빌드 전에 찾아서 준비해 주는 역할을 수행한다. 이 dependencies는 Maven, Ivy 레포지터리에서 다운이 될 수도 있고, local 디렉토리에 있을 수 있고, 아니면 다른 프로젝트에서 빌드되어야 할 수도 있다. 이렇게 dependencies를 찾는 프로세스를 gradle 도메인에서는 Dependency Resolution이라고 한다.
Transitive dependencies
그래들이 필요로 하는 의존성이 의존성을 가질 수 있다. 예로 들어, 내가 어떤 FFMPEG 라이브러리가 필요한데 이 FFMPEG이 SSL인증서가 필요할 수 있다. 이 경우 이 라이브러리 파일도 찾아야 하는데 이를 transitive dependencies라고 부른다.
빌드 스캔 (Build Scan)
그래들로 빌드할 때 —-scan 옵션을 주면, 그래들 클라우드 서비스에 빌드에 대한 리포트가 업데이트된다. 이 클라우드 서비스는 무료고 개인 서버를 이용하고 싶으면 엔터프라이즈 서비스를 구매해야 한다.
그래들 데몬 (Gradle Daemon)
그래들은 자바 버츄어 머신 위에서 돌아가기 때문에 빌드를 할 때마다 버츄어머신을 키고 그래들을 올리는 작업 자체가 시간이 많이 소모되는 작업이다. 데몬으로 돌리면, 항상 프로세스가 있고 또한 데몬이 프로젝트에 대한 정보를 캐싱하고 있기 때문에, 빌드를 더 효율적으로 할 수 있다.
초기화 스크립트 (Initialization Script)
빌드를 실행하기 이전에 실행되는 그래들 스크립트. 주로 전역적으로 어디서 커스텀 플러그인을 찾을 수 있는지에 대한 configuration을 적용하거나, 현재 환경에 따라 프로퍼티를 세팅(개발자 머신과 CI 서버에 따라 다른 설정), 개인정보를 제공하거나 특정머신에 대한 정보(JDK 설치경로), 외부 빌드 리스너나 로거 등록을 할 때 사용된다.
팁
설치
- Gradle runs on all major operating systems and requires only a Java JDK or JRE version 7 or higher to be installed.
그래들 DSL (Gradle DSL)
- 그래들 스크립트는 configuration 스크립트다. 무슨 말인가 하면, 스크립트가 실행되면, 특정 개체의 속성값을 설정한다는 것.
- 그래들 스크립트는 총 3가지 타입이 있다. Build, Init, Settings 이 타입들은 각각 Project 오브젝트, Gradle 오브젝트, Settings 오브젝트를 설정하는 역할을 한다.
- 그래들 스크립트는 Script 인터페이스를 구현한다. 이 인터페이스는 속성의 개수와 메서드를 정의한다.
- a Build 스크립트는, statements와 스크립트 블록으로 구성된다.
- Statement는 메서드 호출, 속성 값 할당, 지역변수 정의를 할 수 잇다.
- 이 스크립트 블록은 내부 블록을 인자로 받는 메서드 호출이다. 또한 다른 스크립트와 마찬가지로 특정 타입 오브젝트의 속성을 결정.
- 가장 상위 스크립트 블록은 아래와 같다.
- allprojects{}
- artifacts{}
- buildscripts{}
- configurations{}
- dependencies{}
- repositories{}
- sourceSets{}
- subprojects{}
- publishing{}
플러그인 (Plugin)
- cpp, java 등과 같은 Gradle 플러그인은 Plugin 인터페이스를 구현한 클래스고, 플러그인이 적용되면(apply plugin: ‘cpp'),
그래들이 플러그인을 인스턴스하고 플러그인의 Plugin.apply(T) 메서드를 호출하고 인자값으로 Project 객체를 넘겨준다.
일반
- gradle.build 파일은 Project 객체에 대한 설정 파일이다.
그래들의 모든 설정값들은 객체에 기반하는데, 예로 들어 Task는 DefaultTask객체고, task를 정의하는 것은 이 DefaultTask의 TaskAction을 덮어쓰는 것 - task(type: Copy) 이 선언으로 시작하는 task 정의는 기본 DefaultTask가 아닌 'Copy Task extends DefaultTask’의 TaskAction을 재정의한다는 것
- 플러그인은 내장 플러그인과 외장 플러그인이 있는데, 내장 플러그인은 플러그인은 id를 명시한 후에 사용.
- settings.gradle 파일은 빌드 프로그램인 gradle의 설정을 정의하는 파일
- gradle wrapper 명령어로 wrapper 쉘 커맨드를 생성한 후에 ./gradlew 명령어로 task와 빌드를 수행하는 것이 일반적. 그 이유는 gradle은 하위호환을 잘 지원하는 편이지만, 그래도 그래들 버젼 차이 문제로 생기는 문제가 있을 수 있기 때문에 프로젝트에 사용된 그래들 버젼을 그대로 사용하기 위해서 사용. 해당 버젼 그래들이 깔려있지 않아도 빌드가 실행되도록 함
- assemble = compile + link, build = assemble + test in Gradle Context
네이티브 빌드와 테스트
- cpp 플러그인은 model이라는 객체를 제공하고 이 모델 객체는 어셈블과 컴파일을 할 수 있는 tasks을 정의한다.
유용한 커맨드 라인
- gradle -q projects
서브 프로젝트를 리스팅한다.
그래들 네이티브 빌드
용어정리
Software Model Concepts
네이티브 빌드에서 사용되는 소프트웨어 모델이라는 개념은 소프트웨어를 구성하는 컴포넌트들끼리 어떤 연관관계를 가지고 빌드 되는지에 대한 개념도다.
Component
소프트웨어의 논리적인 단위다. 예로 들어, 커맨드라인 앱, 웹 앱, 라이브러리. 이 컴포넌트는 다른 컴포넌트들로 구성될 수도 있다.
Library
다른 컴포넌트에 링킹되거나 합쳐지는 재사용이 가능한 컴포넌트.
Source set
소스 파일들의 논리적인 그룹. 대부분의 component들이 다양한 언어의 소스들로부터 빌드된다.
Binary
컴포넌트가 빌드된 결과물. 컴포넌트는 서로 다른 바이너리를 출력할 수 있다.
Variant
서로 독립적인 컴포넌트의 바이너리다. 예로 들어, Java7과 Java8을 타겟으로 빌드된 컴포넌트는 서로 구별되는 라이브러리 각각 2개로 생성된다. 이렇게 서로 다른 바이너리를 variants 라고 한다.
유용한 네이티브 빌드 커맨드 라인
- gradle dependentComponents
- gradle dependentComponents —-all
- gradle components
실제로 나올 바이너리 리스트를 보여준다.
팁
- 그래들은 각각의 세팅으로부터 조합되어 정의된 테스크를 하나씩 하나씩 수행한다. 출력 바이너리에 따라 테스크가 구분된다고 생각하면 된다. 스태틱 라이브러리와 쉐어드 라이브러리는 별개 바이너리이므로 독립적인 테스크로 빌드된다.
- 출력되는 각각의 바이너리들은 컴파일러 집합과 커맨드라인 인자와 매크로 정의와 같은 링커 세팅과 연관되어 있다.
- 이런 세팅들은 모든 바이너리, 개별 바이너리 또는 그룹 바이너리에 적용될 수 있다.
? 어떻게 하면 안드로이드를 아키텍쳐별로 빌드가 떨어지게 할 수 있는가?
안드로이드 라이브러리