2017년 6월 20일 화요일

개인적인 Gradle 공부


요즘 Gradle을 많이 보고 다룰 일이 생겨서 개인적으로 공부해보기로 했습니다.

Gradle, 그래들이라고 불리는 이건 뭘까요?
위키에는 뭐라고 써있는지 보겠습니다.
Gradle은 Groovy를 이용한 빌드 시스템이다. Groovy와 유사한 도메인 언어를 채용하였으며, 현재 안드로이드 앱을 만드는데 필요한 안드로이드 스튜디오의 공식 빌드 시스템이기도 하다. Java, C/C++, Python 등과 같은 여러 가지 언어를 지원한다.
한국 위키는 설명이 좀 부실하네요. 영문 위키가 더 자세히 잘 설명되어있습니다.
https://en.wikipedia.org/wiki/Gradle

그래들이 그루비를 이용한 빌드 시스템이라고 하는데 그럼 그루비는?
https://ko.wikipedia.org/wiki/%EA%B7%B8%EB%A3%A8%EB%B9%84

설명이 꽤나 길군요. 요약해보자면,
자바에 파이썬, 루비, 스몰토크 등의 특징을 더한 
동적 객체 지향 프로그래밍 언어

그래들은 이러한 특징을 가진 그루비를 기반으로 하는 언어를 사용한다고 합니다.
그리고 자바뿐만 아니라 다른 언어를 빌드하는데에도 많이 사용된다고 합니다만,
저는 안드로이드 빌드 때문에 Gradle을 공부하고 싶기때문에
안드로이드 빌드를 중심으로 보겠습니다.

제가 참고한 곳은 안드로이드 개발자 홈페이지 입니다.
https://developer.android.com/studio/build/index.html#detailed-build

빌드의 일반적인 흐름은 다음과 같습니다.


그래들은 이런 빌드 과정을 설정하고 자동화할 수 있도록 해줍니다.
종속성을 어떻게 관리할 것인지, 빌드를 하고 나서 어떻게 처리를 할 것인지,
배포 빌드, 테스트 빌드 등 설정을 할 수가 있습니다.

빌드 구성 파일의 구조는 아래와 같습니다.


제일 위에 있는 build.gradle은 프로젝트의 모든 모듈의 빌드 세팅을 정의합니다.

/**
 * The buildscript {} block is where you configure the repositories and
 * dependencies for Gradle itself--meaning, you should not include dependencies
 * for your modules here. For example, this block includes the Android plugin for
 * Gradle as a dependency because it provides the additional instructions Gradle
 * needs to build Android app modules.
 */

buildscript {

    /**
     * The repositories {} block configures the repositories Gradle uses to
     * search or download the dependencies. Gradle pre-configures support for remote
     * repositories such as JCenter, Maven Central, and Ivy. You can also use local
     * repositories or define your own remote repositories. The code below defines
     * JCenter as the repository Gradle should use to look for its dependencies.
     */

    repositories {
        jcenter()
    }

    /**
     * The dependencies {} block configures the dependencies Gradle needs to use
     * to build your project. The following line adds Android Plugin for Gradle
     * version 2.3.2 as a classpath dependency.
     */

    dependencies {
        classpath 'com.android.tools.build:gradle:2.3.2'
    }
}
/**
 * The allprojects {} block is where you configure the repositories and
 * dependencies used by all modules in your project, such as third-party plugins
 * or libraries. Dependencies that are not required by all the modules in the
 * project should be configured in module-level build.gradle files. For new
 * projects, Android Studio configures JCenter as the default repository, but it
 * does not configure any dependencies.
 */

allprojects {
   repositories {
       jcenter()
   }
}
최상위 build.gradle은 프로젝트의 모든 모듈에 공통되는 gradle 저장소와 종속성을 정의하기 위해 buildscript {} 블록을 사용합니다.

모듈 레벨 빌드파일도 한번 보겠습니다. 보통의 안드로이드 앱 프로젝트라면,
project/app/build.gradle 파일을 말합니다.

/**
 * The first line in the build configuration applies the Android plugin for
 * Gradle to this build and makes the android {} block available to specify
 * Android-specific build options.
 */

apply plugin: 'com.android.application'
/**
 * The android {} block is where you configure all your Android-specific
 * build options.
 */

android {

  /**
   * compileSdkVersion specifies the Android API level Gradle should use to
   * compile your app. This means your app can use the API features included in
   * this API level and lower.
   *
   * buildToolsVersion specifies the version of the SDK build tools, command-line
   * utilities, and compiler that Gradle should use to build your app. You need to
   * download the build tools using the SDK Manager.
   */

  compileSdkVersion 25
  buildToolsVersion "25.0.3"

  /**
   * The defaultConfig {} block encapsulates default settings and entries for all
   * build variants, and can override some attributes in main/AndroidManifest.xml
   * dynamically from the build system. You can configure product flavors to override
   * these values for different versions of your app.
   */

  defaultConfig {

    /**
     * applicationId uniquely identifies the package for publishing.
     * However, your source code should still reference the package name
     * defined by the package attribute in the main/AndroidManifest.xml file.
     */

    applicationId 'com.example.myapp'

    // Defines the minimum API level required to run the app.
    minSdkVersion 15

    // Specifies the API level used to test the app.
    targetSdkVersion 25

    // Defines the version number of your app.
    versionCode 1

    // Defines a user-friendly version name for your app.
    versionName "1.0"
  }

  /**
   * The buildTypes {} block is where you can configure multiple build types.
   * By default, the build system defines two build types: debug and release. The
   * debug build type is not explicitly shown in the default build configuration,
   * but it includes debugging tools and is signed with the debug key. The release
   * build type applies Proguard settings and is not signed by default.
   */

  buildTypes {

    /**
     * By default, Android Studio configures the release build type to enable code
     * shrinking, using minifyEnabled, and specifies the Proguard settings file.
     */

    release {
        minifyEnabled true // Enables code shrinking for the release build type.
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
  }

  /**
   * The productFlavors {} block is where you can configure multiple product
   * flavors. This allows you to create different versions of your app that can
   * override defaultConfig {} with their own settings. Product flavors are
   * optional, and the build system does not create them by default. This example
   * creates a free and paid product flavor. Each product flavor then specifies
   * its own application ID, so that they can exist on the Google Play Store, or
   * an Android device, simultaneously.
   */

  productFlavors {
    free {
      applicationId 'com.example.myapp.free'
    }

    paid {
      applicationId 'com.example.myapp.paid'
    }
  }

  /**
   * The splits {} block is where you can configure different APK builds that
   * each contain only code and resources for a supported screen density or
   * ABI. You'll also need to configure your build so that each APK has a
   * different versionCode.
   */

  splits {
    // Screen density split settings
    density {

      // Enable or disable the density split mechanism
      enable false

      // Exclude these densities from splits
      exclude "ldpi", "tvdpi", "xxxhdpi", "400dpi", "560dpi"
    }
  }
}
/**
 * The dependencies {} block in the module-level build configuration file
 * only specifies dependencies required to build the module itself.
 */

dependencies {
    compile project(":lib")
    compile 'com.android.support:appcompat-v7:25.3.1'
    compile fileTree(dir: 'libs', include: ['*.jar'])
}

제가 보통 보는 블록은 defaultConfig, buildType, dependencies 정도인 것 같네요.
splits나 productFlavors를 잘 사용하면 무료, 유료 앱 따로 빌드하기나 
화면 해상도에 따른 빌드 설정을 각각해줄 수 있을 것 같네요.

그리고 추가적으로, 빌드할 때 필요한 설정을 가지고 있는 파일들이 있습니다.
- gradle.properties: 프로젝트 범위의 그래들 설정을 함. 예, gradle daemon 힙 크기 설정
- local.properties: 빌드 시스템의 로컬 환경을 구성. 예, sdk, ndk 경로 설정

뭔가 간단한 앱을 만들때는 build.gradle 파일을 많이 수정할 일이 없었는데
모듈을 만들어서 붙이고, 다른 플러그인도 같이 사용하게되면
종속성이나 여러가지 신경써야할 포인트가 많은 것 같습니다.

이 포스트를 시작으로 책도 좀 보고 더 깊게 공부해봐야겠습니다.

Gradle의 GitHub 주소를 남기고 글 마치겠습니다.

댓글 없음:

댓글 쓰기

JIRA Plugin - ScriptRunner 소개 #2

관련 글 소개 #1:  https://pineoc.blogspot.com/2019/03/scriptrunner-1.html ScriptRunner 소개 #2 지난 글에서는 Behaviours를 보았고 다음 내용인 콘솔, 리스너 등을 ...