Updated 2011-08-28 14:01:27 by RLE

Purpose: to collect information regarding special tips, techniques, tricks, and got-chas in writing true cross platform Tcl scripts.

Page begun by Larry Virden.

See also Tcl built-ins for cross platform functionality and How should I then code if I want my program to run on most platforms.

Issues:


Other resources:


Here are some example Tcl applications that run on all of UNIX, Win, and MacOS and which are not merely trivial but demonstrate many of the problems/solutions of cross-platform portability.

  • Alphatk [1] is such an application. It is a cross-platform programmer's editor. It has some problems on MacOS, but this is due to a few remaining bugs/issues in MacTk, and not in Alphatk's scripts. It has cross-platform support for things like: executing external scripts, starting up latex processes (and capturing their output), etc. There are now about 170000 lines of Tcl code in there, which work cross-platform!
  • tkbiff [2] includes a lot of code to make it work on all platforms. It sounds like a trivial app but it is actually 4300 lines of Tcl. Besides the things Tcl handles automatically, extra coding is necessary for cross-platform issues like : playing audios, fonts, cursors, preference file locations, keyboard/mouse bindings, invoking browsers, dialogues, and diagnostics. Fairly good rosetta stone since it is small and yet demonstrates things like UNIX/Win exec vs Mac-Applescript and Mac-resources.

Sometimes, even when a command itself isn't available in Tcl or Tk, it can be built rather easily. Hopefully the maintainer of tcllib and developers will continue to work together to gather things like fileutil and other pieces of code together into modules.

Please feel free to add anything you can. Hopefully some new tools could be added to the Tcl and Tk core to improve portability!

expr: The implementation of math functions may differ between platforms. In particular,
 expr atan2(0,0) ;# Windows 2000: returns 0.0
                 ;# Solaris: domain error: argument not in valid range

So be sure to test atan2 calls for non-zero arguments.

Arjen Markus A few things come to mind with to platform-dependencies:

  • Names and paths for external files: Make sure the names of files that you want to read or write (including files you will want to source) are determined correctly. This means: always use the [file join] command if different directories or folders are concerned.
  • Spaces in file names are a particular problem to watch out for - the space can easily be mistaken for a separator! And of course, backslashes can be treated as escape characters. Use the platform-independent file names whenever possible, but be aware that sometimes you have to work with native names.
  • Dealing with floating-point numbers: A lot can be said about floating-point arithmetic, but keep in mind that both the format and the exact value of a number can vary. For instance, some platforms will use three digits to represent the exponent, e.g. 1.23e+001, others use only two and display 1.23e+01. Another difference is the presence or absence of leading zeros: 0.1 or .1. These differences are caused by the underlying C libraries. Values from calculations can differ, sometimes in dramatic ways.
  • Line endings of files is something you do not have to worry about, carriage-return/linefeed or only linefeed or only carriage-return. Unless of course this happens to be relevant information! Use fconfigure to tune the translation of line endings.
  • Binary data can be a nuisance. The two widely found formats, little-endian and big-endian, for integers are supported by Tcl's binary command. Unfortunately, you will have to know the relevant format yourself. The support for floating-point formats is very limited, even though the most common variations are little-endian and big-endian again with the IEEE758 flavour for the bits. (When I have time, I will write a TIP on this one!)

Glenn Halstead Commands that work with Windows that cause an error with UNIX:

  • console show

This command displays a UNIX like console for display of 'puts' commands, etc on Windows but the command does not exist in UNIX version of Tcl and hence causes an error.

Note that catch {console show} can be used so the script will not error on Unix. See also Tkcon, console, and console for Unix for solutions that actually provide a console instead of just skipping the error.
  StephenHill

KPV I wrote a large tcl/tk app that I've gotten feedback from Macintosh users to make it run better on that platform. Below I've listed the issues for which I had to do something special for the Mac:

  • balloon help window: in addition to turning on overrideredirect, I had to add for the Macintosh the following command unsupported1 style .help floating sideTitlebar
  • font: I used geneva versus helvetica for the Mac's balloon help
  • stippling: Mac doesn't seem to support it
  • wm geometry: I don't remember the issue here exactly but on the Mac I had trouble placing a toplevel window on the right edge of the screen
  • dash line patterns: the available dash line patterns is limited on Windows

Environment Variables

glennj: Setting an environment variable to the empty string under MS-Windows actually removes that variable from the environment.
 % puts $tcl_platform(platform)
 windows
 % set env(foo) bar
 % puts $env(foo)
 bar
 % set env(foo) {}
 % puts $env(foo)
 can't read "env(foo)": no such variable

HZe: also, on Windows the name of environment variables is case-insensitive:
 % puts $tcl_platform(platform)
 windows
 % set env(foo) bar
 % puts $env(FOO)
 bar

while on UNIX it is case-sensitive:
 % puts $tcl_platform(platform)
 unix
 % set env(foo) bar
 % puts $env(FOO)
 can't read "env(FOO)": no such variable

MJ - Note that the use of environment variables already throws out platform independence because the environment variables that are usually defined are quite different between Windows and Unix. To ensure platform independence of your script it's therefore advisable to steer clear of environment variables (for instance use the tcl_platform(user) variable instead of env(USER)).

LV For that matter, file names themselves have the same issue, right?

PWQ 14 Sep 07, The real issue is that this page should not be necessary. Originally TCL could be considered a cross development platform, where code written for one OS would work unaltered on another. Unfortunately organisations like TCT and ActiveState are no longer concerned about this and expect the developer to have access to all platforms so they can test their code and add in another 20% code to handle all the differences.

EMJ What language or product successfully hides all platform differences? Tcl is pretty good really. "no longer concerned" and "another 20% code" need some justification - I'm sure I'm not the only one who doesn't see it that way.

LV What leads you to believe that the TCT is no longer concerned about this? If that were true, work on Ttk wouldn't have been completed and moved into Tk 8.5.

ZB Perhaps, instead of checking such "list of differences", the problem - for today - could be resolved by designing another library for tcllib? I mean, instead of:
  if { $::tcl_platform(platform) eq "windows" } {
    set homeDir $::env(USERPROFILE)
  } else {
    set homeDir $::env(HOME)
  }

...something like:
  $::osindependent(HOME)

...could be a cure?