What's the point of using empty string to set cache variable in CMake? - cmake

I've seen different ways of setting / using Cache variables in Cmake.
What is the standard?
What's the point of setting an empty string ("") to the cache variable?
Example
set(NVTX_ROOT_DIR "" CACHE PATH "Folder contains NVIDIA NVTX")

What's the point of setting an empty string ("") to the cache variable?
It is not just setting a value for a CACHE variable.
Command flow set(CACHE) normally performs two things:
Declares the parameter (assigns description and possibly the type)
Sets the parameter's default value. (That is, if the parameter is already set, its value isn't changed).
Empty value for CACHE variable could mean that a parameter denoted by this variable is not set. Depending on the project which uses it, this could be interpreted as:
Do not use functionality described by the parameter.
Emit an error telling the parameter should be set by a user.
In CMake code checking the parameter could be implemented with simple if(VAR):
if(NVTX_ROOT_DIR)
# The parameter is set
else()
# The parameter is not set
endif()
While if(NVTX_ROOT_DIR) is false even if the variable is not set, declaring the parameter is impossible without setting its value. So empty string as a default value is a logical choice for being able to use simple if(NVTX_ROOT_DIR) for check absence of the parameter's setting.

Related

How are variables like GTEST_FOUND set?

I'm trying to see how GTEST_FOUND is set when find_package(GTest REQUIRED) is called, but there's no sign of the variable GTEST_FOUND being set in this file:
https://github.com/Kitware/CMake/blob/master/Modules/FindGTest.cmake
Does anyone know how the variable is set if it's not done in FindGTest.cmake?
The GTEST_FOUND variable is actually set in the FindPackageHandleStandardArgs.cmake file. You can see in FindGTest.cmake, a call to this function is made here:
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(GTest DEFAULT_MSG GTEST_LIBRARY GTEST_INCLUDE_DIR GTEST_MAIN_LIBRARY)
The FIND_PACKAGE_HANDLE_STANDARD_ARGS function uses the first argument for the package name (GTest in this case) to set the <PackageName>_FOUND variable.
Here is a quote from the header information for the FIND_PACKAGE_HANDLE_STANDARD_ARGS function:
The <PackageName>_FOUND variable will be set to TRUE if all
the variables <required-var>... are valid and any optional
constraints are satisfied, and FALSE otherwise. A success or
failure message may be displayed based on the results and on
whether the REQUIRED and/or QUIET option was given to
the :command:find_package call.

Modifying CACHE variable in CMake is not working

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.

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.

In Emacs how do I make a local variable safe to be set in a file for all possible values

In Elisp I have introduced for a special custom mode a variable like:
(defvar leo-special-var "")
(make-variable-buffer-local 'leo-special-var)
Now I set this variable in files I with the lines (in the file to edit):
# Local Variables:
# leo-special-var: "-d http://www.google.com.au"
# End:
And I want to consider this variable as "safe for all its values. That's why safe-local-variable-values doesn't help. Instead I tried (in the lisp code):
# setting the symbol property of the variable
(put 'leo-special-var 'safe-local-variable 'booleanp)
but without success. Do I do something wrong when setting the symbol property? Or is there another way?
You want to use
(put 'leo-special-var 'safe-local-variable #'stringp)
to say that it is safe as long as it's a string.
If you really want to state that it is safe for all values then use this:
(put 'leo-special-var 'safe-local-variable (lambda (_) t))
The function to test safety here returns non-nil for any value.
(But I'd think that you probably do not want to state that a variable is safe for any value.)
It's in the manual: (elisp) File Local Variables
You can specify safe values for a variable with a
`safe-local-variable' property. The property has to be a function of
one argument; any value is safe if the function returns non-`nil' given
that value. Many commonly-encountered file variables have
`safe-local-variable' properties; these include `fill-column',
`fill-prefix', and `indent-tabs-mode'. For boolean-valued variables
that are safe, use `booleanp' as the property value. Lambda
expressions should be quoted so that `describe-variable' can display
the predicate.
When defining a user option using `defcustom', you can set its
`safe-local-variable' property by adding the arguments `:safe FUNCTION'
to `defcustom' (*note Variable Definitions::).

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}"