回答:
CMakeベースのビルドシステムのプリコンパイル済みヘッダーの使用を自動化し、Unityビルドもサポートする、「Cotire」という名前のサードパーティのCMakeモジュールがあります。
次のマクロを使用して、プリコンパイル済みヘッダーを生成および使用します。
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
渡すか、すべての.cppファイルの最上部に/FpC:/foo/bar.h
置くように強制します#include <C:/foo/bar.h>
。MSVCは#include
引数の文字列比較を行います。MSVCは、渡されたものと同じファイルを指しているかどうかをチェックしません/Yu
。Ergoは機能#include <bar.h>
せず、エラーC2857を出力します。
CMakeはPCHのサポートを取得しました。2019-10-01に予定されている次の3.16リリースで利用可能になる予定です。
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/19659
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
私のコードが使用する最も一般的なSTLヘッダーのみが含まれています。
最終的には、larsmマクロの適応バージョンを使用しました。$(IntDir)をpchパスに使用すると、デバッグビルドとリリースビルドのプリコンパイル済みヘッダーが別々に保持されます。
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から改作しましたが、より効率的です(ファイルごとではなく、ターゲットプロパティを設定します)。
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
あなたの例には何がありますか?
CMake 3.16では、プリコンパイル済みヘッダーのサポートが導入されました。内部でtarget_precompile_headers
必要なすべてを実行する新しいCMakeコマンドがあります。詳細については、そのドキュメントを参照してください: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最良の方法は、martjnoが示唆するように、必要に応じて一部のソース(生成されたソースなど)のPCHを無視する機能と組み合わせて、プロジェクト全体に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)
このアプローチはテストされ、完全に機能します。
ビルドがクアッドコアマシンで10分以上かかると、プロジェクトファイルの1行を変更するたびに、Windowsのプリコンパイル済みヘッダーを追加する時期がわかります。* nuxでは、私はccacheだけを使用し、それについては心配しません。
メインアプリケーションと、それが使用するいくつかのライブラリに実装しました。これまでのところうまくいきます。また、pchソースファイルとヘッダーファイルを作成し、ソースファイルにプリコンパイルするすべてのヘッダーを含める必要があることも必要です。私は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ファイルを作成します。どのファイル名が使用されるかわからないので、指定する手間はありませんでした。
プリコンパイル済みヘッダーオプションはrcファイルでは機能しないため、jariが提供するマクロを調整する必要がありました。
#######################################################################
# 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)
編集:このプリコンパイル済みヘッダーを使用すると、メインプロジェクトの全体的なビルド時間が4分30秒から1分40秒に短縮されました。これは私にとって本当に良いことです。プリコンパイルヘッダーには、boost / stl / Windows / mfcのようなヘッダーのみがあります。
そこに行かないでください。プリコンパイル済みヘッダーは、ヘッダーの1つが変更されるたびに、すべてを再構築する必要があることを意味します。これを実現するビルドシステムがあれば幸いです。ほとんどの場合、ビルドは、プリコンパイルされているものを変更したことに気づくまで失敗するため、完全な再ビルドを行う必要があります。あなたが絶対に肯定的であるヘッダーが変更されないことを事前にコンパイルすることによってこれを主に回避することができますが、それからあなたは同様にスピードゲインの大部分を放棄しています。
もう1つの問題は、プリコンパイル済みヘッダーを使用している多くの場所で、知らないか気にしていないあらゆる種類のシンボルで名前空間が汚染されることです。