अब तक की राह
एक साल पहले, Chrome ने Chrome DevTools में नेटिव WebAssembly की डीबगिंग के लिए, शुरुआती सहायता का एलान किया था.
हमने बुनियादी चरणों की सहायता के बारे में बताया. साथ ही, आने वाले समय में सोर्स मैप के बजाय DWARF की जानकारी का इस्तेमाल करने के अवसरों के बारे में भी बताया:
- वैरिएबल के नामों को हल करना
- प्रिटी-प्रिंट के टाइप
- सोर्स भाषाओं में एक्सप्रेशन का आकलन करना
- ...और ऐसी ही अन्य बातें!
आज, हमें यह बताते हुए खुशी हो रही है कि हमने जो सुविधाएं देने का वादा किया था वे अब उपलब्ध हैं. साथ ही, हम Emscripten और Chrome DevTools की टीमों की इस साल की उपलब्धियों के बारे में भी बताना चाहते हैं. खास तौर पर, C और C++ ऐप्लिकेशन के लिए की गई उपलब्धियों के बारे में.
शुरू करने से पहले, कृपया ध्यान रखें कि यह नए वर्शन का बीटा वर्शन है. आपको सभी टूल के नए वर्शन का इस्तेमाल, अपनी जोखिम पर करना होगा. अगर आपको कोई समस्या आती है, तो कृपया https://issues.chromium.org/issues/new?noWizard=true&template=0&component=1456350 पर जाकर शिकायत करें.
आइए, पिछले लेख में दिए गए C के उसी आसान उदाहरण से शुरू करते हैं:
#include <stdlib.h>
void assert_less(int x, int y) {
if (x >= y) {
abort();
}
}
int main() {
assert_less(10, 20);
assert_less(30, 20);
}
इसे कंपाइल करने के लिए, हम new Emscripten का इस्तेमाल करते हैं और डीबग की जानकारी को शामिल करने के लिए, मूल पोस्ट की तरह ही -g
फ़्लैग पास करते हैं:
emcc -g temp.c -o temp.html
अब जनरेट किए गए पेज को localhost एचटीटीपी सर्वर से दिखाया जा सकता है. उदाहरण के लिए, serve की मदद से. साथ ही, इसे Chrome Canary के नए वर्शन में खोला जा सकता है.
इस बार, हमें एक हेल्पर एक्सटेंशन की भी ज़रूरत होगी, जो Chrome DevTools के साथ इंटिग्रेट हो. साथ ही, WebAssembly फ़ाइल में एन्कोड की गई, डीबग करने से जुड़ी सारी जानकारी को समझने में मदद करता हो. कृपया इस लिंक पर जाकर इसे इंस्टॉल करें: goo.gle/vasm-debugging-extension
आपको DevTools के एक्सपेरिमेंट में, WebAssembly को डीबग करने की सुविधा भी चालू करनी होगी. Chrome DevTools खोलें. इसके बाद, DevTools पैनल के सबसे ऊपर दाएं कोने में मौजूद गियर (⚙) आइकॉन पर क्लिक करें. इसके बाद, प्रयोग पैनल पर जाएं और WebAssembly डीबगिंग: DWARF सपोर्ट चालू करें पर सही का निशान लगाएं.
सेटिंग बंद करने पर, DevTools खुद को फिर से लोड करने का सुझाव देगा, ताकि सेटिंग लागू की जा सकें. चलिए, अब ऐसा ही करें. एक बार के लिए सेटअप करने के लिए बस इतना ही.
अब हम सोर्स पैनल पर वापस जा सकते हैं और अपवाद मिलने पर रोकें (⏸ आइकॉन) को चालू कर सकते हैं. इसके बाद, पकड़े गए अपवादों पर रोकें को चुनें और पेज को फिर से लोड करें. आपको DevTools में, अपवाद पर रोके जाने की जानकारी दिखेगी:
डिफ़ॉल्ट रूप से, यह Emscripten से जनरेट किए गए ग्लू कोड पर रुक जाता है, लेकिन दाईं ओर आपको कॉल स्टैक व्यू दिखता है, जो गड़बड़ी के स्टैकट्रेस को दिखाता है. साथ ही, आपको उस ओरिजनल C लाइन पर नेविगेट करने की सुविधा मिलती है जो abort
को शुरू करती है:
अब स्कोप व्यू में जाकर, C/C++ कोड में वैरिएबल के ओरिजनल नाम और वैल्यू देखी जा सकती हैं. साथ ही, अब आपको यह पता लगाने की ज़रूरत नहीं है कि $localN
जैसे गलत नामों का क्या मतलब है और वे आपके लिखे गए सोर्स कोड से कैसे जुड़े हैं.
यह सिर्फ़ पूर्णांक जैसी प्राइमिटिव वैल्यू पर ही नहीं, बल्कि स्ट्रक्चर, क्लास, ऐरे वगैरह जैसे कंपाउंड टाइप पर भी लागू होता है!
रिच टाइप की सुविधा
आइए, इनके बारे में जानने के लिए एक ज़्यादा मुश्किल उदाहरण देखते हैं. इस बार, हम C++ के इस कोड की मदद से मंडेलब्रॉट फ़्रैक्टल बनाएंगे:
#include <SDL2/SDL.h>
#include <complex>
int main() {
// Init SDL.
int width = 600, height = 600;
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* window;
SDL_Renderer* renderer;
SDL_CreateWindowAndRenderer(width, height, SDL_WINDOW_OPENGL, &window,
&renderer);
// Generate a palette with random colors.
enum { MAX_ITER_COUNT = 256 };
SDL_Color palette[MAX_ITER_COUNT];
srand(time(0));
for (int i = 0; i < MAX_ITER_COUNT; ++i) {
palette[i] = {
.r = (uint8_t)rand(),
.g = (uint8_t)rand(),
.b = (uint8_t)rand(),
.a = 255,
};
}
// Calculate and draw the Mandelbrot set.
std::complex<double> center(0.5, 0.5);
double scale = 4.0;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
std::complex<double> point((double)x / width, (double)y / height);
std::complex<double> c = (point - center) * scale;
std::complex<double> z(0, 0);
int i = 0;
for (; i < MAX_ITER_COUNT - 1; i++) {
z = z * z + c;
if (abs(z) > 2.0)
break;
}
SDL_Color color = palette[i];
SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, color.a);
SDL_RenderDrawPoint(renderer, x, y);
}
}
// Render everything we've drawn to the canvas.
SDL_RenderPresent(renderer);
// SDL_Quit();
}
यह देखा जा सकता है कि यह ऐप्लिकेशन अब भी काफ़ी छोटा है-एक ऐसी फ़ाइल है जिसमें 50 लाइनों के कोड होते हैं, लेकिन इस बार मैं कुछ बाहरी एपीआई का भी इस्तेमाल कर रहा/रही हूं, जैसे कि ग्राफ़िक के लिए SDL लाइब्रेरी और C++ स्टैंडर्ड लाइब्रेरी के जटिल नंबर.
मैं इसे ऊपर दिए गए -g
फ़्लैग के साथ ही कंपाइल करूंगा, ताकि डीबग करने से जुड़ी जानकारी शामिल की जा सके. साथ ही, मैं Emscripten से SDL2 लाइब्रेरी उपलब्ध कराने और मनमुताबिक साइज़ की मेमोरी इस्तेमाल करने की अनुमति देने के लिए कहूंगा:
emcc -g mandelbrot.cc -o mandelbrot.html \ -s USE_SDL=2 \ -s ALLOW_MEMORY_GROWTH=1
ब्राउज़र में जनरेट किए गए पेज पर जाने पर, मुझे कुछ रंगों के साथ खूबसूरत फ़्रैक्टल आकार दिखता है:
DevTools खोलने पर, मुझे फिर से ओरिजनल C++ फ़ाइल दिखती है. हालांकि, इस बार कोड में कोई गड़बड़ी नहीं है (वाह!), इसलिए अपने कोड की शुरुआत में कुछ ब्रेकपॉइंट सेट करें.
जब हम पेज को फिर से लोड करेंगे, तो डीबगर हमारे C++ सोर्स में ही रुक जाएगा:
हमें दाईं ओर अपने सभी वैरिएबल पहले से दिख रहे हैं. हालांकि, फ़िलहाल सिर्फ़ width
और height
को शुरू किया गया है. इसलिए, जांचने के लिए ज़्यादा कुछ नहीं है.
आइए, अपने मुख्य मैंडलब्रॉट लूप में एक और ब्रेकपॉइंट सेट करें और थोड़ा आगे जाने के लिए, प्रोग्राम को फिर से शुरू करें.
इस समय, हमारे palette
में कुछ रंग भरे गए हैं. साथ ही, हम ऐरे और अलग-अलग SDL_Color
स्ट्रक्चर, दोनों को बड़ा कर सकते हैं. साथ ही, उनके कॉम्पोनेंट की जांच करके यह पुष्टि कर सकते हैं कि सब कुछ ठीक है या नहीं. उदाहरण के लिए, "अल्फा" चैनल हमेशा पूरी ओपैसिटी पर सेट है. इसी तरह, center
वैरिएबल में सेव की गई कॉम्प्लेक्स संख्या के रीयल और इमेजरी पार्ट को बड़ा करके देखा जा सकता है.
अगर आपको किसी ऐसी प्रॉपर्टी को ऐक्सेस करना है जो स्कोप व्यू से ऐक्सेस करना मुश्किल है, तो कंसोल के आकलन का इस्तेमाल किया जा सकता है! हालांकि, ध्यान दें कि फ़िलहाल C++ के ज़्यादा जटिल एक्सप्रेशन काम नहीं करते.
आइए, कुछ समय के लिए फ़ंक्शन को फिर से शुरू करें. इससे हमें यह पता चलेगा कि अंदर मौजूद x
भी कैसे बदल रहा है. इसके लिए, स्कोप व्यू में फिर से देखें, वॉच लिस्ट में वैरिएबल का नाम जोड़ें, कंसोल में उसका आकलन करें या सोर्स कोड में वैरिएबल पर कर्सर घुमाएं:
यहां से, हम C++ स्टेटमेंट पर चरण-दर-चरण या चरण-दर-चरण जोड़ सकते हैं. साथ ही, देख सकते हैं कि दूसरे वैरिएबल भी कैसे बदल रहे हैं:
ठीक है, डीबग करने की जानकारी उपलब्ध होने पर यह तरीका बहुत अच्छा काम करता है. हालांकि, अगर हमें ऐसे कोड को डीबग करना हो जिसे डिबग करने के विकल्पों के साथ नहीं बनाया गया है, तो क्या होगा?
रॉ WebAssembly डीबगिंग
उदाहरण के लिए, हमने Emscripten से कहा कि वह हमारे लिए खुद को इकट्ठा करने के बजाय, पहले से बनी एसडीएल लाइब्रेरी उपलब्ध कराए. इसलिए, कम से कम फ़िलहाल, डीबगर के लिए इससे जुड़े सोर्स को ढूंढने का कोई तरीका नहीं है.
SDL_RenderDrawColor
में जाने के लिए, फिर से शुरू करें:
हम WebAssembly को डीबग करने के पुराने तरीके पर वापस आ गए हैं.
यह थोड़ा डरावना लगता है और यह ऐसा नहीं है कि ज़्यादातर वेब डेवलपर को समस्या हल करने की ज़रूरत न पड़े. हालांकि, कभी-कभी ऐसा हो सकता है कि आप डीबग की जानकारी के बिना बनाई गई लाइब्रेरी को डीबग करना चाहें. भले ही, यह तीसरे पक्ष की ऐसी लाइब्रेरी हो जिस पर आपका कोई कंट्रोल न हो या फिर कोई ऐसी गड़बड़ी हो रही हो जो सिर्फ़ प्रोडक्शन में होती है.
ऐसे मामलों में मदद करने के लिए, हमने डिबग करने के बुनियादी तरीके में भी कुछ सुधार किए हैं.
सबसे पहले, अगर आपने पहले कभी रॉ WebAssembly डीबगिंग का इस्तेमाल किया है, तो आपको पता चल सकता है कि अब पूरी डिसअसेम्बली एक ही फ़ाइल में दिखती है. अब यह अनुमान लगाने की ज़रूरत नहीं है कि सोर्स एंट्री wasm-53834e3e/
wasm-53834e3e-7
किस फ़ंक्शन से जुड़ी है.
नाम जनरेट करने की नई स्कीम
हमने डिसएसेम्बली व्यू में भी नामों को बेहतर बनाया है. पहले आपको सिर्फ़ संख्या वाले इंडेक्स दिखते थे या फ़ंक्शन के मामले में, कोई नाम नहीं दिखता था.
अब हम डिसअसेम्बल करने वाले अन्य टूल की तरह ही नाम जनरेट कर रहे हैं. इसके लिए, हम WebAssembly के नाम वाले सेक्शन और इंपोर्ट/एक्सपोर्ट पाथ से मिले हिंट का इस्तेमाल करते हैं. अगर इनसे भी नाम जनरेट नहीं हो पाता है, तो हम $func123
जैसे आइटम के टाइप और इंडेक्स के आधार पर नाम जनरेट करते हैं. ऊपर दिए गए स्क्रीनशॉट में देखा जा सकता है कि इससे पहले से ही, थोड़ा बेहतर स्टैक ट्रेस और डिसअसेम्बली पाने में मदद मिलती है.
जब कोई टाइप की जानकारी उपलब्ध न हो, तो प्रिमिटिव के अलावा किसी भी वैल्यू की जांच करना मुश्किल हो सकता है. उदाहरण के लिए, पॉइंटर, नियमित पूर्णांक के तौर पर दिखेंगे. उन्हें यह पता नहीं चलेगा कि मेमोरी में उनके पीछे क्या सेव है.
मेमोरी की जांच
पहले, अलग-अलग बाइट देखने के लिए सिर्फ़ WebAssembly मेमोरी ऑब्जेक्ट को बड़ा किया जा सकता था. इसे स्कोप व्यू में env.memory
के ज़रिए दिखाया जाता था. यह कुछ सामान्य स्थितियों में काम करता था, लेकिन इसे बड़ा करना खास तौर पर आसान नहीं था. साथ ही, इससे बाइट वैल्यू के अलावा किसी दूसरे फ़ॉर्मैट में डेटा को फिर से समझने की अनुमति नहीं मिलती थी. हमने इस काम में आपकी मदद करने के लिए, एक नई सुविधा भी जोड़ी है: लीनियर मेमोरी इंस्पेक्टर.
env.memory
पर राइट क्लिक करने पर, आपको मेमोरी की जांच करें नाम का एक नया विकल्प दिखेगा:
क्लिक करने के बाद, आपको एक मेमोरी इंस्पेक्टर दिखेगा. इसमें, हेक्साडेसिमल और ASCII व्यू में WebAssembly मेमोरी की जांच की जा सकती है. साथ ही, खास पतों पर नेविगेट किया जा सकता है और डेटा को अलग-अलग फ़ॉर्मैट में देखा जा सकता है:
बेहतर स्थितियां और सावधानियां
WebAssembly कोड की प्रोफ़ाइल बनाई जा रही है
DevTools खोलने पर, WebAssembly कोड को डीबग करने की सुविधा चालू करने के लिए, "कम परफ़ॉर्म करने वाले वर्शन" में "कम किया जाता है". यह वर्शन काफ़ी धीमा है. इसका मतलब है कि DevTools खुले होने पर, console.time
, performance.now
, और कोड की स्पीड को मेज़र करने के अन्य तरीकों पर भरोसा नहीं किया जा सकता. ऐसा इसलिए, क्योंकि आपको जो संख्याएं मिलेंगी वे असल परफ़ॉर्मेंस को बिलकुल नहीं दिखाएंगी.
इसके बजाय, आपको DevTools परफ़ॉर्मेंस पैनल का इस्तेमाल करना चाहिए. यह कोड को पूरी स्पीड से चलाएगा और आपको अलग-अलग फ़ंक्शन में बिताए गए समय की पूरी जानकारी देगा:
इसके अलावा, DevTools बंद करके भी ऐप्लिकेशन को चलाया जा सकता है. इसके बाद, कंसोल की जांच करने के लिए, DevTools खोलें.
हम आने वाले समय में, प्रोफ़ाइल बनाने की सुविधा को बेहतर बनाएंगे. हालांकि, फ़िलहाल इस बात का ध्यान रखें. अगर आपको वेब असेंबली के टीयर करने के उदाहरणों के बारे में ज़्यादा जानना है, तो वेब असेंबली कंपाइलेशन पाइपलाइन के बारे में हमारे दस्तावेज़ देखें.
अलग-अलग मशीनों (Docker / होस्ट सहित) पर बिल्ड करना और डीबग करना
Docker, वर्चुअल मशीन या रिमोट बिल्ड सर्वर में बिल्ड करते समय, आपको ऐसी स्थितियों का सामना करना पड़ सकता है जहां बिल्ड के दौरान इस्तेमाल की गई सोर्स फ़ाइलों के पाथ, आपके फ़ाइल सिस्टम के उन पाथ से मेल नहीं खाते जहां Chrome DevTools चल रहे हैं. इस मामले में, फ़ाइलें सोर्स पैनल में दिखेंगी, लेकिन लोड नहीं होंगी.
इस समस्या को ठीक करने के लिए, हमने C/C++ एक्सटेंशन के विकल्पों में पाथ मैपिंग की सुविधा लागू की है. इसका इस्तेमाल, मनमुताबिक पाथ को फिर से मैप करने और DevTools को सोर्स ढूंढने में मदद करने के लिए किया जा सकता है.
उदाहरण के लिए, अगर आपकी होस्ट मशीन पर प्रोजेक्ट, पाथ C:\src\my_project
में है, लेकिन उसे Docker कंटेनर में बनाया गया था, जहां उस पाथ को /mnt/c/src/my_project
के तौर पर दिखाया गया था, तो डीबग करने के दौरान उसे फिर से मैप किया जा सकता है. इसके लिए, उन पाथ को प्रीफ़िक्स के तौर पर बताएं:
पहला मेल खाने वाला प्रीफ़िक्स "wins". अगर आपको C++ के अन्य डीबगर के बारे में पता है, तो यह विकल्प GDB में set substitute-path
कमांड या LLDB में target.source-map
सेटिंग जैसा ही है.
ऑप्टिमाइज़ किए गए बिल्ड को डीबग करना
किसी भी दूसरी भाषा की तरह, ऑप्टिमाइज़ेशन बंद होने पर डीबग करने की प्रोसेस सबसे अच्छी तरह काम करती है. ऑप्टिमाइज़ेशन की वजह से, फ़ंक्शन एक-दूसरे में इनलाइन हो सकते हैं, कोड का क्रम बदल सकता है या कोड के कुछ हिस्से हट सकते हैं. इन सभी वजहों से, डीबगर और उपयोगकर्ता को भ्रम हो सकता है.
अगर आपको डीबग करने के सीमित अनुभव से कोई फ़र्क़ नहीं पड़ता और आपको ऑप्टिमाइज़ किए गए बिल्ड को डीबग करना है, तो फ़ंक्शन इनलाइन करने के अलावा, ज़्यादातर ऑप्टिमाइज़ेशन उम्मीद के मुताबिक काम करेंगे. हम आने वाले समय में बाकी समस्याओं को हल करेंगे.हालांकि, फ़िलहाल -O
लेवल के ऑप्टिमाइज़ेशन के साथ कंपाइल करते समय, इसे बंद करने के लिए -fno-inline
का इस्तेमाल करें. उदाहरण के लिए:
emcc -g temp.c -o temp.html \ -O3 -fno-inline
डीबग की जानकारी को अलग करना
डीबग करने से जुड़ी जानकारी में, आपके कोड, तय किए गए टाइप, वैरिएबल, फ़ंक्शन, स्कोप, और जगहों के बारे में बहुत सारी जानकारी सेव होती है. इसमें ऐसी कोई भी जानकारी शामिल हो सकती है जो डीबगर के लिए काम की हो. इस वजह से, यह अक्सर कोड से बड़ा हो सकता है.
WebAssembly मॉड्यूल को तेज़ी से लोड और कंपाइल करने के लिए, हो सकता है कि आप इस डीबग जानकारी को अलग WebAssembly फ़ाइल में बांटना चाहें. Emscripten में ऐसा करने के लिए, अपनी पसंद के फ़ाइल नाम के साथ -gseparate-dwarf=…
फ़्लैग पास करें:
emcc -g temp.c -o temp.html \ -gseparate-dwarf=temp.debug.wasm
इस मामले में, मुख्य ऐप्लिकेशन सिर्फ़ फ़ाइल का नाम temp.debug.wasm
सेव करेगा. साथ ही, DevTools खोलने पर, हेल्पर एक्सटेंशन उसे ढूंढकर लोड कर पाएगा.
ऊपर बताए गए ऑप्टिमाइज़ेशन के साथ इस्तेमाल करने पर, इस सुविधा का इस्तेमाल आपके ऐप्लिकेशन के करीब-करीब ऑप्टिमाइज़ किए गए प्रोडक्शन बिल्ड भेजने के लिए भी किया जा सकता है. बाद में, इस सुविधा का इस्तेमाल स्थानीय साइड फ़ाइल की मदद से उन्हें डीबग करने के लिए भी किया जा सकता है. इस मामले में, हमें एक्सटेंशन को साइड फ़ाइल ढूंढने में मदद करने के लिए, सेव किए गए यूआरएल को बदलना होगा. उदाहरण के लिए:
emcc -g temp.c -o temp.html \ -O3 -fno-inline \ -gseparate-dwarf=temp.debug.wasm \ -s SEPARATE_DWARF_URL=file://[local path to temp.debug.wasm]
जारी रखना है...
वाह, बहुत सारी नई सुविधाएं!
इन सभी नए इंटिग्रेशन के साथ, Chrome DevTools सिर्फ़ JavaScript के लिए ही नहीं, बल्कि C और C++ ऐप्लिकेशन के लिए भी एक बेहतर, कारगर और डीबगर बन गया है. इसकी वजह से, कई तरह की टेक्नोलॉजी में बनाए गए और शेयर किए गए क्रॉस-प्लैटफ़ॉर्म वेब पर ऐप्लिकेशन इस्तेमाल करना पहले से ज़्यादा आसान हो गया है.
हालांकि, हमारी यात्रा अभी पूरी नहीं हुई है. हम आगे इन चीज़ों पर काम करेंगे:
- डीबग करने की प्रोसेस को आसान बनाया जा रहा है.
- कस्टम टाइप फ़ॉर्मैटर के लिए सहायता जोड़ी गई है.
- WebAssembly ऐप्लिकेशन की प्रोफ़ाइलिंग को बेहतर बनाने के लिए, काम चल रहा है.
- कोड कवरेज के लिए सहायता जोड़ी गई है, ताकि इस्तेमाल न किए गए कोड को आसानी से ढूंढा जा सके.
- कंसोल के आकलन में एक्सप्रेशन के लिए सहायता को बेहतर बनाना.
- ज़्यादा भाषाओं के लिए सहायता जोड़ी जा रही है.
- …और ऐसे ही अन्य ट्रेंड!
इस दौरान, कृपया अपने कोड पर मौजूदा बीटा वर्शन का इस्तेमाल करके और उसमें मिली किसी भी समस्या की शिकायत करके, https://issues.chromium.org/issues/new?noWizard=true&template=0&component=1456350 पर जाएं.
झलक वाले चैनल डाउनलोड करना
Chrome कैनरी, डेवलपर या बीटा को अपने डिफ़ॉल्ट डेवलपमेंट ब्राउज़र के तौर पर इस्तेमाल करें. झलक दिखाने वाले इन चैनलों की मदद से, DevTools की नई सुविधाओं को ऐक्सेस किया जा सकता है. साथ ही, वेब प्लैटफ़ॉर्म के आधुनिक एपीआई को आज़माया जा सकता है. साथ ही, उपयोगकर्ताओं के उपलब्ध होने से पहले, अपनी साइट की समस्याओं का पता लगाया जा सकता है!
Chrome DevTools की टीम से संपर्क करना
DevTools से जुड़ी नई सुविधाओं, अपडेट या किसी भी अन्य चीज़ के बारे में चर्चा करने के लिए, यहां दिए गए विकल्पों का इस्तेमाल करें.
- crbug.com पर जाकर, हमें सुझाव/राय दें या शिकायत करें. साथ ही, किसी सुविधा का अनुरोध करें.
- DevTools में ज़्यादा विकल्प > सहायता > DevTools से जुड़ी समस्या की शिकायत करें का इस्तेमाल करके, DevTools से जुड़ी समस्या की शिकायत करें.
- @ChromeDevTools पर ट्वीट करें.
- DevTools के बारे में YouTube वीडियो में क्या नया है या DevTools के बारे में YouTube वीडियो में सलाह पर टिप्पणियां करें.