bpo-45847: Port _tkinter to PY_STDLIB_MOD (GH-31698)

- Remove ``--with-tclk-*`` options from `configure`
- Use pkg-config to detect `_tkinter` dependencies (Tcl/Tk, X11)
- Manual override via environment variables `TCLTK_CFLAGS` and `TCLTK_LIBS`
This commit is contained in:
Erlend Egeberg Aasland 2022-03-31 12:19:08 +02:00 committed by GitHub
parent 7fc39a21cb
commit b36d222110
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 403 additions and 518 deletions

View file

@ -404,14 +404,6 @@ Libraries options
.. versionadded:: 3.10
.. cmdoption:: --with-tcltk-includes='-I...'
Override search for Tcl and Tk include files.
.. cmdoption:: --with-tcltk-libs='-L...'
Override search for Tcl and Tk libraries.
.. cmdoption:: --with-libm=STRING
Override ``libm`` math library to *STRING* (default is system-dependent).

View file

@ -2019,8 +2019,8 @@ Build Changes
* The ``configure`` script now uses the ``pkg-config`` utility, if available,
to detect the location of Tcl/Tk headers and libraries. As before, those
locations can be explicitly specified with the :option:`--with-tcltk-includes`
and :option:`--with-tcltk-libs` configuration options.
locations can be explicitly specified with the ``--with-tcltk-includes``
and ``--with-tcltk-libs`` configuration options.
(Contributed by Manolis Stamatogiannakis in :issue:`42603`.)
* Add :option:`--with-openssl-rpath` option to ``configure`` script. The option

View file

@ -770,11 +770,17 @@ Build Changes
* Build dependencies, compiler flags, and linker flags for most stdlib
extension modules are now detected by :program:`configure`. libffi, libnsl,
libsqlite3, zlib, bzip2, liblzma, libcrypt, and uuid flags are detected by
``pkg-config`` (when available).
libsqlite3, zlib, bzip2, liblzma, libcrypt, Tcl/Tk libs, and uuid flags
are detected by ``pkg-config`` (when available).
(Contributed by Christian Heimes and Erlend Egeberg Aasland in
:issue:`bpo-45847`, :issue:`45747`, and :issue:`45763`.)
.. note::
Use the environment variables ``TCLTK_CFLAGS`` and ``TCLTK_LIBS`` to
manually specify the location of Tcl/Tk headers and libraries.
The :program:`configure` options ``--with-tcltk-includes`` and
``--with-tcltk-libs`` have been removed.
* CPython now has experimental support for cross compiling to WebAssembly
platform ``wasm32-emscripten``. The effort is inspired by previous work
like Pyodide.

View file

@ -1249,7 +1249,7 @@ Build Changes
of macOS. If a macOS SDK is explicitly configured, by using
:option:`--enable-universalsdk` or ``-isysroot``, only the SDK itself is
searched. The default behavior can still be overridden with
:option:`--with-tcltk-includes` and :option:`--with-tcltk-libs`.
``--with-tcltk-includes`` and ``--with-tcltk-libs``.
(Contributed by Ned Deily in :issue:`34956`.)
* Python can now be built for Windows 10 ARM64.

View file

@ -302,10 +302,6 @@ _PYTHON_HOST_PLATFORM=@_PYTHON_HOST_PLATFORM@
BUILD_GNU_TYPE= @build@
HOST_GNU_TYPE= @host@
# Tcl and Tk config info from --with-tcltk-includes and -libs options
TCLTK_INCLUDES= @TCLTK_INCLUDES@
TCLTK_LIBS= @TCLTK_LIBS@
# The task to run while instrumented when building the profile-opt target.
# To speed up profile generation, we don't run the full unit test suite
# by default. The default is "-m test --pgo". To run more tests, use
@ -736,10 +732,8 @@ sharedmods: $(BUILDPYTHON) pybuilddir.txt @LIBMPDEC_INTERNAL@ @LIBEXPAT_INTERNAL
*) quiet="";; \
esac; \
echo "$(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' \
_TCLTK_INCLUDES='$(TCLTK_INCLUDES)' _TCLTK_LIBS='$(TCLTK_LIBS)' \
$(PYTHON_FOR_BUILD) $(srcdir)/setup.py $$quiet build"; \
$(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' \
_TCLTK_INCLUDES='$(TCLTK_INCLUDES)' _TCLTK_LIBS='$(TCLTK_LIBS)' \
$(PYTHON_FOR_BUILD) $(srcdir)/setup.py $$quiet build

View file

@ -150,12 +150,11 @@
# needs -lcrypt
@MODULE__HASHLIB_TRUE@_hashlib _hashopenssl.c
# needs -ltk, -ltcl, and sometimes -lX11
#@MODULE__TKINTER_TRUE@_tkinter _tkinter.c tkappinit.c
# Linux: -luuid, BSD/AIX: libc's uuid_create()
@MODULE__UUID_TRUE@_uuid _uuidmodule.c
@MODULE__TKINTER_TRUE@_tkinter _tkinter.c tkappinit.c
############################################################################
# macOS specific modules

385
configure generated vendored
View file

@ -654,6 +654,8 @@ MODULE_BINASCII_FALSE
MODULE_BINASCII_TRUE
MODULE_ZLIB_FALSE
MODULE_ZLIB_TRUE
MODULE__TKINTER_FALSE
MODULE__TKINTER_TRUE
MODULE__UUID_FALSE
MODULE__UUID_TRUE
MODULE__SQLITE3_FALSE
@ -821,8 +823,10 @@ DFLAGS
DTRACE
GDBM_LIBS
GDBM_CFLAGS
X11_LIBS
X11_CFLAGS
TCLTK_LIBS
TCLTK_INCLUDES
TCLTK_CFLAGS
LIBSQLITE3_LIBS
LIBSQLITE3_CFLAGS
LIBNSL_LIBS
@ -1032,8 +1036,6 @@ with_system_ffi
with_system_libmpdec
with_decimal_contextvar
enable_loadable_sqlite_extensions
with_tcltk_includes
with_tcltk_libs
with_dbmliborder
enable_ipv6
with_doc_strings
@ -1077,6 +1079,10 @@ LIBNSL_CFLAGS
LIBNSL_LIBS
LIBSQLITE3_CFLAGS
LIBSQLITE3_LIBS
TCLTK_CFLAGS
TCLTK_LIBS
X11_CFLAGS
X11_LIBS
GDBM_CFLAGS
GDBM_LIBS
ZLIB_CFLAGS
@ -1801,10 +1807,6 @@ Optional Packages:
--with-decimal-contextvar
build _decimal module using a coroutine-local rather
than a thread-local context (default is yes)
--with-tcltk-includes='-I...'
override search for Tcl and Tk include files
--with-tcltk-libs='-L...'
override search for Tcl and Tk libs
--with-dbmliborder=db1:db2:...
override order to check db backends for dbm; a valid
value is a colon separated string with the backend
@ -1880,6 +1882,11 @@ Some influential environment variables:
C compiler flags for LIBSQLITE3, overriding pkg-config
LIBSQLITE3_LIBS
linker flags for LIBSQLITE3, overriding pkg-config
TCLTK_CFLAGS
C compiler flags for TCLTK, overriding pkg-config
TCLTK_LIBS linker flags for TCLTK, overriding pkg-config
X11_CFLAGS C compiler flags for X11, overriding pkg-config
X11_LIBS linker flags for X11, overriding pkg-config
GDBM_CFLAGS C compiler flags for gdbm
GDBM_LIBS additional linker flags for gdbm
ZLIB_CFLAGS C compiler flags for ZLIB, overriding pkg-config
@ -12334,50 +12341,280 @@ $as_echo "#define PY_SQLITE_ENABLE_LOAD_EXTENSION 1" >>confdefs.h
fi
# Check for --with-tcltk-includes=path and --with-tcltk-libs=path
found_tcltk=no
for _QUERY in \
"tcl >= 8.5.12 tk >= 8.5.12" \
"tcl8.6 tk8.6" \
"tcl86 tk86" \
"tcl8.5 >= 8.5.12 tk8.5 >= 8.5.12" \
"tcl85 >= 8.5.12 tk85 >= 8.5.12" \
; do
if test -n "$PKG_CONFIG" && \
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$_QUERY\""; } >&5
($PKG_CONFIG --exists --print-errors "$_QUERY") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-tcltk-includes" >&5
$as_echo_n "checking for --with-tcltk-includes... " >&6; }
pkg_failed=no
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for TCLTK" >&5
$as_echo_n "checking for TCLTK... " >&6; }
# Check whether --with-tcltk-includes was given.
if test "${with_tcltk_includes+set}" = set; then :
withval=$with_tcltk_includes;
if test -n "$TCLTK_CFLAGS"; then
pkg_cv_TCLTK_CFLAGS="$TCLTK_CFLAGS"
elif test -n "$PKG_CONFIG"; then
if test -n "$PKG_CONFIG" && \
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$_QUERY\""; } >&5
($PKG_CONFIG --exists --print-errors "$_QUERY") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
pkg_cv_TCLTK_CFLAGS=`$PKG_CONFIG --cflags "$_QUERY" 2>/dev/null`
test "x$?" != "x0" && pkg_failed=yes
else
with_tcltk_includes="default"
pkg_failed=yes
fi
else
pkg_failed=untried
fi
if test -n "$TCLTK_LIBS"; then
pkg_cv_TCLTK_LIBS="$TCLTK_LIBS"
elif test -n "$PKG_CONFIG"; then
if test -n "$PKG_CONFIG" && \
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$_QUERY\""; } >&5
($PKG_CONFIG --exists --print-errors "$_QUERY") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
pkg_cv_TCLTK_LIBS=`$PKG_CONFIG --libs "$_QUERY" 2>/dev/null`
test "x$?" != "x0" && pkg_failed=yes
else
pkg_failed=yes
fi
else
pkg_failed=untried
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_tcltk_includes" >&5
$as_echo "$with_tcltk_includes" >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-tcltk-libs" >&5
$as_echo_n "checking for --with-tcltk-libs... " >&6; }
# Check whether --with-tcltk-libs was given.
if test "${with_tcltk_libs+set}" = set; then :
withval=$with_tcltk_libs;
if test $pkg_failed = yes; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
_pkg_short_errors_supported=yes
else
with_tcltk_libs="default"
_pkg_short_errors_supported=no
fi
if test $_pkg_short_errors_supported = yes; then
TCLTK_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$_QUERY" 2>&1`
else
TCLTK_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$_QUERY" 2>&1`
fi
# Put the nasty error message in config.log where it belongs
echo "$TCLTK_PKG_ERRORS" >&5
found_tcltk=no
elif test $pkg_failed = untried; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
found_tcltk=no
else
TCLTK_CFLAGS=$pkg_cv_TCLTK_CFLAGS
TCLTK_LIBS=$pkg_cv_TCLTK_LIBS
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
found_tcltk=yes
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_tcltk_libs" >&5
$as_echo "$with_tcltk_libs" >&6; }
if test "x$with_tcltk_includes" = xdefault || test "x$with_tcltk_libs" = xdefault
then
if test "x$with_tcltk_includes" != "x$with_tcltk_libs"
then
as_fn_error $? "use both --with-tcltk-includes='...' and --with-tcltk-libs='...' or neither" "$LINENO" 5
fi
if test -n "$PKG_CONFIG" && "$PKG_CONFIG" --exists tcl tk; then
TCLTK_INCLUDES="`"$PKG_CONFIG" tcl tk --cflags-only-I 2>/dev/null`"
TCLTK_LIBS="`"$PKG_CONFIG" tcl tk --libs 2>/dev/null`"
else
TCLTK_INCLUDES=""
TCLTK_LIBS=""
fi
else
TCLTK_INCLUDES="$with_tcltk_includes"
TCLTK_LIBS="$with_tcltk_libs"
fi
if test "x$found_tcltk" = xyes; then :
break
fi
done
if test "x$found_tcltk" = xno; then :
TCLTK_CFLAGS=${TCLTK_CFLAGS-""}
TCLTK_LIBS=${TCLTK_LIBS-""}
fi
case $ac_sys_system in #(
FreeBSD*) :
if test -n "$PKG_CONFIG" && \
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"x11\""; } >&5
($PKG_CONFIG --exists --print-errors "x11") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
pkg_failed=no
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for X11" >&5
$as_echo_n "checking for X11... " >&6; }
if test -n "$X11_CFLAGS"; then
pkg_cv_X11_CFLAGS="$X11_CFLAGS"
elif test -n "$PKG_CONFIG"; then
if test -n "$PKG_CONFIG" && \
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"x11\""; } >&5
($PKG_CONFIG --exists --print-errors "x11") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
pkg_cv_X11_CFLAGS=`$PKG_CONFIG --cflags "x11" 2>/dev/null`
test "x$?" != "x0" && pkg_failed=yes
else
pkg_failed=yes
fi
else
pkg_failed=untried
fi
if test -n "$X11_LIBS"; then
pkg_cv_X11_LIBS="$X11_LIBS"
elif test -n "$PKG_CONFIG"; then
if test -n "$PKG_CONFIG" && \
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"x11\""; } >&5
($PKG_CONFIG --exists --print-errors "x11") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
pkg_cv_X11_LIBS=`$PKG_CONFIG --libs "x11" 2>/dev/null`
test "x$?" != "x0" && pkg_failed=yes
else
pkg_failed=yes
fi
else
pkg_failed=untried
fi
if test $pkg_failed = yes; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
_pkg_short_errors_supported=yes
else
_pkg_short_errors_supported=no
fi
if test $_pkg_short_errors_supported = yes; then
X11_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "x11" 2>&1`
else
X11_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "x11" 2>&1`
fi
# Put the nasty error message in config.log where it belongs
echo "$X11_PKG_ERRORS" >&5
as_fn_error $? "Package requirements (x11) were not met:
$X11_PKG_ERRORS
Consider adjusting the PKG_CONFIG_PATH environment variable if you
installed software in a non-standard prefix.
Alternatively, you may set the environment variables X11_CFLAGS
and X11_LIBS to avoid the need to call pkg-config.
See the pkg-config man page for more details." "$LINENO" 5
elif test $pkg_failed = untried; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it
is in your PATH or set the PKG_CONFIG environment variable to the full
path to pkg-config.
Alternatively, you may set the environment variables X11_CFLAGS
and X11_LIBS to avoid the need to call pkg-config.
See the pkg-config man page for more details.
To get pkg-config, see <http://pkg-config.freedesktop.org/>.
See \`config.log' for more details" "$LINENO" 5; }
else
X11_CFLAGS=$pkg_cv_X11_CFLAGS
X11_LIBS=$pkg_cv_X11_LIBS
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
TCLTK_CFLAGS="$TCLTK_CFLAGS $X11_CFLAGS"
TCLTK_LIBS="$TCLTK_LIBS $X11_LIBS"
fi
fi
;; #(
*) :
;;
esac
save_CFLAGS=$CFLAGS
save_CPPFLAGS=$CPPFLAGS
save_LDFLAGS=$LDFLAGS
save_LIBS=$LIBS
CPPFLAGS="$TCLTK_CFLAGS $CFLAGS"
LIBS="$TCLTK_LIBS $LDFLAGS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <tcl.h>
#include <tk.h>
#if defined(TK_HEX_VERSION)
# if TK_HEX_VERSION < 0x0805020c
# error "Tk older than 8.5.12 not supported"
# endif
#endif
#if (TCL_MAJOR_VERSION < 8) || \
((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION < 5)) || \
((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION == 5) && (TCL_RELEASE_SERIAL < 12))
# error "Tcl older than 8.5.12 not supported"
#endif
#if (TK_MAJOR_VERSION < 8) || \
((TK_MAJOR_VERSION == 8) && (TK_MINOR_VERSION < 5)) || \
((TK_MAJOR_VERSION == 8) && (TK_MINOR_VERSION == 5) && (TK_RELEASE_SERIAL < 12))
# error "Tk older than 8.5.12 not supported"
#endif
int
main ()
{
void *x1 = Tcl_Init;
void *x2 = Tk_Init;
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
have_tcltk=yes
as_fn_append TCLTK_CFLAGS " -Wno-strict-prototypes -DWITH_APPINIT=1"
else
have_tcltk=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
CFLAGS=$save_CFLAGS
CPPFLAGS=$save_CPPFLAGS
LDFLAGS=$save_LDFLAGS
LIBS=$save_LIBS
@ -18312,36 +18549,6 @@ _ACEOF
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for UCS-4 tcl" >&5
$as_echo_n "checking for UCS-4 tcl... " >&6; }
have_ucs4_tcl=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <tcl.h>
#if TCL_UTF_MAX != 6
# error "NOT UCS4_TCL"
#endif
int
main ()
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
$as_echo "#define HAVE_UCS4_TCL 1" >>confdefs.h
have_ucs4_tcl=yes
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_ucs4_tcl" >&5
$as_echo "$have_ucs4_tcl" >&6; }
# check whether wchar_t is signed or not
if test "$wchar_h" = yes
then
@ -23224,6 +23431,40 @@ fi
$as_echo "$py_cv_module__uuid" >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _tkinter" >&5
$as_echo_n "checking for stdlib extension module _tkinter... " >&6; }
if test "$py_cv_module__tkinter" != "n/a"; then :
if true; then :
if test "$have_tcltk" = "yes"; then :
py_cv_module__tkinter=yes
else
py_cv_module__tkinter=missing
fi
else
py_cv_module__tkinter=disabled
fi
fi
as_fn_append MODULE_BLOCK "MODULE__TKINTER=$py_cv_module__tkinter$as_nl"
if test "x$py_cv_module__tkinter" = xyes; then :
as_fn_append MODULE_BLOCK "MODULE__TKINTER_CFLAGS=$TCLTK_CFLAGS$as_nl"
as_fn_append MODULE_BLOCK "MODULE__TKINTER_LDFLAGS=$TCLTK_LIBS$as_nl"
fi
if test "$py_cv_module__tkinter" = yes; then
MODULE__TKINTER_TRUE=
MODULE__TKINTER_FALSE='#'
else
MODULE__TKINTER_TRUE='#'
MODULE__TKINTER_FALSE=
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__tkinter" >&5
$as_echo "$py_cv_module__tkinter" >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module zlib" >&5
$as_echo_n "checking for stdlib extension module zlib... " >&6; }
@ -24084,6 +24325,10 @@ if test -z "${MODULE__UUID_TRUE}" && test -z "${MODULE__UUID_FALSE}"; then
as_fn_error $? "conditional \"MODULE__UUID\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
if test -z "${MODULE__TKINTER_TRUE}" && test -z "${MODULE__TKINTER_FALSE}"; then
as_fn_error $? "conditional \"MODULE__TKINTER\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
if test -z "${MODULE_ZLIB_TRUE}" && test -z "${MODULE_ZLIB_FALSE}"; then
as_fn_error $? "conditional \"MODULE_ZLIB\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5

View file

@ -3546,38 +3546,77 @@ AS_VAR_IF([enable_loadable_sqlite_extensions], [yes], [
[Define to 1 to build the sqlite module with loadable extensions support.])
])
# Check for --with-tcltk-includes=path and --with-tcltk-libs=path
AC_SUBST(TCLTK_INCLUDES)
AC_SUBST(TCLTK_LIBS)
AC_MSG_CHECKING(for --with-tcltk-includes)
AC_ARG_WITH(tcltk-includes,
AS_HELP_STRING([--with-tcltk-includes='-I...'], [override search for Tcl and Tk include files]),
[],
[with_tcltk_includes="default"])
AC_MSG_RESULT($with_tcltk_includes)
AC_MSG_CHECKING(for --with-tcltk-libs)
AC_ARG_WITH(tcltk-libs,
AS_HELP_STRING([--with-tcltk-libs='-L...'], [override search for Tcl and Tk libs]),
[],
[with_tcltk_libs="default"])
AC_MSG_RESULT($with_tcltk_libs)
if test "x$with_tcltk_includes" = xdefault || test "x$with_tcltk_libs" = xdefault
then
if test "x$with_tcltk_includes" != "x$with_tcltk_libs"
then
AC_MSG_ERROR([use both --with-tcltk-includes='...' and --with-tcltk-libs='...' or neither])
fi
if test -n "$PKG_CONFIG" && "$PKG_CONFIG" --exists tcl tk; then
TCLTK_INCLUDES="`"$PKG_CONFIG" tcl tk --cflags-only-I 2>/dev/null`"
TCLTK_LIBS="`"$PKG_CONFIG" tcl tk --libs 2>/dev/null`"
else
TCLTK_INCLUDES=""
TCLTK_LIBS=""
fi
else
TCLTK_INCLUDES="$with_tcltk_includes"
TCLTK_LIBS="$with_tcltk_libs"
fi
dnl
dnl Detect Tcl/Tk. Use pkg-config if available.
dnl
found_tcltk=no
for _QUERY in \
"tcl >= 8.5.12 tk >= 8.5.12" \
"tcl8.6 tk8.6" \
"tcl86 tk86" \
"tcl8.5 >= 8.5.12 tk8.5 >= 8.5.12" \
"tcl85 >= 8.5.12 tk85 >= 8.5.12" \
; do
PKG_CHECK_EXISTS([$_QUERY], [
PKG_CHECK_MODULES([TCLTK], [$_QUERY], [found_tcltk=yes], [found_tcltk=no])
])
AS_VAR_IF([found_tcltk], [yes], [break])
done
AS_VAR_IF([found_tcltk], [no], [
TCLTK_CFLAGS=${TCLTK_CFLAGS-""}
TCLTK_LIBS=${TCLTK_LIBS-""}
])
dnl FreeBSD has an X11 dependency which is not implicitly resolved.
AS_CASE([$ac_sys_system],
[FreeBSD*], [
PKG_CHECK_EXISTS([x11], [
PKG_CHECK_MODULES([X11], [x11], [
TCLTK_CFLAGS="$TCLTK_CFLAGS $X11_CFLAGS"
TCLTK_LIBS="$TCLTK_LIBS $X11_LIBS"
])
])
]
)
WITH_SAVE_ENV([
CPPFLAGS="$TCLTK_CFLAGS $CFLAGS"
LIBS="$TCLTK_LIBS $LDFLAGS"
AC_LINK_IFELSE([
AC_LANG_PROGRAM([
#include <tcl.h>
#include <tk.h>
#if defined(TK_HEX_VERSION)
# if TK_HEX_VERSION < 0x0805020c
# error "Tk older than 8.5.12 not supported"
# endif
#endif
#if (TCL_MAJOR_VERSION < 8) || \
((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION < 5)) || \
((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION == 5) && (TCL_RELEASE_SERIAL < 12))
# error "Tcl older than 8.5.12 not supported"
#endif
#if (TK_MAJOR_VERSION < 8) || \
((TK_MAJOR_VERSION == 8) && (TK_MINOR_VERSION < 5)) || \
((TK_MAJOR_VERSION == 8) && (TK_MINOR_VERSION == 5) && (TK_RELEASE_SERIAL < 12))
# error "Tk older than 8.5.12 not supported"
#endif
], [
void *x1 = Tcl_Init;
void *x2 = Tk_Init;
])
], [
have_tcltk=yes
dnl The X11/xlib.h file bundled in the Tk sources can cause function
dnl prototype warnings from the compiler. Since we cannot easily fix
dnl that, suppress the warnings here instead.
AS_VAR_APPEND([TCLTK_CFLAGS], [" -Wno-strict-prototypes -DWITH_APPINIT=1"])
], [
have_tcltk=no
])
])
dnl check for _gdbmmodule dependencies
dnl NOTE: gdbm does not provide a pkgconf file.
@ -5204,18 +5243,6 @@ then
AC_CHECK_SIZEOF(wchar_t, 4, [#include <wchar.h>])
fi
AC_MSG_CHECKING(for UCS-4 tcl)
have_ucs4_tcl=no
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <tcl.h>
#if TCL_UTF_MAX != 6
# error "NOT UCS4_TCL"
#endif]], [[]])],[
AC_DEFINE(HAVE_UCS4_TCL, 1, [Define this if you have tcl and TCL_UTF_MAX==6])
have_ucs4_tcl=yes
],[])
AC_MSG_RESULT($have_ucs4_tcl)
# check whether wchar_t is signed or not
if test "$wchar_h" = yes
then
@ -6704,6 +6731,8 @@ dnl PY_STDLIB_MOD([_tkinter], [], [], [], [])
PY_STDLIB_MOD([_uuid],
[], [test "$have_uuid" = "yes"],
[$LIBUUID_CFLAGS], [$LIBUUID_LIBS])
PY_STDLIB_MOD([_tkinter], [],
[test "$have_tcltk" = "yes"], [$TCLTK_CFLAGS], [$TCLTK_LIBS])
dnl compression libs
PY_STDLIB_MOD([zlib], [], [test "$have_zlib" = yes],

View file

@ -1357,9 +1357,6 @@
`tzname'. */
#undef HAVE_TZNAME
/* Define this if you have tcl and TCL_UTF_MAX==6 */
#undef HAVE_UCS4_TCL
/* Define to 1 if you have the `umask' function. */
#undef HAVE_UMASK

381
setup.py
View file

@ -213,28 +213,6 @@ def macosx_sdk_root():
return MACOS_SDK_ROOT
def macosx_sdk_specified():
"""Returns true if an SDK was explicitly configured.
True if an SDK was selected at configure time, either by specifying
--enable-universalsdk=(something other than no or /) or by adding a
-isysroot option to CFLAGS. In some cases, like when making
decisions about macOS Tk framework paths, we need to be able to
know whether the user explicitly asked to build with an SDK versus
the implicit use of an SDK when header files are no longer
installed on a running system by the Command Line Tools.
"""
global MACOS_SDK_SPECIFIED
# If already called, return cached result.
if MACOS_SDK_SPECIFIED:
return MACOS_SDK_SPECIFIED
# Find the sdk root and set MACOS_SDK_SPECIFIED
macosx_sdk_root()
return MACOS_SDK_SPECIFIED
def is_macosx_sdk_path(path):
"""
Returns True if 'path' can be located in a macOS SDK
@ -292,59 +270,6 @@ def find_file(filename, std_dirs, paths):
return None
def find_library_file(compiler, libname, std_dirs, paths):
result = compiler.find_library_file(std_dirs + paths, libname)
if result is None:
return None
if MACOS:
sysroot = macosx_sdk_root()
# Check whether the found file is in one of the standard directories
dirname = os.path.dirname(result)
for p in std_dirs:
# Ensure path doesn't end with path separator
p = p.rstrip(os.sep)
if MACOS and is_macosx_sdk_path(p):
# Note that, as of Xcode 7, Apple SDKs may contain textual stub
# libraries with .tbd extensions rather than the normal .dylib
# shared libraries installed in /. The Apple compiler tool
# chain handles this transparently but it can cause problems
# for programs that are being built with an SDK and searching
# for specific libraries. Distutils find_library_file() now
# knows to also search for and return .tbd files. But callers
# of find_library_file need to keep in mind that the base filename
# of the returned SDK library file might have a different extension
# from that of the library file installed on the running system,
# for example:
# /Applications/Xcode.app/Contents/Developer/Platforms/
# MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/
# usr/lib/libedit.tbd
# vs
# /usr/lib/libedit.dylib
if os.path.join(sysroot, p[1:]) == dirname:
return [ ]
if p == dirname:
return [ ]
# Otherwise, it must have been in one of the additional directories,
# so we have to figure out which one.
for p in paths:
# Ensure path doesn't end with path separator
p = p.rstrip(os.sep)
if MACOS and is_macosx_sdk_path(p):
if os.path.join(sysroot, p[1:]) == dirname:
return [ p ]
if p == dirname:
return [p]
else:
assert False, "Internal error: Path not found in std_dirs or paths"
def validate_tzpath():
base_tzpath = sysconfig.get_config_var('TZPATH')
if not base_tzpath:
@ -1433,8 +1358,7 @@ def detect_modules(self):
self.detect_decimal()
self.detect_ctypes()
self.detect_multiprocessing()
if not self.detect_tkinter():
self.missing.append('_tkinter')
self.detect_tkinter()
self.detect_uuid()
# Uncomment the next line if you want to play with xxmodule.c
@ -1443,309 +1367,8 @@ def detect_modules(self):
self.addext(Extension('xxlimited', ['xxlimited.c']))
self.addext(Extension('xxlimited_35', ['xxlimited_35.c']))
def detect_tkinter_fromenv(self):
# Build _tkinter using the Tcl/Tk locations specified by
# the _TCLTK_INCLUDES and _TCLTK_LIBS environment variables.
# This method is meant to be invoked by detect_tkinter().
#
# The variables can be set via one of the following ways.
#
# - Automatically, at configuration time, by using pkg-config.
# The tool is called by the configure script.
# Additional pkg-config configuration paths can be set via the
# PKG_CONFIG_PATH environment variable.
#
# PKG_CONFIG_PATH=".../lib/pkgconfig" ./configure ...
#
# - Explicitly, at configuration time by setting both
# --with-tcltk-includes and --with-tcltk-libs.
#
# ./configure ... \
# --with-tcltk-includes="-I/path/to/tclincludes \
# -I/path/to/tkincludes"
# --with-tcltk-libs="-L/path/to/tcllibs -ltclm.n \
# -L/path/to/tklibs -ltkm.n"
#
# - Explicitly, at compile time, by passing TCLTK_INCLUDES and
# TCLTK_LIBS to the make target.
# This will override any configuration-time option.
#
# make TCLTK_INCLUDES="..." TCLTK_LIBS="..."
#
# This can be useful for building and testing tkinter with multiple
# versions of Tcl/Tk. Note that a build of Tk depends on a particular
# build of Tcl so you need to specify both arguments and use care when
# overriding.
# The _TCLTK variables are created in the Makefile sharedmods target.
tcltk_includes = os.environ.get('_TCLTK_INCLUDES')
tcltk_libs = os.environ.get('_TCLTK_LIBS')
if not (tcltk_includes and tcltk_libs):
# Resume default configuration search.
return False
extra_compile_args = tcltk_includes.split()
extra_link_args = tcltk_libs.split()
self.add(Extension('_tkinter', ['_tkinter.c', 'tkappinit.c'],
define_macros=[('WITH_APPINIT', 1)],
extra_compile_args = extra_compile_args,
extra_link_args = extra_link_args))
return True
def detect_tkinter_darwin(self):
# Build default _tkinter on macOS using Tcl and Tk frameworks.
# This method is meant to be invoked by detect_tkinter().
#
# The macOS native Tk (AKA Aqua Tk) and Tcl are most commonly
# built and installed as macOS framework bundles. However,
# for several reasons, we cannot take full advantage of the
# Apple-supplied compiler chain's -framework options here.
# Instead, we need to find and pass to the compiler the
# absolute paths of the Tcl and Tk headers files we want to use
# and the absolute path to the directory containing the Tcl
# and Tk frameworks for linking.
#
# We want to handle here two common use cases on macOS:
# 1. Build and link with system-wide third-party or user-built
# Tcl and Tk frameworks installed in /Library/Frameworks.
# 2. Build and link using a user-specified macOS SDK so that the
# built Python can be exported to other systems. In this case,
# search only the SDK's /Library/Frameworks (normally empty)
# and /System/Library/Frameworks.
#
# Any other use cases are handled either by detect_tkinter_fromenv(),
# or detect_tkinter(). The former handles non-standard locations of
# Tcl/Tk, defined via the _TCLTK_INCLUDES and _TCLTK_LIBS environment
# variables. The latter handles any Tcl/Tk versions installed in
# standard Unix directories.
#
# It would be desirable to also handle here the case where
# you want to build and link with a framework build of Tcl and Tk
# that is not in /Library/Frameworks, say, in your private
# $HOME/Library/Frameworks directory or elsewhere. It turns
# out to be difficult to make that work automatically here
# without bringing into play more tools and magic. That case
# can be handled using a recipe with the right arguments
# to detect_tkinter_fromenv().
#
# Note also that the fallback case here is to try to use the
# Apple-supplied Tcl and Tk frameworks in /System/Library but
# be forewarned that they are deprecated by Apple and typically
# out-of-date and buggy; their use should be avoided if at
# all possible by installing a newer version of Tcl and Tk in
# /Library/Frameworks before building Python without
# an explicit SDK or by configuring build arguments explicitly.
from os.path import join, exists
sysroot = macosx_sdk_root() # path to the SDK or '/'
if macosx_sdk_specified():
# Use case #2: an SDK other than '/' was specified.
# Only search there.
framework_dirs = [
join(sysroot, 'Library', 'Frameworks'),
join(sysroot, 'System', 'Library', 'Frameworks'),
]
else:
# Use case #1: no explicit SDK selected.
# Search the local system-wide /Library/Frameworks,
# not the one in the default SDK, otherwise fall back to
# /System/Library/Frameworks whose header files may be in
# the default SDK or, on older systems, actually installed.
framework_dirs = [
join('/', 'Library', 'Frameworks'),
join(sysroot, 'System', 'Library', 'Frameworks'),
]
# Find the directory that contains the Tcl.framework and
# Tk.framework bundles.
for F in framework_dirs:
# both Tcl.framework and Tk.framework should be present
for fw in 'Tcl', 'Tk':
if not exists(join(F, fw + '.framework')):
break
else:
# ok, F is now directory with both frameworks. Continue
# building
break
else:
# Tk and Tcl frameworks not found. Normal "unix" tkinter search
# will now resume.
return False
include_dirs = [
join(F, fw + '.framework', H)
for fw in ('Tcl', 'Tk')
for H in ('Headers',)
]
# Add the base framework directory as well
compile_args = ['-F', F]
# Do not build tkinter for archs that this Tk was not built with.
cflags = sysconfig.get_config_vars('CFLAGS')[0]
archs = re.findall(r'-arch\s+(\w+)', cflags)
tmpfile = os.path.join(self.build_temp, 'tk.arch')
if not os.path.exists(self.build_temp):
os.makedirs(self.build_temp)
run_command(
"file {}/Tk.framework/Tk | grep 'for architecture' > {}".format(F, tmpfile)
)
with open(tmpfile) as fp:
detected_archs = []
for ln in fp:
a = ln.split()[-1]
if a in archs:
detected_archs.append(ln.split()[-1])
os.unlink(tmpfile)
arch_args = []
for a in detected_archs:
arch_args.append('-arch')
arch_args.append(a)
compile_args += arch_args
link_args = [','.join(['-Wl', '-F', F, '-framework', 'Tcl', '-framework', 'Tk']), *arch_args]
# The X11/xlib.h file bundled in the Tk sources can cause function
# prototype warnings from the compiler. Since we cannot easily fix
# that, suppress the warnings here instead.
if '-Wstrict-prototypes' in cflags.split():
compile_args.append('-Wno-strict-prototypes')
self.add(Extension('_tkinter', ['_tkinter.c', 'tkappinit.c'],
define_macros=[('WITH_APPINIT', 1)],
include_dirs=include_dirs,
libraries=[],
extra_compile_args=compile_args,
extra_link_args=link_args))
return True
def detect_tkinter(self):
# The _tkinter module.
#
# Detection of Tcl/Tk is attempted in the following order:
# - Through environment variables.
# - Platform specific detection of Tcl/Tk (currently only macOS).
# - Search of various standard Unix header/library paths.
#
# Detection stops at the first successful method.
# Check for Tcl and Tk at the locations indicated by _TCLTK_INCLUDES
# and _TCLTK_LIBS environment variables.
if self.detect_tkinter_fromenv():
return True
# Rather than complicate the code below, detecting and building
# AquaTk is a separate method. Only one Tkinter will be built on
# Darwin - either AquaTk, if it is found, or X11 based Tk.
if (MACOS and self.detect_tkinter_darwin()):
return True
# Assume we haven't found any of the libraries or include files
# The versions with dots are used on Unix, and the versions without
# dots on Windows, for detection by cygwin.
tcllib = tklib = tcl_includes = tk_includes = None
for version in ['8.6', '86', '8.5', '85', '8.4', '84', '8.3', '83',
'8.2', '82', '8.1', '81', '8.0', '80']:
tklib = self.compiler.find_library_file(self.lib_dirs,
'tk' + version)
tcllib = self.compiler.find_library_file(self.lib_dirs,
'tcl' + version)
if tklib and tcllib:
# Exit the loop when we've found the Tcl/Tk libraries
break
# Now check for the header files
if tklib and tcllib:
# Check for the include files on Debian and {Free,Open}BSD, where
# they're put in /usr/include/{tcl,tk}X.Y
dotversion = version
if '.' not in dotversion and "bsd" in HOST_PLATFORM.lower():
# OpenBSD and FreeBSD use Tcl/Tk library names like libtcl83.a,
# but the include subdirs are named like .../include/tcl8.3.
dotversion = dotversion[:-1] + '.' + dotversion[-1]
tcl_include_sub = []
tk_include_sub = []
for dir in self.inc_dirs:
tcl_include_sub += [dir + os.sep + "tcl" + dotversion]
tk_include_sub += [dir + os.sep + "tk" + dotversion]
tk_include_sub += tcl_include_sub
tcl_includes = find_file('tcl.h', self.inc_dirs, tcl_include_sub)
tk_includes = find_file('tk.h', self.inc_dirs, tk_include_sub)
if (tcllib is None or tklib is None or
tcl_includes is None or tk_includes is None):
self.announce("INFO: Can't locate Tcl/Tk libs and/or headers", 2)
return False
# OK... everything seems to be present for Tcl/Tk.
include_dirs = []
libs = []
defs = []
added_lib_dirs = []
for dir in tcl_includes + tk_includes:
if dir not in include_dirs:
include_dirs.append(dir)
# Check for various platform-specific directories
if HOST_PLATFORM == 'sunos5':
include_dirs.append('/usr/openwin/include')
added_lib_dirs.append('/usr/openwin/lib')
elif os.path.exists('/usr/X11R6/include'):
include_dirs.append('/usr/X11R6/include')
added_lib_dirs.append('/usr/X11R6/lib64')
added_lib_dirs.append('/usr/X11R6/lib')
elif os.path.exists('/usr/X11R5/include'):
include_dirs.append('/usr/X11R5/include')
added_lib_dirs.append('/usr/X11R5/lib')
else:
# Assume default location for X11
include_dirs.append('/usr/X11/include')
added_lib_dirs.append('/usr/X11/lib')
# If Cygwin, then verify that X is installed before proceeding
if CYGWIN:
x11_inc = find_file('X11/Xlib.h', [], include_dirs)
if x11_inc is None:
return False
# Check for BLT extension
if self.compiler.find_library_file(self.lib_dirs + added_lib_dirs,
'BLT8.0'):
defs.append( ('WITH_BLT', 1) )
libs.append('BLT8.0')
elif self.compiler.find_library_file(self.lib_dirs + added_lib_dirs,
'BLT'):
defs.append( ('WITH_BLT', 1) )
libs.append('BLT')
# Add the Tcl/Tk libraries
libs.append('tk'+ version)
libs.append('tcl'+ version)
# Finally, link with the X11 libraries (not appropriate on cygwin)
if not CYGWIN:
libs.append('X11')
# XXX handle these, but how to detect?
# *** Uncomment and edit for PIL (TkImaging) extension only:
# -DWITH_PIL -I../Extensions/Imaging/libImaging tkImaging.c \
# *** Uncomment and edit for TOGL extension only:
# -DWITH_TOGL togl.c \
# *** Uncomment these for TOGL extension only:
# -lGL -lGLU -lXext -lXmu \
self.add(Extension('_tkinter', ['_tkinter.c', 'tkappinit.c'],
define_macros=[('WITH_APPINIT', 1)] + defs,
include_dirs=include_dirs,
libraries=libs,
library_dirs=added_lib_dirs))
return True
self.addext(Extension('_tkinter', ['_tkinter.c', 'tkappinit.c']))
def configure_ctypes(self, ext):
return True