CMakeのプリコンパイル済みヘッダーのサポートをまとめてハッキングすることについて、 'ネット上でいくつかの(古い)投稿を見てきました。それらはすべて、その場所全体で少し見えますし、誰もがそれを行う独自の方法を持っています。現在、それを行う最善の方法は何ですか?
「Cotire」という名前のサードパーティCMakeモジュール があり、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プラットフォームでも正常に機能します。きれいです:)
以下は、プロジェクトにプリコンパイル済みヘッダーを使用できるようにするためのコードスニペットです。必要に応じてmyprecompiledheaders
とmyproject_SOURCE_FILES
を置き換えて、CMakeLists.txtに次を追加します。
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)
最終的に、larsmマクロの適応バージョンを使用しました。 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})
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)
車輪を再発明したくない場合は、上の回答が示すようにCotireを使用するか、より単純なものを使用してください-cmake-precompiled-headerここ 。それを使用するには、モジュールをインクルードして呼び出します:
include( cmake-precompiled-header/PrecompiledHeader.cmake )
add_precompiled_header( targetName StdAfx.h FORCEINCLUDE SOURCE_CXX StdAfx.cpp )
私見の最良の方法は、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)
このアプローチはテストされ、完全に機能します。
「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"
)
さて、プロジェクトファイルの1行を変更するたびにクアッドコアマシンでビルドに10分以上かかると、Windows用のプリコンパイル済みヘッダーを追加する時間がわかります。 * nuxでは、ccacheを使用するだけで、心配する必要はありません。
私はメインアプリケーションとそれが使用するいくつかのライブラリに実装しました。ここまではうまくいきます。また、必要なことの1つは、pchソースとヘッダーファイルを作成し、ソースファイルにプリコンパイルするすべてのヘッダーを含める必要があることです。私はMFCで12年間これをしましたが、それを思い出すのに数分かかりました。
CMakeはPCHのサポートを獲得しました。2019-10-01に予定されている3.16リリースで利用可能になるはずです。
https://gitlab.kitware.com/cmake/cmake/merge_requests/355
target_precompile_headers(<target>
<INTERFACE|PUBLIC|PRIVATE> [header1...]
[<INTERFACE|PUBLIC|PRIVATE> [header2...] ...])
ターゲット間でのPCHの共有のサポートに関する継続的な議論があります: https://gitlab.kitware.com/cmake/cmake/issues/19659
最もクリーンな方法は、プリコンパイル済みオプションをグローバルオプションとして追加することです。 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などのヘッダーのみがあります。