Intro: Tcl extensions compiled for Tcl 8 and 9 differ for the most part in shared libraries. Executable scripts and examples would differ by shebangs. Any extension config files would conflict by name. All other files would be the same.
Can a Tcl extension be built for both Tcl 8 and 9 in one Makefile? No, not really. Tried: * Using Tcl 9, an extension lib can be built for Tcl 8. Done in 'post-install', hacky and fragile, brings in a Tcl 9 dep for the Tcl 8 version (extra dep for current users), and doesn't provide more than the .so. No tests or anything. * Port hackrobatics to build both Tcl 8 and 9 versions at the the same time. Highly unsatisfactory and a bit silly. * One tcl9 subdir with the top Makefile being the main Makefile but also declaring a tcl9 subdir. Convoluted and didn't work! Building the port twice would yield the best result for each. I not to create a new dir and a whole new port for Tcl 9. Ultimately I gave in, and this way involves two new dirs. Howto: Two new subdirs: tcl8 and tcl9. Most of the existing Makefile becomes Makefile.inc. The 8/9 specific bits are put into their respective Makefiles. Patches, distinfo and descr remain where they are. New top-level Makefile for the subdirs. One of the two will will be the "main" and contain most of the files. The other will be like a subpackage that depends on the "main" and contains only the files for the Tcl version for which it was built. This approach yields a nice separation and allows working with each port individually. Also easy to handle the small differences. Nothing would change for current (Tcl 8) users of the port. Tcl 9 users would install the Tcl 9 version kind of like a subpackage. This could be also flipped around, with the Tcl 9 version being the "main" and the Tcl 8 version being dependent. Might be more future-looking? Drawback is Tcl 8 users will also get the Tcl 9 version. Naming: Package names for Tcl 9 will have "-tcl9" added, before the version: xyz-1.0 for Tcl 8 (as it is currently), xyz-tcl9-1.0 for Tcl 9. Tcl extension lib naming convention puts "tcl9" before names, so the name could be tcl9xyz-1.0 for Tcl 9. Sorts differently. I prefer "-tcl9" but I'm not picky. Keep stub lib names consistent: Tcl extension libs for Tcl 8 tend to be named like: libxyz123.so, libxyz123.so.0.0 and libxyzstub123.a. Tcl extension libs for Tcl 9 tend to be named like: libtcl9xyz123.so, libtcl9xyz123.so.0.0, and libxyzstub.a. This might mean that that one stub lib is good for both Tcl 8 and 9. I'll look into that, eventually. A stub lib for Tcl 9 will instead be named like libtcl9xyz123.a, which follows the convention for the other libs as well as the Tcl/Tk 9 ports themselves. Extension config files: Extensions that provide linkable and maybe stub libs tend to have an associated *Config.sh file, ex: xyzConfig.sh, that provides build info like lib locations and cc/ld flags. Used like: $ ./configure --with-xyz=/path/to/dir/containing. This means that either the *Config.sh file for Tcl 9 would have to be renamed if installed in the same dir as the *Config.sh file for Tcl 8, or placed in another dir. I have chosen to not change the name and instead put the file in a subdir "tcl9" of the package install dir. The file could be renamed like tcl9*Config.sh and placed in the same dir as the Tcl 8 *Config.sh file, then some ac_something can be set when building against, but this is more straightforward although it does mean a new directory for the Tcl 9 *Config.sh file. Examples and bins: Shebangs are set from the "main" (currently Tcl 8) port. Right now, there are no bins so that can be handled if/when it comes up. Since examples are usually scripts, they can be run from the command line with any tclsh. Also consider a tcl9 subdir for examples, if it seems worth it. Comments: Append to comment lines either " (Tcl8)" or " (Tcl9)". Maybe " (Tcl 8)" / " (Tcl 9)" ? Tclsh: The current TEA (Tcl Extension Architecture) doesn't find tclsh9 but thinks it found tclsh9.0. Set TCLSH_PROG in TEST_FLAGS for Tcl 9 until TEA improves. So far only needed for testing. Note on script-only extensions: Only one copy of a script-only extension needs to be installed. The "main" package will install the files where they're available to the lowest Tcl version: 8. The other might not install any files, but will be needed to pull in dependencies. Dependencies: A port depending on (say) "databases/sqlite3-tcl" would have to change to "databases/sqlite3-tcl/tcl8" to maintain the status quo. This is AIUI. I don't know if that's problematic, or if something could be set to make the Tcl 8 version be "databases/sqlite3-tcl", or what/how should be the the way to go. So that's what I've come up with. I'll be posting some ports that do all of this. Most likely there are things that could be done better. Comments please, the bikeshed is open. Stu
