CMake でプリコンパイル済みヘッダーのサポートをいくつかハッキングすることについて、ネット上でいくつかの (古い) 投稿を見てきました。それらはすべてどこにでもあるように見え、誰もが独自のやり方を持っています。現在それを行う最良の方法は何ですか?
13 に答える
次のマクロを使用して、プリコンパイル済みヘッダーを生成して使用します。
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以外のプラットフォームでも問題なく機能します。かなりきちんと:)
プロジェクトでプリコンパイル済みヘッダーを使用できるようにするコード スニペットを次に示します。以下を 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)
私は最終的に 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)
cmake と Visual Studio 2015 でのプリコンパイル済みヘッダーの使用例
"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"
)
私見の最善の方法は、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)
このアプローチはテスト済みで、完全に機能します。
最もクリーンな方法は、プリコンパイル済みオプションをグローバル オプションとして追加することです。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 ファイルを作成します。どのファイル名が使用されているかは気にしないので、指定する努力はしませんでした。
そこにも行かないでください。プリコンパイル済みヘッダーは、ヘッダーの 1 つが変更されるたびに、すべてを再構築する必要があることを意味します。これを実現するビルドシステムがあればラッキーです。多くの場合、プリコンパイルされているものを変更したことに気付くまでビルドが失敗するため、完全な再構築を行う必要があります。ほとんどの場合、ヘッダーを事前にコンパイルすることでこれを回避できますが、変更は絶対にないと確信していますが、速度向上の大部分も放棄しています。
もう 1 つの問題は、プリコンパイル済みヘッダーを使用する多くの場所で、名前空間が知らない、または気にしないあらゆる種類のシンボルで汚染されることです。