CMake에서 미리 컴파일 된 헤더 사용
CMake에서 미리 컴파일 된 헤더에 대한 일부 지원을 함께 해킹하는 것에 대한 'net'의 몇 가지 (오래된) 게시물을 보았습니다. 그것들은 모두 사방에있는 것처럼 보이며 모두가 자신 만의 방식을 가지고 있습니다. 현재 가장 좋은 방법은 무엇입니까?
있다 '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가 아닌 플랫폼에서도 여전히 잘 작동합니다. 꽤 깔끔한 :)
다음은 프로젝트에 미리 컴파일 된 헤더를 사용할 수있는 코드 스 니펫입니다. 당신의 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)
바퀴를 재발 명하고 싶지 않다면 최고의 답변이 제안하는대로 Cotire를 사용하거나 여기에서 더 간단한 one- cmake-precompiled-header를 사용 하십시오 . 그것을 사용하려면 모듈을 포함하고 다음을 호출하십시오.
include( cmake-precompiled-header/PrecompiledHeader.cmake )
add_precompiled_header( targetName StdAfx.h FORCEINCLUDE SOURCE_CXX StdAfx.cpp )
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)
So, if you have some target MY_TARGET, and list of generated sources IGNORE_PCH_SRC_LIST you'll simply do:
SET_TARGET_PRECOMPILED_HEADER(MY_TARGET stdafx.h stdafx.cpp)
IGNORE_PRECOMPILED_HEADER(IGNORE_PCH_SRC_LIST)
This aproach is tested and works perfectly.
An example of usage precompiled header with cmake and Visual Studio 2015
"stdafx.h", "stdafx.cpp" - precompiled header name.
Put the following below in the root cmake file.
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()
Put the following below in the project cmake file.
"src" - a folder with source files.
set_source_files_properties(src/stdafx.cpp
PROPERTIES
COMPILE_FLAGS "/Ycstdafx.h"
)
Well when builds take 10+ minutes on a quad core machine every time you change a single line in any of the project files it tells you its time to add precompiled headers for windows. On *nux I would just use ccache and not worry about that.
I have implemented in my main application and a few of the libraries that it uses. It works great to this point. One thing that also is needed is you have to create the pch source and header file and in the source file include all the headers that you want to be precompiled. I did this for 12 years with MFC but it took me a few minutes to recall that..
The cleanest way is to add the precompiled option as a global option. In the vcxproj file this will show up as <PrecompiledHeader>Use</PrecompiledHeader>
and not do this for every individual file.
Then you need to add the Create
option to the StdAfx.cpp. The following is how I use it:
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})
This is tested and works for MSVC 2010 and will create a MyDll.pch file, I am not bothered what file name is used so I didn't make any effort to specify it.
As the precompiled header option doesnt work for rc files, i needed to adjust the macro supplied by 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)
Edit: The usage of this precompiled headers reduced the Overall build time of my main Project from 4min 30s down to 1min 40s. This is for me a really good thing. In the precompile header are only headers like boost/stl/Windows/mfc.
CMake has just gained support for PCHs, it should be available in the upcoming 3.16 release, due 2019-10-01:
https://gitlab.kitware.com/cmake/cmake/merge_requests/3553
target_precompile_headers(<target>
<INTERFACE|PUBLIC|PRIVATE> [header1...]
[<INTERFACE|PUBLIC|PRIVATE> [header2...] ...])
There is ongoing discussion on supporting sharing PCHs between targets: https://gitlab.kitware.com/cmake/cmake/issues/19659
There is some additional context (motivation, numbers) available at https://blog.qt.io/blog/2019/08/01/precompiled-headers-and-unity-jumbo-builds-in-upcoming-cmake/
Don't even go there. Precompiled headers mean that whenever one of the headers changes, you have to rebuild everything. You're lucky if you have a build system that realizes this. More often than never, your build will just fail until you realize that you changed something that is being precompiled, and therefore you need to do a full rebuild. You can avoid this mostly by precompiling the headers that you are absolutely positive won't change, but then you're giving up a large part of the speed gain as well.
The other problem is that your namespace gets polluted with all kinds of symbols that you don't know or care about in many places where you'd be using the precompiled headers.
참고URL : https://stackoverflow.com/questions/148570/using-pre-compiled-headers-with-cmake
'Programming' 카테고리의 다른 글
배경 위치를 제외한 모든 속성에 CSS3 전환을 어떻게 적용합니까? (0) | 2020.08.23 |
---|---|
혼란을 줄이는 것 외에 사용하지 않는 가져 오기를 Java에서 정리해야하는 이유가 있습니까? (0) | 2020.08.23 |
스칼라의 여러 케이스 클래스 일치 (0) | 2020.08.23 |
참조 된 프로젝트는 컴파일 시간에 "손실"됩니다. (0) | 2020.08.23 |
객체 직렬화 대신 Parcelable 사용의 이점 (0) | 2020.08.23 |