Yanıtlar:
Bir yoktur 'Cotire' adlı üçüncü parti CKağıt modülü CKağıt inşa tabanlı sistemler için önceden derlenmiş başlıkları kullanımını otomatik hale getirir ve aynı zamanda birlik kurar destekler.
Önceden derlenmiş üstbilgiler oluşturmak ve kullanmak için aşağıdaki makroyu kullanıyorum:
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)
Diyelim ki tüm kaynak dosyalarınızla bir değişken $ {MySources} var, kullanmak isteyeceğiniz kod basitçe
ADD_MSVC_PRECOMPILED_HEADER("precompiled.h" "precompiled.cpp" MySources)
ADD_LIBRARY(MyLibrary ${MySources})
Kod, MSVC olmayan platformlarda da gayet iyi çalışacaktır. Oldukça temiz :)
list( APPEND ... )
kapanışın dışına taşıyor endif()
. Kodun tamamını burada görün: pastebin.com/84dm5rXZ
/Yu
ve /FI
argümanları düzeltin, olmalı ${PrecompiledHeader}
ve olmamalı ${PrecompiledBinary}
.
/YuC:/foo/bar.h
, sizi ya /FpC:/foo/bar.h
bayrağı geçirmeye ya #include <C:/foo/bar.h>
da ilk include ifadesi olarak tüm .cpp dosyalarınızın en üstüne koymaya zorlar . MSVC, #include
argümanlar arasında bir dize karşılaştırması yapar, verilenle aynı dosyaya işaret edip etmediğini kontrol etmez /Yu
. Ergo, #include <bar.h>
çalışmayacak ve C2857 hatası vermeyecek.
CMake, PCH'ler için yeni destek kazandı, 2019-10-01 tarihinde çıkacak olan 3.16 sürümünde mevcut olacaktır:
https://gitlab.kitware.com/cmake/cmake/merge_requests/3553
target_precompile_headers(<target>
<INTERFACE|PUBLIC|PRIVATE> [header1...]
[<INTERFACE|PUBLIC|PRIVATE> [header2...] ...])
PCH'lerin hedefler arasında paylaşılmasının desteklenmesiyle ilgili devam eden tartışma var: https://gitlab.kitware.com/cmake/cmake/issues/19659
Https://blog.qt.io/blog/2019/08/01/precompiled-headers-and-unity-jumbo-builds-in-upcoming-cmake/ adresinde bazı ek içerik (motivasyon, sayılar) mevcuttur.
İşte projeniz için önceden derlenmiş başlık kullanmanıza izin verecek bir kod parçacığı. CMakeLists.txt dosyanızı değiştirerek myprecompiledheaders
ve myproject_SOURCE_FILES
uygun şekilde aşağıdakileri ekleyin :
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
Önce bunun derlendiğinden emin olmalı mıyım? Bu pasajdan en son derlenmiş gibi görünüyor, bu yüzden gecikmeye neden olan belki de bu olabilir. myprecompiledheader.h
yalnızca kodumun kullandığı en yaygın STL başlıklarını içerir.
Larsm makrosunun uyarlanmış bir sürümünü kullandım. $ (IntDir) pch yolu için kullanmak, hata ayıklama ve sürüm yapıları için önceden derlenmiş üstbilgileri ayrı tutar.
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})
Dave'den uyarlanmıştır, ancak daha etkilidir (her dosya için değil, hedef özellikleri belirler):
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
?
Tekerleği yeniden icat etmek istemiyorsanız, ya en iyi yanıtın önerdiği gibi Cotire'ı ya da daha basit olanı kullanın - cmake-precompiled-header burada . Kullanmak için sadece modülü ekleyin ve arayın:
include( cmake-precompiled-header/PrecompiledHeader.cmake )
add_precompiled_header( targetName StdAfx.h FORCEINCLUDE SOURCE_CXX StdAfx.cpp )
CMake 3.16, önceden derlenmiş başlıklar için destek getirdi. target_precompile_headers
Kaputun altında ihtiyacınız olan her şeyi yapan yeni bir CMake komutu var. Daha fazla ayrıntı için belgelerine bakın: https://cmake.org/cmake/help/latest/command/target_precompile_headers.html
"stdafx.h", "stdafx.cpp" - önceden derlenmiş başlık adı.
Aşağıdakileri kök cmake dosyasına koyun.
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()
Aşağıdakileri proje cmake dosyasına koyun.
"src" - kaynak dosyaları içeren bir klasör.
set_source_files_properties(src/stdafx.cpp
PROPERTIES
COMPILE_FLAGS "/Ycstdafx.h"
)
IMHO'nun en iyi yolu, martjno'nun önerdiği gibi, gerekirse bazı kaynaklar için PCH'yi görmezden gelme yeteneği ile birlikte tüm proje için PCH'yi ayarlamaktır (örneğin oluşturulan kaynaklar):
# 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)
Dolayısıyla, MY_TARGET hedefiniz ve oluşturulan IGNORE_PCH_SRC_LIST kaynakların listesi varsa, yapmanız gereken:
SET_TARGET_PRECOMPILED_HEADER(MY_TARGET stdafx.h stdafx.cpp)
IGNORE_PRECOMPILED_HEADER(IGNORE_PCH_SRC_LIST)
Bu yaklaşım test edildi ve mükemmel çalışıyor.
Derlemeler dört çekirdekli bir makinede 10 dakikadan fazla sürdüğünde, herhangi bir proje dosyasında tek bir satırı her değiştirdiğinizde, size pencereler için önceden derlenmiş başlıklar ekleme zamanının geldiğini söyler. * Nux'ta sadece ccache kullanırdım ve bu konuda endişelenmezdim.
Ana uygulamamda ve kullandığı birkaç kitaplıkta uyguladım. Bu noktada harika çalışıyor. Gerekli olan bir şey de, pch kaynak ve başlık dosyasını oluşturmanız ve kaynak dosyada önceden derlenmesini istediğiniz tüm başlıkları içermenizdir. Bunu 12 yıl boyunca MFC ile yaptım ama hatırlamam birkaç dakikamı aldı ..
En temiz yol, önceden derlenmiş seçeneği genel bir seçenek olarak eklemektir. Vcxproj dosyasında bu, her dosya için bu şekilde görünecek <PrecompiledHeader>Use</PrecompiledHeader>
ve yapmayacaktır.
O zaman Create
seçeneği StdAfx.cpp'ye eklemeniz gerekir . Bunu nasıl kullanıyorum:
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})
Bu test edildi ve MSVC 2010 için çalışıyor ve bir MyDll.pch dosyası oluşturacak, hangi dosya adının kullanıldığından rahatsız olmadım, bu yüzden onu belirtmek için herhangi bir çaba göstermedim.
Önceden derlenmiş başlık seçeneği rc dosyalarında çalışmadığından, jari tarafından sağlanan makroyu ayarlamam gerekiyordu.
#######################################################################
# 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)
Düzenleme: Bu önceden derlenmiş başlıkların kullanımı, ana Projemin Genel derleme süresini 4 dakika 30 saniyeden 1 dakika 40 saniyeye düşürdü. Bu benim için gerçekten iyi bir şey. Ön derleme başlığında yalnızca boost / stl / Windows / mfc gibi başlıklar bulunur.
Oraya gitme bile. Önceden derlenmiş başlıklar, başlıklardan biri değiştiğinde her şeyi yeniden oluşturmanız gerektiği anlamına gelir . Bunu gerçekleştiren bir yapı sisteminiz varsa şanslısınız. Önceden derlenmekte olan bir şeyi değiştirdiğinizi ve bu nedenle tam bir yeniden oluşturma yapmanız gerektiğini anlayana kadar yapınız hiç olmadığı kadar sıklıkla başarısız olacaktır. Bundan çoğunlukla, kesinlikle pozitif olduğunuz başlıkları önceden derleyerek önleyebilirsiniz, ancak daha sonra hız kazancının büyük bir bölümünü de bırakmış olursunuz.
Diğer sorun, ad alanınızın önceden derlenmiş başlıkları kullanacağınız birçok yerde bilmediğiniz veya umursamadığınız her tür sembolle kirlenmesidir.