Top Level Namespace

Defined Under Namespace

Modules: Teek, TeekDemo

Instance Method Summary collapse

Instance Method Details

#find_tcltkObject



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'ext/teek/extconf.rb', line 8

def find_tcltk
  # Try pkg-config first
  tcl_found = pkg_config('tcl') || pkg_config('tcl9.0') || pkg_config('tcl8.6')
  tk_found = pkg_config('tk') || pkg_config('tk9.0') || pkg_config('tk8.6')

  unless tcl_found && tk_found
    # Manual search paths
    tcl_dirs = [
      '/opt/homebrew/opt/tcl-tk',
      '/usr/local/opt/tcl-tk',
      '/usr/local',
      '/usr'
    ]

    tcl_dirs.each do |dir|
      inc = "#{dir}/include"
      lib = "#{dir}/lib"
      # Check for tcl-tk subdirectory (Homebrew layout)
      if File.exist?("#{inc}/tcl-tk/tcl.h")
        inc = "#{inc}/tcl-tk"
      end

      # Check for versioned subdirectories (Debian/Ubuntu layout:
      # /usr/include/tcl9.0/tcl.h, /usr/include/tcl8.6/tcl.h)
      unless File.exist?("#{inc}/tcl.h")
        versioned = Dir.glob("#{inc}/tcl*/tcl.h").max
        if versioned
          tcl_ver_dir = File.dirname(versioned)
          tk_ver_dir = tcl_ver_dir.sub(/tcl/, 'tk')
          $INCFLAGS << " -I#{tcl_ver_dir}"
          $INCFLAGS << " -I#{tk_ver_dir}" if File.directory?(tk_ver_dir)
          $LDFLAGS << " -L#{lib}"
          break
        end
      end

      if File.exist?("#{inc}/tcl.h") && File.exist?("#{inc}/tk.h")
        $INCFLAGS << " -I#{inc}"
        $LDFLAGS << " -L#{lib}"
        break
      end
    end
  end

  # Check for required headers
  have_header('tcl.h') or abort "tcl.h not found"
  have_header('tk.h') or abort "tk.h not found"

  # Link against STUB libraries, not main libraries
  # Try versioned stub names first, then unversioned
  tcl_stub = have_library('tclstub9.0') ||
             have_library('tclstub8.6') ||
             have_library('tclstub')

  tk_stub = have_library('tkstub9.0') ||
            have_library('tkstub8.6') ||
            have_library('tkstub')

  # MSYS2/MinGW uses names without dots (tclstub86 instead of tclstub8.6)
  if RbConfig::CONFIG['host_os'] =~ /mingw|mswin/
    tcl_stub ||= have_library('tclstub90') || have_library('tclstub86')
    tk_stub ||= have_library('tkstub90') || have_library('tkstub86')
  end

  # If stub libraries not found by simple name, try via pkg-config
  unless tcl_stub
    # pkg-config may have added them already via --libs
    # Check if we can find the stubs table
    if try_link(<<~CODE)
      #define USE_TCL_STUBS
      #include <tcl.h>
      int main() { return 0; }
    CODE
      tcl_stub = true
    end
  end

  abort "Tcl stub library not found" unless tcl_stub
  abort "Tk stub library not found" unless tk_stub

  # Also link the real Tcl shared library so it's loaded at runtime.
  # Some distros (e.g. Fedora) ship Tcl symbols in a separate .so that
  # stubs alone don't pull in, causing dlsym() to fail at bootstrap.
  have_library('tcl9.0') || have_library('tcl8.6') || have_library('tcl')
end