What is the CMake cache? - caching

What is CMake cache?
I'm reading the cmake manual and have occasionally come across the term cmake cache. For instance this paragraph:
-C <initial-cache>
Pre-load a script to populate the cache.
When cmake is first run in an empty build tree, it creates a
CMakeCache.txt file and populates it with customizable settings for
the project. This option may be used to specify a file from which to
load cache entries before the first pass through the project’s cmake
listfiles. The loaded entries take priority over the project’s default
values. The given file should be a CMake script containing SET
commands that use the CACHE option, not a cache-format file.
What is this cache?
Are there different types of cache?
Or would a better question be: what is cache in general?
Also, what is the importance of cache?
And are there certain caveats when dealing with cache?
For example, does the cache reset when you turn restart your computer?

CMake cache refers to a set of persistent variables - persisted in a file named CMakeCache.txt in the build directory. These include things like user configurable options, which define some behavior of your project. For example, you may run cmake -D CMAKE_BUILD_TYPE=Release . in the build directory and find that variable saved in CMakeCache.txt.
CMake only has one type of cache. It is created and saved into CMakeCache.txt after the first configuring the build, and under normal use does not reset itself.

Related

Specifying uncached compile-time constants in CMakeLists file

In one of my CMakeList files I specified an option which conditionally defines a compile-time constant in a generated header file.
However, I recognized that the value of the option is being cached by cmake.
This leads to the unintentional behaviour that I need to delete the cmake cache everytime I change the option and issue cmake ..
Currently this is the only option being used. Later on I would like to use more options.
It is really confusing to me that the CMakeLists.txt does not represent the actual build setting due to the caching mechanism.
E.g. an build flag set in the CMakeLists.txt but still unset in the cache.
I don't want to disable caching, I just want that my build is always in sync with the build flag set in the CMakeLists.txt. I understand that cmake's caching mechanism is saving lot of time during large builds. Which is actually good.
Does there exist some means to force an option to be up-to-date on cmake .?
I tried to turn the option into a set instruction. The cmake still uses the cached value instead of the actual one.
What am I doing wrong?
Here is my CMakeLists.txt:
cmake_minimum_required(VERSION 3.10)
project(Test VERSION 1.0)
option(MY_BUILD_FLAG "bla" OFF)
configure_file(TestConfig.h.in TestConfig.h)
Here is my change which I unsuccessfully tried out:
cmake_minimum_required(VERSION 3.10)
project(Test VERSION 1.0)
# Here you can set several build flags ON or OFF
set(MY_BUILD_FLAG "bla" OFF)
configure_file(TestConfig.h.in TestConfig.h)
I understand that cmake's caching mechanism is saving lot of time during large builds.
This is incorrect. The purpose of cmake cache variables is to persist variables across information for subsequent reconfigurations of the same build directory.
The fact that e.g. .o files remain in the build directory unless explicitly cleared and aren't rebuilt, if the sources for compiling it is an entirely different mechanism.
Note that you may in fact see improvements of the CMake configuration time, since e.g. results of try_compile are cached. This may actually result in a perceived improved build time, if you often rewrite the cmake files and therefore trigger an automatic cmake reconfiguration of your project before the actual build starts. However if you do not change the cmake logic, the use of CMake cache variables doesn't improve build times at all (or conditionally applying other logic resulting in a different amount of work for compiler or linker).
Note: Another notable use for cache variables is to provide project configuration options to the user. I'm not elaborating on this, since this doesn't affect build times without additional CMake logic dependent on the value influencing the amount of code to build.

CMake - Build custom build paths for different configurations

I have a project whose make process generates different build artifacts for each configuration, e.g. if initiated with make a=a0 b=b0 it would build object files into builds/a0.b0, generate a binary myproject.a0.b0, and finally update an ambiguous executable link to point to the most recently built project ln -s myproject.a0.b0 myproject. For this project, this is a useful feature mainly because:
It separates the object files for different configurations (so when I rebuild in another configuration I don't have to recompile every single source with new defines and configurations set, (unfortunately) a very common procedure).
It retains the binaries for each configuration (so it's not required to rebuild to use a different configuration if it has already been built).
It makes a copy (or link) to the last built binary which is useful in testing.
Right now this is implemented in an ugly decades-old non-portable Makefile. I'd like to reproduce the same behavior in CMake to allow easier building on other platforms but I have not been able to reproduce it in any reasonable manner. It seems like adding targets with add_library/executable, but doing this for each possible permutation of input parameters seems wrong. And I'm not sure I could get the utilization correct, allowing make, make a=a0, make b=b0 a=a0 as opposed to what specifying a cmake target would require: make myproject-a0.b0.
Is this possible to do in cmake? Namely:
Specify the build directory based on input parameters.
Accept the parameters as make arguments which can be left out (defaulted) to select the appropriate target at the level of the makefile (so it's not required to rerun cmake for a new configuration).

Method to make IncludeDirs available to external tool

I'm currently trying to make splint available as an external tool in Visual Studio 2010.
It has problems with finding all includes for the file, since it seems that the INCLUDE variable is only set at build time and I haven't found any other possibility to extract the include files in any way.
My question: Would there be any way to extract the IncludeDir field from the current file's project's Properties page, ideally with the VC++'s AdditionalIncludeDirectories?
Note also that AdditionalIncludeDirectories is per file, as it can be changed for individual source files as well as on the project level, and if it contains macros it can evaluate differently for each source file too!
I'm not familiar with driving the MSBuild objects via the API, but that's used by the IDE. Whether that way or by simply running MSBuild.exe, you need to get it to figure out all the properties, conditions, etc. and then tell you the result. If everything is well behaved, you could create a target that also uses the ClCompile item array and emits the %(AdditionalIncludeDirectories) metadata somehow such as writing it to a file or passing it to your other tool somehow. That's what's used to generate the /I parameters to CL, and you can get the same values.
If things are not well behaved in that necessary values are changed during the detailed build process, you would need to get the same prelims done just like the ClCompile target normally does, too. Or just override ClCompile with your own (last definition of a target is used) so it certainly is in the same context.
Either way, there are places where build script files can be automatically included into all projects, so you can add your stuff there or use a command argument (I think) to MSBuild to add another Include.
—John

How can I change disk cache path in PhantomJS?

I want to change disk cache directory path for PhantomJS. It's required for my product.
When I'm using --disk-cache=true --max-disk-cache-size=1024 option in phantomJS command line.
It works perfectly. But cache is saved to this below directory. I want to change it to my specified directory.
C:\Users\Administrator\AppData\Local\Ofi Labs\PhantomJS to my_dir
Is it possible or not?
This seems only possible by compiling the code yourself with the necessary changes.
The method writableLocation in the file qstandardpaths_win.cpp handles the paths. There you can set your own path and compile it for your platform.
I suggest to implement it dynamically to add a command line flag for this and create a pull request so that it will be merged back into the project. I see you already opened an issue there.
It has been implemented recently, and in phantomjs v2.1.1 or newer you can use --disk-cache-path=...
https://github.com/ariya/phantomjs/commit/c9e30ebafdeb42efe33900da7823142e146b0a1d

How do I suppress Xcode from generating a folder named after the build configuration in cmake?

I have a cmake configuration that works great for my project on Windows and Linux. We're tinkering with MacOS right now and we're at the point where Xcode spits out the libraries built one directory off from what we define. Instead of it being dropped in ~/bin it is dropped in ~/bin/Debug, for example. As best I can tell Xcode is taking upon itself to add this folder to the path and I don't want that.
How can I disable Xcode from doing this from within my cmake configuration?
You'll need to specify the target properties ARCHIVE_OUTPUT_DIRECTORY_<CONFIG>, LIBRARY_OUTPUT_DIRECTORY_<CONFIG>, and/or RUNTIME_OUTPUT_DIRECTORY_<CONFIG> for each config type and each target you want to affect.
To affect all targets, you can set variables named as these with CMAKE_ prepended. Any relevant target added after these have been set will be affected.
So, for example you could either do:
add_library(MyLib ${Sources})
set_target_properties(MyLib PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}
ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR})
or you could do:
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR})
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR})
add_library(MyLib ${Sources})
Having said that, I normally find it's best to let multi-configuration generators like XCode and MSVC just add the config-specific directories. Unless you plan to also change the default names of exes and libs, these multi-config IDEs will overwrite one config's outputs with another's. So, it's hard to tell whether you're looking at a Debug or Release exe for example.
For single-config generators, I think it's common to have separate build trees per configuration to keep the distinction clear.
Basically, I wouldn't fight against the generator. CMake automates so much of the build process that I never find this slight difference between generators to be a problem. You rarely have to consider whether the output path contains a config dir or not.

Resources