How are variables like GTEST_FOUND set? - cmake

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.

Related

What's the point of using empty string to set cache variable in 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.

How do I make Meson object constant?

As explained here, I like to create file objects in subdirs, and library / executables in the top-level file. However, since all the variables end up in global scope, two subdir files could accidentally use the same variable names. For example:
# Top-level meson.build
subdir('src/abc')
subdir('src/def')
# src/abc/meson.build
my_files=files('1.c','2.c')
# src/def/meson.build
my_files=files('3.c','4.c')
I want meson to throw an error when src/def/meson.build tries to assign a value to my_files. Is this possible in Meson 0.50?
Reassigning variables is rather legitimate operation in meson, so it looks as it is not possible to generate error in standard way. One way of avoiding this problem is following some naming rules e.g. according to folders/sub-folders' names (abc_files, def_files in your case).
But if you really need to have variables with the same name and make sure they are not reassigned, you can use is_variable() function which returns true if variable with given name has been assigned. So, place the following assert before each assignment:
assert(not is_variable('my_files'), 'my_files already assigned!!!')
my_files=files('3.c','4.c')

can't access cmake variable defined inside function using PARENT_SCOPE

So I have the following CMake code:
function(get_sources output_var)
set(${output_var} "a" PARENT_SCOPE)
message(${output_var}) # prints "SOURCES" (as expected)
message(${${output_var}}) # throws an error - why?
...
endfunction(get_sources)
get_sources(SOURCES)
message(${SOURCES}) # prints "a" - ok, so the above function created a var
The get_sources function is supposed to create a variable with given name in parent scope and fill it with some content.
It seems like get_sources(SOURCES) creates the variable as expected - message(${SOURCES}) outside function prints "a", but there's a problem with the line message(${${output_var}}). It should evaluate to message(a) and print "a", but instead it throws an error:
CMake Error at CMakeLists.txt:41 (message):
message called with incorrect number of arguments
I am confused. Is it supposed to be like that? Should I make a function scoped variable, fill it in and then at the end copy its contents to a parent scope variable? I checked it - it works, but I wanted it to be without any additional variables.
EDIT:
I enclosed a ${${output_var}} in quotation marks and now it doesn't throw an error, but it prints nothing.
PARENT_SCOPE sets variable only for parent scope, not for the current one. This is explicitely stated in CMake documentation about 'set' command:
If the PARENT_SCOPE option is given the variable will be set in the scope above the current scope. Each new directory or function creates a new scope. This command will set the value of a variable into the parent directory or calling function (whichever is applicable to the case at hand). The previous state of the variable’s value stays the same in the current scope (e.g., if it was undefined before, it is still undefined and if it had a value, it is still that value).
This is a proper way for handle PARENT_SCOPE variables:
Should I make a function scoped variable, fill it in and then at the end copy its contents to a parent scope variable?

Set a variable in current scope and PARENT_SCOPE?

If I do:
set(SourceDir ${CMAKE_CURRENT_SOURCE_DIR} PARENT_SCOPE)
message("SourceDir: " ${SourceDir})
The message says that SourceDir is empty. Presumably it is being set in the parent scope only. Is there a way to set the variable in the current scope AND the parent scope? So that I don't have to do:
set(SourceDir ${CMAKE_CURRENT_SOURCE_DIR} PARENT_SCOPE)
set(SourceDir ${CMAKE_CURRENT_SOURCE_DIR})
message("SourceDir: " ${SourceDir})
When you set it for PARENT_SCOPE, it doesn't do it for current scope somehow. But a two step process works. The first line sets it locally, the second line exports it to the parent scope.
set (LIB_VER 6)
set (LIB_VER ${LIB_VER} PARENT_SCOPE)
I think you can not. The documentation says:
Each new directory or function creates a new scope.
If I understand it correctly when your SET gets executed, its scope is already created by copying the parent scope. So no matter what you do to the original (PARENT_SCOPE) your local scope won't change.
You'd better ask the question on CMake's user list to verify that they don't do fallback to parent when a variable is not defined in the local scope. If they do however, this is a bug.

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::).