TIP 628: Shared 8.7/9.0 build environment

Login
Bounty program for improvements to Tcl and certain Tcl packages.
    Author:        Jan Nijtmans <[email protected]>
    State:         Draft
    Type:          Project
    Vote:          Pending
    Created:       22-06-2022
    Tcl-Version:   9.0
    Keywords:      Tcl
    Tcl-Branch:    tcl8-compat

Abstract

Imagine the situation we want to compile an extensions for both Tcl 8.7 and 9.0. That means, two environments need to be set up, with each of them having it's own 'tcl.h' and 'libtclstub<version>.a'.

This TIP proposes bringing this challenge down to a single environment with can compile the extension for both 8.7 (possibly 8.6 also) and 9.0 (with some additional restrictions).

Specification

First, the stub library 'libtclstub9.0.a' is renamed to 'libtclstub.a', so without version number. Reason: the source code of 'libtclstub9.0.a' is exactly the same as 'libtclstub8.7.a', there is no reason to have a version-number in the filename. Actually 'libtclstub9.0.a' has some more functions, which are not usable in Tcl 8.7, but that is handled by proper if'def'ing in 'tcl.h'. This makes 'libtclstub.a' usable for both Tcl 8.x and 9.0.

The biggest difference between 'tcl.h' in 8.7 and 9.0 is that in Tcl 8.7 many variables have 'int' arguments while in Tcl 9.0 those are 'size_t' arguments. That can be handled in 'tcl.h' as follows:

 #if !defined(TCL_MAJOR_VERSION)
 #   define TCL_MAJOR_VERSION 9
 #endif
 #if TCL_MAJOR_VERSION > 8
 #   define Tcl_Size size_t
 #else
 #   define Tcl_Size int
 #endif

All parameters in 'tcl.h', 'tclDecls.h' ... are changed to use 'Tcl_Size' in stead of 'size_t'. This makes 'tcl.h' from 9.0 usable for Tcl 8.7 too with the following additional restrictions:

Demo

So, how should an extension for Tcl 8.7 be compiled in a Tcl 9.0 environment? The only thing to be done is add -DTCL_MAJOR_VERSION=8 to the CFLAGS. Everything else is exactly the same as compiling for Tcl 9.0.

Example. Let's build 'pkga.dll'. This dll can be compiled as follows (for 64-bit Windows) for loading it in tclsh90:

    x86_64-w64-mingw32-gcc -shared -DUSE_TCL_STUBS=1 -o tcl9pkga.dll unix/dltest/pkga.c -ltclstub
Now, compile the same dll for use in Tcl 8.6 or 8.7:
    x86_64-w64-mingw32-gcc -shared -DUSE_TCL_STUBS=1 -DTCL_MAJOR_VERSION=8 -o pkga.dll unix/dltest/pkga.c -ltclstub

You can try it out:

> tclsh90
$ load ./tcl9pkga.dll
$ pkga_eq
wrong # args: should be "pkga_eq string1 string2"
$ exit
> tclsh86
$ load ./pkga.dll
$ pkga_eq
wrong # args: should be "pkga_eq string1 string2"
$ exit
> tclsh90
$ load ./pkga.dll
interpreter uses an incompatible stubs mechanism
$ exit

Implementation

See branch tcl8-compat

win/Makefile is adapted such that the 'registry' and 'dde' dll's are compiled for both Tcl 9.0 and 8.6 (since those 2 dll's fulfill all restrictions mentioned above). And also unix/dltest/Makefile is adapted such that 'pkga', 'pkgb' and 'pkgc' also are compiled for both (8.6 and 9.0) environments.

Compatibility

The proposed change is 100% source and binary compatible with Tcl 9.0, but it also makes the 'tcl.h' header file and the stub library compatible with a subset of Tcl 8.7.

Copyright

This document has been placed in the public domain.