How do I make Meson object constant? - meson-build

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')

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.

Distinguish two functions with the same name

I want to use multiple external CMake files in my project. Unfortunately two different files use the same CMake function name foo. I don't want to modify these external files.
Is there a way to call one specific function or will CMake error out? Would it help if one of the functions has a named parameter, i.e., foo(a b c …) and foo(DESTINATION a b c …)?
New function's definition replaces the previous one with the same name. So access to the previous function is lost.
If different functions (but with the same name) are used in different subprojects, you may try to build one subproject as ExternalProject, so function's collision wouldn't occure.
In CMake any function definitions contains the only piece of information for the caller - minimal number of parameters which should be passed to the function. By using this information it is impossible to resolve function's overloading, if it would be implemented.

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

CMake: Access variables across sub directories

I have a two sub directories from root on which one has the line:
set(${LIBNAME}_publicheaders
LocalizeResource.h
)
I want to be able to access this variable from the other subdirectory. How can I do this?
#JoakimGebart's answer is probably the more common way to go about this. However, you can also use get_directory_property directly from within the second subdir to achieve what you're after.
I see that in your comment, you've used ${LIB_NAME}_publicheaders, but in your question you have ${LIBNAME}_publicheaders. This could be the cause of your problems, since the command should work like this:
get_directory_property(MyVar
DIRECTORY ${CMAKE_SOURCE_DIR}/abc
DEFINITION ${LIBNAME}_publicheaders)
However, there are a couple of provisos:
This has to be called after setting the variable in the subdir. i.e. you'd have to ensure add_subdirectory(abc) was called before the add_subdirectory for the one where this will be used.
If LIBNAME is also set inside the same subdir (abc), you'll need to retrieve the value for that first.
So, while this is probably a less common solution, it has the advantage that it doesn't "pollute" the global namespace with subdir-specific variables - this works from with a subdir referring to another subdir.
You can set the variable in the parent scope using the PARENT_SCOPE option to set()
Example:
set(${LIBNAME}_publicheaders
LocalizeResource.h
PARENT_SCOPE
)
See http://www.cmake.org/cmake/help/v2.8.10/cmake.html#command:set
This, however, means that the variable is available not only in the other subdirectory, but in any other subdirectories on the same level as well.