a question about source in Tcl - tcl

I have a file named test7.tcl:
namespace eval ::dai {
variable name "ratzip"
variable birthday "1982"
proc hello {} {
variable name
variable birthday
puts "Hello, I am $name birthday is $birthday"
}
}
and I want to source this file into another file, called test8.tcl in this way:
source test7.tcl
::dai::hello
but it gives me error: couldn't read file "test7.tcl": no such file or directory
but the two files are under the same folder, what happened?

To source a file that is in the same directory as the currently executing script, use this:
source [file join [file dirname [info script]] "test7.tcl"]
Note that this doesn't work inside procedures defined inside the outer script (test8.tcl in your case) because they're typically called after the source finishes. If that's the case for you, the simplest fix is to just save the output of info script in a variable in your outer script (or just source all files immediately instead of lazily for the ultimately best approach).

Use source [file join [file dirname [info script]] test7.tcl] -- that way you'll be sourcing the target file by its full pathname constructed from the full pathname of the file executing source; this will work no matter what your current directory is during the execution.

You don't have to specify the path of the file to be sourced relative to the path of test8.tcl but relative to the current working directory. E.g. use the absolute path:
source /path/to/test7.tcl

Related

TCL issue - file path

I'm having an issue with a TCL hook script.
There's a *.vhd file that I need to open using this line of code:
set f [open C:/Users/myusername/Desktop/myfile.vhd]
this file is set to be part of xil_defaultlib and I try to access it using the library, since the TCL script should be for others to use and they won't be able to access the file using the path I mentioned above.
I've tried choosing the work library instead and referencing the file the following way:
set f [open work.myfile.vhd]
but the TCL console writes:
couldn't open "work.myfile.vhd": no such file or directory
What would be the correct way to open the file using the work or xil_defaultlib libraries as the path to it?
Thanks in advance.

How to obtain the target path pointed by a symbolic link in Tcl

I need to find the path of the target file pointed by a symbolic link in tcl. ie. if C:\temp\link is a symbolic link file pointed to the target C:\bin\sub\sub1\originalfile , how can we find the path C:\bin\sub\sub1\originalfile from the symbolic link file C:\temp\link using Tcl?
i used
set item "C:\temp\link"
file readlink $item
But it returned the following error
could not readlink "C:/temp/link": not a directory
Can anyone help?
There's a trick to handle this problem. It is introduced by the Tcler's Wiki: https://wiki.tcl-lang.org/page/file+normalize, by just appending /something at the end of the path of your symbol link file.
Below I post their original words:
Resolving symlinks in the last component of a path
To resolve symlinks
in a path's final component (i.e., the target file or directory name
itself) you can use the following trick: add /something to the path
before normalizing it then strip the extra component away with file
dirname.
For example,
set resolvedArgv0 [file dirname [file normalize $argv0/___]]]
dbohdan 2015-05-12: This trick was implemented by AK in Tclssg's main > procedure and I thought it deserved wider exposure. The credit is all AK's.
PYK 2015-05-12: This technique is also employed in main script.

Tcl: Sourcing a File.tcl from Another Directory

I created a main tcl file in a specified directory and I want to source another tcl file, which is not in a same directory of the main one.
Give the complete path to the Tcl file as argument to source.
Example: your main file (main.tcl) is in /, the other file (other.tcl) is in /foo/bar/.
source /foo/bar/other.tcl
As always, one must be careful with backslashes separating directories on the Windows platform. If the path is C:\foo\bar\, one must either escape the backslashes (C:\\foo\\bar\\ or {C:\foo\bar\}) or replace them with regular slashes, as in C:/foo/bar/. If the path is relative to the current directory, one can side-step the issue by using file join foo bar.
Documentation: filename, source

How to get path of current script?

Sometimes its needed to get current path of a script. What are the ways to do that?
While a script is being evaluated (but not necessarily while its procedures are being called) the current script name (strictly, whatever was passed to source or the C API equivalent, Tcl_EvalFile() and related) is the result of info script; it's highly advisable to normalise that to an absolute pathname so that any calls to cd don't change the interpretation.
Scripts that need the information tend to put something like this inside themselves:
# This is a *good* use of [variable]…
variable myLocation [file normalize [info script]]
They can then retrieve the value (or things derived from it) easily:
proc getResourceDirectory {} {
variable myLocation
return [file dirname $myLocation]
}
The other common locations are:
$::argv0 which is the “main” script (and you're evaluating the main script if it's equal to info script)
[info nameofexecutable] which is the Tcl interpreter program itself (typically the argv[0] at the C level)
[info library] which is where Tcl's own library scripts are located
$::tcl_pkgPath which is a Tcl list of directories where packages are installed
$::auto_path which is a Tcl list of directories where scripts are searched for (including packages! The package path is used to initialise this.)
The best way I found to do that:
set script_path [ file dirname [ file normalize [ info script ] ] ]
puts $script_path
You may also try like this:
file normalize $argv0
file normalize [info nameofexecutable]
to get fully normalized name
You might have a look at http://wiki.tcl.tk/1710. The solution there also takes care of possible (multiple) symbolic links and points to the physical root location of the script.
In case it does not work with "info script", you can do
regsub {/[a-zA-Z0-9_]+$} $argv0 {} path
do $path/other_script_on_the_same_path_as_this.tcl
Now you will have the path of the current script on the variable $path.

Wrapped Tcl script stops working when moved

I'm new to Tcl and I have a script that is wrapped using freewrapTCLSH.exe
At first, when started, the program complained about not finding a package
I edited the line the seems to "include" it to
lappend auto_path ../../lib/crc
This worked fine and the .exe started without issues. But then I moved the exe to another folder and it started complaining again. I thought that once the exe was created everything would be done. But it doesn't seem to handle this very well.
At first the entire path to the lib was hard coded into the script and then everything worked fine. But since we can't rely on the exe always being built in the same folder this had to be changed.
Any ideas on how to get around this annoying problem?
../../lib/crc is interpreted using the current working directory each time a package is searched. Having this thing it your ::auto_path is almost always not what you want.
I use [file dirname [info script]] to get a directory of currently sourced Tcl file, adding a relative path to some lib/crc with file join, ensuring to get a full pathname with file normalize. The result of file normalize is what I add to ::auto_path (or remember for future use in some other way):
lappend ::auto_path [file normalize [file join [file dirname [info script]] ../mylib]]
It might be obvious, but still: info script returns the path to file currently being sources, not the path somehow remembered when the file containing a call to it was sourced. If you want to get the current script location, ensure it happens at right time (e.g. do it at top level).
You should deliver the required package (and the dependencies of that package) into your exe.
usually this only involves copying the directory of the required packages to the lib folder in your vfs.