HOME > gradle

Gradle - Jar 라이브러리에서 일부 클래스를 삭제하는 방법 (duplicated dependency 문제 해결)

By JS | 10 Nov 2019

프로젝트에 Jar를 두개 이상 의존성을 추가하고 빌드를하였는데, 두개의 Jar가 동일한 클래스를 포함하고 있어서 빌드가 실패되었습니다.

Googling해보니, 다음과 같은 방법으로 Jar의 의존성을 제거할 수 있다고 합니다.

dependencies {
  implementation "io.realm:realm-android-kotlin-extensions:$realm_version" {
      exclude group: "org.jetbrains.kotlin", module: "kotlin-stdlib-jdk7"
  }
}

하지만 직접 Jar를 프로젝트에 추가하는 경우 다음과 같은 방법으로 중복되는 클래스를 제거할 수 없습니다.

위의 코드에서 exclude 명령어는 "Transitive Dependencies"가 있는 경우 그것을 제거하는 것이라고 합니다. Jar파일에는 "Transitive Dependencies"가 없기 때문에 이것으로 일부 의존성 클래스를 제거할 수 없습니다.

그렇기 때문에, Jar 파일을 압축풀고 거기서 중복된 클래스 파일을 삭제하고 다시 Jar로 만드는 방법뿐이 생각나는게 없었습니다.

Gradle의 task를 이용하면 자동화가 가능하기 때문에, 이 방법으로 구현해보기로 하였습니다.

Jar의 중복 클래스 제거

app의 "build.gradle"파일에서 repackJars라는 태스크를 만들었습니다.

task repackJars(type: Zip) {
    println 'Excluding duplicated classes'
    from (zipTree('libs/services.core.jar')) {
        exclude '**/android/gsi/**.class'
        exclude '**/android/hardware/contexthub/V1_0/**.class'
        exclude '**/android/hardware/vibrator/V1_0/**.class'
        exclude '**/android/os/IDumpstate**.class'
        exclude '**/android/os/IInstalld**.class'
        exclude '**/android/os/IStoraged**.class'
        exclude '**/android/os/IVold**.class'
    }

    println 'Repackaging Jar'
    archiveName 'services.core.repack.jar'
    destinationDir(file('libs/'))
}
  • zipTree는 jar의 압축을 풉니다.
  • exclude는 파일들중에 중복되는 클래스를 제거합니다.
  • archiveName는 설정한 파일이름으로 zip 형식으로 압축해 줍니다.
  • destinationDir는 zip파일이 저장될 위치를 설정합니다.

build 태스크보다 먼저 실행되게 만들기

최종적으로, repackaging된 Jar를 프로젝트에서 사용할 생각입니다. 그렇기 때문에 build 태스크보다 repackJars 태스크가 먼저 실행되어야 합니다. dependencies { implementation files('libs/services.core.repack.jar') ... }

다음 코드처럼, preBuild.dependsOn repackJars로 build 태스크보다 repackJars가 먼저 실행되도록 의존성을 설정할 수 있습니다.

task repackJars(type: Zip) {
    ....
}
preBuild.dependsOn repackJars

아래 명령어로 빌드를 해보면

$ gradle build

build하기 전에 repackJars 태스크가 수행되는 것을 볼 수 있습니다.

> Configure project :app
Excluding duplicated classes
Repackaging Jar

> Task :app:compileDebugJavaWithJavac
....

참고