कोको टच फ्रेमवर्क (सिम्युलेटर और डिवाइस के लिए) "निर्यात" कैसे करें?


107

Xcode 6 के साथ हमें खुद का डायनामिक बनाने की क्षमता मिलती है Cocoa Frameworks

यहां छवि विवरण दर्ज करें

वजह से:

  • सिम्युलेटर अभी भी 32-bitपुस्तकालय का उपयोग करते हैं

  • 1 जून, 2015 से ऐप स्टोर में प्रस्तुत किए गए एप्लिकेशन अपडेट में 64-बिट समर्थन शामिल होना चाहिए और इसे iOS 8 SDK ( developer.appl.com ) के साथ बनाया जाना चाहिए।

हमें डिवाइस और सिमुलेटर पर प्रोजेक्ट चलाने के लिए फैट लाइब्रेरी बनाना होगा। यानी फ्रेमवर्क में 32 और 64 बिट दोनों का समर्थन करें।

लेकिन मुझे कोई नियमावली नहीं मिली, भविष्य के एकीकरण के लिए सार्वभौमिक वसा फ्रेमवर्क को अन्य परियोजनाओं के साथ कैसे निर्यात किया जाए (और इस पुस्तकालय को किसी के साथ साझा करें)।

यहाँ पुन: पेश करने के लिए मेरे कदम हैं:

  1. सेट ONLY_ACTIVE_ARCH=NOमेंBuild Settings

    यहां छवि विवरण दर्ज करें

  2. (सुनिश्चित armv7 armv7s arm64 i386 x86_64करने के Architecturesलिए) समर्थन जोड़ें

यहां छवि विवरण दर्ज करें

  1. फ्रेमवर्क बनाएँ और इसे फाइंडर में खोलें:

यहां छवि विवरण दर्ज करें यहां छवि विवरण दर्ज करें

  1. इस फ्रेमवर्क को किसी अन्य प्रोजेक्ट में जोड़ें

वास्तविक परिणाम:

लेकिन अंत में मैं अभी भी उपकरणों और सिम्युलेटर पर इस ढांचे के साथ चल रहे प्रोजेक्ट के साथ समस्या है।

  • अगर मैं Debug-iphoneosफ़ोल्डर से फ्रेमवर्क लेता हूं - यह उपकरणों पर काम करता है और सिमुलेटर पर त्रुटि प्राप्त करता है:ld: symbol(s) not found for architecture i386

      xcrun lipo -info CoreActionSheetPicker

    वसा फ़ाइल में आर्किटेक्चर: CoreActionSheetPicker हैं: armv7 armv7s arm64

  • अगर मैं Debug-iphonesimulatorफ़ोल्डर से फ्रेमवर्क लेता हूं - यह सिमुलेटर पर काम करता है। और डिवाइस पर मेरी त्रुटि है:ld: symbol(s) not found for architecture arm64

      xcrun lipo -info CoreActionSheetPicker

    वसा फ़ाइल में आर्किटेक्चर: CoreActionSheetPicker हैं: i386 x86_64

तो, एक गतिशील ढांचा कैसे बनाएं जो उपकरणों और सिमुलेटर पर काम करता है?

Xcode 6 iOS से संबंधित यह उत्तर एक कोको टच फ्रेमवर्क बनाना - आर्किटेक्चर मुद्दों पर यह डुप्लिकेट नहीं है।


अपडेट करें:

मुझे इस मामले के लिए "गंदा हैक" मिला। नीचे मेरा जवाब देखें । अगर किसी को अधिक सुविधाजनक तरीका पता है - कृपया, मुझे बताएं!


डुप्लिकेट जारी करें stackoverflow.com/questions/24039470/…
एंड्रियस Steponavičius

@ AndriusSteponavičius यह सवाल 2 महीने पहले पूछा गया था।
स्काईविंदर जूल

हां, लेकिन वहाँ बहुत अधिक विस्तृत उत्तर हैं, जो मुझे लगता है कि उपयोगकर्ताओं को इसके बारे में पता होना चाहिए
एंड्रीस स्टेपोनवीसियस

बिल्ड सेटिंग्स में ONLY_ACTIVE_ARCH = NO सेट करना एक महत्वपूर्ण कदम है।
जेडीजाजा

अगर आप सिम्युलेटर ईवीएन पर इसे चलाना चाहते हैं तो आपके फ्रेमवर्क में i386 x86_64 स्लाइस दोनों की जरूरत है यदि आपका कंप्यूटर 64 बिट आर्किटैक्ट है !!! कठिन तरीका सीखा।
जेबेनी

जवाबों:


82

इस उत्तर की वास्तविकता यह है: जुलाई 2015. यह सबसे अधिक संभावना है कि चीजें बदल जाएंगी।

TLDR;

वर्तमान में Xcode में सार्वभौमिक वसा ढांचे के स्वचालित निर्यात के उपकरण नहीं हैं, इसलिए डेवलपर को lipoउपकरण के मैनुअल उपयोग का सहारा लेना चाहिए । इसके अलावा इस रडार के अनुसार AppStore डेवलपर जो फ्रेमवर्क के उपभोक्ता है, को प्रस्तुत करने से पहले lipoएक फ्रेमवर्क से सिम्युलेटर स्लाइस को बंद करने के लिए भी उपयोग करना चाहिए ।

लंबे समय तक जवाब इस प्रकार है


मैंने विषय में इसी तरह का शोध किया (उत्तर के निचले भाग में लिंक)।

मैं की तो मेरे अनुसंधान के साथ की Apple डेवलपर मंच, कार्थेज और क्षेत्र की परियोजनाओं और मेरे अपने प्रयोगों अन्वेषण पर आधारित था वितरण के बारे में कोई आधिकारिक दस्तावेज नहीं मिला था xcodebuild, lipo,codesign उपकरण।

Apple डेवलपर फ़ोरम थ्रेड से एम्बेडेड ऐप्पल के साथ लंबी बोली (मेरे साथ मार्कअप के साथ) यहाँ है :

फ्रेमवर्क प्रोजेक्ट से फ्रेमवर्क निर्यात करने का उचित तरीका क्या है?

वर्तमान में एकमात्र तरीका वही है जो आपने किया है:

  • सिम्युलेटर और iOS डिवाइस दोनों के लिए लक्ष्य बनाएं।
  • उस प्रोजेक्ट के लिए Xcode के DerivedData फ़ोल्डर में नेविगेट करें और एक ही फ्रेमवर्क में दो बायनेरिज़ को एक साथ लिपो करें। हालाँकि, जब आप Xcode में फ्रेमवर्क लक्ष्य का निर्माण करते हैं, तो सुनिश्चित करें कि 'नो के लिए एक्टिव आर्किटेक्चर केवल' का निर्माण करने वाली टारगेट सेटिंग को समायोजित करें। यह Xcode को कई द्विपदीय प्रकारों (arm64, armv7, आदि) के लिए लक्ष्य बनाने की अनुमति देगा। यही कारण है कि यह Xcode से काम करता है, लेकिन एक स्टैंडअलोन बाइनरी के रूप में नहीं।

  • इसके अलावा आप यह सुनिश्चित करना चाहेंगे कि योजना रिलीज़ रिलीज़ के लिए सेट हो और रिलीज़ के विरुद्ध फ्रेमवर्क लक्ष्य का निर्माण करें। यदि आपको अभी भी लाइब्रेरी लोड नहीं हो रही है, तो फ्रेम में कोड स्लाइस की जांच करें।

  • lipo -info MyFramworkBinaryपरिणाम का उपयोग करें और जांच करें ।

lipo -info MyFrameworkBinary

परिणाम है i386 x86_64 armv7 arm64

  • आधुनिक सार्वभौमिक ढांचे में 4 स्लाइस शामिल होंगे, लेकिन इसमें और अधिक शामिल हो सकते हैं: i386 x86_64 armv7 arm64 यदि आपको कम से कम यह 4 नहीं दिखता है तो बिल्ड एक्टिव आर्किटेक्चर सेटिंग के कारण इसे जोड़ा जाना चाहिए।

इस प्रक्रिया का वर्णन बहुत हद तक वैसा ही है जैसा @skywinder ने अपने जवाब में किया था।

इस तरह से कार्थेज लिपो का उपयोग करता है और दायरे लिपो का उपयोग करता है


महत्वपूर्ण विवरण

रडार है: Xcode 6.1.1 और 6.2: सिम्युलेटर स्लाइस वाले iOS फ्रेमवर्क को ऐप स्टोर में जमा नहीं किया जा सकता है और इसके चारों ओर एक लंबी चर्चा Realm # 1163 और Carthage # 188 पर की जा सकती है जो विशेष वर्कअराउंड में समाप्त हुई:

AppStore को प्रस्तुत करने से पहले iOS फ्रेमवर्क बायनेरी को सिम्युलेटर स्लाइस से वापस छीन लिया जाना चाहिए

कार्थेज का विशेष कोड है: CopyFrameworks और संबंधित दस्तावेज का टुकड़ा:

यह स्क्रिप्ट सार्वभौमिक बायनेरिज़ द्वारा ट्रिगर किए गए ऐप स्टोर सबमिशन बग के आसपास काम करती है ।

दायरे में विशेष स्क्रिप्ट होती है: स्ट्रिपफ्रेमवर्कशीश और संबंधित दस्तावेज का टुकड़ा:

यूनिवर्सल बायनेरिज़ संग्रह करते समय ऐप स्टोर सबमिशन बग के चारों ओर काम करने के लिए इस कदम की आवश्यकता होती है ।

इसके अलावा अच्छा लेख है: डायनामिक लाइब्रेरीज़ से Xcode में अनचाहे आर्किटेक्चर को अलग करना

मैंने खुद दायरे का उपयोग किया है strip-frameworks.shजो मेरे लिए पूरी तरह से बिना किसी संशोधन के काम करता है, हालांकि कोई भी खरोंच से लिखने के लिए स्वतंत्र है।


मेरे विषय का लिंक जिसे मैं पढ़ने की सलाह देता हूं क्योंकि इसमें इस प्रश्न का एक और पहलू है: कोड साइनिंग - iOS / OSX फ्रेमवर्क बनाना: क्या अन्य डेवलपर्स को वितरित करने से पहले उन्हें कोड करना आवश्यक है?


1
मैंने लाइपो का इस्तेमाल किया लेकिन जब सिम्युलेटर में फ्रेमवर्क बन रहा है तो यह क्लास के नाम के साथ अनसुलझे पहचानकर्ता को दिखा रहा है लेकिन डिवाइस में यह काम करता है। यदि बाइनरी के सिम्युलेटर संस्करण का उपयोग करें तो यह काम कर रहा है .. कोई विचार नहीं है?
सुसीम सामंत ११'१६ को

2
मुझे दिसंबर 2016 में Xcode 8.2 द्वारा बदल दिया गया कोई सबूत नहीं मिला है।: /
जियोफ्री विस्मैन

1
@Geoffrey, क्या यह Xcode 9.2 में बदल गया है या कुछ अलग है? यह मेरा पहली बार वितरण के लिए एक द्विआधारी ढांचा बना रहा है, और मैं पहले से ही डर गया हूं ...
स्कॉट्टीबी

यह थोड़ा सा नहीं किया है, दुख की बात है - नहीं कह सकता। सौभाग्य।
जेफ्री विस्मैन

57

यह इतना स्पष्ट समाधान नहीं है, लेकिन एक ही रास्ता है, जो मुझे लगता है:

  1. सेट ONLY_ACTIVE_ARCH=NOमेंBuild Settings

    • सिम्युलेटर के लिए पुस्तकालय बनाएँ
    • डिवाइस के लिए लाइब्रेरी बनाएं
  2. Productsअपने ढांचे के लिए कंसोल फ़ोल्डर में खोलें (आप इसे खुले ढांचे के फ़ोल्डर से और cd ..वहां से खोल सकते हैं )

यहां छवि विवरण दर्ज करें यहां छवि विवरण दर्ज करें

  1. इस स्क्रिप्ट को Productsफ़ोल्डर से चलाएँ । यह इस फोल्डर में फैट फ्रेमवर्क बनाता है। (या इसे मैन्युअल रूप से 3 में नीचे बताया गया है । 4. )

या:

  1. इस लिपि द्वारा लिपो का उपयोग करके इन 2 फ्रेमवर्क को मिलाएं ( YourFrameworkNameअपने फ्रेमवर्क नाम से बदलें )

    lipo -create -output "YourFrameworkName" "Debug-iphonesimulator/YourFrameworkName.framework/YourFrameworkName" "Debug-iphoneos/YourFrameworkName.framework/YourFrameworkName"
  2. मौजूदा ढांचे में से एक को नए बाइनरी से बदलें:

    cp -R Debug-iphoneos/YourFrameworkName.framework ./YourFrameworkName.framework
    mv YourFrameworkName ./YourFrameworkName.framework/YourFrameworkName

  1. लाभ: ./YourFrameworkName.framework- तैयार-टू-यूज़ वसा बाइनरी! आप इसे अपनी परियोजना में आयात कर सकते हैं!

प्रोजेक्ट के लिए, कार्यस्थानों में नहीं:

आप यहाँ वर्णित के रूप में इस जिप का उपयोग करने का प्रयास भी कर सकते हैं । लेकिन ऐसा लगता है, कि यह कार्यक्षेत्रों में परियोजनाओं के लिए काम नहीं करता है।


मैंने सोचा कि Apple अब वसा बायनेरी स्वीकार नहीं करता है। kodmunki.wordpress.com/2015/03/04/…
Monstieur

1
@skywinder क्या आपको वसा बाइनरी का उपयोग करने के लिए तैयार करने के लिए कोई अन्य सरल तरीका निर्यात कोको टच फ्रेमवर्क मिला? मैं ऊपर के समान दृष्टिकोण का उपयोग कर रहा हूं लेकिन मुझे यह पसंद नहीं है। Xcode में कुछ होना चाहिए जो प्रक्रिया को स्वचालित करता है।
देव जीआर

1
@ फिर भी नहीं .. इसीलिए मैंने अपना जवाब स्वीकार नहीं किया। फिर भी एक बेहतर समाधान की तलाश में।
स्काइविंदर

1
सिम्युलेटर में नहीं चल सकता है लेकिन 3 और 4 चरणों के साथ डिवाइस में काम करता है
jose920405

1
@ किसी को भी केवल क्यों समझा Debug- फ़ोल्डर का उपयोग किया जाता है lipo -create? क्या इस ढांचे का उपयोग Releaseविन्यास के लिए किया जा सकता है और क्यों? धन्यवाद।
येविन दुबीनिन

10

@ सेटलेव का उत्तर बहुत मददगार था, लेकिन मैंने इसके बजाय फ्रेमवर्क के दो संस्करणों (डिवाइस के लिए एक और सिम्युलेटर के लिए) को संकलित करने के लिए क्या किया था और फिर Run Script Phaseचल रहे आर्किटेक्चर के लिए आवश्यक पूर्व-निर्धारित फ्रेमवर्क को स्वचालित रूप से कॉपी करने के लिए निम्नलिखित को जोड़ा।

echo "Copying frameworks for architecture: $CURRENT_ARCH"
if [ "${CURRENT_ARCH}" = "x86_64" ] || [ "${CURRENT_ARCH}" = "i386" ]; then
  cp -af "${SRCROOT}/Frameworks/Simulator/." "${SRCROOT}/Frameworks/Active"
else
  cp -af "${SRCROOT}/Frameworks/Device/." "${SRCROOT}/Frameworks/Active"
fi

इस तरह मेरे पास ऐप स्टोर में जमा करते समय अनावश्यक स्लाइस को हटाने lipoके strip-frameworks.shलिए न तो फैट फ्रेमवर्क बनाने का कोई उपयोग है और न ही दायरे का ।


आप किसके खिलाफ लिंक करते हैं?
जाका जनकर

@ JakaJančar मैं ${SRCROOT}/Frameworks/Activeफ़ोल्डर में लोगों के खिलाफ लिंक करता हूं । उन्हें संकलन समय पर सक्रिय वास्तुकला के लिए सही प्री-कम्पाइल किए गए फ्रेमवर्क के लिए प्रतिस्थापित किया जाता है।
ओड्म

2
इसे प्यार करना! यह कंबाइन-तब-आंसू-अलग-अलग lipoदृष्टिकोण की तुलना में बहुत सरल है ।
clozach

2

मूल रूप से इसके लिए मुझे बहुत अच्छा समाधान मिला। आपको बस इन सरल चरणों का पालन करने की आवश्यकता है।

  1. कोको टच फ्रेमवर्क बनाएं।
  2. बिटकोड सेट करें
  3. अपना लक्ष्य चुनें और संपादन योजनाएँ चुनें। चलाएँ का चयन करें और जानकारी टैब से रिलीज़ चुनें।
  4. किसी अन्य सेटिंग की आवश्यकता नहीं है।
  5. अब किसी भी सिम्युलेटर के लिए फ्रेमवर्क का निर्माण करें क्योंकि सिम्युलेटर x86 आर्किटेक्चर पर चलता है।
  6. प्रोजेक्ट नेविगेटर में उत्पाद समूह पर क्लिक करें और .framework फ़ाइल ढूंढें।
  7. इस पर राइट क्लिक करें और शो इन फाइंडर पर क्लिक करें। इसे किसी भी फ़ोल्डर में कॉपी और पेस्ट करें, मैं व्यक्तिगत रूप से 'सिम्युलेटर' नाम को पसंद करता हूं।
  8. अब जेनेरिक iOS डिवाइस के लिए फ्रेमवर्क का निर्माण करें और 9. के माध्यम से चरण 6 का पालन करें। बस 'सिम्युलेटर' के बजाय फ़ोल्डर को 'डिवाइस' में बदलें।
  9. डिवाइस को कॉपी करें। किसी भी अन्य निर्देशिका में .framework फाइल और पेस्ट करें। मैं दोनों की तत्काल सुपर निर्देशिका पसंद करता हूं। तो अब निर्देशिका संरचना बन गई है:
    • डेस्कटॉप
    • युक्ति
      • MyFramework.framework
    • सिम्युलेटर
      • MyFramework.framework
    • MyFramework.framework अब डेस्कटॉप पर cd और cd खोलें। अब निम्नलिखित कमांड टाइप करना शुरू करें:

lipo -create 'डिवाइस / MyFramework.framework / MyFramework' 'सिम्युलेटर / MyFramework.framework / MyFramework' -output 'MyFramework.framework / MyFramework

और बस। यहां हम MyFramework.framework के अंदर मौजूद MyFramework बाइनरी के सिम्युलेटर और डिवाइस संस्करण को मर्ज करते हैं। हमें एक सार्वभौमिक ढांचा मिलता है जो सिम्युलेटर और डिवाइस सहित सभी आर्किटेक्चर के लिए बनाता है।


मैं बिटकोड सक्षम के साथ FAT फ़ाइल बनाना चाहते हैं। कृपया मेरा मार्ग दर्शन कीजिए।
user3898700

2

मैं सिर्फ इस महान जवाब को @odm द्वारा अपडेट करना चाहता हूं। Xcode 10 के बाद से, CURRENT_ARCHचर अब बिल्ड आर्किटेक्चर को प्रतिबिंबित नहीं करता है। इसलिए मैंने इसके बजाय प्लेटफ़ॉर्म की जांच करने के लिए स्क्रिप्ट बदल दी:

echo "Copying frameworks for platform: $PLATFORM_NAME"
rm -R "${SRCROOT}/Frameworks/Active"
if [ "${PLATFORM_NAME}" = "iphonesimulator" ]; then
    cp -af "${SRCROOT}/Frameworks/Simulator/." "${SRCROOT}/Frameworks/Active"
else
    cp -af "${SRCROOT}/Frameworks/Device/." "${SRCROOT}/Frameworks/Active"
fi

मैंने प्रतिलिपि बनाने से पहले लक्ष्य निर्देशिका को साफ़ करने के लिए एक पंक्ति भी जोड़ दी, क्योंकि मैंने देखा कि उपनिर्देशिकाओं में अतिरिक्त फ़ाइलों को अन्यथा नहीं लिखा जाएगा।


1

मेरा उत्तर नीचे के बिंदुओं को कवर करता है:

  • सिम्युलेटर और डिवाइस दोनों के लिए काम करने वाली रूपरेखा तैयार करें

  • कोको टच फ्रेमवर्क (सिम्युलेटर और डिवाइस दोनों के लिए) कैसे निर्यात करें?

  • वास्तुकला के लिए अपरिभाषित प्रतीक x86_64

  • ld: आर्किटेक्चर x86_64 के लिए प्रतीक नहीं मिला

चरण 1: पहले सिम्युलेटर लक्ष्य के साथ अपने ढांचे का निर्माण करें

चरण 2: सिम्युलेटर निर्माण प्रक्रिया की सफलता के बाद, अब डिवाइस लक्ष्य चयन या जेनेरिक iOS डिवाइस चयन के साथ अपने ढांचे के लिए निर्माण करें

चरण 3: अब अपना फ्रेमवर्क लक्ष्य चुनें और इसके लिए "बिल्ड चरणों" के तहत "रन स्क्रिप्ट जोड़ें" चुनें और नीचे दिए गए स्क्रिप्ट कोड को कॉपी करें)

Step4: अब अंत में, फिर से निर्माण करें और आपका फ्रेमवर्क सिम्युलेटर और डिवाइस संगतता दोनों के लिए तैयार है। हुर्रे !!!!

[नोट: हमारे पास अंतिम चरण ४ (सिम्युलेटर और डिवाइस आर्किटेक्चर संगत) से पहले दोनों संगत रूपरेखा तैयार होनी चाहिए, यदि कृपया चरण १ और २ के ऊपर सही तरीके से पालन नहीं करते हैं)

संदर्भ चित्र देखें:

यहां छवि विवरण दर्ज करें

यहां छवि विवरण दर्ज करें

कोड को शेल क्षेत्र में डालें:

#!/bin/sh


UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal


# make sure the output directory exists

mkdir -p "${UNIVERSAL_OUTPUTFOLDER}"


# Step 1. Build Device and Simulator versions

xcodebuild -target "${PROJECT_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos  BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build

xcodebuild -target "${PROJECT_NAME}" -configuration ${CONFIGURATION} -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build


# Step 2. Copy the framework structure (from iphoneos build) to the universal folder

cp -R "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework" "${UNIVERSAL_OUTPUTFOLDER}/"


# Step 3. Copy Swift modules from iphonesimulator build (if it exists) to the copied framework directory

SIMULATOR_SWIFT_MODULES_DIR="${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework/Modules/${PROJECT_NAME}.swiftmodule/."

if [ -d "${SIMULATOR_SWIFT_MODULES_DIR}" ]; then

cp -R "${SIMULATOR_SWIFT_MODULES_DIR}" "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/Modules/${PROJECT_NAME}.swiftmodule"

fi


# Step 4. Create universal binary file using lipo and place the combined executable in the copied framework directory

lipo -create -output "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/${PROJECT_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework/${PROJECT_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework/${PROJECT_NAME}"


# Step 5. Convenience step to copy the framework to the project's directory

cp -R "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework" "${PROJECT_DIR}"


# Step 6. Convenience step to open the project's directory in Finder

open "${BUILD_DIR}/${CONFIGURATION}-universal"


यह स्क्रिप्ट अपने आप को बुलाती है और इस प्रकार एक अनंत लूप का कारण बनती है !! इसे चलाने के बाद मेरे कंप्यूटर को पुनरारंभ करना था! लगातार नई xcodebuild प्रक्रियाओं को पैदा कर रहा था ... और नए खोजक खिड़कियां खोल रहा था
जेबेनी

पुनरावृत्ति समस्या के बिना एक समान स्क्रिप्ट के लिए इस एसओ क्यू / ए में @ l0gg3r का उत्तर देखें ।
जेबेनी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.