هل هناك طريقة لاستخدام الرؤوس المترجمة مسبقًا في VC++ دون الحاجة إلى stdafx.h؟

StackOverflow https://stackoverflow.com/questions/290034

سؤال

لدي مجموعة من التعليمات البرمجية القديمة التي أحتاج إلى كتابة اختبارات الوحدة لها.يستخدم الرؤوس المجمعة مسبقًا في كل مكان، لذا فإن جميع ملفات .cpp تقريبًا تعتمد على stdafx.h مما يجعل من الصعب كسر التبعيات لكتابة الاختبارات.

حدسي الأول هو إزالة جميع ملفات stdafx.h هذه، والتي تحتوي في معظمها على توجيهات #include ووضع تلك #includes مباشرة في الملفات المصدر حسب الحاجة.

وهذا من شأنه أن يجعل من الضروري إيقاف تشغيل الرؤوس المترجمة مسبقًا نظرًا لأنها تعتمد على وجود ملف مثل stdafx.h لتحديد مكان توقف الرؤوس المترجمة مسبقًا.

هل هناك طريقة للاحتفاظ بالرؤوس المترجمة مسبقًا دون تبعيات stdafx.h؟هل هناك طريقة أفضل للتعامل مع هذه المشكلة؟

هل كانت مفيدة؟

المحلول

نعم، هناك طريقة أفضل.

المشكلة، IMHO، مع "نمط المعالج" للرؤوس المترجمة مسبقًا هي أنها تشجع على الاقتران غير المطلوب وتجعل إعادة استخدام التعليمات البرمجية أصعب مما ينبغي.أيضًا، التعليمات البرمجية التي تمت كتابتها بأسلوب "فقط قم بلصق كل شيء في stdafx.h" من المحتمل أن تكون صعبة الصيانة لأن تغيير أي شيء في أي ملف رأس من المحتمل أن يتسبب في إعادة ترجمة قاعدة التعليمات البرمجية بأكملها في كل مرة.وهذا يمكن أن يجعل إعادة البناء البسيطة تستغرق وقتًا طويلاً، حيث تستغرق كل دورة تغيير وإعادة ترجمة وقتًا أطول بكثير مما ينبغي.

الطريقة الأفضل، مرة أخرى IMHO، هي استخدام #pragma hdrstop و/Yc و/Yu.يمكّنك هذا من إعداد تكوينات البناء التي تستخدم الرؤوس المترجمة مسبقًا بسهولة وكذلك إنشاء التكوينات التي لا تستخدم الرؤوس المترجمة مسبقًا.الملفات التي تستخدم الرؤوس المترجمة مسبقًا لا تعتمد بشكل مباشر على الرأس المترجم مسبقًا نفسه في الملف المصدر مما يتيح إمكانية إنشائها باستخدام الرأس المترجم مسبقًا أو بدونه.يحدد ملف المشروع الملف المصدر الذي ينشئ الرأس المترجم مسبقًا ويحدد خط #pragma hdrstop في كل ملف مصدر أي التضمينات مأخوذة من الرأس المترجم مسبقًا (إذا تم استخدامه) والتي يتم أخذها مباشرة من الملف المصدر...هذا يعني أنه عند إجراء الصيانة، ستستخدم التكوين الذي لا يستخدم الرؤوس المترجمة مسبقًا ولن يتم إعادة إنشاء سوى الكود الذي تحتاج إلى إعادة بنائه بعد تغيير ملف الرأس.عند القيام بالبنيات الكاملة، يمكنك استخدام تكوينات الرأس المترجمة مسبقًا لتسريع عملية التجميع.شيء جيد آخر حول وجود خيار إنشاء رأس غير مترجم مسبقًا هو أنه يتأكد من أن ملفات cpp الخاصة بك تتضمن فقط ما يحتاجون إليه وتتضمن كل ما يحتاجون إليه (وهو أمر صعب إذا كنت تستخدم "نمط المعالج" للرأس المترجم مسبقًا.

لقد كتبت قليلاً عن كيفية عمل هذا هنا: http://www.lenholgate.com/blog/2004/07/fi-stlport-precompiled-headers-warning-level-4-and-pragma-hdrstop.html (تجاهل الأشياء المتعلقة بـ /FI) ولدي بعض الأمثلة على المشاريع التي تم إنشاؤها باستخدام طريقة #pragma hdrstop و/Yc /Yu هنا: http://www.lenholgate.com/blog/2008/04/practical-testing-16---fixing-a-timeout-bug.html .

بالطبع، غالبًا ما يكون الانتقال من استخدام الرأس المترجم مسبقًا "نمط المعالج" إلى نمط أكثر تحكمًا أمرًا غير تافه ...

نصائح أخرى

عندما تستخدم عادةً الرؤوس المترجمة مسبقًا، فإن "stdafx.h" يخدم غرضين.فهو يحدد مجموعة من ملفات التضمين المشتركة والمستقرة.وفي كل ملف .cpp أيضًا، فإنه يعمل بمثابة علامة تشير إلى المكان الذي تنتهي فيه الرؤوس المترجمة مسبقًا.

يبدو أن ما تريد القيام به هو:

  • اترك الرأس المترجم مسبقًا قيد التشغيل.
  • اترك تضمين "stdafx.h" في كل ملف .cpp.
  • قم بإفراغ التضمينات من "stdafx.h".
  • بالنسبة لكل ملف ‎.cpp، اكتشف ما هي التضمينات المطلوبة من ملف "stdafx.h" القديم.أضف هذه العناصر قبل تضمين "stdafx.h" في كل ملف .cpp.

إذن، لديك الآن الحد الأدنى من مجموعة التبعيات، وما زلت تستخدم الرؤوس المترجمة مسبقًا.الخسارة هي أنك لا تقوم بتجميع مجموعتك المشتركة من الرؤوس مرة واحدة فقط.سيكون هذا بمثابة ضربة كبيرة لإعادة البناء الكامل.بالنسبة لوضع التطوير، حيث تقوم فقط بإعادة ترجمة عدد قليل من الملفات في المرة الواحدة، سيكون ذلك أقل نجاحًا.

لا، هناك ربما <م> لا طريقة أفضل.

ومع ذلك، لملف .cpp بعينه، قد تقرر أنك لا تحتاج إلى رأس المترجمة مسبقا. هل يمكن تعديل إعدادات لهذا الملف .cpp واحد وإزالة السطر STDAFX.H.

و(في الواقع، على الرغم من أنني لا أعرف نظام رأس جمعها قبل وinterferring مع كتابة الاختبارات وحدتك).

ولا. رؤوس قبل تجميعها تعتمد على رأس واحد وشملت جميع مصادر جمعها بهذه الطريقة. يمكنك تحديد لمصدر واحد (أو كل) عدم استخدام رؤوس ما قبل تجميعها على الإطلاق، ولكن هذا ليس ما تريد.

في الماضي، لم مترجم بورلاند C ++ قبل تجميع دون رأس محدد. ومع ذلك، إذا تضمنت ملفين مصادر نفس الرؤوس ولكن في مختلف على النظام ، أو كانوا المترجمة بشكل منفصل، لأنه، في الواقع، من اجل رأس الملفات في C ++ يمكن أن يهم ...

وهكذا فإن ذلك يعني أن بورلاند رؤوس قبل تجميعها لم توفيرا للوقت إلا إذا قمت بتضمين جامد جدا المصادر في نفس النظام، أو كان لتشمل واحدة تضمن ملف (أولا) من قبل جميع الملفات الأخرى ... - يبدو مألوفا؟! ؟!

نعم. اسم "STDAFX.H / stdafx.pch" هو اصطلاح فقط. يمكنك إعطاء كل .CPP رأس المترجمة مسبقا الخاصة به. هذا ربما يكون أسهل لتحقيق من قبل برنامج نصي صغير لتحرير XML في .vcproj الخاص بك. الجانب السلبي: كنت في نهاية المطاف مع كومة كبيرة من رؤوس المترجمة مسبقا، وانهم ليسوا المشتركة بين لTU

وممكن، ولكن الذكي؟ لا أستطيع أن أقول على وجه اليقين.

نصيحتي هي - لا تقم بإزالة الرؤوس المترجمة مسبقًا إلا إذا كنت تريد أن تجعل بنياتك بطيئة بشكل مؤلم.لديك في الأساس ثلاثة خيارات هنا:

  1. تخلص من الرؤوس المترجمة مسبقًا (غير مستحسن)
  2. إنشاء مكتبة منفصلة للكود القديم؛بهذه الطريقة يمكنك بناءه بشكل منفصل.
  3. استخدم عدة رؤوس مجمعة مسبقًا ضمن مشروع واحد.يمكنك تحديد ملفات C++ فردية في Solution Explorer الخاص بك وإخبارهم بالرأس المترجم مسبقًا الذي يجب استخدامه.ستحتاج أيضًا إلى إعداد OtherStdAfx.h/cpp لإنشاء رأس مُجمَّع مسبقًا.
وتستند رؤوس

وقبل تجميعها على فكرة أن كل شيء سوف تشمل نفس مجموعة من الاشياء. إذا كنت ترغب في الاستفادة من رؤوس قبل تجميعها ثم عليك أن تعيش مع تبعيات هذا يعني. يتعلق الأمر الى انخفاض مفاضلة من تبعيات مقابل سرعة البناء. إذا يمكنك بناء في فترة زمنية معقولة مع رؤوس جمعت قبل إيقاف ثم بكل الوسائل تفعل ذلك.

وشيء آخر هو أن تنظر أنه يمكن أن يكون برستيج واحد في المكتبة. لذلك قد تكون قادرة على تقسيم الشفرة إلى مكتبات صغيرة ويكون لكل منهم مجموعة أكثر تشددا من التبعيات.

وأنا فقط استخدام رؤوس المترجمة مسبقا لرمز التي تحتاج لتشمل الاشياء afx___ - عادة مجرد واجهة المستخدم، وأنا لا وحدة الاختبار. كود UI يعالج UI ويدعو المهام التي لديها اختبارات وحدة (رغم أن معظم لا حاليا بسبب تركة التطبيق الراهن).

لمعظم رمز أنا لا تستخدم رؤوس المترجمة مسبقا.

وG.

يمكن أن توفر الرؤوس المترجمة مسبقًا الكثير من الوقت عند إعادة بناء المشروع، ولكن إذا تغير الرأس المترجم مسبقًا، كل سيتم إعادة ترجمة الملف المصدر اعتمادًا على الرأس، سواء كان التغيير يؤثر عليه أم لا.ولحسن الحظ، يتم استخدام الرؤوس المترجمة مسبقًا لـ ترجمة, ، لا وصلة; ليس من الضروري أن يستخدم كل ملف مصدر الملف نفس رأس تم تجميعه مسبقًا.

pch1.h:

#include <bigHeader1.h>
#include ...


pch1.cpp:

#include "pch1.h"


source1.cpp:

#include "pch1.h"
[code]


pch2.h:

#include <bigHeader2.h>
#include ...


pch2.cpp:

#include "pch2.h"


source2.cpp

#include "pch2.h"
[code]

يختار pch1.cpp, ، انقر على اليمين، الخصائص، خصائص التكوين، C/C++، الرؤوس المترجمة مسبقًا.
رأس مترجم مسبقًا: إنشاء(/Yc)
ملف الرأس المترجم مسبقًا: pch1.h
ملف إخراج الرأس المترجم مسبقًا:$(intDir)pch1.pch

يختار source1.cpp
رأس مترجم مسبقًا: استخدم(/يو)
ملف الرأس المترجم مسبقًا: pch1.h
ملف إخراج الرأس المترجم مسبقًا:$(intDir)pch1.pch (لا أعتقد أن هذا يهم /Yu)

افعل نفس الشيء من أجل pch2.cpp و source2.cpp, ، باستثناء تعيين الملف الاساسي و ملف إخراج الرأس ل pch2.h و pch2.pch.هذا يعمل بالنسبة لي.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top