2008-11-14 5 views
10

मुझे विरासत कोड का एक गुच्छा मिला है जिसके लिए मुझे इकाई परीक्षण लिखने की आवश्यकता है। यह हर जगह प्री-कंपाइल हेडर का उपयोग करता है, इसलिए लगभग सभी .cpp फ़ाइलों में stdafx.h पर निर्भरता होती है जो परीक्षण लिखने के लिए निर्भरताओं को तोड़ना मुश्किल बनाता है।क्या stdafx.h की आवश्यकता के बिना वीसी ++ में प्री-कंपाइल हेडर का उपयोग करने का कोई तरीका है?

मेरा पहला वृत्ति इन सभी stdafx.h फ़ाइलों को निकालना है, जिनमें अधिकांश भाग के लिए # अंतर्निहित निर्देश होते हैं और उन # को सीधे स्रोत फ़ाइलों में शामिल करते हैं।

इससे पूर्व-संकलित शीर्षलेख बंद करना आवश्यक हो जाएगा क्योंकि यह निर्धारित करने के लिए कि प्री-संकलित हेडर कहां रुकते हैं, वे stdafx.h जैसी फ़ाइल रखने पर निर्भर हैं।

क्या stdafx.h निर्भरताओं के बिना पूर्व-संकलित शीर्षलेख रखने का कोई तरीका है? क्या इस समस्या से संपर्क करने का कोई बेहतर तरीका है?

+0

व्यक्तिगत तौर पर मैं precompiled हेडर (दोनों सामान्य कोड और इकाई परीक्षण के लिए) का उपयोग लेकिन नाम Precompiled.h/सीपीपी का उपयोग करें। यूनिट परीक्षणों के लिए प्रीकंपिल्ड हेडर में अतिरिक्त शीर्षलेख शामिल होते हैं ताकि संकलन तेज हो। – Daemin

+0

इस के लिए कृपया वोट: http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/4931119-allow-precompiled-headers-to-be-shared-between-pro –

+0

हाँ, वहाँ एक बेहतर है मार्ग। प्रत्येक स्रोत फ़ाइल के लिए केवल एक प्रीकंपील्ड हेडर का उपयोग किया जा सकता है, लेकिन पीएच को प्रत्येक * स्रोत फ़ाइल या स्रोत फ़ाइलों के सेट को निर्दिष्ट किया जा सकता है। आप यह भी निर्दिष्ट कर सकते हैं कि कौन सी स्रोत फाइलें प्रीकंपील्ड हेडर का उपयोग करती हैं या नहीं। नीचे मेरा जवाब देखें। – riderBill

उत्तर

9

हां, एक बेहतर तरीका है।

समस्या, आईएमएचओ, प्रीकंपिल्ड हेडर के 'जादूगर शैली' के साथ समस्या यह है कि वे बिना शर्त युग्मन को प्रोत्साहित करते हैं और कोड को पुन: उपयोग करने से कठिन बनाते हैं। साथ ही, कोड जो 'stdafx.h' शैली में बस सब कुछ छड़ी के साथ लिखा गया है, किसी भी हेडर फ़ाइल में कुछ भी बदलने के रूप में बनाए रखने के लिए दर्द होना प्रवण होता है, जिससे पूरे कोडबेस को हर बार फिर से सम्मिलित किया जा सकता है। यह सरल रिफैक्टरिंग हमेशा के लिए ले सकता है क्योंकि प्रत्येक परिवर्तन और पुन: संकलन चक्र इसे जितना लंबा लेना चाहिए।

एक बेहतर तरीका, फिर से IMHO, #pragma hdrstop और/yc और/yu का उपयोग करना है। यह आपको आसानी से बिल्ड कॉन्फ़िगरेशन सेट अप करने में सक्षम बनाता है जो प्रीकंपिल्ड हेडर का उपयोग करते हैं और कॉन्फ़िगरेशन भी बनाते हैं जो प्रीकंपिल्ड हेडर का उपयोग नहीं करते हैं। प्रीकंपील्ड हेडर का उपयोग करने वाली फ़ाइलों को प्रीकंपिल्ड हेडर पर सीधे स्रोत फ़ाइल में प्रत्यक्ष निर्भरता नहीं होती है जो उन्हें प्रीकंपिल्ड हेडर के साथ या बिना निर्माण करने में सक्षम बनाता है। प्रोजेक्ट फ़ाइल निर्धारित करती है कि कौन सी स्रोत फ़ाइल प्रीकंपिल्ड हेडर बनाता है और प्रत्येक स्रोत फ़ाइल में #pragma hdrstop लाइन निर्धारित करती है कि प्रीकंपील्ड हेडर (यदि उपयोग किया जाता है) से कौन सा शामिल किया जाता है और जो सीधे स्रोत फ़ाइल से लिया जाता है ... इसका मतलब है कि जब रखरखाव करना आप कॉन्फ़िगरेशन का उपयोग करेंगे जो प्रीकंपिल्ड हेडर का उपयोग नहीं करता है और केवल उस कोड को जिसे हेडर फ़ाइल परिवर्तन के बाद पुनर्निर्माण करने की आवश्यकता है, पुनर्निर्माण करेगा। पूर्ण निर्माण करते समय आप संकलन प्रक्रिया को तेज करने के लिए प्रीकंपील्ड हेडर कॉन्फ़िगरेशन का उपयोग कर सकते हैं।गैर-प्रीकंपील्ड हेडर बिल्ड विकल्प होने के बारे में एक और अच्छी बात यह है कि यह सुनिश्चित करता है कि आपकी सीपीपी फाइलों में केवल वही शामिल है जो उन्हें चाहिए और उन्हें जो कुछ भी चाहिए उसे शामिल करें (यदि आप प्रीकंपील्ड हेडर की 'जादूगर शैली' का उपयोग करते हैं तो कुछ मुश्किल है।

मैं यह कैसे कार्य करता के बारे में थोड़ा लिखा है: http://www.lenholgate.com/blog/2004/07/fi-stlport-precompiled-headers-warning-level-4-and-pragma-hdrstop.html (के बारे में/FI सामान की अनदेखी) और मैं कुछ उदाहरण परियोजनाओं कि #pragma hdrstop और/Yc/यू विधि यहाँ के साथ निर्माण किया है:। http://www.lenholgate.com/blog/2008/04/practical-testing-16---fixing-a-timeout-bug.html

बेशक, 'विज़ार्ड स्टाइल' से प्राप्त होने से अधिक नियंत्रित शैली में प्रीकंपिल्ड हेडर उपयोग अक्सर गैर-तुच्छ ...

+0

कृपया देखें: http://stackoverflow.com/questions/7282853/what-does-pragma-hdrstop-without-parameter-do-when-used-in-multiple-files - धन्यवाद। –

2

नहीं, शायद बेहतर तरीका नहीं है।

हालांकि, किसी दिए गए व्यक्ति के लिए .cpp फ़ाइल के लिए, आप यह तय कर सकते हैं कि आपको प्रीकंपील्ड हेडर की आवश्यकता नहीं है। आप उस .cpp फ़ाइल के लिए सेटिंग्स को संशोधित कर सकते हैं और stdafx.h लाइन को हटा सकते हैं।

(असल में, हालांकि, मुझे नहीं लगता कि प्री-कंपाइल हेडर योजना आपके यूनिट परीक्षणों के लेखन में हस्तक्षेप कर रही है)।

+0

हां, एक बेहतर तरीका है। नीचे मेरा जवाब देखें। @ लेन होल्गेट का जवाब भी काम करता है। – riderBill

2

नहीं पूर्व-संकलित शीर्षलेख इस तरह से संकलित सभी स्रोतों द्वारा शामिल एक शीर्षलेख पर निर्भर करता है। आप एक एकल स्रोत (या सभी) के लिए निर्दिष्ट कर सकते हैं कि पूर्व-संकलित शीर्षलेखों का उपयोग न करें, लेकिन यह वही नहीं है जो आप चाहते हैं।

अतीत में, बोर्लैंड सी ++ कंपाइलर ने एक विशिष्ट शीर्षलेख के बिना प्री-संकलन किया था। लेकिन, अगर दो स्रोतों फ़ाइलें एक ही हेडर शामिल है, लेकिन अलग अलग आदेश पर, वे अलग से, के बाद से, वास्तव में, C++ बात कर सकते हैं हेडर फाइल के आदेश ...

इस प्रकार यह मतलब है कि Borland पूर्व संकलित किया गया संकलित हेडर ने केवल समय बचाया है यदि आप बहुत ही कठोर रूप से उसी क्रम में स्रोतों को शामिल करते हैं, या इसमें एक ही फ़ाइल शामिल है (पहले) अन्य सभी फ़ाइलों द्वारा ... - परिचित लगता है?!?

+0

सच नहीं है; आप प्रत्येक अलग-अलग स्रोत फ़ाइल के लिए एक अलग प्रीकंपिल्ड हेडर निर्दिष्ट कर सकते हैं, या निर्दिष्ट कर सकते हैं कि कुछ सॉस फाइलें एक का उपयोग करती हैं और अन्य नहीं। – riderBill

1

मेरी सलाह है - प्रीकंपिल्ड हेडर को तब तक न हटाएं जब तक कि आप अपने निर्माण को दर्दनाक रूप से धीमा नहीं करना चाहते। आप मूल रूप से यहाँ तीन विकल्प हैं:

  1. precompiled हेडर से छुटकारा (अनुशंसित नहीं)
  2. विरासत कोड के लिए एक अलग पुस्तकालय बनाएं; इस तरह आप इसे अलग से बना सकते हैं।
  3. एक एकल प्रोजेक्ट के भीतर एकाधिक प्रीकंपील्ड हेडर का उपयोग करें। आप अपने समाधान एक्सप्लोरर में व्यक्तिगत सी ++ फाइलों का चयन कर सकते हैं और उन्हें बता सकते हैं कि कौन से प्रीकॉम्ड हेडर का उपयोग करना है। प्रीकंपील्ड हेडर उत्पन्न करने के लिए आपको अपने अन्य StdAfx.h/cpp को भी सेट अप करने की आवश्यकता होगी।
0

मैं केवल कोड के लिए प्री-कंपाइल हेडर का उपयोग करता हूं जिसमें afx___ सामान शामिल करने की आवश्यकता होती है - आमतौर पर केवल यूआई, जिसे मैं यूनिट-टेस्ट नहीं करता हूं। यूआई कोड यूआई को संभालता है और उन कार्यों को कॉल करता है जिनमें यूनिट-टेस्ट होते हैं (हालांकि वर्तमान में ऐप की विरासत होने के कारण अधिकांश नहीं हैं)।

कोड के बड़े हिस्से के लिए मैं पूर्व-संकलित शीर्षलेख का उपयोग नहीं करता हूं।

जी।

4

जब आप आमतौर पर प्रीकंपिल्ड हेडर का उपयोग करते हैं, तो "stdafx.h" 2 उद्देश्यों को पूरा करता है। यह स्थिर, सामान्य फाइलों के एक सेट को परिभाषित करता है। प्रत्येक .cpp फ़ाइल में भी, यह एक मार्कर के रूप में कार्य करता है जहां प्रीकंपिल्ड हेडर समाप्त होते हैं।

ऐसा लगता है कि आप क्या करना चाहते हैं:

  • छोड़ दो precompiled शीर्ष लेख पर दिया।
  • प्रत्येक .cpp फ़ाइल में "stdafx.h" को छोड़ दें।
  • "stdafx.h" से शामिल खाली करें।
  • प्रत्येक .cpp फ़ाइल के लिए, पुराने "stdafx.h" से जरूरी जानकारी शामिल है। प्रत्येक .cpp फ़ाइल में #include "stdafx.h" से पहले इन्हें जोड़ें।

तो अब आपके पास निर्भरता का न्यूनतम सेट है, और आप अभी भी प्रीकंपील्ड हेडर का उपयोग कर रहे हैं। नुकसान यह है कि आप केवल एक बार हेडर के अपने सामान्य सेट को प्रीकंपलिंग नहीं कर रहे हैं। यह एक पूर्ण पुनर्निर्माण के लिए एक बड़ी हिट होगी। विकास मोड के लिए, जहां आप एक समय में केवल कुछ फ़ाइलों को पुन: संकलित कर रहे हैं, यह एक हिट से कम होगा।

+0

धन्यवाद। मैंने इस दृष्टिकोण की विविधता पर फैसला किया। stdafx.h में केवल बाहरी पुस्तकालयों (विंडोज हेडर, एसटीएल, बूस्ट इत्यादि) शामिल हैं। सभी आंतरिक ऐप हेडर सीधे .cpp फ़ाइलों में शामिल किए जाने चाहिए। – Ferruccio

2

हां। "Stdafx.h/stdafx.pch" नाम सिर्फ सम्मेलन है। आप प्रत्येक .cpp को अपने स्वयं के प्रीकंपील्ड हेडर दे सकते हैं। यह आपके .vcproj में एक्सएमएल को संपादित करने के लिए शायद एक छोटी लिपि द्वारा हासिल करना सबसे आसान होगा। डाउनसाइड: आप प्रीकंपिल्ड हेडर के बड़े ढेर के साथ समाप्त होते हैं, और वे टीयू के बीच साझा नहीं होते हैं।

संभव, लेकिन स्मार्ट? मैं निश्चित रूप से नहीं कह सकता।

1

प्री-कंपाइल हेडर इस विचार पर आधारित हैं कि सब कुछ सामान के एक ही सेट को शामिल करेगा। यदि आप पूर्व-संकलित शीर्षलेखों का उपयोग करना चाहते हैं तो आपको निर्भरताओं के साथ रहना होगा जो इसका तात्पर्य है। यह बिल्डिंग गति बनाम निर्भरताओं के व्यापार-बंद होने के लिए आता है। यदि आप पूर्व-संकलित शीर्षलेखों के साथ उचित समय में बंद कर सकते हैं तो हर तरह से इसे करें।

विचार करने की एक और बात यह है कि आपके पास प्रति पुस्तकालय एक पीएचसी हो सकती है। तो आप अपने कोड को छोटे पुस्तकालयों में विभाजित करने में सक्षम हो सकते हैं और उनमें से प्रत्येक को निर्भरता का एक कठिन सेट है।

0

प्रीकंपिल्ड हेडर बहुत से टी को बचा सकता है ime जब एक प्रोजेक्ट का पुनर्निर्माण करते हैं, लेकिन यदि प्रीकंपिल्ड हेडर बदलता है, तो हेडर के आधार पर प्रत्येक स्रोत फ़ाइल को फिर से संकलित किया जाएगा, चाहे परिवर्तन इसे प्रभावित करता है या नहीं। सौभाग्य से, precompiled शीर्षलेख संकलन, लिंक पर उपयोग नहीं किया जाता है; प्रत्येक स्रोत फ़ाइल को समान पूर्व-संकलित शीर्षलेख का उपयोग करने की आवश्यकता नहीं है।

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++, Precompiled हेडर
precompiled शीर्ष लेख: बनाएँ (/ Yc)
precompiled शीर्ष लेख फ़ाइल: pch1.h
precompiled शीर्ष लेख आउटपुट फ़ाइल: $ (intDir) pch1.pch

करें source1.cpp
प्रीकंपिल्ड हेडर: उपयोग (/ यूयू)
प्रीकंपील्ड हेडर फ़ाइल: pch1.h
precompiled शीर्ष लेख आउटपुट फ़ाइल: $ (intDir) pch1.pch (मुझे नहीं लगता कि इस के लिए/यू मायने रखती है)

pch2.cpp और source2 के लिए एक ही बात करते हैं।सीपीपी, सिवाय हैडर फ़ाइल और हैडर आउटपुट फ़ाइलpch2.h करने और pch2.pch निर्धारित किया है। ये मेरे लिए सही है।

संबंधित मुद्दे

 संबंधित मुद्दे