ग्रैडल में कार्यान्वयन और संकलन के बीच क्या अंतर है?


1025

एंड्रॉइड स्टूडियो 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'

उनके बीच क्या अंतर है और मुझे क्या उपयोग करना चाहिए?

जवाबों:


1277

tl; डॉ

बस प्रतिस्थापित करें:

  • compileके साथ implementation(यदि आपको ट्रांज़िटिविटी की आवश्यकता नहीं है) या api(यदि आपको ट्रांज़िटिविटी की आवश्यकता है)
  • testCompile साथ में testImplementation
  • debugCompile साथ में debugImplementation
  • androidTestCompile साथ में androidTestImplementation
  • compileOnlyअभी भी वैध है। यह 3.0 में जोड़ा गया था ताकि प्रदत्त और संकलन न हो सके। ( providedपेश किया गया जब ग्रैडल के पास उस उपयोग-मामले के लिए कॉन्फ़िगरेशन नाम नहीं था और इसे मावेन के प्रदान किए गए दायरे के नाम पर रखा गया था।)

यह ग्रेड 3.0 के साथ आने वाले परिवर्तनों में से एक है जिसे Google ने IO17 में घोषित किया था

compileविन्यास है अब पदावनत और द्वारा प्रतिस्थापित किया जाना चाहिए implementationयाapi

से Gradle प्रलेखन :

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

apiकॉन्फ़िगरेशन में दिखाई देने वाली निर्भरताएं लाइब्रेरी के उपभोक्ताओं के लिए सकारात्‍मक रूप से सामने आएंगी, और जैसा कि उपभोक्‍ताओं के संकलित वर्गपथ पर दिखाई देगा।

implementationदूसरी ओर, विन्यास में पाई जाने वाली निर्भरता , उपभोक्ताओं के सामने उजागर नहीं होगी, और इसलिए उपभोक्ताओं के संकलित वर्ग में लीक नहीं होगी। यह कई लाभों के साथ आता है:

  • निर्भरता अब उपभोक्ताओं के संकलित वर्गपथ में लीक नहीं होती है, इसलिए आप कभी भी गलती से एक सकर्मक निर्भरता पर निर्भर नहीं होंगे
  • तेजी से संकलन कम classpath आकार के लिए धन्यवाद
  • कम निर्भरता जब कार्यान्वयन निर्भरता बदल जाती है: उपभोक्ताओं को पुन: स्थापित करने की आवश्यकता नहीं होगी
  • क्लीनर प्रकाशन: जब नए मावेन-पब्लिश प्लगइन के साथ संयोजन में उपयोग किया जाता है, तो जावा लाइब्रेरीज़ POM फ़ाइलों का उत्पादन करती हैं, जो लाइब्रेरी के खिलाफ संकलन करने के लिए आवश्यक है और रनटाइम पर (दूसरे शब्दों में, लाइब्रेरी का उपयोग करने के लिए आवश्यक है) के बीच अंतर करती हैं। पुस्तकालय को संकलित करने के लिए क्या आवश्यक है और पुस्तकालय के खिलाफ संकलन करने के लिए क्या आवश्यक है) को मिलाएं।

संकलन कॉन्फ़िगरेशन अभी भी मौजूद है, लेकिन इसका उपयोग नहीं किया जाना चाहिए क्योंकि यह उन गारंटियों की पेशकश नहीं करेगा जो apiऔर implementationकॉन्फ़िगरेशन प्रदान करते हैं।


नोट: यदि आप केवल अपने ऐप मॉड्यूल में एक पुस्तकालय का उपयोग कर रहे हैं-आम मामला- तो आपको कोई अंतर नहीं दिखाई देगा।
यदि आप एक दूसरे के आधार पर मॉड्यूल के साथ एक जटिल परियोजना है, या आप एक पुस्तकालय बना रहे हैं आप केवल अंतर देखेंगे।


137
"उपभोक्ता" कौन हैं?
सुरगाछ

34
उपभोक्ता पुस्तकालय का उपयोग करने वाला मॉड्यूल है। Android के मामले में, यह Android एप्लिकेशन है। मुझे लगता है कि यह स्पष्ट है और मुझे यकीन नहीं है कि यह वही है जो आप पूछ रहे हैं।
बजे

21
यह वही है जो मेरे लिए भी लग रहा था। लेकिन अगर मैं एक पुस्तकालय बना रहा हूं, तो निश्चित रूप से मैं चाहता हूं कि इसका एपीआई ऐप के संपर्क में आए। अन्यथा, ऐप डेवलपर मेरी लाइब्रेरी का उपयोग कैसे करेगा? इसलिए मुझे implementationनिर्भरता छिपाने का अर्थ नहीं है । क्या मेरा प्रश्न समझ में आता है?
6

234
हाँ, यह अब समझ में आता है, अगर आपका ऐप लाइब्रेरी x पर निर्भर करता है जो खुद y, z पर निर्भर करता है। यदि आप implementationकेवल x एपी का उपयोग करते हैं, तो आप उजागर हो जाएंगे, लेकिन यदि आप apiy का उपयोग करते हैं , तो z भी सामने आ जाएगा।
बजे

36
समझ गया! यह अब अधिक समझ में आता है। आप इस स्पष्टीकरण को अपने उत्तर में जोड़ सकते हैं। यह उद्धृत दस्तावेज की तुलना में अधिक स्पष्ट है।
सुरगाछ

378

इस उत्तर के बीच अंतर का प्रदर्शन करेंगे implementation, apiऔर compileएक परियोजना पर।


मान लीजिए कि मेरे पास तीन ग्रेड मॉड्यूल के साथ एक परियोजना है:

  • एप्लिकेशन (एक Android आवेदन)
  • myandroidlibrary (एक Android लाइब्रेरी)
  • myjavalibrary (एक जावा पुस्तकालय)

appहै myandroidlibraryनिर्भरता के रूप में। myandroidlibraryहै myjavalibrary निर्भरता के रूप में।

Dependency1

myjavalibraryएक MySecretवर्ग है

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, इसलिए appबिल्ड.ग्रेड का उपयोग करें implementation

( नोट : आप एपीआई / संकलन का भी उपयोग कर सकते हैं। लेकिन एक क्षण के लिए उस विचार को पकड़ें।)

dependencies {
    implementation project(':myandroidlibrary')      
}

Dependency2

आपको क्या लगता है myandroidlibrarybuild.gradle कैसा दिखना चाहिए? हमें किस स्कोप का उपयोग करना चाहिए?

हमारे पास तीन विकल्प हैं:

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

Dependency3

उनके बीच क्या अंतर है और मुझे क्या उपयोग करना चाहिए?

संकलन या आपी (विकल्प # 2 या # 3) Dependency4

यदि आप उपयोग कर रहे हैं compileया api। हमारा Android एप्लिकेशन अब myandroidcomponentनिर्भरता तक पहुंचने में सक्षम है , जो एक MySecretवर्ग है।

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

कार्यान्वयन (विकल्प # 1)

Dependency5

यदि आप 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

तो, आपको कौन सा कॉन्फ़िगरेशन चुनना चाहिए? यह वास्तव में आपकी आवश्यकता पर निर्भर करता है।

यदि आप उपयोग निर्भरता को उजागर करना चाहते हैं apiया compile

यदि आप निर्भरता को उजागर नहीं करना चाहते हैं (अपने आंतरिक मॉड्यूल को छिपाना) तो उपयोग करें implementation

ध्यान दें:

यह ग्रैडल कॉन्फ़िगरेशन का सिर्फ एक सार है, तालिका 49.1 का संदर्भ लें जावा लाइब्रेरी प्लगइन - अधिक विस्तृत विवरण के लिए निर्भरता घोषित करने के लिए उपयोग किए जाने वाले कॉन्फ़िगरेशन

इस उत्तर के लिए नमूना परियोजना https://github.com/aldoKelvianto/ImplementationVsCompile पर उपलब्ध है


1
मैंने कार्यान्वयन का उपयोग करके एक जार फ़ाइल में निर्भरता जोड़ दी है, अगर यह उस तक पहुंच का खुलासा नहीं करता है कि मैं अभी भी क्यों प्राप्त कर पा रहा हूं और मेरा कोड ठीक काम कर रहा है?
smkrn110

@ smkrn110 कार्यान्वयन आपके जार पुस्तकालय को उजागर करेगा, लेकिन आपके जार निर्भरता पुस्तकालयों को नहीं।
अलदोक

2
@IjaySharma स्वीकृत उत्तर बताता है कि जो compileगारंटी देता है वही चीजें गारंटी नहीं apiदेती हैं।
उप 6 संसाधन

9
मुझे लगता है कि यह स्वीकृत उत्तर होना चाहिए। अच्छी तरह से समझाया!
शशांक कपसेम

9
@ StevenW.Klassen मैंने कभी सुना है कि सबसे अवांछनीय पतन है। यदि आपको लगता है कि सूचना का क्रम इष्टतम नहीं है, तो इसके बारे में शिकायत करने के बजाय एक संपादन का सुझाव दें
टिम

65

Compileविन्यास पदावनत किया गया था और द्वारा प्रतिस्थापित किया जाना चाहिए implementationया api

आप डॉक्स को https://docs.gradle.org/current/userguide/java_library_plugin.html#sec:java_library_separation पर पढ़ सकते हैं ।

संक्षिप्त हिस्सा है-

मानक जावा प्लगइन और जावा लाइब्रेरी प्लगइन के बीच महत्वपूर्ण अंतर यह है कि बाद वाला उपभोक्ताओं के लिए एक एपीआई की अवधारणा का परिचय देता है। एक पुस्तकालय एक जावा घटक है जिसका उपयोग अन्य घटकों द्वारा किया जाता है। मल्टी-प्रोजेक्ट बिल्ड में यह बहुत ही सामान्य उपयोग का मामला है, लेकिन जैसे ही आपके पास बाहरी निर्भरता होती है।

प्लगइन दो कॉन्फ़िगरेशनों को उजागर करता है जिनका उपयोग निर्भरता घोषित करने के लिए किया जा सकता है: एपीआई और कार्यान्वयन। Api कॉन्फ़िगरेशन का उपयोग निर्भरताएँ घोषित करने के लिए किया जाना चाहिए, जो लाइब्रेरी API द्वारा निर्यात की जाती हैं, जबकि कार्यान्वयन कॉन्फ़िगरेशन का उपयोग निर्भरताएँ घोषित करने के लिए किया जाना चाहिए जो घटक के लिए आंतरिक हैं।

आगे की व्याख्या के लिए इस छवि को देखें। संक्षिप्त विवरण


46

संक्षिप्त समाधान:

बेहतर दृष्टिकोण सभी compileनिर्भरता को implementationनिर्भरता से बदलना है । और केवल जहां आप एक मॉड्यूल का इंटरफ़ेस लीक करते हैं, आपको उपयोग करना चाहिए api। यह एक बहुत कम 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'
         })
 }

अधिक समझाएं:

एंड्रॉइड ग्रैगल प्लगइन 3.0 से पहले : हमें एक बड़ी समस्या थी जो एक कोड परिवर्तन के कारण सभी मॉड्यूल को फिर से जोड़ दिया जाता है। इसका मूल कारण यह है कि ग्रैडल को यह पता नहीं होता है कि आप किसी मॉड्यूल के इंटरफेस को दूसरे के माध्यम से लीक करते हैं या नहीं।

एंड्रॉइड ग्रैगल प्लगइन 3.0 के बाद : नवीनतम एंड्रॉइड ग्रैडल प्लगइन को अब आपको मॉड्यूल के इंटरफ़ेस को लीक करने के लिए स्पष्ट रूप से परिभाषित करने की आवश्यकता है। उसके आधार पर यह सही विकल्प बना सकता है कि इसे क्या करना चाहिए।

जैसे कि compileनिर्भरता को हटा दिया गया है और दो नए लोगों द्वारा प्रतिस्थापित किया गया है:

  • api: आप अपने स्वयं के इंटरफ़ेस के माध्यम से इस मॉड्यूल के इंटरफ़ेस को लीक करते हैं, जिसका अर्थ पुराने compileनिर्भरता के समान है

  • implementation: आप केवल इस मॉड्यूल का उपयोग आंतरिक रूप से करते हैं और इसे अपने इंटरफ़ेस के माध्यम से लीक नहीं करते हैं

तो अब आप स्पष्ट रूप से ग्रेड को एक मॉड्यूल को फिर से शुरू करने के लिए कह सकते हैं यदि एक प्रयुक्त मॉड्यूल का इंटरफ़ेस बदलता है या नहीं।

जेरेन मोल्स ब्लॉग के सौजन्य से


2
स्वच्छ और संक्षिप्त विवरण। धन्यवाद!
लियोन - हान ली

20
+--------------------+----------------------+-------------+--------------+-----------------------------------------+
| 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.  |
+--------------------+----------------------+-------------+--------------+-----------------------------------------+

सीधे सवाल का जवाब नहीं देता
skryvets

1
वहाँ भी एक विकास है
होहेंहिमसेंबर्ग

यदि मुझे रनटाइम और कंपाइल टाइम दोनों की आवश्यकता हो तो मुझे क्या उपयोग करना चाहिए? वर्तमान में, मैं एक के implementationबाद है runtime
मैरून

8

आम आदमी के कार्यकाल में संक्षिप्त अंतर है:

  • यदि आप एक ऐसे इंटरफ़ेस या मॉड्यूल पर काम कर रहे हैं, जो आपके द्वारा बताई गई निर्भरता के सदस्यों को उजागर करके अन्य मॉड्यूल को सहायता प्रदान करता है, तो आपको 'एप' का उपयोग करना चाहिए।
  • यदि आप एक एप्लिकेशन या मॉड्यूल बना रहे हैं जो आंतरिक रूप से बताई गई निर्भरता को लागू करने या उपयोग करने जा रहा है, तो 'कार्यान्वयन' का उपयोग करें।
  • as संकलन ’ने i आपी’ के समान काम किया है, हालांकि, यदि आप केवल किसी पुस्तकालय का कार्यान्वयन या उपयोग कर रहे हैं, तो 'कार्यान्वयन ’बेहतर काम करेगा और आपको संसाधनों को बचाएगा।

व्यापक उदाहरण के लिए @aldok द्वारा उत्तर पढ़ें।


लेकिन बात यह है कि अगर कोई व्यक्ति जानबूझकर इन सवालों के जवाब की तलाश में यहां आया है, तो वह एक आम आदमी नहीं है।
रिशव

6

5.6.3 संस्करण के बाद से ग्रेडल प्रलेखन एक पुराने compileनिर्भरता (या एक नया) को implementationएक apiनिर्भरता के साथ प्रतिस्थापित किया जाना चाहिए या नहीं यह पहचानने के लिए अंगूठे के सरल नियम प्रदान करते हैं :

  • संभव होने implementationपर कॉन्फ़िगरेशन को प्राथमिकता देंapi

यह उपभोक्ता के संकलित वर्गपथ पर निर्भरता को दूर रखता है। इसके अलावा, यदि उपभोक्ता किसी भी प्रकार के गलती से सार्वजनिक एपीआई में लीक हो जाते हैं, तो उपभोक्ता तुरंत संकलन करने में विफल होंगे।

तो आपको apiकॉन्फ़िगरेशन का उपयोग कब करना चाहिए ? एपीआई निर्भरता वह है जिसमें कम से कम एक प्रकार शामिल होता है जिसे लाइब्रेरी बाइनरी इंटरफ़ेस में उजागर किया जाता है, जिसे अक्सर इसके एबीआई (एप्लिकेशन इंटरफ़ेस इंटरफ़ेस) के रूप में संदर्भित किया जाता है। इसमें शामिल है, लेकिन यह तक सीमित नहीं है:

  • सुपर क्लास या इंटरफेस में उपयोग किए जाने वाले प्रकार
  • सार्वजनिक विधि मापदंडों में उपयोग किए जाने वाले प्रकार, जेनेरिक पैरामीटर प्रकार सहित (जहां सार्वजनिक कुछ ऐसा है जो संकलक को दिखाई देता है। अर्थात्, जावा दुनिया में निजी सदस्यों को सार्वजनिक, संरक्षित और पैकेज करता है)
  • सार्वजनिक क्षेत्रों में उपयोग किए जाने वाले प्रकार
  • सार्वजनिक एनोटेशन प्रकार

इसके विपरीत, निम्नलिखित सूची में उपयोग किया जाने वाला कोई भी प्रकार एबीआई के लिए अप्रासंगिक है, और इसलिए इसे एक implementationआश्रित के रूप में घोषित किया जाना चाहिए :

  • प्रकार विशेष रूप से विधि निकायों में उपयोग किया जाता है
  • प्रकार विशेष रूप से निजी सदस्यों में उपयोग किया जाता है
  • आंतरिक वर्गों में विशेष रूप से पाए जाने वाले प्रकार (ग्रेड के भविष्य के संस्करण आपको यह घोषित करने देंगे कि कौन से पैकेज सार्वजनिक एपीआई से संबंधित हैं)

6

Gradle 3.0 अगले बदलाव पेश किए:

  • compile -> api

    api कीवर्ड डिप्रेस्ड के समान है compile

  • compile -> implementation

    है बेहतर तरीका है क्योंकि कुछ फायदे हैं। निर्माण समय पर implementationकेवल एक स्तर तक निर्भरता को उजागर करें (निर्भरता रनटाइम पर उपलब्ध है)। परिणामस्वरूप आपके पास एक तेज़ बिल्ड है (उपभोक्ताओं को फिर से जोड़ने की कोई आवश्यकता नहीं है जो उच्चतर हैं तो 1 स्तर ऊपर)

  • provided -> compileOnly

    यह निर्भरता केवल संकलन समय में उपलब्ध है (निर्भरता रनटाइम पर उपलब्ध नहीं है)। यह निर्भरता सकर्मक नहीं हो सकती है .aar। यह संकलन समय एनोटेशन प्रोसेसर के साथ उपयोग किया जा सकता है और आपको अंतिम आउटपुट फ़ाइल को कम करने की अनुमति देता है

  • compile -> annotationProcessor

    बहुत समान है, compileOnlyलेकिन यह भी गारंटी देता है कि उपभोक्ता के लिए सकर्मक निर्भरता दिखाई नहीं देती है

  • apk -> runtimeOnly

    निर्भरता संकलन समय में उपलब्ध नहीं है, लेकिन रनटाइम पर उपलब्ध है।


तो दूसरे शब्दों में api = public, implementation = internalऔर compileOnly = private- मुझे इन कार्यों के लिए ऐसे उपनाम बनाने की आवश्यकता है क्योंकि वे सुपर भ्रामक हैं।
t3chb0t
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.