your programing

Gradle에서 구현과 컴파일의 차이점은 무엇입니까?

lovepro 2020. 9. 28. 09:48
반응형

Gradle에서 구현과 컴파일의 차이점은 무엇입니까?


안드로이드 스튜디오 3.0으로 업데이트하고 새 프로젝트를 생성 한 후, 나는있는 것으로 나타났습니다 build.gradle대신 새로운 종속성을 추가 할 수있는 새로운 방법이 compile존재 implementation하고 대신 testCompile있다 testImplementation.

예:

 implementation 'com.android.support:appcompat-v7:25.0.0'
 testImplementation 'junit:junit:4.12'

대신에

 compile 'com.android.support:appcompat-v7:25.0.0'
 testCompile 'junit:junit:4.12'

그들 사이의 차이점은 무엇이며 무엇을 사용해야합니까?


tl; dr

다음을 교체하십시오.

  • compileimplementation(당신이 이행 성을 필요로하지 않는 경우) 또는 api(당신이 이행 성을 필요로하는 경우)
  • testCompiletestImplementation
  • debugCompiledebugImplementation
  • androidTestCompileandroidTestImplementation
  • compileOnly여전히 유효합니다. 제공되는 것을 대체하고 컴파일하지 않기 위해 3.0에서 추가되었습니다. ( providedGradle에 해당 사용 사례에 대한 구성 이름이 없을 때 도입되었으며 Maven에서 제공 한 범위를 따서 명명했습니다.)

Google 이 IO17에서 발표 한 Gradle 3.0의 주요 변경 사항 중 하나입니다 .

이제 compile구성이 더 이상 사용되지 않으며implementation 또는 로 대체되어야합니다.api

로부터 Gradle을 문서 :

dependencies {
    api 'commons-httpclient:commons-httpclient:3.1'
    implementation 'org.apache.commons:commons-lang3:3.5'
}

api구성에 나타나는 종속성 은 라이브러리 소비자에게 전 이적으로 노출되며 소비자의 컴파일 클래스 경로에 나타납니다.

implementation반면 구성 에서 발견 된 종속성 은 소비자에게 노출되지 않으므로 소비자의 컴파일 클래스 경로로 유출되지 않습니다. 다음과 같은 몇 가지 이점이 있습니다.

  • 종속성은 더 이상 소비자의 컴파일 클래스 경로로 누출되지 않으므로 실수로 전이 종속성에 의존하지 않습니다.
  • 감소 된 클래스 경로 크기로 인한 빠른 컴파일
  • 구현 종속성 변경시 재 컴파일 감소 : 소비자를 재 컴파일 할 필요가 없음
  • 깔끔한 게시 : 새로운 maven-publish 플러그인과 함께 사용하면 Java 라이브러리는 라이브러리에 대해 컴파일하는 데 필요한 항목과 런타임에 라이브러리를 사용하는 데 필요한 항목을 정확히 구분하는 POM 파일을 생성합니다 (즉, 라이브러리 자체를 컴파일하는 데 필요한 것과 라이브러리에 대해 컴파일하는 데 필요한 것을 혼합).

컴파일 구성은 여전히 ​​존재하지만 apiimplementation구성이 제공 하는 보증을 제공하지 않으므로 사용해서는 안됩니다 .


참고 : 앱 모듈에서 라이브러리 만 사용하는 경우 (일반적인 경우) 차이를 느끼지 못할 것입니다.
서로 의존하는 모듈이있는 복잡한 프로젝트가 있거나 라이브러리를 만드는 경우에만 차이를 볼 수 있습니다.


이 답변은 프로젝트 implementation에서 api, 및 의 차이점을 보여줍니다 compile.


세 개의 Gradle 모듈이있는 프로젝트가 있다고 가정 해 보겠습니다.

  • 앱 (Android 애플리케이션)
  • myandroidlibrary (Android 라이브러리)
  • myjavalibrary (Java 라이브러리)

appmyandroidlibrary종속한다. myandroidlibrarymyjavalibrary종속한다.

종속성 1

myjavalibraryMySecret클래스를

public class MySecret {

    public static String getSecret() {
        return "Money";
    }
}

myandroidlibrary보유 MyAndroidComponent로부터 값을 조작 클래스 MySecret클래스.

public class MyAndroidComponent {

    private static String component = MySecret.getSecret();

    public static String getComponent() {
        return "My component: " + component;
    }    
}

마지막으로, app단지에서 값에 관심이있다myandroidlibrary

TextView tvHelloWorld = findViewById(R.id.tv_hello_world);
tvHelloWorld.setText(MyAndroidComponent.getComponent());

이제 종속성에 대해 이야기하겠습니다.

app소비해야 :myandroidlibrary하므로 appbuild.gradle 에서 implementation.

( 참고 : api / compile도 사용할 수 있습니다.하지만 잠시만 생각하세요.)

dependencies {
    implementation project(':myandroidlibrary')      
}

종속성 2

myandroidlibrarybuild.gradle이 어떤 모습이어야 한다고 생각 하십니까? 어떤 범위를 사용해야합니까?

세 가지 옵션이 있습니다.

dependencies {
    // Option #1
    implementation project(':myjavalibrary') 
    // Option #2
    compile project(':myjavalibrary')      
    // Option #3
    api project(':myjavalibrary')           
}

종속성 3

그들 사이의 차이점은 무엇이며 무엇을 사용해야합니까?

컴파일 또는 API (옵션 # 2 또는 # 3) 종속성 4

당신이 사용하는 경우 compileapi. 이제 Android 애플리케이션 myandroidcomponentMySecret클래스 인 종속성 에 액세스 할 수 있습니다 .

TextView textView = findViewById(R.id.text_view);
textView.setText(MyAndroidComponent.getComponent());
// You can access MySecret
textView.setText(MySecret.getSecret());

구현 (옵션 # 1)

종속성 5

implementation구성을 사용하는 경우 MySecret노출되지 않습니다.

TextView textView = findViewById(R.id.text_view);
textView.setText(MyAndroidComponent.getComponent());
// You can NOT access MySecret
textView.setText(MySecret.getSecret()); // Won't even compile

그렇다면 어떤 구성을 선택해야합니까? 그것은 귀하의 요구 사항에 따라 다릅니다.

If you want to expose dependencies use api or compile.

If you don't want to expose dependencies (hiding your internal module) then use implementation.

Note:

This is just a gist of Gradle configurations, refer to Table 49.1. Java Library plugin - configurations used to declare dependencies for more detailed explanation.

The sample project for this answer is available on https://github.com/aldoKelvianto/ImplementationVsCompile


Compile configuration was deprecated and should be replaced by implementation or api.

You can read the docs at https://docs.gradle.org/current/userguide/java_library_plugin.html#sec:java_library_separation.

The brief part being-

The key difference between the standard Java plugin and the Java Library plugin is that the latter introduces the concept of an API exposed to consumers. A library is a Java component meant to be consumed by other components. It's a very common use case in multi-project builds, but also as soon as you have external dependencies.

The plugin exposes two configurations that can be used to declare dependencies: api and implementation. The api configuration should be used to declare dependencies which are exported by the library API, whereas the implementation configuration should be used to declare dependencies which are internal to the component.

For further explanation refer to this image. 간략한 설명


Brief Solution:

The better approach is to replace all compile dependencies with implementation dependencies. And only where you leak a module’s interface, you should use api. That should cause a lot less recompilation.

 dependencies {
         implementation fileTree(dir: 'libs', include: ['*.jar'])

         implementation 'com.android.support:appcompat-v7:25.4.0'
         implementation 'com.android.support.constraint:constraint-layout:1.0.2'
         // …

         testImplementation 'junit:junit:4.12'
         androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', {
             exclude group: 'com.android.support', module: 'support-annotations'
         })
 }

Explain More:

Before Android Gradle plugin 3.0: we had a big problem which is one code change causes all modules to be recompiled. The root cause for this is that Gradle doesn’t know if you leak the interface of a module through another one or not.

After Android Gradle plugin 3.0: the latest Android Gradle plugin now requires you to explicitly define if you leak a module’s interface. Based on that it can make the right choice on what it should recompile.

As such the compile dependency has been deprecated and replaced by two new ones:

  • api: you leak the interface of this module through your own interface, meaning exactly the same as the old compile dependency

  • implementation: you only use this module internally and does not leak it through your interface

So now you can explicitly tell Gradle to recompile a module if the interface of a used module changes or not.

Courtesy of Jeroen Mols blog


+--------------------+----------------------+-------------+--------------+-----------------------------------------+
| Name               | Role                 | Consumable? | Resolveable? | Description                             |
+--------------------+----------------------+-------------+--------------+-----------------------------------------+
| api                | Declaring            |      no     |      no      | This is where you should declare        |
|                    | API                  |             |              | dependencies which are transitively     |
|                    | dependencies         |             |              | exported to consumers, for compile.     |
+--------------------+----------------------+-------------+--------------+-----------------------------------------+
| implementation     | Declaring            |      no     |      no      | This is where you should                |
|                    | implementation       |             |              | declare dependencies which are          |
|                    | dependencies         |             |              | purely internal and not                 |
|                    |                      |             |              | meant to be exposed to consumers.       |
+--------------------+----------------------+-------------+--------------+-----------------------------------------+
| compileOnly        | Declaring compile    |     yes     |      yes     | This is where you should                |
|                    | only                 |             |              | declare dependencies                    |
|                    | dependencies         |             |              | which are only required                 |
|                    |                      |             |              | at compile time, but should             |
|                    |                      |             |              | not leak into the runtime.              |
|                    |                      |             |              | This typically includes dependencies    |
|                    |                      |             |              | which are shaded when found at runtime. |
+--------------------+----------------------+-------------+--------------+-----------------------------------------+
| runtimeOnly        | Declaring            |      no     |      no      | This is where you should                |
|                    | runtime              |             |              | declare dependencies which              |
|                    | dependencies         |             |              | are only required at runtime,           |
|                    |                      |             |              | and not at compile time.                |
+--------------------+----------------------+-------------+--------------+-----------------------------------------+
| testImplementation | Test dependencies    |      no     |      no      | This is where you                       |
|                    |                      |             |              | should declare dependencies             |
|                    |                      |             |              | which are used to compile tests.        |
+--------------------+----------------------+-------------+--------------+-----------------------------------------+
| testCompileOnly    | Declaring test       |     yes     |      yes     | This is where you should                |
|                    | compile only         |             |              | declare dependencies                    |
|                    | dependencies         |             |              | which are only required                 |
|                    |                      |             |              | at test compile time,                   |
|                    |                      |             |              | but should not leak into the runtime.   |
|                    |                      |             |              | This typically includes dependencies    |
|                    |                      |             |              | which are shaded when found at runtime. |
+--------------------+----------------------+-------------+--------------+-----------------------------------------+
| testRuntimeOnly    | Declaring test       |      no     |      no      | This is where you should                |
|                    | runtime dependencies |             |              | declare dependencies which              |
|                    |                      |             |              | are only required at test               |
|                    |                      |             |              | runtime, and not at test compile time.  |
+--------------------+----------------------+-------------+--------------+-----------------------------------------+

The brief difference in layman's term is:

  • If you are working on an interface or module that provides support to other modules by exposing the members of the stated dependency you should be using 'api'.
  • If you are making an application or module that is going to implement or use the stated dependency internally, use 'implementation'.
  • 'compile'은 'api'와 동일하게 작동하지만 라이브러리를 구현하거나 사용하는 경우 'implementation'이 더 잘 작동하고 리소스를 절약합니다.

포괄적 인 예를 보려면 @aldok의 답변을 읽으십시오.

참고 URL : https://stackoverflow.com/questions/44493378/whats-the-difference-between-implementation-and-compile-in-gradle

반응형