Modifying CACHE variable in CMake is not working - cmake

I am using CMake 3.10.2 in Windows.
When I set the variable using CACHE like this
SET(ABAQUS_MAJORVERSION 2016)
SET(ABAQUS_MAJORVERSION ${ABAQUS_MAJORVERSION} CACHE STRING "" )
When I change the ABAQUS_MAJORVERSION variable to 2014 in GUI, this change is not updated in CMake. It keeps generating for 2016 version.
Please help in this regard.
Thanks in Advance
Edit1:
This is the project structure:
|CMakeLists.txt
|FindABAQUS.cmake
|-project1
|---source1.cpp
|---CMakeLists.txt which has SET(ABAQUS_MAJORVERSION 2016 CACHE STRING "")
|-project2
|---source2.cpp
|---CMakeLists.txt which has SET(ABAQUS_MAJORVERSION 2016 CACHE STRING "")
I changed the ABAQUS_MAJORVERSION to 2014 in GUI. The ABAQUS_MAJORVERSION became 2014 in CMakeCache.txt file.
But when printed with message(${ABAQUS_MAJORVERSION }) it shows 2016
Solution:
example: SET(MAJORVERSION 2016 CACHE STRING "")
One might need to unset all the Include paths and library paths, to take effect of the new version Include path and library paths.
example: UNSET(INCLUDE_PATH CACHE)
UNSET(LIBRARY_PATH CACHE)

It may depend on how you're using (or accidentally not using) the cache variable. You can have a normal variable and cache variable of the same name existing at the same time (which is exactly what you have going on) and still access them both (as per the docs on variable references) using ${var_name} for the regular variable, and $CACHE{var_name} for the cache variable.
This can trip people up because they aren't used to writing the explicit cache form, because usually the following behaviour takes effect:
When evaluating Variable References, CMake first searches the function call stack, if any, for a binding and then falls back to the binding in the current directory scope, if any. If a "set" binding is found, its value is used. If an "unset" binding is found, or no binding is found, CMake then searches for a cache entry. If a cache entry is found, its value is used. Otherwise, the variable reference evaluates to an empty string. The $CACHE{VAR} syntax can be used to do direct cache entry lookups.
I'm guessing this is what's tripping you up.
The following scenario can be another cause of confusion for anyone not aware of its behaviour, but I don't think it's what's tripping you up here.
In the CMake docs for setting cache variables:
Since cache entries are meant to provide user-settable values this does not overwrite existing cache entries by default. Use the FORCE option to overwrite existing entries.
For example, cache variables can be set on the command line with -D var_name:TYPE=VALUE.

Related

How to set value by code to a CACHE variable defined by 3d party CMake?

In my project, the CMakeLists includes other cmake files from a library and those dependencies need some cache variables to be configured by user values.
It is all working well if I define those values from the command line with the cmake command:
-DTHIRDPARTY_FRAMEWORK_ROOT="$thirdpartyFrameworkPath"
But can I define (= hardcode) such values in my own CMakeLists file?
To avoid my own users to do it when they configure my project (some values of the 3d party configuration are constant in my project), and make my own cmake interface simpler.
I tried to simply set the variable with a value, but it is both defined and used in the included cmake so it gets overwritten with their default value just before being used.
Using set(... FORCE) seems to work but it does not look clean to me, and might lead to confusing errors if they rename or change the type of the variables on their side. It also forces me to add a type and a doc string because of the set(... CACHE ...) syntax.
Is there a better way to do this?
Setting CACHE INTERNAL variable is a proper way for hardcode a parameter of the inner project in the outer one:
set(THIRDPARTY_FRAMEWORK_ROOT CACHE INTERNAL "Hardcoded root for 'thirdparty'" <value>)
INTERNAL type makes sure that this setting will overwrite the option (FORCE doesn't need) and makes sure that the option won't be shown for a "normal" user.
Since the parameter is not intended to be changed by a user, its real type is meaningless, so there is no needs for it to coincide with the one set in the inner project.
As for description, you could set it to be empty (the parameter is not shown to the normal user, remember?). Alternatively, in the description you could explain why do you set the variable in the outer project. So an "advanced" user will see your description.

Why do I need FORCE to override a CMake option?

I want to override an option, which formely was set to OFF. I am using
SET(USE_OPTION ON CACHE BOOL "Override option" FORCE)
Just for my curiosity: Why do I need 'FORCE' (without it, the set() does not work)
Options are variables meant to be changeable by the user after the configuration step and before the actual build enviroment generation through tools like the cmake-gui, ccmake or through the -D command line switch.
That's why they are cached in the first place. The choice the user has done has to be persisted. So
option(USE_OPTION "My option" ON)
is an equivalent to
set(USE_OPTION ON CACHE BOOL "My option")
So to change or force an "user definable value" / cached variable you have to FORCE it.
Or hide/overwrite it for the current variable scope with a non-cached variable:
set(USE_OPTION ON)
Reference
What's the CMake syntax to set and use variables?
From the docs:
If CACHE is present, then the is put in the cache instead,
unless it is already in the cache
I assume the previous option was also CACHE.
If FORCE is specified, the value of the cache variable is set, even
if the variable is already in the cache.
So, if you don't specify FORCE it doesn't get added to the cache as per above.

TFS 2015 Build Variable Expansion

We have a VNext build definition, on the Variables tab we have added a few custom variables. In one of the variable values we refer to another variable, i.e.
FileDescription = $(Build.DefinitionName)
However it appears that when we reference it in a PowerShell script the FILEDESCRIPTION environment variable exists but the value is not expanded(it contains "$(Build.DefinitionName)" ) and is treated as a string literal.
The documentation appears to suggest that we should be able to refer to it and it will be subsituted at run-time -
https://msdn.microsoft.com/en-us/library/vs/alm/build/scripts/variables
Is there a way to get TFS to automatically expand the variable at runtime?
In vNext build, it seems not expanded the variable everywhere.
For example, in MSBuild-Arguments, /p:OUTPUT="$(FileDescription)" is expanded to /p:OUTPUT="(the name of build definition)" , but in powershell it will only prints "$(Build.DefinitionName)" directly.
Try to use below Workaround: Try to use the corresponding generated environment variables (for example $env:Build.DefinitionName).
$FileDescription = $env:Build.DefinitionName
Note: If you need to change the path, you have to change the PS script instead of a build variable.

CMake cache variables vs. global properties: Simple syntax to use the variable value

To make values available to the whole CMake environment from within a subdirectory one may set a cache variable using the set(VARIABLE_NAME Value CACHE INTERNAL "") syntax or set a global property using the set_property(GLOBAL PROPERTY VARIABLE_NAME Value) syntax (see also this very good answer about variables in CMake).
Using the latter has the advantages that you are not "polluting" the CMake cache for something it is not designed for and that you are not dependent on the cache being deleted when not using the FORCE parameter.
But the syntax to use the variable value is not that user-friendly as you have to retrieve the value using get_property instead of simply using the ${...} notation.
Is there a simpler syntax to use instead of get_property (some kind of syntactic sugar)?
Let's summarize the comments.
To my actual question: There is no specific shortcut to use get_property.
Useful comments:
As CACHE INTERNAL implies FORCE it is okay to use cached variables to make variables globally accessible.
It is good practice to start the CMake file by explicitly cleaning / setting the internal cache variables to avoid unpredictable behavior at repeated runs.

Modeshape configuration - combine XML + programmatic?

I have configured a Modeshape workspace on my dev box using XML, pointing to:
workspaceRootPath="C:/jcr/modeshape/dev/..."
I will deploy to Linux with a workspace mounted on a different volume:
workspaceRootPath="/jcr/modeshape/prod/..."
Is it possible to use an environment variable to configure this or do I need to resort to programmatic configuration? Is there an approach recommended by the Modeshape team?
Thanks
If you're using later versions of ModeShape, you can use a variable in the configuration file that will be replaced at configuration load time with the value of the System property of the same name. For example, if you use the following:
workspaceRootPath="${myWorkspaceDirectory}"
and have a System property "myWorkspaceDirectory" set to "/foo/bar", then when ModeShape loads the configuration it will resolve the variable into the equivalent:
workspaceRootPath="/foo/bar"
Of course, the variable can be just a part of the attribute value, and you can even use multiple variables (as long as they're not nested). For example, this is valid, too:
workspaceRootPath="${my.system.root.path}/modeshape/${my.system.deploymentType}"
Finally, the grammar of each variable is:
"${" systemPropName { "," systemPropName } [ ":" defaultValue ] "}"
This allows 1 or more System property names and an optional default value to be specified within a single variable. The System property names are evaluated from left to right, and the first to have a corresponding real system property will be used. Here's another contrived example:
workspaceRootPath="${my.system.path1,my.system.path2,my.system.path3:/default/path}/modeshape/${my.system.deploymentType}"