المسار الذي تم اتّباعه حتى الآن
قبل عام، أعلن Chrome عن توفّر ميزة تصحيح أخطاء WebAssembly الأصلي في Chrome DevTools.
لقد عرضنا الدعم الأساسي للخطوات وتحدثنا عن الفرص التي يوفّرها لنا استخدام معلومات 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);
}
لتجميعه، نستخدم أحدث إصدار من Emscripten
ونُرسل علامة -g
، تمامًا كما هو الحال في المشاركة الأصلية، لتضمين معلومات debugging:
emcc -g temp.c -o temp.html
يمكننا الآن عرض الصفحة التي تم إنشاؤها من خادم HTTP على المضيف المحلي (مثل serve)، و فتحها في أحدث إصدار من Chrome Canary.
سنحتاج هذه المرة أيضًا إلى إضافة مساعدة تتكامل مع Chrome DevTools وتساعده في فهم جميع معلومات تصحيح الأخطاء المُشفَّرة في ملف WebAssembly. يُرجى تثبيتها من خلال الانتقال إلى هذا الرابط: goo.gle/wasm-debugging-extension
عليك أيضًا تفعيل تصحيح أخطاء WebAssembly في DevTools التجارب. افتح "أدوات مطوّري البرامج في Chrome"، وانقر على رمز الترس (⚙) في أعلى يسار لوحة "أدوات مطوّري البرامج"، وانتقِل إلى لوحة التجارب وضَع علامة في المربّع بجانب تصحيح أخطاء WebAssembly: تفعيل ميزة DWARF.
عند إغلاق الإعدادات، ستقترح عليك "أدوات مطوّري البرامج" إعادة تحميل نفسها لتطبيق الإعدادات، لذا لنفعل ذلك. لقد انتهينا من عملية الإعداد لمرة واحدة.
يمكننا الآن الرجوع إلى لوحة المصادر وتفعيل الإيقاف المؤقت عند الاستثناءات (رمز ⏸)، ثم وضع علامة في المربّع إيقاف مؤقت عند رصد الاستثناءات وإعادة تحميل الصفحة. من المفترض أن تظهر لك "أدوات مطوّري البرامج" متوقفة مؤقتًا عند استثناء:
يتوقف المسار تلقائيًا عند رمز ربط تم إنشاؤه بواسطة 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
عند الانتقال إلى الصفحة التي تم إنشاؤها في المتصفّح، يمكنني رؤية شكل الالتفاف الجميل ببعض الألوان العشوائية:
عند فتح أدوات المطوّرين، يمكنني مرة أخرى الاطّلاع على ملف C++ الأصلي. في هذه المرة، لن يظهر خطأ في الرمز البرمجي (يُحسَن)، لذا لنضع نقطة رصد في بداية الرمز البرمجي بدلاً من ذلك.
عند إعادة تحميل الصفحة مرة أخرى، سيتوقف مصحِّح الأخطاء مؤقتًا داخل مصدر C++ مباشرةً:
يمكننا رؤية جميع المتغيّرات على اليمين، ولكن تمّت بدء width
وheight
فقط في الوقت الحالي، لذا ليس هناك الكثير مما يمكن
فحصه.
لنضع نقطة توقّف أخرى داخل حلقة ماندلبروت الرئيسية، ونستأنف التنفيذ للانتقال إلى الأمام قليلاً.
في هذه المرحلة، تم ملء palette
ببعض الألوان العشوائية،
ويمكننا توسيع النطاق نفسه، بالإضافة إلى SDL_Color
الفردية
وفحص مكوّناتها للتأكّد من أنّ
كل شيء يبدو جيدًا (على سبيل المثال، يتم ضبط قناة "الشفافية" دائمًا
على مستوى الشفافية الكامل). وبالمثل، يمكننا توسيع الأجزاء الحقيقية والتخيّلية للعدد المركّب المخزّن في المتغيّر center
والتحقّق منها.
إذا كنت تريد الوصول إلى موقع إلكتروني مُدمَج بعمق يصعب بالتالي التنقّل إليه من خلال عرض النطاق، يمكنك استخدام تقييم وحدة التحكّم أيضًا. ومع ذلك، تجدر الإشارة إلى أنّ التعبيرات الأكثر تعقيدًا من C++ ليست متاحة بعد.
لنستأنف التنفيذ عدة مرات ونرى كيف يتم
تغيير x
الداخلي أيضًا، إما من خلال الاطّلاع على عرض النطاق مرة أخرى، أو من خلال إضافة اسم المتغيّر إلى قائمة المراقبة، أو تقييمه في وحدة التحكّم، أو من خلال التمرير فوق المتغيّر في رمز المصدر:
من هنا، يمكننا المتابعة أو التخطّي لبيان C++، وملاحظة كيفية تغيُّر المتغيّرات الأخرى أيضًا:
حسنًا، يعمل كل هذا بشكلٍ رائع عندما تتوفّر معلومات تصحيح الأخطاء، ولكن ماذا لو أردنا تصحيح أخطاء رمز لم يتم إنشاؤه باستخدام خيارات تصحيح الأخطاء؟
تصحيح أخطاء WebAssembly الأوّلي
على سبيل المثال، طلبنا من Emscripten توفير مكتبة SDL مُسبقة الإنشاء
لنا، بدلاً من تجميعها بأنفسنا من المصدر، لذا ليس هناك طريقة لبرنامج تصحيح الأخطاء للعثور على المصادر المرتبطة، على الأقل
حاليًا.
لنطّلِع مرة أخرى على SDL_RenderDrawColor
:
لقد عدنا إلى تجربة تصحيح أخطاء WebAssembly الأوّلية.
قد يبدو هذا الأمر مخيفًا بعض الشيء، وهو ليس شيئًا يحتاج إليه معظم مطوّري الويب مطلقًا، ولكن قد تحتاج أحيانًا إلى تصحيح أخطاء مكتبة تم إنشاؤها بدون معلومات تصحيح الأخطاء، سواءً كانت مكتبة تابعة لجهة خارجية لا يمكنك التحكّم فيها أو لأنّك تواجه أحد الأخطاء التي تحدث في مرحلة الإنتاج فقط.
للمساعدة في هذه الحالات، أجرينا أيضًا بعض التحسينات على تجربة debugging الأساسية.
أولاً، إذا سبق لك استخدام تصحيح أخطاء WebAssembly الأوّلي، قد
تلاحظ أنّ عملية التفكيك بالكامل تظهر الآن في ملف واحد، ما يُغنيك عن تخمين الوظيفة التي يتوافق معها إدخال المصادر wasm-53834e3e/
wasm-53834e3e-7
.
مخطّط جديد لإنشاء الأسماء
لقد أجرينا أيضًا تحسينات على الأسماء في طريقة عرض التفكيك. في السابق، كان يظهر أمامك فقط فهارس رقمية، أو لا يظهر أي اسم على الإطلاق في حال استخدام الدوالّ.
ننشئ الآن الأسماء بالطريقة نفسها التي تستخدمها أدوات التفكيك الأخرى، وذلك باستخدام
التلميحات من قسم أسماء WebAssembly،
ومسارات الاستيراد/التصدير، وأخيرًا، إذا تعذّر إنشاء الأسماء بأي طريقة أخرى، يتم إنشاؤها
استنادًا إلى النوع والفهرس الخاص بالعنصر، مثل $func123
. يمكنك في لقطة الشاشة أعلاه الاطّلاع على كيفية مساعدة ذلك في الحصول على تتبعات تسلسل استدعاء الدوال البرمجية وعمليات التفكيك التي يمكن قراءتها بشكلٍ أفضل.
عندما لا تتوفّر معلومات عن النوع، قد يكون من الصعب فحص أي قيم غير القيم الأساسية. على سبيل المثال، ستظهر المؤشرات كأرقام صحيحة عادية، بدون أي طريقة لمعرفة ما يتم تخزينه في الذاكرة.
فحص الذاكرة
في السابق، كان بإمكانك توسيع عنصر ذاكرة WebAssembly فقط، الذي يُمثّله الرمز env.memory
في عرض النطاق، للبحث عن ملف شخصي
بايت فردي. كان هذا الإجراء مناسبًا في بعض السيناريوهات البسيطة، ولكنه لم يكن
مناسبًا بشكل خاص للتوسيع ولم يسمح بإعادة تفسير البيانات
بتنسيقات أخرى غير قيم البايت. أضفنا ميزة جديدة للمساعدة في حلّ هذه المشكلة أيضًا: أداة فحص الذاكرة.
إذا نقرت بزر الماوس الأيمن على env.memory
، من المفترض أن يظهر لك الآن خيار
جديد باسم فحص الذاكرة:
بعد النقر على هذا الخيار، سيظهر أداة فحص الذاكرة، والتي يمكنك من خلالها فحص ذاكرة WebAssembly في العرض الثنائي العشري وASCII، والانتقال إلى عناوين معيّنة، بالإضافة إلى تفسير البيانات بتنسيقات مختلفة:
سيناريوهات وتحذيرات متقدّمة
تحليل رمز WebAssembly
عند فتح "أدوات مطوّري البرامج"، يتم "تصنيف" رمز WebAssembly إلى إصدار
غير محسّن لتفعيل تصحيح الأخطاء. هذا الإصدار أبطأ بكثير،
ما يعني أنّه لا يمكنك الاعتماد على console.time
وperformance.now
وطرق أخرى لقياس سرعة الرمز البرمجي أثناء فتح DevTools، لأنّ الأرقام التي تحصل عليها لن تمثّل الأداء الفعلي
على الإطلاق.
بدلاً من ذلك، عليك استخدام لوحة الأداء في "أدوات المطوّر"، والتي ستُشغّل الرمز البرمجي بالسرعة الكاملة وتوفّر لك تحليلاً مفصّلاً للوقت الذي تمّ إنفاقه في الدوالّ المختلفة:
بدلاً من ذلك، يمكنك تشغيل تطبيقك مع إغلاق أدوات مطوّري البرامج، وفتحها بعد الانتهاء من فحص وحدة التحكّم.
سنعمل على تحسين سيناريوهات وضع الملفات الشخصية في المستقبل، ولكن في الوقت الحالي، يجب مراعاة بعض النقاط. للاطّلاع على مزيد من المعلومات حول WebAssembly وسيناريوهات التصنيف، يمكنك الاطّلاع على مستنداتنا حول مسار تجميع WebAssembly.
إنشاء التطبيقات وتصحيح الأخطاء عليها على أجهزة مختلفة (بما في ذلك Docker / المضيف)
عند إنشاء التطبيق في Docker أو على جهاز افتراضي أو على خادم إنشاء عن بُعد، من المحتمل أن تواجه حالات لا تتطابق فيها مسارات الملفات المصدر المستخدَمة أثناء عملية الإنشاء مع المسارات في نظام الملفات الخاص بك الذي يتم فيه تشغيل "أدوات مطوّري تطبيقات Chrome". في هذه الحالة، ستظهر الملفات في لوحة المصادر ولكن لن يتم تحميلها.
لحلّ هذه المشكلة، نفّذنا وظيفة ربط المسارات في خيارات إضافة C/C++. ويمكنك استخدامه لإعادة ربط المسارات العشوائية و مساعدة أدوات المطوّرين في تحديد مصادر البيانات.
على سبيل المثال، إذا كان المشروع على جهاز المضيف ضمن مسار
C:\src\my_project
، ولكن تم إنشاؤه داخل حاوية Docker حيث
تم تمثيل هذا المسار على أنّه /mnt/c/src/my_project
، يمكنك إعادة ربطه
مرة أخرى أثناء تصحيح الأخطاء من خلال تحديد هذه المسارات كبادئات:
تكون البادئة الأولى التي تمت مطابقتها هي "البادئة الفائزة". إذا كنت على دراية بأداة تصحيح أخطاء C++
أخرى، يشبه هذا الخيار الأمر set substitute-path
في GDB أو إعداد target.source-map
في LLDB.
تصحيح أخطاء النُسخ المحسَّنة
كما هو الحال مع أي لغات أخرى، يعمل تصحيح الأخطاء على أفضل نحو في حال كانت ميزة التحسينات متوقفة. قد تؤدي التحسينات إلى تضمين الدوالّ في بعضها أو إعادة ترتيب الرمز أو إزالة أجزاء من الرمز تمامًا، وقد يؤدي كل ذلك إلى إثارة ارتباك لدى أداة تصحيح الأخطاء وبالتالي لديك بصفتك المستخدم.
إذا لم تكن تمانع في تجربة تصحيح أخطاء أكثر محدودية وكنت لا تزال تريد
تصحيح أخطاء إصدار محسّن، ستعمل معظم التحسينات على النحو الذي هو عليه
المتوقّع، باستثناء تضمين الدوالّ البرمجية. نخطّط لمعالجة الصعوبات المتبقية في المستقبل، ولكن في الوقت الحالي، يُرجى استخدام -fno-inline
لإيقافها عند الترجمة باستخدام أي تحسينات على مستوى -O
، على سبيل المثال:
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
، وستتمكّن إضافة المساعِد من تحديد موقعه وتحميله عند فتح "أدوات المطوّر".
وعند دمج هذه الميزة مع التحسينات الموضّحة أعلاه، يمكن استخدامها لطرح إصدارات مُحسَّنة تقريبًا من تطبيقك، ثم تصحيح أخطاءها لاحقًا باستخدام ملف جانبي على الجهاز. في هذه الحالة، علينا أيضًا إلغاء عنوان URL المخزّن لمساعدة الإضافة في العثور على الملف الجانبي، على سبيل المثال:
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" أداة تصحيح أخطاء فعّالة وقوية، ليس فقط لتطبيقات JavaScript، بل أيضًا لتطبيقات C وC++، ما يسهّل أكثر من أي وقت مضى استخدام التطبيقات المُنشأة باستخدام مجموعة متنوعة من تكنولوجيات الويب المشترَكة على جميع المنصات.
مع ذلك، لم تنتهِ رحلتنا بعد. في ما يلي بعض الأمور التي سنعمل عليها من الآن فصاعدًا:
- إزالة المشاكل في تجربة تصحيح الأخطاء
- إضافة إمكانية استخدام أدوات تنسيق الأنواع المخصّصة
- العمل على تحسينات في ميزة التحليل لتطبيقات WebAssembly
- إتاحة تغطية التعليمات البرمجية لتسهيل العثور على التعليمات البرمجية غير المستخدَمة
- تحسين التوافق مع التعبيرات في تقييم وحدة التحكّم
- إضافة مزيد من اللغات
- …وغير ذلك
في الوقت الحالي، يُرجى مساعدتنا من خلال تجربة الإصدار التجريبي الحالي على الرمز البرمجي الخاص بك والإبلاغ عن أي مشاكل تم رصدها على الرابط التالي: https://issues.chromium.org/issues/new?noWizard=true&template=0&component=1456350.
تنزيل قنوات المعاينة
ننصحك باستخدام إصدار Canary أو Dev أو الإصدار التجريبي من Chrome كمتصفّح التطوير التلقائي. تتيح لك قنوات المعاينة هذه الوصول إلى أحدث ميزات DevTools، وتتيح لك اختبار واجهات برمجة تطبيقات منصات الويب المتطوّرة، وتساعدك في العثور على المشاكل في موقعك الإلكتروني قبل أن يعثر عليها المستخدمون.
التواصل مع فريق "أدوات مطوّري البرامج في Chrome"
استخدِم الخيارات التالية لمناقشة الميزات الجديدة أو التحديثات أو أي شيء آخر مرتبط بـ "أدوات مطوّري البرامج".
- يمكنك إرسال الملاحظات وطلبات الميزات إلينا على crbug.com.
- يمكنك الإبلاغ عن مشكلة في "أدوات مطوّري البرامج" باستخدام رمز خيارات إضافية > مساعدة > الإبلاغ عن مشكلة في "أدوات مطوّري البرامج" في "أدوات مطوّري البرامج".
- يمكنك نشر تغريدة على Twitter على @ChromeDevTools.
- يمكنك إضافة تعليقات على فيديوهات YouTube التي تعرض الميزات الجديدة في "أدوات مطوّري البرامج" أو فيديوهات YouTube التي تعرض نصائح حول "أدوات مطوّري البرامج".