CMake Performance Tips: Difference between revisions
No edit summary |
Andreas Mohr (talk | contribs) (Many-to-one dependencies, include guards, new sections.) |
||
Line 1: | Line 1: | ||
While CMake itself is already very fast, there are some things you can do to ensure works | While CMake itself is already very fast, there are some tuning things you can do to ensure works | ||
as fast as possible. | as fast as possible. | ||
=CMake build time= | |||
==Build it with optimization enabled== | ==Build it with optimization enabled== | ||
Line 54: | Line 56: | ||
LIST(APPEND ...) is for large lists and appends much faster than using SET(). | LIST(APPEND ...) is for large lists and appends much faster than using SET(). | ||
=CMake configure time= | |||
==Reduce add_custom_commands DEPENDS lists== | |||
If your build setup happens to contain many targets which ''all'' depend on a ''sizeable list'' of file dependencies, | |||
then it might be useful to establish ''one single'' custom command (plus its associated target) which DEPENDS on those many files and creates one single OUTPUT "stamp file" ("one of the files changed" watchdog file) which can then be DEPENDS-fed into all affected add_custom_command()s as a ''single'' file dependency. | |||
A very nice way to figure out whether this applies to your build environment is to do: | |||
<source lang="bash"> | |||
ninja -t graph > /tmp/graphviz.log | |||
dot -Tsvg /tmp/graphviz.log >/tmp/cmake_ninja.svg | |||
</source> | |||
and watch the resulting graph monstrosity in awe :) | |||
==Use an include guard== | |||
For CMake modules (files referenced via include() statement), you could use something like: | |||
<source lang="CMake"> | |||
if(my_module_xyz_included) | |||
return() | |||
endif(my_module_xyz_included) | |||
set(my_module_xyz_included true) | |||
</source> | |||
at the beginning of your module file, to avoid repeated parsing within sibling scopes (sub directories, etc.), | |||
which also cuts down on amount of | |||
<source lang="bash"> | |||
cmake --trace | |||
</source> | |||
log traffic. | |||
==Split modules into functions/definitions== | |||
As a general hint, it might be useful to split module files into containing ''either'' clean stateless non-specific (generic) helper functions ''or'' content which defines specific settings and calls some helper functions. | |||
[[Category:CMake]] | [[Category:CMake]] |
Revision as of 19:25, 13 August 2012
While CMake itself is already very fast, there are some tuning things you can do to ensure works as fast as possible.
CMake build time
Build it with optimization enabled
Ok, this is obvious, but anyway. Let's say you build CMake yourself without any special settings, e.g.
$ cmake .. $ make
If you do it this way, you will get a CMake with optimizations turned off. There are different ways to get an optimized build. You can select one of the predefined build types:
$ cmake -DCMAKE_BUILD_TYPE=RELEASE .. $ make
Also possible are RELWITHDEBINFO and MINSIZEREL.
or
$ export CXXFLAGS=-O2 $ cmake .. $ make
or
$ export CXXFLAGS=-O2 $ cmake .. $ make edit_cache (or ccmake ..) ... edit CMAKE_CXX_FLAGS in the advanced view $ make
CMake built with optimizations enabled can give you an almost 50% performance boost (time for running CMake on VTK went down from 25 s to 14 s).
Use LIST(APPEND ...)
There are two ways to append values to a variable in CMake:
SET(myVar ${myVar} newItem)
and since CMake 2.4 there is the new LIST() command:
LIST(APPEND myVar newItem)
LIST(APPEND ...) is for large lists and appends much faster than using SET().
CMake configure time
Reduce add_custom_commands DEPENDS lists
If your build setup happens to contain many targets which all depend on a sizeable list of file dependencies, then it might be useful to establish one single custom command (plus its associated target) which DEPENDS on those many files and creates one single OUTPUT "stamp file" ("one of the files changed" watchdog file) which can then be DEPENDS-fed into all affected add_custom_command()s as a single file dependency. A very nice way to figure out whether this applies to your build environment is to do: <source lang="bash"> ninja -t graph > /tmp/graphviz.log dot -Tsvg /tmp/graphviz.log >/tmp/cmake_ninja.svg </source> and watch the resulting graph monstrosity in awe :)
Use an include guard
For CMake modules (files referenced via include() statement), you could use something like: <source lang="CMake"> if(my_module_xyz_included)
return()
endif(my_module_xyz_included) set(my_module_xyz_included true) </source> at the beginning of your module file, to avoid repeated parsing within sibling scopes (sub directories, etc.), which also cuts down on amount of <source lang="bash"> cmake --trace </source> log traffic.
Split modules into functions/definitions
As a general hint, it might be useful to split module files into containing either clean stateless non-specific (generic) helper functions or content which defines specific settings and calls some helper functions.