Have you tried using the "auto_path" and "tclIndex" capabilities of tcl?
I believe that solves the problem.
I use this method extensively and find it very useful to remove complications that you describe...
Plus: The compiler does a better optimization of the code this way versus 'source'ing in-line.
Example: Create/generate a ./tclIndex file:
./hello.tcl
proc hello {args} {
puts {hello world!}
}
% tclsh
% auto_mkindex [pwd] *.tcl
Output:
./tclIndex
# Tcl autoload index file, version 2.0
# This file is generated by the "auto_mkindex" command
# and sourced to set up indexing information for one or
# more commands. Typically each line is a command that
# sets an element in the auto_index array, where the
# element name is the name of a command and the value is
# a script that loads the command.
set auto_index(hello) [list source [file join $dir hello.tcl]]
Example: Add a path to TCL's "auto_path" search mechanism.
% tclsh
% lappend auto_path <path>
% hello
hello world!
In practice, to make this uniform in a development project and leverage it in an application -- I create a script in each tcl/src directory:
./update_tclIndex
#! /usr/bin/env tclsh
set dirlist [list "."]
foreach procdir $dirlist {
auto_mkindex $procdir *.tcl
}
And I execute this script anytime a new tcl procedure is added and this can be either a new tcl file or an existing tcl file that contains multiple procedures -- this works for both/any scenarios.
Using the 'update_tclIndex' script in combination with version control on the directory (svn for example) I can quickly see if content of tclIndex changed whenever ./update_tclIndex is ran. (svn status -u)
With respect to using this in a "main/program", I have implemented a convention which is to maintain a "init.tcl" file in the src directory of the tcl/program.
The first line in the "tcl/main/program" is to source the "init.tcl" file and then call the 'main' tcl procedure.
./main
#! /usr/bin/env tclsh
source <program_installation_path>/init.tcl
main <args>
The init.tcl file is responsible for knowing all the src directories the program needs for itself.
./init.tcl
lappend auto_path <program_installation_path>/tcl
lappend auto_path <program_installation_path>/tcl/subdir
etc...
This init.tcl file is usually more flexible, and uses $::env(PROGRAM_INSTALL) variables for the path and some additional checks to print nice messages if the variables aren't defined or we don't find basic/sanity checks that we expect -- so that users are given 'nice/pretty' messages and instructions on how the program is expecting to be ran, etc...
For example the hello proc can be called in the 'init.tcl' script to test that it found the procedure before proceeding to 'main'.
The 'main' program is a tcl procedure as well:
./main.tcl
proc main {args} {
<body>
}
Example User Calling the Program:
% main <args>
Hope that's helpful,
Jim
PS. If you follow all that and find it remotely useful -- the next question, typically (at least in my mind that's what happened), is how to pass arguments to a procedure (non-position-ally that is). If you're at that point and have that question -- feel free to post a new ticket and I'll share the code I have to do that...
i.e: main -arg <value> -arg <value> -arg <value>