TCL: how to check if environment variable already set - module

I am trying to construct a module file and I would like to include an if statement to check whether certain environment variables (e.g. PATH, LD_LIBRAY_PATH, PYTHON_PATH, ...) have already been set.
I have tried several different syntax options (after searching on here, official documentation and other forums) but when I then try:
module use modulefiles
module load mymodule
I keep getting ERROR:102: Tcl command execution failed error. Here are a few of the options that I have tried:
i)
set myTools /path/to/my/Tools
if { info exists $LD_LIBRARY_PATH } {
setenv LD_LIBRARY_PATH $myTools/lib:$myTool/lib64:$LD_LIBRARY_PATH
} else {
setenv LD_LIBRARY_PATH $myTools/lib:$myTools/lib64
}
ii)
set myTools /path/to/my/Tools
if { [info exists $LD_LIBRARY_PATH] } {
setenv LD_LIBRARY_PATH $myTools/lib:$myTool/lib64:$LD_LIBRARY_PATH
} else {
setenv LD_LIBRARY_PATH $myTools/lib:$myTools/lib64
}
iii)
set myTools /path/to/my/Tools
if { $?LD_LIBRARY_PATH } {
setenv LD_LIBRARY_PATH $myTools/lib:$myTool/lib64:$LD_LIBRARY_PATH
} else {
setenv LD_LIBRARY_PATH $myTools/lib:$myTools/lib64
}
What is the correct syntax to check for the existence of environment variables that may have already been set, e.g. in a .cshrc or .login file?
Apologies if this is a basic question. I've done stuff like this before in the shell (mainly csh), but I am new to TCL and building module files, so any help and advice wold be greatly appreciated!
Thanks!

The http://wiki.tcl.tk/1624 about env contains probably the answer to your question.
Following the hints given in the other answers and the wiki link given above I constructed following code which works for me.
if { [info exists ::env(IDL_PATH)] } {
if {![string match *<IDL_DEFAULT>* $::env(IDL_PATH)]} {
puts stderr "Warning: ill defined IDL_PATH environment variable
}
} else {
setenv IDL_PATH "<IDL_DEFAULT>"
}

the env global array could be also used to set the value of the environment variable, and it is better to use ::env instead of env to access it from the level 0 (or declare it as global env)
set myTools /path/to/my/Tools
if { [info exists ::env(LD_LIBRARY_PATH)] } {
set ::env(LD_LIBRARY_PATH) $myTools/lib:$myTool/lib64:$env(LD_LIBRARY_PATH)
} else {
set ::env(LD_LIBRARY_PATH) $myTools/lib:$myTools/lib64
}

It really helps if you have the actual error message and not the summary “something went wrong”.
Generally speaking, environment variables are mapped into elements of the global env array in Tcl; they don't just become individual global variables (as that would be open to too much abuse). Also, when talking about a variable you don't read from it and so don't prefix it with $ (which in Tcl is strictly a read operation). That said, using the setenv is important because that is about manipulating the environment in the caller, not in the Tcl code itself.
So we use a variation on your second attempt.
set myTools /path/to/my/Tools
if { [info exists env(LD_LIBRARY_PATH)] } {
setenv LD_LIBRARY_PATH $myTools/lib:$myTool/lib64:$env(LD_LIBRARY_PATH)
} else {
setenv LD_LIBRARY_PATH $myTools/lib:$myTools/lib64
}
The problem with the first attempt is that you need to use square-bracket syntax to use the output of a Tcl command. The problem with the third one is that $? doesn't mean anything to Tcl at all (I guess we could change that, but it would be a long road to walk and it doesn't help you now).

Related

Best way to check optional module availability

In a module I'm writing there is just one method which requires an additional module, so I wish to make that module optional by not listing it in the depends part of the META6.json file. The method will return a Failure object if the optional module is not available.
I know I can do something like this:
if (try require Optional::Module) !=== Nil {
# go on
} else {
# fail
}
Is there any better way to do it?
I want to thank everyone who answered or commented on this question.
I benchmarked my proposed solution and the two ones given in the comments to my question:
my $pre = now;
for ^10000 {
$*REPO.repo-chain.map(*.?candidates('Available::Module').Slip).grep(*.defined);
$*REPO.repo-chain.map(*.?candidates('Unavailable::Module').Slip).grep(*.defined);
}
say now - $pre; # 13.223087
$pre = now;
for ^10000 {
$*REPO.resolve(CompUnit::DependencySpecification.new(:short-name("Available::Module")));
$*REPO.resolve(CompUnit::DependencySpecification.new(:short-name("Unavailable::Module")));
}
say now - $pre; # 3.105257
$pre = now;
for ^10000 {
(try require Available::Module) !=== Nil;
(try require Unavailable::Module) !=== Nil;
}
say now - $pre; # 4.963793
Change the module names to match one that you have available on your system and one that you don't.
The comments show the results in seconds on my computer.
Something like this?
my $loaded = False;
CATCH {
default { $loaded = True }
}
require Optional::Module;
if ( ! $loaded ) {
# Fail
}
# Go on
In this case it will try and load the module and catch the exception at runtime.

How can Poplar codelets include code from other header files?

Is it possible for codelets to reference code in other files, like header files?
If I have a codelet file
//FileA.cpp
#include "FileB.h"
class SomeCustomVertex : public Vertex {
public:
bool compute() {
int a = SomeConstantDefinedInFileB;
}
...
}
and some other "codelet" file
//FileB.h
const int SomeConstantDefineInFileB = 42;
and in the host graph program:
graph.addCodelets({"codelets/FileA.cpp", "codelets/FileB.h"});
I get a compile error from popc:
fatal error: 'FileB.h' file not found
#include "FileB.h"
^~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
terminate called after throwing an instance of 'poplar::graph_program_compilation_error'
what(): Codelet compilation failed (see compiler output for details)
I figured this out.
Graph::addCodelets has a parameter StringRef compileFlags = "", which you can use to inject compiler options.
popc --help shows an option
-I arg Add directory to include search path
So when I use graph.addCodelets({"codelets/FileA.cpp"}, "-I codelets"); in the host program, and have my codelets in 'codelets' subdirectory, this works. No need to explicitly list the ".h" files in the arguments.
Incidentally, also a good way to ensure compiler optimisation (-O3) for the custom codelets.

I have a problem in sass, why the variable not understandable for lang['en'] but in case selector is ok

[lang='en'] { $left:left; $right:right; }
[lang='ar'] { $left:right; $right:left; }
Why am I getting error in first one?
It is because your variable $left is undefined in the global context. You only defined it in the context of [lang='en'] and [lang='ar'].
As sass variables are imperative, you can initiate it with a default value and overwrite it later.

Typescript build error (TS5007)

I've been trying to get typescript building via the build servers on visualstudio.com, and I've done the normal thing of bringing typescript into source control. But I'm getting the following issue:
VSTSC : error TS5007: Build:
Cannot resolvereferenced file:
'COMPUTE_PATHS_ONLY'.
[C:\a\src\Main\RecruitCloud\RecruitCloud.csproj]
I'm aware of the encoding issues, but in all the examples I've seen the culprit file has been named in the error message.
I'm starting to think this could be down to the number of typescript files I'm compiling in the project.
Any ideas?
This is a configuration option for the VsTsc task, the one that runs the compiler. It is used in the PreComputeCompileTypeScript target. The intention is to make the VsTsc task go through all the motions, except to run the compiler. That didn't pan out on your machine, it actually did run the compiler. Which then threw a fit since it can't find a file named COMPUTE_PATHS_ONLY.
The VsTsc task is stored in C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v12.0\TypeScript\TypeScript.Tasks.dll. Looking at the assembly with a decompiler:
protected override int ExecuteTool(string pathToTool, string responseFileCommands, string commandLineCommands)
{
if (this.Configurations.Contains("--sourcemap"))
{
this.generateSourceMaps = true;
}
else
{
this.generateSourceMaps = false;
}
if (this.Configurations.Contains("--declaration"))
{
this.generateDeclarations = true;
}
else
{
this.generateDeclarations = false;
}
this.GenerateOutputPaths();
if (!responseFileCommands.Contains("COMPUTE_PATHS_ONLY"))
{
return base.ExecuteTool(pathToTool, responseFileCommands, commandLineCommands);
}
return 0;
}
Note the !responseFileCommands.Contains() test to bypass the base.ExecuteTool() call.
All I can guess is that the method doesn't look like this on your machine. With the most likely cause that you have an outdated version of TypeScript.Tasks.dll. On my machine with VS2013 Update 4 installed it is dated Nov 11, 2014 with a size of 27816 bytes.
Your best bet would be to simply resave all the files in Unicode encoding. You can do it from a quick powershell script (Change files' encoding recursively on Windows?)
Get-ChildItem *.txt | ForEach-Object {
$content = $_ | Get-Content
Set-Content -PassThru $_.Fullname $content -Encoding UTF8 -Force}

Yii trace - proper usage

Unit testing and xdebug usage aside, I wish to have a way to throw some browser message is a value is not expected to be present.
Let's say: $className = 45;
If we have:
public function setMainClass($className) {
if (is_string($className)) {
$this->_mainClass = $className;
} else {
echo Yii::trace(CVarDumper::dumpAsString($className),'vardump');
}
}
We will get this output to the browser on development stage.
It's great.
I'm not sure however, if this is a proper way of use Yii::trace of if I'm miss using it.
Please advice.
It is not necessary to echo the call Yii::trace() (it returns void so the echo does nothing). The other recommendation is that you might consider changing category to resemble a path alias as discussed in the documentation. For example-
} else {
Yii::trace(CVarDumper::dumpAsString($className), 'application.models.MyGreatModel');
}