Repository navigation
Tkinter fails to build with Tcl 9.0 due to Tcl_AppInit() undeclared #104363
Description
Activity
@serhiy-storchaka This issue is about patching _tkinter.
I agree with the analysis of @chrstphrchvz. I came to the same two possible quick solutions, and I also not qualified to decide what is better.
For now, it looks safer to add the missing declaration of
Tcl_AppInit:#if TK_MAJOR_VERSION >= 9 int Tcl_AppInit(Tcl_Interp *); #endif
If the user code uses an embedded Python or a custom build of Python with statically linked Tcl/Tk and third-party binary Tcl/Tk libraries, they will still be able to define a custom
Tcl_AppInit().In future we may implement more modern approach, but this minimum is necessary to build Tkinter with Tcl/Tk 9.0.
I'll add this change in #112681 because both changes are needed to unblock a build.
Tkinter builds now with Tcl 9.0. I leave this issue open for the case if we find better solution.
Reacted by Data Scientist 89It shouldn't be necessary to call at all; it's there for
tclshitself and Tcl only calls it fromTcl_Main(which tkinter definitely shouldn't use, as it is a never-return function!)Cutting out bits that ought to be ignorable, in Tcl 9.0 it's just (on POSIX; Windows has a different RC file name):
int Tcl_AppInit(Tcl_Interp *interp) { if (Tcl_Init(interp) == TCL_ERROR) { return TCL_ERROR; } (void) Tcl_EvalEx(interp, "set tcl_rcFileName [file tildeexpand ~/.tclshrc]", -1, TCL_EVAL_GLOBAL); return TCL_OK; }
The setting of
tcl_rcFileNameis only relevant if you're running interactively, which I'm fairly sure is not a good idea for you either. Which means you can just replace the call toTcl_AppInitwith a call toTcl_Init, which is exported.The build failure itself was fixed in #112681 (gh-112681) by adding the missing declaration under
#if TK_MAJOR_VERSION >= 9, and Tkinter has built against Tcl/Tk 9.0/9.1 since. I left this open in case a cleaner approach emerged, but on review the minimal declaration is the right one.The tempting alternative — rename our
Tcl_AppInitto a private name and drop the version guard — would break a documented customization seam.configuresets-DWITH_APPINIT=1on every standard build, so the liveTcl_AppInitis the one inModules/tkappinit.c, which is the hook for statically linking Tcl/Tk packages (-DWITH_TIX/WITH_BLT/WITH_TOGL/…). Renaming it silently breaks anyone patching that file.@dkfellows is right that the name isn't special (Tcl only calls it from
Tcl_Main, which we don't use) — which is exactly why declaring and calling our own is fine. And we can't reduce the call to a bareTcl_Init, since ourTcl_AppInitalso handles_tkinter_skip_tk_initandTkinter_TkInit.So closing as completed. Retiring
tkappinit.c/WITH_APPINITaltogether (Tix is gone in Tcl 9; BLT/Togl/static-PIL are long dead) is worth considering, but that's a separate cleanup.- added a commit that references this issue
on Sep 11, 2026
Since Tcl 8.0.5 (tcltk/tcl@17481a9), tcl.h has clarified that
Tcl_AppInit()is not an exported Tcl library function, and declaresTcl_AppInit()for compatibility/convenience only:This declaration is deprecated in Tcl 8.7 and removed in Tcl 9.0. Without it, _tkinter.c will fail to build if the compiler treats implicit function declarations as errors:
Although it seems possible to have _tkinter.c declare
Tcl_AppInit()when tcl.h does not, I am not familiar enough withTcl_AppInit()usage to know whether that is a good solution. From reading theTcl_AppInit()documentation, it sounds like Tkinter could instead rename itsTcl_AppInit()in tkappinit.c to something else, which it then always declares in _tkinter.c.