Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
MacOS homebrew python 3.8.6 with tcl-tk (properly)
class Python < Formula
desc "Interpreted, interactive, object-oriented programming language"
homepage "https://www.python.org/"
url "https://www.python.org/ftp/python/3.8.6/Python-3.8.6.tar.xz"
sha256 "a9e0b79d27aa056eb9cce8d63a427b5f9bab1465dee3f942dcfdb25a82f4ab8a"
head "https://github.com/python/cpython.git"
license "Python-2.0"
revision 1
bottle do
sha256 "123ddd272ba0670d72578b36c4801b59449ac21e9d5a7e47c34c9e489330600a" => :catalina
sha256 "6367896e90735c0f1476d297d608ee08cd5f7fccf7c794c45589093fa86f4faa" => :mojave
sha256 "8714bfcc84ab6486cc7c757028298478fc28609f148ef27497940cd5cd7292e7" => :high_sierra
end
# setuptools remembers the build flags python is built with and uses them to
# build packages later. Xcode-only systems need different flags.
pour_bottle? do
reason <<~EOS
The bottle needs the Apple Command Line Tools to be installed.
You can install them, if desired, with:
xcode-select --install
EOS
satisfy { MacOS::CLT.installed? }
end
depends_on "pkg-config" => :build
depends_on "gdbm"
depends_on "openssl@1.1"
depends_on "readline"
depends_on "sqlite"
depends_on "xz"
depends_on "tcl-tk" # as apple's one is shiiiiite
uses_from_macos "bzip2"
uses_from_macos "libffi"
uses_from_macos "ncurses"
uses_from_macos "unzip"
uses_from_macos "zlib"
skip_clean "bin/pip3", "bin/pip-3.4", "bin/pip-3.5", "bin/pip-3.6", "bin/pip-3.7", "bin/pip-3.8"
skip_clean "bin/easy_install3", "bin/easy_install-3.4", "bin/easy_install-3.5", "bin/easy_install-3.6", "bin/easy_install-3.7", "bin/easy_install-3.8"
resource "setuptools" do
url "https://files.pythonhosted.org/packages/a7/e0/30642b9c2df516506d40b563b0cbd080c49c6b3f11a70b4c7a670f13a78b/setuptools-50.3.2.zip"
sha256 "ed0519d27a243843b05d82a5e9d01b0b083d9934eaa3d02779a23da18077bd3c"
end
resource "pip" do
url "https://files.pythonhosted.org/packages/0b/f5/be8e741434a4bf4ce5dbc235aa28ed0666178ea8986ddc10d035023744e6/pip-20.2.4.tar.gz"
sha256 "85c99a857ea0fb0aedf23833d9be5c40cf253fe24443f0829c7b472e23c364a1"
end
resource "wheel" do
url "https://files.pythonhosted.org/packages/83/72/611c121b6bd15479cb62f1a425b2e3372e121b324228df28e64cc28b01c2/wheel-0.35.1.tar.gz"
sha256 "99a22d87add3f634ff917310a3d87e499f19e663413a52eb9232c447aa646c9f"
end
# Remove this block when upstream adds arm64 compatibility
if Hardware::CPU.arm?
# Upstream PRs #20171, #21114, #21224 and #21249
patch do
url "https://raw.githubusercontent.com/Homebrew/formula-patches/113aa84/python/3.8.3.patch"
sha256 "9c0d7c28c33c6036860457bd9c5a03026c71bd034907b77fbf861ff5fe216ed0"
end
end
# Homebrew's tcl-tk is built in a standard unix fashion (due to link errors)
# so we have to stop python from searching for frameworks and linking against
# X11.
patch :DATA
def install
# Unset these so that installing pip and setuptools puts them where we want
# and not into some other Python the user has installed.
ENV["PYTHONHOME"] = nil
ENV["PYTHONPATH"] = nil
xy = (buildpath/"configure.ac").read.slice(/PYTHON_VERSION, (3\.\d)/, 1)
lib_cellar = prefix/"Frameworks/Python.framework/Versions/#{xy}/lib/python#{xy}"
args = %W[
--prefix=#{prefix}
--enable-ipv6
--datarootdir=#{share}
--datadir=#{share}
--enable-framework=#{frameworks}
--enable-loadable-sqlite-extensions
--without-ensurepip
--with-dtrace
--with-openssl=#{Formula["openssl@1.1"].opt_prefix}
]
# args << "--without-gcc" if ENV.compiler == :clang
cflags = []
ldflags = []
cppflags = []
if MacOS.sdk_path_if_needed
# Help Python's build system (setuptools/pip) to build things on SDK-based systems
# The setup.py looks at "-isysroot" to get the sysroot (and not at --sysroot)
cflags << "-isysroot #{MacOS.sdk_path}" << "-I#{MacOS.sdk_path}/usr/include"
ldflags << "-isysroot #{MacOS.sdk_path}"
# For the Xlib.h, Python needs this header dir with the system Tk
# Yep, this needs the absolute path where zlib needed a path relative
# to the SDK.
# as external tck is added later on uncomment this
# cflags << "-I#{MacOS.sdk_path}/System/Library/Frameworks/Tk.framework/Versions/8.5/Headers"
end
# Avoid linking to libgcc https://mail.python.org/pipermail/python-dev/2012-February/116205.html
args << "MACOSX_DEPLOYMENT_TARGET=#{MacOS.version}"
# We want our readline! This is just to outsmart the detection code,
# superenv makes cc always find includes/libs!
inreplace "setup.py",
"do_readline = self.compiler.find_library_file(self.lib_dirs, 'readline')",
"do_readline = '#{Formula["readline"].opt_lib}/libhistory.dylib'"
inreplace "setup.py" do |s|
s.gsub! "sqlite_setup_debug = False", "sqlite_setup_debug = True"
s.gsub! "for d_ in self.inc_dirs + sqlite_inc_paths:",
"for d_ in ['#{Formula["sqlite"].opt_include}']:"
end
# Allow python modules to use ctypes.find_library to find homebrew's stuff
# even if homebrew is not a /usr/local/lib. Try this with:
# `brew install enchant && pip install pyenchant`
inreplace "./Lib/ctypes/macholib/dyld.py" do |f|
f.gsub! "DEFAULT_LIBRARY_FALLBACK = [", "DEFAULT_LIBRARY_FALLBACK = [ '#{HOMEBREW_PREFIX}/lib',"
f.gsub! "DEFAULT_FRAMEWORK_FALLBACK = [", "DEFAULT_FRAMEWORK_FALLBACK = [ '#{HOMEBREW_PREFIX}/Frameworks',"
end
# ADD tcl-tk include / lib paths
tcl_tk = Formula["tcl-tk"].opt_prefix
cppflags << "-I#{tcl_tk}/include"
ldflags << "-L#{tcl_tk}/lib"
args << "CFLAGS=#{cflags.join(" ")}" unless cflags.empty?
args << "LDFLAGS=#{ldflags.join(" ")}" unless ldflags.empty?
args << "CPPFLAGS=#{cppflags.join(" ")}" unless cppflags.empty?
system "./configure", *args
system "make"
ENV.deparallelize do
# Tell Python not to install into /Applications (default for framework builds)
system "make", "install", "PYTHONAPPSDIR=#{prefix}"
system "make", "frameworkinstallextras", "PYTHONAPPSDIR=#{pkgshare}"
end
# Any .app get a " 3" attached, so it does not conflict with python 2.x.
Dir.glob("#{prefix}/*.app") { |app| mv app, app.sub(/\.app$/, " 3.app") }
# Prevent third-party packages from building against fragile Cellar paths
inreplace Dir[lib_cellar/"**/_sysconfigdata__darwin_darwin.py",
lib_cellar/"config*/Makefile",
frameworks/"Python.framework/Versions/3*/lib/pkgconfig/python-3.?.pc"],
prefix, opt_prefix
# Help third-party packages find the Python framework
inreplace Dir[lib_cellar/"config*/Makefile"],
/^LINKFORSHARED=(.*)PYTHONFRAMEWORKDIR(.*)/,
"LINKFORSHARED=\\1PYTHONFRAMEWORKINSTALLDIR\\2"
# Fix for https://github.com/Homebrew/homebrew-core/issues/21212
inreplace Dir[lib_cellar/"**/_sysconfigdata__darwin_darwin.py"],
%r{('LINKFORSHARED': .*?)'(Python.framework/Versions/3.\d+/Python)'}m,
"\\1'#{opt_prefix}/Frameworks/\\2'"
# A fix, because python and python3 both want to install Python.framework
# and therefore we can't link both into HOMEBREW_PREFIX/Frameworks
# https://github.com/Homebrew/homebrew/issues/15943
# ["Headers", "Python", "Resources"].each { |f| rm(prefix/"Frameworks/Python.framework/#{f}") }
# rm prefix/"Frameworks/Python.framework/Versions/Current"
# Symlink the pkgconfig files into HOMEBREW_PREFIX so they're accessible.
(lib/"pkgconfig").install_symlink Dir["#{frameworks}/Python.framework/Versions/#{xy}/lib/pkgconfig/*"]
# Remove the site-packages that Python created in its Cellar.
(prefix/"Frameworks/Python.framework/Versions/#{xy}/lib/python#{xy}/site-packages").rmtree
%w[setuptools pip wheel].each do |r|
(libexec/r).install resource(r)
end
# Remove wheel test data.
# It's for people editing wheel and contains binaries which fail `brew linkage`.
rm libexec/"wheel/tox.ini"
rm_r libexec/"wheel/tests"
# Install unversioned symlinks in libexec/bin.
{
"idle" => "idle3",
"pydoc" => "pydoc3",
"python" => "python3",
"python-config" => "python3-config",
}.each do |unversioned_name, versioned_name|
(libexec/"bin").install_symlink (bin/versioned_name).realpath => unversioned_name
end
end
def post_install
ENV.delete "PYTHONPATH"
xy = (prefix/"Frameworks/Python.framework/Versions").children.min.basename.to_s
site_packages = HOMEBREW_PREFIX/"lib/python#{xy}/site-packages"
site_packages_cellar = prefix/"Frameworks/Python.framework/Versions/#{xy}/lib/python#{xy}/site-packages"
# Fix up the site-packages so that user-installed Python software survives
# minor updates, such as going from 3.3.2 to 3.3.3:
# Create a site-packages in HOMEBREW_PREFIX/lib/python#{xy}/site-packages
site_packages.mkpath
# Symlink the prefix site-packages into the cellar.
site_packages_cellar.unlink if site_packages_cellar.exist?
site_packages_cellar.parent.install_symlink site_packages
# Write our sitecustomize.py
rm_rf Dir["#{site_packages}/sitecustomize.py[co]"]
(site_packages/"sitecustomize.py").atomic_write(sitecustomize)
# Remove old setuptools installations that may still fly around and be
# listed in the easy_install.pth. This can break setuptools build with
# zipimport.ZipImportError: bad local file header
# setuptools-0.9.8-py3.3.egg
rm_rf Dir["#{site_packages}/setuptools*"]
rm_rf Dir["#{site_packages}/distribute*"]
rm_rf Dir["#{site_packages}/pip[-_.][0-9]*", "#{site_packages}/pip"]
%w[setuptools pip wheel].each do |pkg|
(libexec/pkg).cd do
system bin/"python3", "-s", "setup.py", "--no-user-cfg", "install",
"--force", "--verbose", "--install-scripts=#{bin}",
"--install-lib=#{site_packages}",
"--single-version-externally-managed",
"--record=installed.txt"
end
end
rm_rf [bin/"pip", bin/"easy_install"]
mv bin/"wheel", bin/"wheel3"
# Install unversioned symlinks in libexec/bin.
{
"easy_install" => "easy_install-#{xy}",
"pip" => "pip3",
"wheel" => "wheel3",
}.each do |unversioned_name, versioned_name|
(libexec/"bin").install_symlink (bin/versioned_name).realpath => unversioned_name
end
# post_install happens after link
%W[pip3 pip#{xy} easy_install-#{xy} wheel3].each do |e|
(HOMEBREW_PREFIX/"bin").install_symlink bin/e
end
# Help distutils find brewed stuff when building extensions
include_dirs = [HOMEBREW_PREFIX/"include", Formula["openssl@1.1"].opt_include,
Formula["sqlite"].opt_include]
library_dirs = [HOMEBREW_PREFIX/"lib", Formula["openssl@1.1"].opt_lib,
Formula["sqlite"].opt_lib]
# Again tcl-tk
include_dirs << Formula["tcl-tk"].opt_include
library_dirs << Formula["tcl-tk"].opt_lib
cfg = prefix/"Frameworks/Python.framework/Versions/#{xy}/lib/python#{xy}/distutils/distutils.cfg"
cfg.atomic_write <<~EOS
[install]
prefix=#{HOMEBREW_PREFIX}
[build_ext]
include_dirs=#{include_dirs.join ":"}
library_dirs=#{library_dirs.join ":"}
EOS
end
def sitecustomize
xy = (prefix/"Frameworks/Python.framework/Versions").children.min.basename.to_s
<<~EOS
# This file is created by Homebrew and is executed on each python startup.
# Don't print from here, or else python command line scripts may fail!
# <https://docs.brew.sh/Homebrew-and-Python>
import re
import os
import sys
if sys.version_info[0] != 3:
# This can only happen if the user has set the PYTHONPATH for 3.x and run Python 2.x or vice versa.
# Every Python looks at the PYTHONPATH variable and we can't fix it here in sitecustomize.py,
# because the PYTHONPATH is evaluated after the sitecustomize.py. Many modules (e.g. PyQt4) are
# built only for a specific version of Python and will fail with cryptic error messages.
# In the end this means: Don't set the PYTHONPATH permanently if you use different Python versions.
exit('Your PYTHONPATH points to a site-packages dir for Python 3.x but you are running Python ' +
str(sys.version_info[0]) + '.x!\\n PYTHONPATH is currently: "' + str(os.environ['PYTHONPATH']) + '"\\n' +
' You should `unset PYTHONPATH` to fix this.')
# Only do this for a brewed python:
if os.path.realpath(sys.executable).startswith('#{rack}'):
# Shuffle /Library site-packages to the end of sys.path
library_site = '/Library/Python/#{xy}/site-packages'
library_packages = [p for p in sys.path if p.startswith(library_site)]
sys.path = [p for p in sys.path if not p.startswith(library_site)]
# .pth files have already been processed so don't use addsitedir
sys.path.extend(library_packages)
# the Cellar site-packages is a symlink to the HOMEBREW_PREFIX
# site_packages; prefer the shorter paths
long_prefix = re.compile(r'#{rack}/[0-9\._abrc]+/Frameworks/Python\.framework/Versions/#{xy}/lib/python#{xy}/site-packages')
sys.path = [long_prefix.sub('#{HOMEBREW_PREFIX/"lib/python#{xy}/site-packages"}', p) for p in sys.path]
# Set the sys.executable to use the opt_prefix, unless explicitly set
# with PYTHONEXECUTABLE:
if 'PYTHONEXECUTABLE' not in os.environ:
sys.executable = '#{opt_bin}/python#{xy}'
EOS
end
def caveats
xy = if prefix.exist?
(prefix/"Frameworks/Python.framework/Versions").children.min.basename.to_s
else
version.to_s.slice(/(3\.\d)/) || "3.8"
end
<<~EOS
Python has been installed as
#{opt_bin}/python3
Unversioned symlinks `python`, `python-config`, `pip` etc. pointing to
`python3`, `python3-config`, `pip3` etc., respectively, have been installed into
#{opt_libexec}/bin
You can install Python packages with
#{opt_bin}/pip3 install <package>
They will install into the site-package directory
#{HOMEBREW_PREFIX/"lib/python#{xy}/site-packages"}
See: https://docs.brew.sh/Homebrew-and-Python
EOS
end
test do
xy = (prefix/"Frameworks/Python.framework/Versions").children.min.basename.to_s
# Check if sqlite is ok, because we build with --enable-loadable-sqlite-extensions
# and it can occur that building sqlite silently fails if OSX's sqlite is used.
system "#{bin}/python#{xy}", "-c", "import sqlite3"
# Check if some other modules import. Then the linked libs are working.
system "#{bin}/python#{xy}", "-c", "import tkinter; root = tkinter.Tk()"
system "#{bin}/python#{xy}", "-c", "import _gdbm"
system "#{bin}/python#{xy}", "-c", "import zlib"
system bin/"pip3", "list", "--format=columns"
end
end
__END__
diff --git a/setup.py b/setup.py
index 20d7f35..b9616d3 100644
--- a/setup.py
+++ b/setup.py
@@ -1851,8 +1851,6 @@ class PyBuildExt(build_ext):
# 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
@@ -1901,21 +1899,6 @@ class PyBuildExt(build_ext):
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:
@@ -1937,9 +1920,6 @@ class PyBuildExt(build_ext):
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:
@ivanoats
Copy link

ivanoats commented Mar 27, 2020

FWIW, I tried both the pyenv and the homebrew replacement and only the homebrew replacement really worked. Thank you !

@sri0sharma
Copy link

sri0sharma commented Mar 28, 2020

@codyd51
Copy link

codyd51 commented Apr 19, 2020

This worked like a charm. Thank you!

@TonioGela
Copy link

TonioGela commented Apr 28, 2020

@iexa I'm curious, why doesn't this thing get merged in homebrew formulas?

@iexa
Copy link
Author

iexa commented May 7, 2020

@TonioGela homebrew had it, my changes are based on their old patches. They removed support probably since python 3.7.x?

The use of tkinter with python is quite low (according to them).
It is a bit dated I have to admit (one specially strange thing is the scrollbars with canvas / textarea trickery).

And also there is pyside / pyqt / wx / kiwi ...and many others.
I like tk for its relative simplicity, ease of use and (mainly) that it is built into python - so I can use it everywhere python is installed without installing anything else. There wont be a stupidly large codebase because of this (not unlike electron or nw.js with its massive sizes).
Also for projects low-mid complexity in need of a gui - imho tk is enough.

@sergey-arkhipov
Copy link

sergey-arkhipov commented Jul 24, 2020

For clear installation homebrew python@3.8 (3.8.5) can apply path for /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/Formula/python@3.8.rb and run after that
$ brew reinstall python@3.8 --build-from-source
This way is more simpler as doesn't demand removal of python@3.8 which is required by other installed homebrew programs

-> MBA ! ~ % python3
Python 3.8.5 (default, Jul 24 2020, 21:52:41) 
[Clang 11.0.3 (clang-1103.0.32.62)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import tkinter as tk
>>> print(tk.TkVersion, tk.TclVersion)
8.6 8.6
>>> 

PATH File

--- python@3.8.rb	2020-07-24 21:59:39.000000000 +0300
+++ python@3.8.5.rb	2020-07-24 21:54:51.000000000 +0300
@@ -28,6 +28,7 @@
   depends_on "readline"
   depends_on "sqlite"
   depends_on "xz"
+  depends_on "tcl-tk"  # as apple's one is shiiiiite
 
   uses_from_macos "bzip2"
   uses_from_macos "libffi"
@@ -77,6 +78,11 @@
     end
   end
 
+  # Homebrew's tcl-tk is built in a standard unix fashion (due to link errors)
+  # so we have to stop python from searching for frameworks and linking against
+  # X11.
+  patch :DATA
+
   def install
     # Unset these so that installing pip and setuptools puts them where we want
     # and not into some other Python the user has installed.
@@ -110,7 +116,8 @@
       # For the Xlib.h, Python needs this header dir with the system Tk
       # Yep, this needs the absolute path where zlib needed a path relative
       # to the SDK.
-      cflags << "-I#{MacOS.sdk_path}/System/Library/Frameworks/Tk.framework/Versions/8.5/Headers"
+      # cflags << "-I#{MacOS.sdk_path}/System/Library/Frameworks/Tk.framework/Versions/8.5/Headers"
+      cflags << "-I#{MacOS.sdk_path}/usr/local/opt/tcl-tk/include"
     end
     # Avoid linking to libgcc https://mail.python.org/pipermail/python-dev/2012-February/116205.html
     args << "MACOSX_DEPLOYMENT_TARGET=#{MacOS.version}"
@@ -135,6 +142,11 @@
       f.gsub! "DEFAULT_FRAMEWORK_FALLBACK = [", "DEFAULT_FRAMEWORK_FALLBACK = [ '#{HOMEBREW_PREFIX}/Frameworks',"
     end
 
+    # ADD tcl-tk include / lib paths
+    tcl_tk = Formula["tcl-tk"].opt_prefix
+    cppflags << "-I#{tcl_tk}/include"
+    ldflags  << "-L#{tcl_tk}/lib"
+
     args << "CFLAGS=#{cflags.join(" ")}" unless cflags.empty?
     args << "LDFLAGS=#{ldflags.join(" ")}" unless ldflags.empty?
     args << "CPPFLAGS=#{cppflags.join(" ")}" unless cppflags.empty?
@@ -255,6 +267,10 @@
     library_dirs = [HOMEBREW_PREFIX/"lib", Formula["openssl@1.1"].opt_lib,
                     Formula["sqlite"].opt_lib]
 
+    # Again tcl-tk
+    include_dirs << Formula["tcl-tk"].opt_include
+    library_dirs << Formula["tcl-tk"].opt_lib
+
     cfg = prefix/"Frameworks/Python.framework/Versions/#{xy}/lib/python#{xy}/distutils/distutils.cfg"
 
     cfg.atomic_write <<~EOS
@@ -339,3 +355,50 @@
     system bin/"pip3", "list", "--format=columns"
   end
 end
+__END__
+diff --git a/setup.py b/setup.py
+index 20d7f35..b9616d3 100644
+--- a/setup.py
++++ b/setup.py
+@@ -1851,8 +1851,6 @@ class PyBuildExt(build_ext):
+         # 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
+@@ -1901,21 +1899,6 @@ class PyBuildExt(build_ext):
+             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:
+@@ -1937,9 +1920,6 @@ class PyBuildExt(build_ext):
+         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:
+

@jethro-djan
Copy link

jethro-djan commented Aug 16, 2020

uninitialized constant Formula (NameError)

This error occurred at step 3. Thanks in advance for your help

Traceback (most recent call last): 29: from /usr/local/Homebrew/Library/Homebrew/brew.rb:23:in

'
28: from /usr/local/Homebrew/Library/Homebrew/brew.rb:23:in require_relative' 27: from /usr/local/Homebrew/Library/Homebrew/global.rb:133:in <top (required)>'
26: from /usr/local/Homebrew/Library/Homebrew/vendor/portable-ruby/2.6.3_2/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in require' 25: from /usr/local/Homebrew/Library/Homebrew/vendor/portable-ruby/2.6.3_2/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in require'
24: from /usr/local/Homebrew/Library/Homebrew/tap.rb:3:in <top (required)>' 23: from /usr/local/Homebrew/Library/Homebrew/vendor/portable-ruby/2.6.3_2/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in require'
22: from /usr/local/Homebrew/Library/Homebrew/vendor/portable-ruby/2.6.3_2/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in require' 21: from /usr/local/Homebrew/Library/Homebrew/commands.rb:3:in <top (required)>'
20: from /usr/local/Homebrew/Library/Homebrew/vendor/portable-ruby/2.6.3_2/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in require' 19: from /usr/local/Homebrew/Library/Homebrew/vendor/portable-ruby/2.6.3_2/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in require'
18: from /usr/local/Homebrew/Library/Homebrew/cask/cmd.rb:14:in <top (required)>' 17: from /usr/local/Homebrew/Library/Homebrew/vendor/portable-ruby/2.6.3_2/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in require'
16: from /usr/local/Homebrew/Library/Homebrew/vendor/portable-ruby/2.6.3_2/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in require' 15: from /usr/local/Homebrew/Library/Homebrew/cask/cmd/audit.rb:3:in <top (required)>'
14: from /usr/local/Homebrew/Library/Homebrew/vendor/portable-ruby/2.6.3_2/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in require' 13: from /usr/local/Homebrew/Library/Homebrew/vendor/portable-ruby/2.6.3_2/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in require'
12: from /usr/local/Homebrew/Library/Homebrew/cli/parser.rb:6:in <top (required)>' 11: from /usr/local/Homebrew/Library/Homebrew/vendor/portable-ruby/2.6.3_2/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in require'
10: from /usr/local/Homebrew/Library/Homebrew/vendor/portable-ruby/2.6.3_2/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in require' 9: from /usr/local/Homebrew/Library/Homebrew/formula.rb:6:in <top (required)>'
8: from /usr/local/Homebrew/Library/Homebrew/vendor/portable-ruby/2.6.3_2/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in require' 7: from /usr/local/Homebrew/Library/Homebrew/vendor/portable-ruby/2.6.3_2/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in require'
6: from /usr/local/Homebrew/Library/Homebrew/formula_pin.rb:3:in <top (required)>' 5: from /usr/local/Homebrew/Library/Homebrew/vendor/portable-ruby/2.6.3_2/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in require'
4: from /usr/local/Homebrew/Library/Homebrew/vendor/portable-ruby/2.6.3_2/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in require' 3: from /usr/local/Homebrew/Library/Homebrew/keg.rb:4:in <top (required)>'
2: from /usr/local/Homebrew/Library/Homebrew/vendor/portable-ruby/2.6.3_2/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in require' 1: from /usr/local/Homebrew/Library/Homebrew/vendor/portable-ruby/2.6.3_2/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in require'
/usr/local/Homebrew/Library/Homebrew/language/python.rb:1:in <top (required)>': uninitialized constant Formula (NameError)

@sri0sharma
Copy link

sri0sharma commented Sep 20, 2020

I am sorry that I could not respond to earlier. I hope you have already got it working, but if not, here are my thoughts (This is for macOS Catalina 10.15.6 using a virtual environment, pyenv. One can do the same without pyenv installation):

  1. I would do a clean install of homebrew:
    (a) To Uninstall brew:
    /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/uninstall.sh)"
    (b) To install brew
    /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"

Then I would go through all the steps already listed:

  1. brew install pyenv
  2. brew install tcl-tk --build-from-source

I will add the following to my /.zshrc

echo 'export PATH="/usr/local/opt/tcl-tk/bin:$PATH"' >> ~/.zshrc
export LDFLAGS="-L/usr/local/opt/tcl-tk/lib"
export CPPFLAGS="-I/usr/local/opt/tcl-tk/include"
export PKG_CONFIG_PATH="/usr/local/opt/tcl-tk/lib/pkgconfig"
  1. To get tcl-tk 8.6 to work with the pyenv install of python, I would
    edit the python-build script file. It may be located in one these two locations:

~/.pyenv/plugins/python-build/bin/python-build
or:
/usr/local/Cellar/pyenv/1.2.20/plugins/python-build/bin/python-build

Once I have the script file open using TextEdit, I would search for:
$CONFIGURE_OPTS ${!PACKAGE_CONFIGURE_OPTS} "${!PACKAGE_CONFIGURE_OPTS_ARRAY}" || return 1
and replace with:
$CONFIGURE_OPTS --with-tcltk-includes='-I/usr/local/opt/tcl-tk/include' --with-tcltk-libs='-L/usr/local/opt/tcl-tk/lib -ltcl8.6 -ltk8.6' ${!PACKAGE_CONFIGURE_OPTS} "${!PACKAGE_CONFIGURE_OPTS_ARRAY}" || return 1

I have read a feedback from Thomas Opplet that it did not work him, so he added it to /.zshrc. He did not say if that worked for him.

  1. pyenv install 3.8.5
  2. pyenv global 3.8.5 (I did not do it this time around)
  3. pyenv version
    Refreshed the current terminal and checked

python -V
Python 3.8.5

  1. pip install --upgrade pip
    When running it now, it shows "trackback" issues>. I did dome research on this and found out that the problem is with pip. In my case, I went ahead with next steps and it worked fine for me.

  2. python -m tkinter -c 'tkinter._test()'
    I did get "deprecated" warning, as commented by Ivan Stock, but it did not affect the installation.
    Tk window pops up. I hit ‘Quit’ to back to Terminal.

  3. idle3
    Python 3.8.5 Shell window pops up.
    When I used "idle", I got "deprecated" warning. Everything was fine when using "idle3" .

@mlazovjp
Copy link

mlazovjp commented Sep 21, 2020

I have been struggling with using Nuitka to compile a very small Python script that uses Tcl/Tk for the past 6 months but I finally got it working a minute ago!!!

Using this Homebrew code, I was able to install Python 3.8+Tcl/Tk (thank you!). I was able to run the .py file on my MacBook Pro running macOS, but when I tried to create a standalone distribution using Nuitka it would begin processing and eventually bomb, complaining "Could not find Tcl. Aborting standalone generation."

Two things I did differently this time around. I don't know yet if the first one makes any difference, but the second one definitely did.

1.) I had been trying to use a Python virtual environment in VS Code. I had seen a few references to the fact that penv might not behave properly, so I changed the interpreter in VS Code to use the Homebrew one located at /usr/local/bin/python3

2.) When I Googled "Could not find Tcl.", of all places I found a reference to a bug in OpenSUSE when compiling something using Nuitka. That bug report page is at openSUSE tk error #490 . Their fix was to run the following:

export TCL_LIBRARY=%{_libdir}/tcl/tcl8.6
export TK_LIBRARY=%{_libdir}/tcl/tk8.6

I added the following statements to the script file I use to compile the .py file using Nuitka and it works! Hopefully this will help someone else.

export _libdir=/usr/local/Cellar/tcl-tk/8.6.10/lib
export TCL_LIBRARY=${_libdir}/tcl8.6
export TK_LIBRARY=${_libdir}/tk8.6

For reference, this is the bash script I used to compile a standalone distribution with Nuitka.

#!/bin/bash

PROJ_PATH=~/Documents/testTCL
PYTHON_DIR=/usr/local/Cellar/python/3.8.1/bin/

_libdir=/usr/local/Cellar/tcl-tk/8.6.10/lib
TCL_LIBRARY=${_libdir}/tcl8.6
TK_LIBRARY=${_libdir}/tk8.6

COMPILE_CMD="$PYTHON_DIR/python3 -m nuitka --standalone --clang --plugin-enable=tk-inter --show-progress \
  --windows-icon="$PROJ_PATH/misc/UDLogo.ico" --output-dir="$PROJ_PATH/Nuitka_TestmacOS_dist" \
  --assume-yes-for-downloads Nuitka_Test.py"

$COMPILE_CMD

@iexa
Copy link
Author

iexa commented Nov 5, 2020

@sergey-arkhipov Thanks for your input, your method is in fact faster - if you've already did this install once at least (xcode, brew no autoupdate, etc.).

@rd0fun
Copy link

rd0fun commented Nov 5, 2020

Been struggling for some time now, step 3 just doesn't seem to work

HOMEBREW_NO_AUTO_UPDATE=1 brew install --build-from-source python@3.8
==> Searching for similarly named formulae...
This similarly named formula was found:
python@3.8
To install it, run:
  brew install python@3.8
Error: No available formula or cask with the name "python@3.8".
==> Searching taps on GitHub...
Error: No formulae found in taps.

brew doctor shows the following

Warning: You have uncommitted modifications to Homebrew/homebrew-core.
If this is a surprise to you, then you should stash these modifications.
Stashing returns Homebrew to a pristine state but can be undone
should you later need to do so for some reason.
  cd /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core && git stash && git clean -d -f

Uncommitted files:
   M Formula/python@3.8.rb

@sergey-arkhipov
Copy link

sergey-arkhipov commented Nov 5, 2020

@sergey-arkhipov Thanks for your input, your method is in fact faster - if you've already did this install once at least (xcode, brew no autoupdate, etc.).
Yes, I checked this way. Xcode is not necessary, but Command Line tools is necessary for compilation from source codes (homebrew demands Command Line tools, so it has to be already installed).
The described sequence of actions does not demand anything more, necessary dependencies will be installed in process. During of installation (REINSTALL !!!) the brew does not replace patched file. Certainly, at the following updates of versions this procedure should be made again, making changes in path, if python@3.8.rb will be replaced.(3.8.6 for now, path for 3.8.5)

@iexa
Copy link
Author

iexa commented Nov 5, 2020

@rd0fun if you type brew show python@3.8 what will it print? if it seems to not find a recipe, then there must be something wrong with the python@3.8.rb file. I had that first but fixed it (and fixed version is up here).

@sergey-arkhipov
Copy link

sergey-arkhipov commented Nov 5, 2020

I have just tried this path for python homebrew version 3.9.
This works as described above. I have python@3.9 and tcl-tk already installed via Homebrew
Attached the full steps.

  1. brew upgrade
  2. path python@3.9.rb
  3. brew reinstall python@3.9 --build-from-source

++++++++++++++++++++++++++++++++++++++++++++++++++++
-> MBA ! ~ % python3 -V
Python 3.9.0
-> MBA ! ~ % echo "import tkinter as tk\nprint(tk.TkVersion,tk.TclVersion)" |python3
8.5 8.5

++++++++++++++++++++++++++++++++++++++++++++++++++++

-> MBA ! % colordiff python@3.9.rb python@3.9.pathed.rb

36a37
>   depends_on "tcl-tk"  # as apple's one is shiiiiite
77d77
< 
87c87
< 
---
>   patch :DATA
121c121,122
<       cflags << "-I#{MacOS.sdk_path}/System/Library/Frameworks/Tk.framework/Versions/8.5/Headers"
---
>       #cflags << "-I#{MacOS.sdk_path}/System/Library/Frameworks/Tk.framework/Versions/8.5/Headers"
>       cflags << "-I#{MacOS.sdk_path}/usr/local/opt/tcl-tk/include"
145c146,151
< 
---
>     
>     # ADD tcl-tk include / lib paths
>     tcl_tk = Formula["tcl-tk"].opt_prefix
>     cppflags << "-I#{tcl_tk}/include"
>     ldflags  << "-L#{tcl_tk}/lib"
>     
265c271,275
< 
---
>     
>     # Again tcl-tk
>     include_dirs << Formula["tcl-tk"].opt_include
>     library_dirs << Formula["tcl-tk"].opt_lib
>     
349a360,405
> __END__
> diff --git a/setup.py b/setup.py
> index 20d7f35..b9616d3 100644
> --- a/setup.py
> +++ b/setup.py
> @@ -1851,8 +1851,6 @@ class PyBuildExt(build_ext):
>          # 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
> @@ -1901,21 +1899,6 @@ class PyBuildExt(build_ext):
>              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:
> @@ -1937,9 +1920,6 @@ class PyBuildExt(build_ext):
>          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:

++++++++++++++++++++++++++++++++++++++++++++++++++++
-> MBA ! % cp python@3.9.pathed.rb /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/Formula/python@3.9.rb
overwrite /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/Formula/python@3.9.rb? (y/n [n]) y

++++++++++++++++++++++++++++++++++++++++++++++++++++
-> MBA ! ~/ownCloud/AS/Python/Patch/3.9 % brew reinstall python@3.9 --build-from-source
==> Downloading https://files.pythonhosted.org/packages/a7/e0/30642b9c2df516506d40b563b0cbd080c49c6b3f11a70b4c7a670f13a78b/setuptools-50.3.2.zip
Already downloaded: /Users/as/Library/Caches/Homebrew/downloads/6c4cd84935cccfee61e433509bdda7951ea6b77ae5db203b1e708eea72d93603--setuptools-50.3.2.zip
==> Downloading https://files.pythonhosted.org/packages/0b/f5/be8e741434a4bf4ce5dbc235aa28ed0666178ea8986ddc10d035023744e6/pip-20.2.4.tar.gz
Already downloaded: /Users/as/Library/Caches/Homebrew/downloads/8420c2f6f4c2831dfbd1b0e1caa05c0c044729c31b52f8884a785a56038ad0e7--pip-20.2.4.tar.gz
==> Downloading https://files.pythonhosted.org/packages/83/72/611c121b6bd15479cb62f1a425b2e3372e121b324228df28e64cc28b01c2/wheel-0.35.1.tar.gz
Already downloaded: /Users/as/Library/Caches/Homebrew/downloads/1aa1a9563d6af09f2712c180679dfd512aac6c710fc3fb573175e88eaa7c6de3--wheel-0.35.1.tar.gz
==> Downloading https://www.python.org/ftp/python/3.9.0/Python-3.9.0.tar.xz
Already downloaded: /Users/as/Library/Caches/Homebrew/downloads/d37370983bfa2dfe731256050c2097e61210550756783e4623a6eb9a8812b210--Python-3.9.0.tar.xz
==> Reinstalling python@3.9
==> Patching
==> ./configure --prefix=/usr/local/Cellar/python@3.9/3.9.0_1 --enable-ipv6 --datarootdir=/usr/local/Cellar/python@3.9/3.9.0_1/share --datadir=/usr/local/Cellar
==> make
==> make install PYTHONAPPSDIR=/usr/local/Cellar/python@3.9/3.9.0_1
==> make frameworkinstallextras PYTHONAPPSDIR=/usr/local/Cellar/python@3.9/3.9.0_1/share/python@3.9
Unlinking /usr/local/Cellar/python@3.8/3.8.6_1... 9 symlinks removed
==> /usr/local/Cellar/python@3.9/3.9.0_1/bin/python3 -s setup.py --no-user-cfg install --force --verbose --install-scripts=/usr/local/Cellar/python@3.9/3.9.0_1/
==> /usr/local/Cellar/python@3.9/3.9.0_1/bin/python3 -s setup.py --no-user-cfg install --force --verbose --install-scripts=/usr/local/Cellar/python@3.9/3.9.0_1/
==> /usr/local/Cellar/python@3.9/3.9.0_1/bin/python3 -s setup.py --no-user-cfg install --force --verbose --install-scripts=/usr/local/Cellar/python@3.9/3.9.0_1/
==> Caveats
Python has been installed as
/usr/local/bin/python3

Unversioned symlinks python, python-config, pip etc. pointing to
python3, python3-config, pip3 etc., respectively, have been installed into
/usr/local/opt/python@3.9/libexec/bin

You can install Python packages with
pip3 install
They will install into the site-package directory
/usr/local/lib/python3.9/site-packages

See: https://docs.brew.sh/Homebrew-and-Python
==> Summary
🍺 /usr/local/Cellar/python@3.9/3.9.0_1: 9,224 files, 136.2MB, built in 3 minutes 28 seconds
++++++++++++++++++++++++++++++++++++++++++++++++++++

-> MBA ! % echo "import tkinter as tk\nprint(tk.TkVersion,tk.TclVersion)" |python3
8.6 8.6

-> MBA ! % date
Thu Nov 5 23:12:20 MSK 2020

@rd0fun
Copy link

rd0fun commented Nov 5, 2020

Is this a problem with my version of brew?

$ brew show
Error: Unknown command: show
brew --version
Homebrew 2.5.8
Homebrew/homebrew-core (git revision a0e08; last commit 2020-11-05)
Homebrew/homebrew-cask (git revision 97d5ff; last commit 2020-11-05)

@iexa
Copy link
Author

iexa commented Nov 6, 2020

@rd0fun sorry, I mixed it up, do brew info python@3.8 -- not show... there are so many command line tools I use (brew, node, pip, npm, yarn, etc.) i just try each option until one works with each one of them.

@iexa
Copy link
Author

iexa commented Nov 6, 2020

@sergey-arkhipov -- good to know that python 3.9 works as well. I know there's not much change from 3.8 -> 3.9 (like before the walrus operator for instance and f-string speedups) - some speedups for sure. Once it hits 3.9.2 or so I will update.

Do you have any problems with any pip packages on 3.9? I mean packages that have native parts and not just pure python.

@sergey-arkhipov
Copy link

sergey-arkhipov commented Nov 6, 2020

Do you have any problems with any pip packages on 3.9? I mean packages that have native parts and not just pure python.

I haven't faced yet any problems just now :-)

+++++++++++++++++++++++++++++++++++

-> MBA ! ~ % pip3 -V
pip 20.2.4 from /usr/local/lib/python3.9/site-packages/pip (python 3.9)
-> MBA ! ~ % pip3 list outdated
Package    Version
---------- -------
pip        20.2.4
setuptools 50.3.2
wheel      0.35.1
-> MBA ! ~ % pip3 list --outdated 
-> MBA ! ~ % pip3 install numpy
Collecting numpy
  Downloading numpy-1.19.4-cp39-cp39-macosx_10_9_x86_64.whl (15.4 MB)
     |████████████████████████████████| 15.4 MB 12.8 MB/s 
Installing collected packages: numpy
Successfully installed numpy-1.19.4
 -> MBA ! ~ % echo "import numpy as np\na = np.arange(15).reshape(3, 5)\nprint(a)\nprint(a.ndim)" |python3
[[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]]
2
-> MBA ! ~ % 

+++++++++++++++++++++++++++++++++++

@iexa
Copy link
Author

iexa commented Nov 6, 2020

Ok, good to know it's fine. I like your piping of a small python code string into the python interpreter. It got me for a bit until I saw the |.

@a4840639
Copy link

a4840639 commented Nov 18, 2020

Apparently you now need to rename the classname from Python to PythonAT38
Took me a while to figure this out

@sergey-arkhipov
Copy link

sergey-arkhipov commented Nov 23, 2020

I can confirm that it works at Mac OS Big Sur. I used the same patch and steps, described above.

-> mba ! ~ % sw_vers          
ProductName:	macOS
ProductVersion:	11.0.1
BuildVersion:	20B29
-> mba ! ~ % python3 -V
Python 3.9.0
-> mba ! ~ % echo "import tkinter as tk\nprint(tk.TkVersion,tk.TclVersion)" |python3
8.6 8.6
-> mba ! ~ % date
Tue Nov 24 01:37:38 MSK 2020
-> mba ! ~ % 

@sergey-arkhipov
Copy link

sergey-arkhipov commented Nov 23, 2020

-> mba ! ~ % colordiff -Naur python@3.9.rb python@3.9.pathed.rb
--- python@3.9.rb	2020-11-24 01:04:58.000000000 +0300
+++ python@3.9.pathed.rb	2020-11-24 01:45:40.000000000 +0300
@@ -34,6 +34,7 @@
   depends_on "readline"
   depends_on "sqlite"
   depends_on "xz"
+  depends_on "tcl-tk"  # as apple's one is shiiiiite
 
   uses_from_macos "bzip2"
   uses_from_macos "libffi"
@@ -85,6 +86,7 @@
     end
   end
 
+  patch :DATA
   def install
     # Unset these so that installing pip and setuptools puts them where we want
     # and not into some other Python the user has installed.
@@ -118,7 +120,8 @@
       # For the Xlib.h, Python needs this header dir with the system Tk
       # Yep, this needs the absolute path where zlib needed a path relative
       # to the SDK.
-      cflags << "-I#{MacOS.sdk_path}/System/Library/Frameworks/Tk.framework/Versions/8.5/Headers"
+      #cflags << "-I#{MacOS.sdk_path}/System/Library/Frameworks/Tk.framework/Versions/8.5/Headers"
+      cflags << "-I#{MacOS.sdk_path}/usr/local/opt/tcl-tk/include"
     end
     # Avoid linking to libgcc https://mail.python.org/pipermail/python-dev/2012-February/116205.html
     args << "MACOSX_DEPLOYMENT_TARGET=#{MacOS.version}"
@@ -142,7 +145,12 @@
       f.gsub! "DEFAULT_LIBRARY_FALLBACK = [", "DEFAULT_LIBRARY_FALLBACK = [ '#{HOMEBREW_PREFIX}/lib',"
       f.gsub! "DEFAULT_FRAMEWORK_FALLBACK = [", "DEFAULT_FRAMEWORK_FALLBACK = [ '#{HOMEBREW_PREFIX}/Frameworks',"
     end
-
+    
+    # ADD tcl-tk include / lib paths
+    tcl_tk = Formula["tcl-tk"].opt_prefix
+    cppflags << "-I#{tcl_tk}/include"
+    ldflags  << "-L#{tcl_tk}/lib"
+    
     args << "CFLAGS=#{cflags.join(" ")}" unless cflags.empty?
     args << "LDFLAGS=#{ldflags.join(" ")}" unless ldflags.empty?
     args << "CPPFLAGS=#{cppflags.join(" ")}" unless cppflags.empty?
@@ -262,7 +270,11 @@
                     Formula["sqlite"].opt_include]
     library_dirs = [HOMEBREW_PREFIX/"lib", Formula["openssl@1.1"].opt_lib,
                     Formula["sqlite"].opt_lib]
-
+    
+    # Again tcl-tk
+    include_dirs << Formula["tcl-tk"].opt_include
+    library_dirs << Formula["tcl-tk"].opt_lib
+    
     cfg = prefix/"Frameworks/Python.framework/Versions/#{xy}/lib/python#{xy}/distutils/distutils.cfg"
 
     cfg.atomic_write <<~EOS
@@ -347,3 +359,49 @@
     system bin/"pip3", "list", "--format=columns"
   end
 end
+__END__
+diff --git a/setup.py b/setup.py
+index 20d7f35..b9616d3 100644
+--- a/setup.py
++++ b/setup.py
+@@ -1851,8 +1851,6 @@ class PyBuildExt(build_ext):
+         # 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
+@@ -1901,21 +1899,6 @@ class PyBuildExt(build_ext):
+             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:
+@@ -1937,9 +1920,6 @@ class PyBuildExt(build_ext):
+         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:

@iexa
Copy link
Author

iexa commented Nov 27, 2020

@sergey-arkhipov thanks for the info - i wont update to big sur for a good while so thanks for testing it out.

@neilyoung
Copy link

neilyoung commented Nov 27, 2020

I had to change the first line of this gist to match the first line of the existing python@3.8.rb:

class PythonAT38 < Formula

otherwise the error was Error: No available formula or cask with the name "python@3.8.rb".

I was a bit irritated about the diff statement in the .rb, but this was no problem.

Mac OS Catalina 10.15.7.

EDIT: Even though tk sources have been downloaded, this gist didn't bring me TK support

EDIT_2: Got it working now

@iexa
Copy link
Author

iexa commented Dec 1, 2020

The homebrew package changed it. I'll update to 3.9 once 3.9.1 or 3.9.2 is out. Then this change won't be necessary.

@jimmybrancaccio
Copy link

jimmybrancaccio commented Dec 30, 2020

I'd love to see this get updated for 3.9.1. I had a look myself but couldn't seem to figure out the setup.py bit. ☹️

@dhinakg
Copy link

dhinakg commented Feb 19, 2021

With Homebrew/homebrew-core@e41f896, this doesn't seem to be needed anymore. Can anyone confirm?
image

@jimmybrancaccio
Copy link

jimmybrancaccio commented Feb 22, 2021

Looks like you're right @dhinakg 👍 🎉

@tomoyanonymous
Copy link

tomoyanonymous commented Mar 30, 2021

Homebrew/homebrew-core@80412c2#diff-38ae209ebc6d2954d5532ae8c3e6e579dc77a7d3002bed515fa930d6ea528139

Now tkinter is newly in python-tk formula. If you fail to execute tkinter, just run brew update && brew install python-tk .

@iexa
Copy link
Author

iexa commented Jun 24, 2021

So finally tk made its way back to brew. It's back in the official repo so I'm glad :)
https://github.com/Homebrew/homebrew-core/blob/master/Formula/python-tk@3.9.rb

https://www.youtube.com/watch?v=d-diB65scQU

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment