जवाबों:
वहाँ एक है तीसरे पक्ष CMake मॉड्यूल 'Cotire' नाम दिया जो CMake आधारित निर्माण प्रणालियों के लिए precompiled हेडर के उपयोग को स्वचालित है और यह भी एकता बनाता है समर्थन करता है।
पूर्ववर्ती हेडर बनाने और उपयोग करने के लिए Im निम्नलिखित मैक्रो का उपयोग कर रहा है:
MACRO(ADD_MSVC_PRECOMPILED_HEADER PrecompiledHeader PrecompiledSource SourcesVar)
IF(MSVC)
GET_FILENAME_COMPONENT(PrecompiledBasename ${PrecompiledHeader} NAME_WE)
SET(PrecompiledBinary "${CMAKE_CURRENT_BINARY_DIR}/${PrecompiledBasename}.pch")
SET(Sources ${${SourcesVar}})
SET_SOURCE_FILES_PROPERTIES(${PrecompiledSource}
PROPERTIES COMPILE_FLAGS "/Yc\"${PrecompiledHeader}\" /Fp\"${PrecompiledBinary}\""
OBJECT_OUTPUTS "${PrecompiledBinary}")
SET_SOURCE_FILES_PROPERTIES(${Sources}
PROPERTIES COMPILE_FLAGS "/Yu\"${PrecompiledHeader}\" /FI\"${PrecompiledHeader}\" /Fp\"${PrecompiledBinary}\""
OBJECT_DEPENDS "${PrecompiledBinary}")
# Add precompiled header to SourcesVar
LIST(APPEND ${SourcesVar} ${PrecompiledSource})
ENDIF(MSVC)
ENDMACRO(ADD_MSVC_PRECOMPILED_HEADER)
मान लें कि आपके पास अपने सभी सोर्सफाइल्स के साथ एक चर $ {MySources} है, जिस कोड का आप उपयोग करना चाहते हैं वह बस होगा
ADD_MSVC_PRECOMPILED_HEADER("precompiled.h" "precompiled.cpp" MySources)
ADD_LIBRARY(MyLibrary ${MySources})
गैर-MSVC प्लेटफॉर्म पर भी कोड अभी भी ठीक काम करेगा। काफी साफ़ :)
list( APPEND ... )
बाहर के समापन की ओर बढ़ता है endif()
। यहां पूरा कोड देखें: pastebin.com/84dm5rXZ
/Yu
और /FI
तर्क सही करें , उन्हें होना चाहिए ${PrecompiledHeader}
और नहीं ${PrecompiledBinary}
।
/YuC:/foo/bar.h
आपको /FpC:/foo/bar.h
ध्वज को पास करने के लिए मजबूर करेगा या #include <C:/foo/bar.h>
पहले शामिल बयान के रूप में अपनी .cpp फ़ाइलों के सभी में सबसे ऊपर रख देगा । MSVC #include
तर्कों की तुलना एक तार से करता है, यह जाँच नहीं करता है कि यह उसी फ़ाइल की ओर इशारा करता है जैसा कि दिया गया था /Yu
। एर्गो, #include <bar.h>
काम नहीं करेगा और त्रुटि C2857 का उत्सर्जन करेगा।
सीएमके को सिर्फ पीसीएच के लिए समर्थन मिला है, यह आगामी 3.16 रिलीज में उपलब्ध होना चाहिए, 2019-10-01 के कारण:
https://gitlab.kitware.com/cmake/cmake/merge_requests/3553
target_precompile_headers(<target>
<INTERFACE|PUBLIC|PRIVATE> [header1...]
[<INTERFACE|PUBLIC|PRIVATE> [header2...] ...])
लक्ष्य के बीच PCH साझा करने का समर्थन करने पर चर्चा चल रही है: https://gitlab.kitware.com/cmake/cmake/issues/19479
Https://blog.qt.io/blog/2019/08/01/precompiled-headers-and-unity-jumbo-builds-in-upcoming-cmake/ पर कुछ अतिरिक्त संदर्भ (प्रेरणा, संख्या) उपलब्ध हैं।
यहाँ एक कोड स्निपेट है जिससे आप अपनी परियोजना के लिए पहले से तैयार हेडर का उपयोग कर सकते हैं। अपने CMakeLists.txt की जगह निम्नलिखित myprecompiledheaders
और myproject_SOURCE_FILES
उपयुक्त के रूप में जोड़ें :
if (MSVC)
set_source_files_properties(myprecompiledheaders.cpp
PROPERTIES
COMPILE_FLAGS "/Ycmyprecompiledheaders.h"
)
foreach( src_file ${myproject_SOURCE_FILES} )
set_source_files_properties(
${src_file}
PROPERTIES
COMPILE_FLAGS "/Yumyprecompiledheaders.h"
)
endforeach( src_file ${myproject_SOURCE_FILES} )
list(APPEND myproject_SOURCE_FILES myprecompiledheaders.cpp)
endif (MSVC)
with set( CMAKE_AUTOMOC ON )
।
myprecompiledheader.cpp
पहले संकलित किया गया है? इस स्निपेट से ऐसा लगता है कि इसे अंतिम रूप से संकलित किया जाएगा, इसलिए शायद यही देरी का कारण हो सकता है। myprecompiledheader.h
मेरे कोड का उपयोग करने वाले केवल सबसे सामान्य एसटीएल हेडर शामिल हैं।
मैंने लार्स मैक्रो के एक अनुकूलित संस्करण का उपयोग करके समाप्त किया। Pch पथ के लिए $ (IntDir) का उपयोग करना डिबग के लिए पहले से तैयार हेडर रखता है और रिलीज़ अलग बनाता है।
MACRO(ADD_MSVC_PRECOMPILED_HEADER PrecompiledHeader PrecompiledSource SourcesVar)
IF(MSVC)
GET_FILENAME_COMPONENT(PrecompiledBasename ${PrecompiledHeader} NAME_WE)
SET(PrecompiledBinary "$(IntDir)/${PrecompiledBasename}.pch")
SET(Sources ${${SourcesVar}})
SET_SOURCE_FILES_PROPERTIES(${PrecompiledSource}
PROPERTIES COMPILE_FLAGS "/Yc\"${PrecompiledHeader}\" /Fp\"${PrecompiledBinary}\""
OBJECT_OUTPUTS "${PrecompiledBinary}")
SET_SOURCE_FILES_PROPERTIES(${Sources}
PROPERTIES COMPILE_FLAGS "/Yu\"${PrecompiledHeader}\" /FI\"${PrecompiledHeader}\" /Fp\"${PrecompiledBinary}\""
OBJECT_DEPENDS "${PrecompiledBinary}")
# Add precompiled header to SourcesVar
LIST(APPEND ${SourcesVar} ${PrecompiledSource})
ENDIF(MSVC)
ENDMACRO(ADD_MSVC_PRECOMPILED_HEADER)
ADD_MSVC_PRECOMPILED_HEADER("stdafx.h" "stdafx.cpp" MY_SRCS)
ADD_EXECUTABLE(MyApp ${MY_SRCS})
डेव से अनुकूलित, लेकिन अधिक कुशल (प्रत्येक फ़ाइल के लिए लक्ष्य गुण सेट करता है):
if (MSVC)
set_target_properties(abc PROPERTIES COMPILE_FLAGS "/Yustd.h")
set_source_files_properties(std.cpp PROPERTIES COMPILE_FLAGS "/Ycstd.h")
endif(MSVC)
abc
आपके उदाहरण में क्या है ?
यदि आप पहिया को फिर से स्थापित नहीं करना चाहते हैं, तो या तो कॉटियर का उपयोग करें क्योंकि शीर्ष उत्तर का सुझाव दिया गया है या यहां एक सरल - सेमीके-प्रिकेल्ड-हेडर है । इसका उपयोग करने के लिए बस मॉड्यूल और कॉल शामिल करें:
include( cmake-precompiled-header/PrecompiledHeader.cmake )
add_precompiled_header( targetName StdAfx.h FORCEINCLUDE SOURCE_CXX StdAfx.cpp )
सीएमके 3.16 ने प्रिकॉम्स्ड हेडर के लिए समर्थन पेश किया। एक नया सीएमके आदेश है target_precompile_headers
जो हुड के तहत आपकी जरूरत के सभी काम करता है। अधिक जानकारी के लिए इसके दस्तावेज देखें: https://cmake.org/cmake/help/latest/command/target_precompile_headers.html
"stdafx.h", "stdafx.cpp" - पूर्वनिर्धारित हेडर नाम।
नीचे दिए गए मूल cmake फ़ाइल में रखें।
if (MSVC)
# For precompiled header.
# Set
# "Precompiled Header" to "Use (/Yu)"
# "Precompiled Header File" to "stdafx.h"
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Yustdafx.h /FIstdafx.h")
endif()
नीचे प्रोजेक्ट cmake फ़ाइल में नीचे रखें।
"src" - स्रोत फ़ाइलों के साथ एक फ़ोल्डर।
set_source_files_properties(src/stdafx.cpp
PROPERTIES
COMPILE_FLAGS "/Ycstdafx.h"
)
IMHO सबसे अच्छा तरीका है कि पूरे प्रोजेक्ट के लिए PCH सेट किया जाए, जैसा कि martjno ने सुझाव दिया है, यदि आवश्यक हो तो कुछ स्रोतों के लिए PCH को अनदेखा करने की क्षमता के साथ संयुक्त (उदाहरण के लिए उत्पन्न स्रोत):
# set PCH for VS project
function(SET_TARGET_PRECOMPILED_HEADER Target PrecompiledHeader PrecompiledSource)
if(MSVC)
SET_TARGET_PROPERTIES(${Target} PROPERTIES COMPILE_FLAGS "/Yu${PrecompiledHeader}")
set_source_files_properties(${PrecompiledSource} PROPERTIES COMPILE_FLAGS "/Yc${PrecompiledHeader}")
endif(MSVC)
endfunction(SET_TARGET_PRECOMPILED_HEADER)
# ignore PCH for a specified list of files
function(IGNORE_PRECOMPILED_HEADER SourcesVar)
if(MSVC)
set_source_files_properties(${${SourcesVar}} PROPERTIES COMPILE_FLAGS "/Y-")
endif(MSVC)
endfunction(IGNORE_PRECOMPILED_HEADER)
इसलिए, यदि आपके पास कुछ लक्ष्य MY_TARGET है, और उत्पन्न स्रोतों की सूची IGNORE_PCH_SRC_LIST आप बस करेंगे:
SET_TARGET_PRECOMPILED_HEADER(MY_TARGET stdafx.h stdafx.cpp)
IGNORE_PRECOMPILED_HEADER(IGNORE_PCH_SRC_LIST)
इस aproach का परीक्षण किया जाता है और यह पूरी तरह से काम करता है।
जब आप क्वाड कोर मशीन पर हर बार 10+ मिनट का समय लेते हैं तो आप किसी भी प्रोजेक्ट फाइल में एक ही लाइन को बदलते हैं, यह आपको विंडोज़ के लिए precompiled हेडर जोड़ने के लिए अपना समय बताता है। * नक्स पर मैं सिर्फ ccache का उपयोग करूंगा और इस बारे में चिंता नहीं करूंगा।
मैंने अपने मुख्य एप्लिकेशन और कुछ पुस्तकालयों में इसे लागू किया है जो इसका उपयोग करता है। यह इस बिंदु पर बहुत अच्छा काम करता है। एक बात जो भी आवश्यक है वह यह है कि आपको पीच स्रोत और हेडर फाइल बनानी होगी और सोर्स फाइल में वे सभी हेडर शामिल करने होंगे जिन्हें आप पहले से तैयार करना चाहते हैं। मैंने इसे MFC के साथ 12 साल के लिए किया था लेकिन मुझे यह याद करने में कुछ मिनट लगे।
सबसे साफ तरीका यह है कि ग्लोबल ऑप्शन के रूप में प्रीकम्प्लेस्ड ऑप्शन को जोड़ा जाए। Vcxproj फ़ाइल में यह <PrecompiledHeader>Use</PrecompiledHeader>
प्रत्येक व्यक्तिगत फ़ाइल के रूप में दिखाई देगा और ऐसा नहीं करेगा ।
फिर आपको Create
StdAfx.cpp विकल्प को जोड़ना होगा । निम्नलिखित यह है कि मैं इसका उपयोग कैसे करता हूं:
MACRO(ADD_MSVC_PRECOMPILED_HEADER SourcesVar)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /YuStdAfx.h")
set_source_files_properties(StdAfx.cpp
PROPERTIES
COMPILE_FLAGS "/YcStdAfx.h"
)
list(APPEND ${${SourcesVar}} StdAfx.cpp)
ENDMACRO(ADD_MSVC_PRECOMPILED_HEADER)
file(GLOB_RECURSE MYDLL_SRC
"*.h"
"*.cpp"
"*.rc")
ADD_MSVC_PRECOMPILED_HEADER(MYDLL_SRC)
add_library(MyDll SHARED ${MYDLL_SRC})
यह MSVC 2010 के लिए परीक्षण और काम करता है और एक MyDll.pch फ़ाइल का निर्माण करेगा, मैं परेशान नहीं हूं कि फ़ाइल नाम का उपयोग क्या है इसलिए मैंने इसे निर्दिष्ट करने का कोई प्रयास नहीं किया।
जैसा कि precompiled हेडर विकल्प आरसी फ़ाइलों के लिए काम नहीं करता है, मुझे जरी द्वारा आपूर्ति की गई मैक्रो को समायोजित करने की आवश्यकता है।
#######################################################################
# Makro for precompiled header
#######################################################################
MACRO(ADD_MSVC_PRECOMPILED_HEADER PrecompiledHeader PrecompiledSource SourcesVar)
IF(MSVC)
GET_FILENAME_COMPONENT(PrecompiledBasename ${PrecompiledHeader} NAME_WE)
SET(PrecompiledBinary "$(IntDir)/${PrecompiledBasename}.pch")
SET(Sources ${${SourcesVar}})
# generate the precompiled header
SET_SOURCE_FILES_PROPERTIES(${PrecompiledSource}
PROPERTIES COMPILE_FLAGS "/Zm500 /Yc\"${PrecompiledHeader}\" /Fp\"${PrecompiledBinary}\""
OBJECT_OUTPUTS "${PrecompiledBinary}")
# set the usage of this header only to the other files than rc
FOREACH(fname ${Sources})
IF ( NOT ${fname} MATCHES ".*rc$" )
SET_SOURCE_FILES_PROPERTIES(${fname}
PROPERTIES COMPILE_FLAGS "/Zm500 /Yu\"${PrecompiledHeader}\" /FI\"${PrecompiledHeader}\" /Fp\"${PrecompiledBinary}\""
OBJECT_DEPENDS "${PrecompiledBinary}")
ENDIF( NOT ${fname} MATCHES ".*rc$" )
ENDFOREACH(fname)
# Add precompiled header to SourcesVar
LIST(APPEND ${SourcesVar} ${PrecompiledSource})
ENDIF(MSVC)
ENDMACRO(ADD_MSVC_PRECOMPILED_HEADER)
संपादित करें: इस पूर्वनिर्धारित हेडर के उपयोग ने मेरे मुख्य प्रोजेक्ट के समग्र निर्माण समय को 4min 30s से घटाकर 1min 40s कर दिया। यह मेरे लिए बहुत अच्छी बात है। Precompile हैडर में केवल हेडर जैसे बूस्ट / stl / Windows / mfc होते हैं।
वहाँ भी मत जाओ। Precompiled हेडर का मतलब है कि जब भी हेडर में से कोई एक बदलता है, तो आपको सब कुछ पुनर्निर्माण करना होगा । आप भाग्यशाली हैं यदि आपके पास एक बिल्ड सिस्टम है जो यह महसूस करता है। अधिक से अधिक कभी नहीं, आपका निर्माण तब तक विफल हो जाएगा जब तक आपको एहसास नहीं हो जाता है कि आपने कुछ बदल दिया है जो कि पहले से तैयार किया जा रहा है, और इसलिए आपको पूर्ण पुनर्निर्माण करने की आवश्यकता है। आप ज्यादातर हेडर को प्राथमिकता देकर इससे बच सकते हैं कि आप बिल्कुल सकारात्मक नहीं हैं, लेकिन फिर आप गति हासिल करने का एक बड़ा हिस्सा भी दे रहे हैं।
दूसरी समस्या यह है कि आपका नामस्थान उन सभी प्रकार के प्रतीकों से प्रदूषित हो जाता है, जिन्हें आप नहीं जानते हैं या उन कई स्थानों की परवाह नहीं करते हैं जहाँ आप पहले से तैयार हेडर का उपयोग कर रहे हैं।