How to specify default values for environment variables in CMakePresets - cmake

When using CMakePresets.json the documentation states that I can use either $env{<variable-name>} or $penv{<variable-name>} to query environment variables.
Is it possible to specify a default value in case the environment variable is not set?
Note:
Since the variable that I am trying to set is also inside the presets, I can't handle the issue inside a CMake script.
If default values are not supported is there any workaround with which I could achieve the same inside the presets file?

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.

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

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