The documentation for if/ifdef is slightly confusing. For <?if [expression] ?>, it states:
Variables can be used to check for existence
...
If the variable doesn't exist, evaluation will fail and an error will be raised.
It turns out if you just go: <?if $(env.MY_VAR) ?> and MY_VAR is not defined, compilation will fail. How do I check for existence?
Ordinarily, this is where one would use an ifdef, but these work strangely in Wix too. Instead of using $(var.Variable) syntax, they use <?ifdef Variable?>, meaning environment variables can't be checked this way.
What do I need to do to get the equivalent of normal c pre-processor:
#ifdef MY_ENVIRONMENT_VARIABLE
in Wix?
The correct way to reference environment variables in ifdef sections is:
<?ifdef env.MY_VAR?>
...
<?endif?>
This works as expected.
<Condition Message="Missing Environment Variable Message Goes Here"><![CDATA[%envvargoeshere]]></Condition>
Put the above element in the Package element of the wxs file.
The installation will fail at runtime (install time) with a nice message if the environment variable does not exist.
Related
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')
In NLog, is there a way to have a variable with a conditional value? I've seen this: https://github.com/NLog/NLog/wiki/When-Layout-Renderer and tried the following:
<variable name="EnvironmentString" value="${when:when='${IsProd}' == 'true':Prod:else:Stage}"/>
but the value is just returned as a literal; the logic is not being processed.
Thanks,
1) Change the syntax to this:
${when:when='${var:IsProd}'=='true':inner=Prod:else=Stage}
Note:
:else= rather than :else:
:inner=
var:IsProd (assuming IsProd is another variable)
2) Move the whole conditional to the final Layout
<target ... layout="other stuff|${when:when='${var:IsProd}'=='true':inner=Prod:else=Stage}|other stuff" ... />
I've not managed to get conditionals working in variables. Perhaps someone else could say why.
This should work.
But it depends how the variable is used.
If you use:
${EnvironmentString}
Then it's evaluated when loading the configuration, and so you could use it for all parameters.
To evaluate it dynamically, use
${var:EnvironmentString}
But please note that ${var} only works if the parameter of the Target/Layout is of type Layout
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.
I've been trying to figure out why my condition isn't working for my SetDirectory. I haven't been able to find any examples of anyone actually doing this, only that it is possible to do so, according to the WiX documentation.
I've tried the following:
<SetDirectory Id="INSTALLLOCATION" Value="TEST">ComputerName=LJPRESCOTT1</SetDirectory>
This compiles, but gets ignored at runtime. The files end up getting installed straight on the C:\ Drive, and not in C:\TEST like I'm aiming for.
and
<SetDirectory Id="INSTALLLOCATION" Value="TEST">[ComputerName]=LJPRESCOTT1</SetDirectory>
This doesn't compile and throws a "Bad conditional string" error.
If I do this, it creates a directory named LJPRESCOTT1 as expected:
<SetDirectory Id="INSTALLLOCATION" Value="[ComputerName]" />
So I know the Comp Name is correct.
Am I doing something wrong here, or is this not possible?
Thanks!
You use the syntax [ComputerName] only when you are doing formatting, or using values that are of type Formatted, hence the syntax error in the second example.
But in the first example what you are doing is comparing the value of the ComputerName property with the value of the LJPRESCOTT1 (public) property, which I imagine always evaluates to false. If you want to compare ComputerName to a hard string value you need some quotes:
ComputerName="LJPRESCOTT1"
I have the following two files:
a.tcl:
set condition false
source b.tcl
b.tcl:
if {$condition} {
puts "hello"
}
When I run a.tcl, it prints "hello". Is this a correct practice for accessing variable defined in a.tcl? What is the scope of $condition in b.tcl? Thank you.
The scope of condition is global. The source command evaluates the script read from the specified file in the context it's run; in your case this context is also global, hence your puts works.
The question about practice is more complicated as it hightly depends on what you actually do.
The way the source command works is pretty much exactly as if it was reading the file into a string and then passing that to eval (the sole subtlety is to do with info script). That means that the scope that the source was done in will be the one that the outermost level of the script is evaluated in, and so that you could have condition be a local variable there:
proc funkystuff {condition} {
source b.tcl
}
funkystuff true
That will work (and is in fact vital for how Tcl's package definition scripts work; they're evaluated in a context where there is a local variable $dir that describes where the package definition is located) but it can most certainly lead to code that is confusing!
Because of this, it's good practice to write your scripts so that the code inside them makes no assumptions about what context it is evaluated in. The easiest way to do that is often to put the code in the script inside a namespace, where the name of the namespace is fully qualified.
namespace eval ::foobar {
# Do stuff here...
}
It's also a good thing to try to write code that isn't excessively parameterized on sourcing, instead saving that for either which version of the code you load (e.g., one file for Linux, another for Windows) or what parameters you pass to the commands. Of course you don't have to work that way, but it does help make your code robust and easy to understand.
Finally, the scope used for the main script to a Tcl interpreter is always evaluated at the global level (i.e., in the :: namespace with no parent scope).