!!!!!! **Introduction** !!!!!! [FPX]: I spent some time in early 2008 porting Tcl to [VxWorks]. The result is a patch that I posted to the Tcl feature tracker here: http://sourceforge.net/tracker/index.php?func=detail&aid=1955146&group_id=10894&atid=360894. This file is far from being a readily mergeable patch -- see some of the ugly technical details below -- but it should get someone started who is desperate to run Tcl on VxWorks. These instructions will result in a Tcl DKM (downloadable kernel module) that can be run and interacted with on the console. Running as a VxWorks RTP (real-time process) mode is not supported, although that should be a comparatively small step. ---- !!!!!! **Building Tcl for VxWorks** !!!!!! ---- These instructions are for a cross-build from Windows to, for reference, the "SIMNTgnu" target (which is the Windows-based VxWorks simulator that comes with Workbench) from the Cygwin command line. For other targets, update the tools and their parameters accordingly (i.e., use the ''ccppc'' compiler instead of ''ccpentium''). ***Apply VxWorks Patch*** Download the Tcl 8.5.2 source code. Download the patch: http://sourceforge.net/tracker/download.php?group_id=10894&atid=360894&file_id=276425&aid=1955146 (this is a plain-text file). Apply the patch to the Tcl 8.5.2 source code using the "patch" program. ***Configure for SIMNTgnu*** Some of these settings must be adjusted based on your target. export WIND_BASE="c:\\WindRiver\\vxworks-6.3" export CC="ccpentium" export CPPFLAGS="-D_WRS_KERNEL -DCPU=SIMNT -DTOOL_FAMILY=gnu -DTOOL=gnu -Ic:/WindRiver/vxworks-6.3/target/h -Ic:/WindRiver/vxworks-6.3/target/h/wrn/coreip -DUSE_FIONBIO" export CFLAGS="-mtune=i486 -march=i486 -ansi" export LDFLAGS="-r -nostdlib" export EXTRA_TCLSH_LIBS="-Wl,-X -T `cygpath --mixed ${WIND_BASE}/target/h/tool/gnu/ldscripts/link.OUT`" export DL_OBJS="tclLoadVxWorks.o" export SHLIB_SUFFIX=".out" export SHLIB_LD="ccpentium -r -nostdlib" export SHLIB_LD_LIBS="-Wl,-X -T `cygpath --mixed ${WIND_BASE}/target/h/tool/gnu/ldscripts/link.OUT`" export AR="arpentium" export ac_cv_c_bigendian=no ***Generic Configuration*** These settings are to convince the ''configure'' script of the existence of various VxWorks functionality, rather than determining the host's functionality. export ac_cv_func_memcmp_clean=yes export ac_cv_func_strtoll=no export ac_cv_func_strtoull=no export ac_cv_func_strncasecmp=no export ac_cv_func_realpath=no export ac_cv_func_uname=no export ac_cv_func_gethostbyname_r=no export ac_cv_func_gethostbyaddr_r=no export tcl_cv_strstr_unbroken=ok export tcl_cv_strtoul_unbroken=ok export tcl_cv_strtod_unbroken=ok export tcl_cv_strtod_buggy=ok export tcl_cv_timezone_long=no export tcl_cv_timezone_time=no export tcl_cv_putenv_copy=yes export ac_cv_lib_pthread_pthread_mutex_init=yes export no_pipe=yes ***Run Configure*** Now run the autoconf script: ./configure --enable-threads --disable-shared --enable-symbols --host=vxworksdkm ***Fix Makefiles for Cygwin*** When building on Windows using Cygwin, the Makefile needs to be hacked so that ''make'' sees cygwin-style paths while the compiler sees Windows-style paths: sed -e 's/\$(CC)\(.*\)\(\$[A-Za-z0-9_./()]*\)$/$(CC)\1\`cygpath --windows \2\`/' < Makefile > Makefile.1 sed -e 's/-I\(\${[A-Z_]*}\)/-I\`cygpath --windows \1\`/g' < Makefile.1 > Makefile.2 sed -e 's%-L/cygdrive/\(.\)\(/[A-Za-z0-9._/]*\)%-L\1:\2%g' < Makefile.2 > Makefile.3 sed -e 's%\t\t\(\$(GENERIC_DIR)/tclPkgConfig.c\)%\t\t\`cygpath --windows \1\`%' < Makefile.3 > Makefile.4 sed -e 's%\t\t\(\$(UNIX_DIR)/tclUnixInit.c\)%\t\t\`cygpath --windows \1\`%' < Makefile.4 > Makefile.5 This shouldn't be necessary for a cross-build from Unix. ***Build*** After all of the above, Tcl should build fine. On Windows, use the hacked ''Makefile.5'' (see above). This should result in the loadable module '''tclsh.out'''. ---- !!!!!! **Using Tcl** !!!!!! ---- In the VxWorks C interpreter, load the Tcl DKM built above -- assumed to be in the ''/tcl'' directory, adjust as necessary -- using ld < /tcl/tclsh.out Before starting Tcl, the ''pre-init'' script must be set to configure Tcl's library path, e.g., by running the following command in the VxWorks C interpreter: TclSetPreInitScript ("set ::tclDefaultLibrary /tcl/library"); Note: if this step omitted, then Tcl will fail, complaining that it can not find the ''init.tcl'' file. Then it will crash. The Tcl module provides two entrypoints that can be called from the C interpreter: `tcl`: Enters an interactive Tcl shell session. Line editing and history follows the usual VxWorks rules. Use `shellConfigSet INTERPRETER=C` to return to the C interpreter. Tcl interpreter state is preserved when switching in and out of the interactive session. Ctrl-C can be used to restart the interpreter (at which point state is lost). `tclsh ''file''`: This executes the contents of ''file'' in a new Tcl interpreter (no state is shared with other sessions). ---- !!!!!! **Tcl Extensions** !!!!!! ---- The following VxWorks-specific commands are available: ***shellConfigSet*** Usage: shellConfigSet config This calls `shellConfigSet (CURRENT_SHELL_SESSION, ''config'')`. The primary purpose of this command is to switch back from an interactive Tcl session to the C interpreter using `shellConfigSet INTERPRETER=C`. See the `shellLib` documentation for more information. ***shellEvaluate*** Usage: shellEvaluate cmd ?interpreter? This evaluates ''cmd'' in ''interpreter'' and returns the result. If omitted, ''interpreter'' defaults to `C`. See the documentation for `shellInterpEvaluate()` for more information. Only integer-type return values are supported. While `shellInterpEvaluate()` appears to return the polymorphic type `SHELL_EVAL_VALUE`, it is not documented, and I have not seen its `type` field be anything else than `SHELL_INT`. ***shellExec*** Usage: shellExec cmd ?interpreter? This evaluates ''cmd'' in ''interpreter'' and returns the output, similar to capturing a process' standard output. If omitted, ''interpreter'' defaults to `C`. The shell echoes commands as they are interpreted, so `cmd` is included in the output. The C shell also prints the value that each individual command evaluates to. So some post-processing of the returned value is necessary. A new interpreter session is created, which has its working directory initialized to some default, rather than inheriting Tcl's working directory. ''cmd'' should use absolute file names or change to the desired directory before accessing any files. This command may hang if ''cmd'' attempts to read from the console. ***exit*** The `exit` command is replaced to delete the current interpreter rather than exiting from the process -- the latter would make Tcl unusable. If this happens at an inopportune time, the error "eval called on a deleted interpreter" may occur. This is harmless, but Tcl should be modified to avoid this error. If `exit` is used in an interactive session, the current Tcl interpreter is deleted, and the session is returned to the C interpreter. When `tcl` is called again, a new Tcl interpreter session is started. ---- !!!!!! **BSP Features** !!!!!! ---- For reference, I needed to enable the following features in the kernel configurator beyond the "default": * INCLUDE_GETADDRINFO * INCLUDE_GETIFADDRS * INCLUDE_GETNAMEINFO * INCLUDE_GETNAMEINFO_SYSCTL * INCLUDE_GETSERVBYNAME * INCLUDE_STRICMP ---- !!!!!! **Tcl Features** !!!!!! ---- Loading Tcl modules must be built as DKMs, and should be stub-enabled. Sorry, no threads yet. No pipes or [exec]. ---- !!!!!! **The Gory Details** !!!!!! ---- Details to follow, especially on the event notifier hack, so that others may improve upon it. ---- !!!!!! %| [Category Porting] |% !!!!!!