I am a beginner with Tcl/Tk, but I am already in need to deploy an .app with Tcl/Tk frameworks in it (because the .app needs to rely on its own Tcl/Tk version and not on macOS standard and old Tcl/Tk). Can somebody point me to where I can find precompiled Frameworks or to a step-by-step guide on how to compile them on macOS?
Half a day of search has not been very fruitful in this regard. I guess my need is not at all very special, as I see many .apps shipping their own Tcl/Tk Frameworks. (PS: I need to access these Frameworks from Perl, but this shouldn't make any difference.)
Here is my build script. You will need to make modifications to suit
your needs.
- I make modifications to init.tcl so that Tcl will search in the proper locations
and will not look first in the MacOS standard location. This part of the
script will break starting with Tcl/Tk 8.7. It also has a path that is
very specific to my installation (the 'darwin 64 tcl lib' part).
It won't hurt anything to leave it in, or you can modify the path for your needs.
- I make the application relocatable so that it can be run from any location.
This can be a security issue. It is recommended that additional processing be
done after installation to set the library paths to a static location.
I personally recommend Tcl/Tk 8.6.8 at this time, but it has to be built with
an earlier XCode version (I use XCode Command Line Tools 9.2 on Sierra).
There are still various bug fixes for MacOS Mojave being worked on.
Other people may recommend otherwise.
Variables:
- macosxminver : The earliest version of MacOS that Tcl/Tk will be compiled for.
- INSTLOC : The installation location. Point this somewhere other than your target
directory and copy the files to your target directory afterwards.
Note that the INSTLOC directory is completely removed by the script.
- sver : short Tcl version. The only place this is used is in the SRCDIR definition.
You may not need this depending on your SRCDIR directory structure.
- ver : Tcl version number.
- mver : Tcl major version number.
- SRCDIR : Where the Tcl/Tk source trees are located. For the purposes of this
script, I have a directory with the following structure:
directory structure:
tcl868/
tcl8.6.8/
tk8.6.8/
tclbuild.sh:
#!/bin/bash
macosxminver=10.9
sver=868cp
ver=8.6.8
mver=8.6
tclmver=$mver
tkmver=$mver
SRCDIR=$HOME/t/tcl${sver}
INSTLOC=$HOME/t/localB
if [[ $1 != "" ]]; then
INSTLOC=$1
fi
if [[ -d $INSTLOC ]]; then
rm -rf $INSTLOC
fi
mkdir $INSTLOC
cd $SRCDIR
test -d build && rm -rf build
cd $SRCDIR
cd tcl${ver}
if [[ $? -eq 0 ]]; then
f=library/init.tcl
if [[ ! -f $f-orig ]]; then
cp -pf $f $f-orig
fi
cp -pf $f-orig $f
ed $f << _HERE_
/issafe/
i
foreach Dir [list \$::tcl_library [file dirname \$::tcl_library]] {
if { [string match *Tcl.framework* \$Dir] } {
regsub Tcl.framework \$Dir Tk.framework Dir
if {\$Dir ni \$::auto_path} {
lappend ::auto_path \$Dir
}
}
}
# This needs to be at the end
# The real wish executable is in an odd place.
# Find the tcl directory in the path.
set Dir [file dirname [info nameofexecutable]]
if { [string match *MacOS* \$Dir] } {
regsub {MacOS.*} \$Dir {MacOS} Dir
set Dir [file join \$Dir darwin 64 tcl lib]
lappend ::auto_path \$Dir
} else {
set Dir [file join [file dirname [file dirname \\
[info nameofexecutable]]] lib]
}
.
?catch
?set Dir
.,.+4 s/^/#/
/catch
.+1,.+5 s/^/#/
w
q
_HERE_
make -C macosx \
PREFIX="" \
CFLAGS_OPTIMIZE="-O2 -mmacosx-version-min=${macosxminver}" \
INSTALL_ROOT=$INSTLOC install
cd $SRCDIR
chmod u+w $INSTLOC/bin/tclsh${tclmver}
install_name_tool -change \
"/Library/Frameworks/Tcl.framework/Versions/${tclmver}/Tcl" \
@executable_path/../Library/Frameworks/Tcl.framework/Versions/${tclmver}/Tcl \
$INSTLOC/bin/tclsh${tclmver}
fi
cd $SRCDIR
cd tk${ver}
if [[ $? -eq 0 ]]; then
make -C macosx \
PREFIX="" \
CFLAGS_OPTIMIZE="-O2 -mmacosx-version-min=${macosxminver}" \
INSTALL_ROOT=$INSTLOC install
cd $SRCDIR
chmod u+w $INSTLOC/Library/Frameworks/Tk.framework/Versions/${tkmver}/Resources/Wish.app/Contents/MacOS/Wish
install_name_tool -change \
"/Library/Frameworks/Tk.framework/Versions/${tkmver}/Tk" \
@executable_path/../../../../Tk \
$INSTLOC/Library/Frameworks/Tk.framework/Versions/${tkmver}/Resources/Wish.app/Contents/MacOS/Wish
install_name_tool -change \
"/Library/Frameworks/Tcl.framework/Versions/${tclmver}/Tcl" \
@executable_path/../../../../../../../Tcl.framework/Versions/${tclmver}/Tcl \
$INSTLOC/Library/Frameworks/Tk.framework/Versions/${tkmver}/Resources/Wish.app/Contents/MacOS/Wish
fi
cd $SRCDIR
find $INSTLOC -type f -print0 | xargs -0 chmod u+w
exit 0
The proposed script fails for me on Mojave, after compiling for several minutes, with the following error:
ERROR: version conflict for package "Tcl": have 8.5.9, need 8.6-
If running this script from 'make html', set the NATIVE_TCLSH environment
variable to point to an installed tclsh8.6 (or the equivalent tclsh86.exe
on Windows).
make[3]: *** [html-tcl] Error 1
make[2]: *** [install-strip] Error 2
make[1]: *** [install-tcl] Error 2
make: *** [install-deploy] Error 2
tclbuild.sh: line 74: cd: /Users/xl/t/tcl869cp: No such file or directory
tclbuild.sh: line 83: cd: /Users/xl/t/tcl869cp: No such file or directory
tclbuild.sh: line 84: cd: tk8.6.9: No such file or directory
tclbuild.sh: line 103: cd: /Users/xl/t/tcl869cp: No such file or directory
I have the latest Tcl/Tk (8.6.9) resources and the same folder structure as indicated above.