[前][次][番号順一覧][スレッド一覧]

ruby-changes:16150

From: nagai <ko1@a...>
Date: Mon, 31 May 2010 23:50:58 +0900 (JST)
Subject: [ruby-changes:16150] Ruby:r28111 (trunk): * ext/tk/extconf.rb: use tclConfig.sh/tkConfig.sh when frameworks

nagai	2010-05-31 23:50:39 +0900 (Mon, 31 May 2010)

  New Revision: 28111

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=28111

  Log:
    * ext/tk/extconf.rb: use tclConfig.sh/tkConfig.sh when frameworks
      are enabled on MacOS X.
    * ext/tk/stubs.c: dirty hack for frameworks and stubs on MacOS X.
    * ext/tk/lib/tk.rb: stop creating a dummy Tcl/Tk interpreter. 
      And hide a root window before starting eventloop. (for ruby 1.9)
    * ext/tk/tcltklib.c: add codes to support Ruby/Tk-Kit (Rubykit).

  Modified files:
    trunk/ChangeLog
    trunk/ext/tk/extconf.rb
    trunk/ext/tk/lib/tk.rb
    trunk/ext/tk/stubs.c
    trunk/ext/tk/tcltklib.c

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 28110)
+++ ChangeLog	(revision 28111)
@@ -1,3 +1,15 @@
+Mon May 31 23:44:22 2010  Hidetoshi NAGAI  <nagai@a...>
+
+	* ext/tk/extconf.rb: use tclConfig.sh/tkConfig.sh when frameworks
+	  are enabled on MacOS X.
+
+	* ext/tk/stubs.c: dirty hack for frameworks and stubs on MacOS X.
+
+	* ext/tk/lib/tk.rb: stop creating a dummy Tcl/Tk interpreter. 
+	  And hide a root window before starting eventloop. (for ruby 1.9)
+
+	* ext/tk/tcltklib.c: add codes to support Ruby/Tk-Kit (Rubykit).
+
 Mon May 31 21:49:42 2010  Tanaka Akira  <akr@f...>
 
 	* lib/resolv.rb (Resolv::DNS::Requester#request): rescue ECONNRESET
Index: ext/tk/stubs.c
===================================================================
--- ext/tk/stubs.c	(revision 28110)
+++ ext/tk/stubs.c	(revision 28111)
@@ -92,6 +92,10 @@
 # define TK_INDEX 7
 # define TCL_NAME "libtcl8.9%s"
 # define TK_NAME "libtk8.9%s"
+# if defined(__APPLE__) && defined(__MACH__)   /* Mac OS X */
+#  undef DLEXT
+#  define DLEXT ".dylib"
+# endif
 #endif
 
 static DL_HANDLE tcl_dll = (DL_HANDLE)0;
@@ -321,6 +325,22 @@
         if (!p_Tk_Init)
             return NO_Tk_Init;
 
+#if defined USE_TK_STUBS && defined TK_FRAMEWORK && defined(__APPLE__) && defined(__MACH__)
+	/*
+	  FIX ME : dirty hack for Mac OS X frameworks.
+	  With stubs, fails to find Resource/Script directory of Tk.framework.
+	  So, teach it to a Tcl interpreter by an environment variable.
+	  e.g. when $tcl_library == 
+	               /Library/Frameworks/Tcl.framwwork/8.5/Resources/Scripts
+		   ==> /Library/Frameworks/Tk.framwwork/8.5/Resources/Scripts
+	*/
+	if (Tcl_Eval(tcl_ip,
+		     "if {[array get env TK_LIBRARY] == {}} { set env(TK_LIBRARY) [regsub -all -nocase {(t)cl} $tcl_library  {\\1k}] }"
+		     ) != TCL_OK) {
+	  return FAIL_Tk_Init;
+	}
+#endif
+
         if ((*p_Tk_Init)(tcl_ip) == TCL_ERROR)
             return FAIL_Tk_Init;
 
Index: ext/tk/tcltklib.c
===================================================================
--- ext/tk/tcltklib.c	(revision 28110)
+++ ext/tk/tcltklib.c	(revision 28111)
@@ -4,7 +4,8 @@
  *              Oct. 24, 1997   Y. Matsumoto
  */
 
-#define TCLTKLIB_RELEASE_DATE "2010-03-26"
+#define TCLTKLIB_RELEASE_DATE "2010-05-31"
+/* #define CREATE_RUBYTK_KIT */
 
 #include "ruby.h"
 
@@ -56,6 +57,20 @@
 #define va_init_list(a,b) va_start(a)
 #endif
 #include <string.h>
+
+#if !defined HAVE_VSNPRINTF && !defined vsnprintf
+#  ifdef WIN32
+     /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */
+#    define vsnprintf _vsnprintf
+#  else
+#    ifdef HAVE_RUBY_RUBY_H
+#      include "ruby/missing.h"
+#    else
+#      include "missing.h"
+#    endif
+#  endif
+#endif
+
 #include <tcl.h>
 #include <tk.h>
 
@@ -68,10 +83,15 @@
 
 #ifndef HAVE_RB_ERRINFO
 #define rb_errinfo() (ruby_errinfo+0) /* cannot be l-value */
+#else
+VALUE rb_errinfo(void);
 #endif
 #ifndef HAVE_RB_SAFE_LEVEL
-#define rb_safe_level() (ruby_safe_level+0) /* cannot be l-value */
+#define rb_safe_level() (ruby_safe_level+0)
 #endif
+#ifndef HAVE_RB_SOURCEFILE
+#define rb_sourcefile() (ruby_sourcefile+0)
+#endif
 
 #include "stubs.h"
 
@@ -529,7 +549,6 @@
     VALUE args;
 };
 
-
 /*----------------------------*/
 /* use Tcl internal functions */
 /*----------------------------*/
@@ -837,7 +856,196 @@
     return einfo;
 }
 
+/*-------------------------------------------------------*/
+#if defined CREATE_RUBYTK_KIT || defined CREATE_RUBYKIT
 
+/* Tcl/Tk stubs may work, but probably it is meaningless. */
+#if defined USE_TCL_STUBS || defined USE_TK_STUBS
+#  error Not support Tcl/Tk stubs with Ruby/Tk-Kit or Rubykit.
+#endif
+
+#ifndef KIT_INCLUDES_TK
+#  define KIT_INCLUDES_TK  1
+#endif
+/* #define KIT_INCLUDES_ITCL 1 */
+/* #define KIT_INCLUDES_THREAD  1 */
+
+#ifdef KIT_INCLUDES_ITCL
+Tcl_AppInitProc Itcl_Init;
+#endif
+Tcl_AppInitProc Mk4tcl_Init, Vfs_Init, Rechan_Init, Zlib_Init;
+#if 10 * TCL_MAJOR_VERSION + TCL_MINOR_VERSION < 85
+Tcl_AppInitProc Pwb_Init;
+#endif
+#if defined TCL_THREADS && defined KIT_INCLUDES_THREAD
+Tcl_AppInitProc Thread_Init;
+#endif
+#ifdef _WIN32
+Tcl_AppInitProc Dde_Init, Registry_Init;
+#endif
+
+static const char *tcltklib_filepath = "[info nameofexecutable]";
+static char *rubytkkit_preInitCmd = (char *)NULL;
+static const char *rubytkkit_preInitCmd_head = "set ::rubytkkit_exe [list ";
+static const char *rubytkkit_preInitCmd_tail =
+"]\n"
+/*=== following init scripts are quoted from kitInit.c of Tclkit ===*/
+/* Tclkit license terms ---
+ LICENSE
+
+   The Tclkit-specific sources are license free, they just have a copyright.
+   Hold the author(s) harmless and any lawful use is permitted.
+
+   This does *not* apply to any of the sources of the other major Open Source
+   Software used in Tclkit, which each have very liberal BSD/MIT-like licenses:
+         Tcl/Tk, Incrtcl, Metakit, TclVFS, Zlib
+*/
+#ifdef _WIN32_WCE
+/* silly hack to get wince port to launch, some sort of std{in,out,err} problem
+*/
+"open /kitout.txt a; open /kitout.txt a; open /kitout.txt a\n"
+/* this too seems to be needed on wince - it appears to be related to the above
+*/
+"catch {rename source ::tcl::source}\n"
+"proc source file {\n"
+    "set old [info script]\n"
+    "info script $file\n"
+    "set fid [open $file]\n"
+    "set data [read $fid]\n"
+    "close $fid\n"
+    "set code [catch {uplevel 1 $data} res]\n"
+    "info script $old\n"
+    "if {$code == 2} { set code 0 }\n"
+    "return -code $code $res\n"
+"}\n"
+#endif
+"proc tclKitInit {} {\n"
+    "rename tclKitInit {}\n"
+    "load {} Mk4tcl\n"
+#if defined KIT_VFS_WRITABLE && !defined CREATE_RUBYKIT
+    /* running command cannot open itself for writing */
+    "mk::file open exe $::rubytkkit_exe\n"
+#else
+    "mk::file open exe $::rubytkkit_exe -readonly\n"
+#endif
+    "set n [mk::select exe.dirs!0.files name boot.tcl]\n"
+    "if {$n != \"\"} {\n"
+        "set s [mk::get exe.dirs!0.files!$n contents]\n"
+        "if {![string length $s]} { error \"empty boot.tcl\" }\n"
+        "catch {load {} zlib}\n"
+        "if {[mk::get exe.dirs!0.files!$n size] != [string length $s]} {\n"
+            "set s [zlib decompress $s]\n"
+        "}\n"
+    "} else {\n"
+        "set f [open setup.tcl]\n"
+        "set s [read $f]\n"
+        "close $f\n"
+    "}\n"
+    "uplevel #0 $s\n"
+#ifdef _WIN32
+    "package ifneeded dde 1.3.1 {load {} dde}\n"
+    "package ifneeded registry 1.1.5 {load {} registry}\n"
+#endif
+"}\n"
+"tclKitInit"
+;
+
+#if 0
+/* Not use this script. 
+   It's a memo to support an initScript for Tcl interpreters in the future. */
+static const char initScript[] =
+"if {[file isfile [file join $::rubytkkit_exe main.tcl]]} {\n"
+    "if {[info commands console] != {}} { console hide }\n"
+    "set tcl_interactive 0\n"
+    "incr argc\n"
+    "set argv [linsert $argv 0 $argv0]\n"
+    "set argv0 [file join $::rubytkkit_exe main.tcl]\n"
+"} else continue\n"
+;
+#endif
+
+#if !defined(TclSetPreInitScript) && !defined(TclSetPreInitScript_TCL_DECLARED)
+EXTERN char* TclSetPreInitScript _((char *));
+#endif
+static char*
+setup_preInitCmd(const char *path)
+{
+  int head_len, path_len, tail_len;
+  char *ptr;
+
+  head_len = strlen(rubytkkit_preInitCmd_head);
+  path_len = strlen(path);
+  tail_len = strlen(rubytkkit_preInitCmd_tail);
+
+  rubytkkit_preInitCmd = ALLOC_N(char, head_len + path_len + tail_len + 1);
+
+  ptr = rubytkkit_preInitCmd;
+  memcpy(ptr, rubytkkit_preInitCmd_head, head_len);
+
+  ptr += head_len;
+  memcpy(ptr, path, path_len);
+
+  ptr += path_len;
+  memcpy(ptr, rubytkkit_preInitCmd_tail, tail_len);
+
+  ptr += tail_len;
+  *ptr = '\0';
+
+  return TclSetPreInitScript(rubytkkit_preInitCmd);
+}
+
+static void
+init_static_tcltk_packages()
+{
+#ifdef KIT_INCLUDES_ITCL
+    Tcl_StaticPackage(0, "Itcl", Itcl_Init, NULL);
+#endif
+    Tcl_StaticPackage(0, "Mk4tcl", Mk4tcl_Init, NULL);
+#if 10 * TCL_MAJOR_VERSION + TCL_MINOR_VERSION < 85
+    Tcl_StaticPackage(0, "pwb", Pwb_Init, NULL);
+#endif
+    Tcl_StaticPackage(0, "rechan", Rechan_Init, NULL);
+    Tcl_StaticPackage(0, "vfs", Vfs_Init, NULL);
+    Tcl_StaticPackage(0, "zlib", Zlib_Init, NULL);
+#if defined TCL_THREADS && defined KIT_INCLUDES_THREAD
+    Tcl_StaticPackage(0, "Thread", Thread_Init, NULL);
+#endif
+#ifdef _WIN32
+    Tcl_StaticPackage(0, "dde", Dde_Init, NULL);
+    Tcl_StaticPackage(0, "registry", Registry_Init, NULL);
+#endif
+#ifdef KIT_INCLUDES_TK
+    Tcl_StaticPackage(0, "Tk", Tk_Init, Tk_SafeInit);
+#endif
+}
+
+/* SetExecName --  Hack to get around Tcl bug 1224888. */
+void SetExecName(Tcl_Interp *interp) {
+  /* dummy */
+}
+#endif /* defined CREATE_RUBYTK_KIT || defined CREATE_RUBYKIT */
+
+static int
+call_tclkit_init_script(Tcl_Interp  *interp)
+{
+#if 0
+  /* Currently, nothing do in this function. 
+     It's a memo (quoted from kitInit.c of Tclkit) 
+     to support an initScript for Tcl interpreters in the future. */
+  if (Tcl_Eval(interp, initScript) == TCL_OK) {
+    Tcl_Obj* path = TclGetStartupScriptPath();
+    TclSetStartupScriptPath(Tcl_GetObjResult(interp));
+    if (path == NULL)
+      Tcl_Eval(interp, "incr argc -1; set argv [lrange $argv 1 end]");
+  }
+#endif
+
+  return 1;
+}
+
+
+/**********************************************************************/
+
 /* stub status */
 static void
 tcl_stubs_check()
@@ -5668,6 +5876,30 @@
     rb_thread_critical = thr_crit_bup;
 }
 
+/*--------------------------------------------------------*/
+
+#ifdef __WIN32__
+/* #include <tkWinInt.h> *//* conflict definition of struct timezone */
+/* #include <tkIntPlatDecls.h> */
+/* #include <windows.h> */
+EXTERN void TkWinSetHINSTANCE(HINSTANCE hInstance);
+void rbtk_win32_SetHINSTANCE(const char *module_name)
+{
+  /* TCHAR szBuf[256]; */
+  HINSTANCE hInst;
+
+  /* hInst = GetModuleHandle(NULL); */
+  /* hInst = GetModuleHandle("tcltklib.so"); */
+  hInst = GetModuleHandle(module_name);
+  TkWinSetHINSTANCE(hInst);
+
+  /* GetModuleFileName(hInst, szBuf, sizeof(szBuf) / sizeof(TCHAR)); */
+  /* MessageBox(NULL, szBuf, TEXT("OK"), MB_OK); */
+}
+#endif
+
+/*--------------------------------------------------------*/
+
 /* initialize interpreter */
 static VALUE
 ip_init(argc, argv, self)
@@ -5739,6 +5971,8 @@
     DUMP2("IP ref_count = %d", ptr->ref_count);
     current_interp = ptr->ip;
 
+    call_tclkit_init_script(current_interp);
+
     ptr->has_orig_exit
         = Tcl_GetCommandInfo(ptr->ip, "exit", &(ptr->orig_exit_info));
 
@@ -10315,18 +10549,18 @@
    /* --------------------------------------------------------------- */
 
 #ifdef __WIN32__
-#define TK_WINDOWING_SYSTEM "win32"
+#  define TK_WINDOWING_SYSTEM "win32"
 #else
-#ifdef MAC_TCL
-#define TK_WINDOWING_SYSTEM "classic"
-#else
-#ifdef MAC_OSX_TK
-#define TK_WINDOWING_SYSTEM "aqua"
-#else
-#define TK_WINDOWING_SYSTEM "x11"
+#  ifdef MAC_TCL
+#    define TK_WINDOWING_SYSTEM "classic"
+#  else
+#    ifdef MAC_OSX_TK
+#      define TK_WINDOWING_SYSTEM "aqua"
+#    else
+#      define TK_WINDOWING_SYSTEM "x11"
+#    endif
+#  endif
 #endif
-#endif
-#endif
     rb_define_const(lib, "WINDOWING_SYSTEM",
                     rb_obj_freeze(rb_str_new2(TK_WINDOWING_SYSTEM)));
 
@@ -10581,6 +10815,19 @@
 
     /* --------------------------------------------------------------- */
 
+#if defined CREATE_RUBYTK_KIT
+#ifdef __WIN32__
+    rbtk_win32_SetHINSTANCE("tcltklib.so");
+#endif
+    tcltklib_filepath = strdup(rb_sourcefile());
+#endif
+#if defined CREATE_RUBYTK_KIT || defined CREATE_RUBYKIT
+    init_static_tcltk_packages();
+    setup_preInitCmd(tcltklib_filepath);
+#endif
+
+    /* --------------------------------------------------------------- */
+
     /* Tcl stub check */
     tcl_stubs_check();
 
Index: ext/tk/lib/tk.rb
===================================================================
--- ext/tk/lib/tk.rb	(revision 28110)
+++ ext/tk/lib/tk.rb	(revision 28111)
@@ -1179,40 +1179,43 @@
     unless self.const_defined? :RUN_EVENTLOOP_ON_MAIN_THREAD
       if WITH_RUBY_VM ### check Ruby 1.9 !!!!!!!
         # *** NEED TO FIX ***
-        ip = TclTkIp.new(name, opts)
-        if RUBY_PLATFORM =~ /cygwin/
+        case RUBY_PLATFORM
+        when /cygwin/
           RUN_EVENTLOOP_ON_MAIN_THREAD = true
-          INTERP = ip
-        elsif ip._invoke_without_enc('tk', 'windowingsystem') == 'aqua' &&
-            (TclTkLib.get_version<=>[8,4,TclTkLib::RELEASE_TYPE::FINAL,6]) > 0
-          # *** KNOWN BUG ***
-          #   Main event loop thread of TkAqua (> Tk8.4.9) must be the main
-          #   application thread. So, ruby1.9 users must call Tk.mainloop on
-          #   the main application thread.
-          #
-          # *** ADD (2009/05/10) ***
-          #   In some cases (I don't know the description of conditions), 
-          #   TkAqua 8.4.7 has a same kind of hang-up trouble. 
-          #   So, if 8.4.7 or later, set RUN_EVENTLOOP_ON_MAIN_THREAD to true. 
-          #   When you want to control this mode, please call the following 
-          #   (set true/false as you want) before "require 'tk'".
-          #   ----------------------------------------------------------
-          #   module TkCore; RUN_EVENTLOOP_ON_MAIN_THREAD = true; end
-          #   ----------------------------------------------------------
-          #
-          RUN_EVENTLOOP_ON_MAIN_THREAD = true
-          INTERP = ip
-        else
-          unless self.const_defined? :RUN_EVENTLOOP_ON_MAIN_THREAD
+        when /darwin/ # MacOS X
+=begin
+          ip = TclTkIp.new(name, opts)
+          if ip._invoke_without_enc('tk', 'windowingsystem') == 'aqua' &&
+             (TclTkLib.get_version<=>[8,4,TclTkLib::RELEASE_TYPE::FINAL,6]) > 0
+=end
+          if TclTkLib::WINDOWING_SYSTEM == 'aqua' &&
+             (TclTkLib.get_version<=>[8,4,TclTkLib::RELEASE_TYPE::FINAL,6]) > 0
+            # *** KNOWN BUG ***
+            #  Main event loop thread of TkAqua (> Tk8.4.9) must be the main
+            #  application thread. So, ruby1.9 users must call Tk.mainloop on
+            #  the main application thread.
+            #
+            # *** ADD (2009/05/10) ***
+            #  In some cases (I don't know the description of conditions),
+            #  TkAqua 8.4.7 has a same kind of hang-up trouble.
+            #  So, if 8.4.7 or later, set RUN_EVENTLOOP_ON_MAIN_THREAD to true.
+            #  When you want to control this mode, please call the following
+            #  (set true/false as you want) before "require 'tk'".
+            #  ----------------------------------------------------------
+            #  module TkCore; RUN_EVENTLOOP_ON_MAIN_THREAD = true; end
+            #  ----------------------------------------------------------
+            #
+            RUN_EVENTLOOP_ON_MAIN_THREAD = true
+          else
             RUN_EVENTLOOP_ON_MAIN_THREAD = false
-          end
-          if RUN_EVENTLOOP_ON_MAIN_THREAD
-            INTERP = ip
-          else
+=begin
             ip.delete
+            ip = nil
+=end
           end
+        else
+          RUN_EVENTLOOP_ON_MAIN_THREAD = false
         end
-        ip = nil
 
       else # Ruby 1.8.x
         RUN_EVENTLOOP_ON_MAIN_THREAD = false
@@ -1243,6 +1246,30 @@
         Thread.current[:status] = status
         #sleep
 
+        # like as 1.8, withdraw a root widget before calling Tk.mainloop
+        interp._eval <<EOS
+rename wm __wm_orig__
+proc wm {subcmd win args} {
+  eval [list __wm_orig__ $subcmd $win] $args
+  if {[string equal $subcmd withdraw] && [string equal $win .]} {
+    rename wm {}
+    rename __wm_orig__ wm
+  }
+}
+proc __startup_rbtk_mainloop__ {args} {
+  rename __startup_rbtk_mainloop__ {}
+  if {[info command __wm_orig__] == "__wm_orig__"} {
+    rename wm {}
+    rename __wm_orig__ wm
+    if [string equal [wm state .] withdrawn] {
+      wm deiconify .
+    }
+  }
+}
+set __initial_state_of_rubytk__ 1
+trace add variable __initial_state_of_rubytk__ unset __startup_rbtk_mainloop__
+EOS
+
         begin
           begin
             #TclTkLib.mainloop_abort_on_exception = false
@@ -1808,6 +1835,9 @@
         return TkCore::INTERP._thread_tkwait('window', '.') if check_root
       end
 
+      # like as 1.8, withdraw a root widget before calling Tk.mainloop
+      TkCore::INTERP._eval_without_enc('unset __initail_state_of_rubytk__')
+
       begin
         TclTkLib.set_eventloop_window_mode(true)
         if check_root
@@ -5663,7 +5693,7 @@
 #Tk.freeze
 
 module Tk
-  RELEASE_DATE = '2010-02-01'.freeze
+  RELEASE_DATE = '2010-05-31'.freeze
 
   autoload :AUTO_PATH,        'tk/variable'
   autoload :TCL_PACKAGE_PATH, 'tk/variable'
Index: ext/tk/extconf.rb
===================================================================
--- ext/tk/extconf.rb	(revision 28110)
+++ ext/tk/extconf.rb	(revision 28111)
@@ -1,13 +1,14 @@
 ##############################################################
 # extconf.rb for tcltklib
-# release date: 2010-05-19
+# release date: 2010-05-31
 ##############################################################
 require 'mkmf'
 
 TkLib_Config = {}
 TkLib_Config['search_versions'] = 
   # %w[8.9 8.8 8.7 8.6 8.5 8.4 8.3 8.2 8.1 8.0 7.6 4.2]
-  %w[8.7 8.6 8.5 8.4 8.3 8.2 8.1 8.0]
+  # %w[8.7 8.6 8.5 8.4 8.3 8.2 8.1 8.0]
+  %w[8.7 8.6 8.5 8.4 8.0] # to shorten search steps
 
 
 ##############################################################
@@ -178,7 +179,9 @@
   path_dirs = []
 
   if TkLib_Config["ActiveTcl"].kind_of?(String)  # glob path
-    path_dirs.concat Dir.glob(TkLib_Config["ActiveTcl"], File::FNM_CASEFOLD).sort.reverse
+    # path_head << TkLib_Config["ActiveTcl"]
+    path_head.concat Dir.glob(TkLib_Config["ActiveTcl"], File::FNM_CASEFOLD).sort.reverse
+    # path_dirs.concat Dir.glob(File.join(TkLib_Config["ActiveTcl"], 'lib'), File::FNM_CASEFOLD).sort.reverse
   end
 
   if CROSS_COMPILING
@@ -288,6 +291,7 @@
     "/Library/Frameworks",
     "/Network/Library/Frameworks", "/System/Library/Frameworks"
   ]
+  paths.reverse! unless TkLib_Config["ActiveTcl"] # system has higher priority
 
   paths.map{|dir| dir.strip.chomp('/')}.each{|dir|
     next unless File.directory?(tcldir = File.join(dir, "Tcl.framework"))
@@ -379,7 +383,7 @@
     if TkLib_Config["ActiveTcl"]
       dirs = []
       if TkLib_Config["ActiveTcl"].kind_of?(String)
-        dirs << TkLib_Config["ActiveTcl"]
+        dirs << File.join(TkLib_Config["ActiveTcl"], 'lib')
       end
       dirs.concat [
         "c:/ActiveTcl*/lib", "c:/Tcl*/lib",
@@ -411,13 +415,32 @@
 
     config_dir.concat(dirs.zip(dirs))
 
-  elsif framework = find_macosx_framework()
-    config_dir.unshift(framework)
+  else
+    if framework = find_macosx_framework()
+      config_dir.unshift(framework)
+    end
 
-  else
     if activeTcl = TkLib_Config['ActiveTcl']
       # check latest version at first
-      config_dir.concat(Dir.glob(activeTcl, File::FNM_CASEFOLD).sort.reverse)
+      if is_macosx?
+        base = File.expand_path(activeTcl)
+        config_dir << [
+          File.join(base, 'Tcl.framework'), File.join(base, 'Tk.framework')
+        ]
+
+        config_dir << [
+          File.join(base, 'Tcl.framework', 'Versions', 'Current'),
+          File.join(base, 'Tk.framework', 'Versions', 'Current')
+        ]
+
+        Dir.glob(File.join(base, 'Tcl.framework', 
+                           'Versions', '*')).sort.reverse.each{|dir|
+          next if dir =~ /Current/
+          config_dir << [dir, dir.gsub(/Tcl/, 'Tk')]
+        }
+      else
+        config_dir.concat(Dir.glob(File.join(activeTcl, 'lib'), File::FNM_CASEFOLD).sort.reverse)
+      end
     end
 
     config_dir.concat [
@@ -448,27 +471,88 @@
     }
 
     # for MacOS X
-    #config_dir << "~/Library/Tcl"
-    #config_dir.concat(Dir.glob("~/Library/Tcl/*", File::FNM_CASEFOLD).sort.reverse)
-    config_dir << "/Library/Tcl"
-    config_dir.concat(Dir.glob("/Library/Tcl/*", File::FNM_CASEFOLD).sort.reverse)
-    config_dir << "/Network/Library/Tcl"
-    config_dir.concat(Dir.glob("/Network/Library/Tcl/*", File::FNM_CASEFOLD).sort.reverse)
-    config_dir << "/System/Library/Tcl"
-    config_dir.concat(Dir.glob("/System/Library/Tcl/*", File::FNM_CASEFOLD).sort.reverse)
-    [
+    paths = [
+      #"~/Library/Tcl",
+      "/Library/Tcl", "/Network/Library/Tcl", "/System/Library/Tcl"
+    ]
+    paths.reverse! unless TkLib_Config["ActiveTcl"]
+
+    paths.each{|path|
+      config_dir << path
+      config_dir.concat(Dir.glob(File.join(path, '{tcl,tk}*'), File::FNM_CASEFOLD).sort.reverse.find_all{|d| File.directory?(d)})
+    }
+
+    paths = [
       #"~/Library/Frameworks", 
       "/Library/Frameworks",
       "/Network/Library/Frameworks", "/System/Library/Frameworks"
-    ].each{|framework|
-      config_dir << [File.expand_path(File.join(framework, 'Tcl.framework')),
-        File.expand_path(File.join(framework, 'Tk.framework'))]
+    ]
+    paths.reverse! unless TkLib_Config["ActiveTcl"]
+
+    paths.each{|framework|
+      base = File.expand_path(framework)
+      config_dir << [
+        File.join(base, 'Tcl.framework'), File.join(base, 'Tk.framework')
+      ]
+
+      config_dir << [
+        File.join(base, 'Tcl.framework', 'Versions', 'Current'),
+        File.join(base, 'Tk.framework', 'Versions', 'Current')
+      ]
+
+      Dir.glob(File.join(base, 'Tcl.framework', 
+                         'Versions', '*')).sort.reverse.each{|dir|
+        next if dir =~ /Current/
+        config_dir << [dir, dir.gsub(/Tcl/, 'Tk')]
+      }
     }
   end
 
   config_dir
 end
 
+def libcheck_for_tclConfig(dir, tclconf, tkconf)
+  tcllib_ok = tklib_ok = false
+
+  if TkLib_Config["tcltk-stubs"]
+    stub = "stub"
+    tclfunc = "Tcl_InitStubs"
+    tkfunc  = "Tk_InitStubs"
+  else
+    stub = ""
+    tclfunc = "Tcl_FindExecutable"
+    tkfunc  = "Tk_Init"
+  end
+
+  libpath = $LIBPATH
+  tcllibs = nil
+
+  begin
+    tcllib_ok ||= Dir.glob(File.join(dir, "*tcl#{stub}#{tclconf['TCL_MAJOR_VERSION']}{.,}#{tclconf['TCL_MINOR_VERSION']}*.*"), File::FNM_CASEFOLD).find{|file|
+      if file =~ /^.*(tcl#{stub}#{tclconf['TCL_MAJOR_VERSION']}(\.|)#{tclconf['TCL_MINOR_VERSION']}.*)\.[^.]*$/
+        #puts "check #{file} #{$1} #{tclfunc} #{dir}"
+        #find_library($1, tclfunc, dir)
+        tcllibs = append_library($libs, $1)
+        $LIBPATH = libpath | [dir]
+        try_func(tclfunc, tcllibs)
+      end
+    }
+    tklib_ok ||= Dir.glob(File.join(dir, "*tk#{stub}#{tkconf['TK_MAJOR_VERSION']}{.,}#{tkconf['TK_MINOR_VERSION']}*.*"), File::FNM_CASEFOLD).find{|file|
+      if file =~ /^.*(tk#{stub}#{tkconf['TK_MAJOR_VERSION']}(\.|)#{tkconf['TK_MINOR_VERSION']}.*)\.[^.]*$/
+        #puts "check #{file} #{$1} #{tkfunc} #{dir}"
+        # find_library($1, tkfunc, dir)
+        tklibs = append_library(tcllibs, $1)
+        $LIBPATH = libpath | [dir]
+        try_func(tkfunc, tklibs)
+      end
+    }
+  ensure
+    $LIBPATH = libpath
+  end
+
+  [tcllib_ok, tklib_ok]
+end
+
 def search_tclConfig(*paths) # libdir list or [tcl-libdir|file, tk-libdir|file]
   TkLib_Config["tclConfig_paths"] = []
 
@@ -518,7 +602,7 @@
     if File.file?(tkdir)
       tkcfg_files = [tkdir] * tails.length
     else
-      tkcfg_files = tails.map{|f| File.join(tcldir, 'tk' << f)}
+      tkcfg_files = tails.map{|f| File.join(tkdir, 'tk' << f)}
     end
 
     tclcfg_files.zip(tkcfg_files).uniq.each{|tclpath, tkpath|
@@ -532,7 +616,7 @@
 
       # nativethread check
       if !TkLib_Config["ruby_with_thread"] && tclconf['TCL_THREADS'] == '1'
-        puts "WARNING: found #{tclpath.inspect}, but it WITH nativethread-support under ruby WITHOUT nativethread-support. So, ignore it."
+        puts "\nWARNING: found #{tclpath.inspect}, but it WITH nativethread-support under ruby WITHOUT nativethread-support. So, ignore it."
         TkLib_Config["tcltk-NG-path"] << File.dirname(tclpath)
         next
       end
@@ -541,43 +625,54 @@
       conf = [tclconf, tkconf] unless conf
 
       # check Tcl library
-      if TkLib_Config["tcltk-stubs"]
-        stub = "stub"
-        tclfunc = "Tcl_InitStubs"
-        tkfunc  = "Tk_InitStubs"
+      if is_macosx? && TkLib_Config["tcltk-framework"]
+        # if use framework, not check (believe it is installed properly)
+        tcllib_ok = tklib_ok = true
       else
-        stub = ""
-        tclfunc = "Tcl_FindExecutable"
-        tkfunc  = "Tk_Init"
+        tcllib_ok, tklib_ok = libcheck_for_tclConfig(File.dirname(tclpath),
+                                                      tclconf, tkconf)
+=begin
+        tcllib_ok = tklib_ok = false
+        if TkLib_Config["tcltk-stubs"]
+          stub = "stub"
+          tclfunc = "Tcl_InitStubs"
+          tkfunc  = "Tk_InitStubs"
+        else
+          stub = ""
+          tclfunc = "Tcl_FindExecutable"
+          tkfunc  = "Tk_Init"
+        end
+        dir = File.dirname(tclpath)
+        libpath = $LIBPATH
+        tcllibs = nil
+
+        begin
+          tcllib_ok ||= Dir.glob(File.join(dir, "*tcl#{stub}#{tclconf['TCL_MAJOR_VERSION']}{.,}#{tclconf['TCL_MINOR_VERSION']}*.*"), File::FNM_CASEFOLD).find{|file|
+            if file =~ /^.*(tcl#{stub}#{tclconf['TCL_MAJOR_VERSION']}(\.|)#{tclconf['TCL_MINOR_VERSION']}.*)\.[^.]*$/
+              #puts "check #{file} #{$1} #{tclfunc} #{dir}"
+              #find_library($1, tclfunc, dir)
+              tcllibs = append_library($libs, $1)
+              $LIBPATH = libpath | [dir]
+              try_func(tclfunc, tcllibs)
+            end
+          }
+          tklib_ok ||= Dir.glob(File.join(dir, "*tk#{stub}#{tkconf['TK_MAJOR_VERSION']}{.,}#{tkconf['TK_MINOR_VERSION']}*.*"), File::FNM_CASEFOLD).find{|file|
+            if file =~ /^.*(tk#{stub}#{tkconf['TK_MAJOR_VERSION']}(\.|)#{tkconf['TK_MINOR_VERSION']}.*)\.[^.]*$/
+              #puts "check #{file} #{$1} #{tkfunc} #{dir}"
+              # find_library($1, tkfunc, dir)
+              tklibs = append_library(tcllibs, $1)
+              $LIBPATH = libpath | [dir]
+              try_func(tkfunc, tklibs)
+            end
+          }
+        ensure
+          $LIBPATH = libpath
+        end
+=end
       end
-      dir = File.dirname(tclpath)
-      libpath = $LIBPATH
-      tcllibs = nil
-      begin
-        tcllib_ok = Dir.glob(File.join(dir, "*tcl#{stub}#{tclconf['TCL_MAJOR_VERSION']}{.,}#{tclconf['TCL_MINOR_VERSION']}*.*"), File::FNM_CASEFOLD).find{|file|
-          if file =~ /^.*(tcl#{stub}#{tclconf['TCL_MAJOR_VERSION']}(\.|)#{tclconf['TCL_MINOR_VERSION']}.*)\.[^.]*$/
-            #puts "check #{file} #{$1} #{tclfunc} #{dir}"
-            #find_library($1, tclfunc, dir)
-            tcllibs = append_library($libs, $1)
-            $LIBPATH = libpath | [dir]
-            try_func(tclfunc, tcllibs)
-          end
-        }
-        tklib_ok = Dir.glob(File.join(dir, "*tk#{stub}#{tkconf['TK_MAJOR_VERSION']}{.,}#{tkconf['TK_MINOR_VERSION']}*.*"), File::FNM_CASEFOLD).find{|file|
-          if file =~ /^.*(tk#{stub}#{tkconf['TK_MAJOR_VERSION']}(\.|)#{tkconf['TK_MINOR_VERSION']}.*)\.[^.]*$/
-            #puts "check #{file} #{$1} #{tkfunc} #{dir}"
-            # find_library($1, tkfunc, dir)
-            tklibs = append_library(tcllibs, $1)
-            $LIBPATH = libpath | [dir]
-            try_func(tkfunc, tklibs)
-          end
-        }
-      ensure
-        $LIBPATH = libpath
-      end
 
       unless tcllib_ok && tklib_ok
-        puts "WARNING: found #{tclpath.inspect}, but cannot find valid Tcl/Tk libraries on the same directory. So, ignore it."
+        puts "\nWARNING: found #{tclpath.inspect}, but cannot find valid Tcl/Tk libraries on the same directory. So, ignore it."
         TkLib_Config["tcltk-NG-path"] << File.dirname(tclpath)
         next
       end
@@ -590,6 +685,13 @@
     # print("\n");
   }
 
+  if is_macosx? && TkLib_Config["tcltk-stubs"]
+    CONFIG['LDSHARED'] << " -Xlinker -bind_at_load"
+    if config_string('LDSHAREDXX')
+      config_string('LDSHAREDXX') << " -Xlinker -bind_at_load"
+    end
+  end
+
   if TkLib_Config["tclConfig_paths"].empty?
     [nil, nil]
   else
@@ -691,6 +793,10 @@
         else
           dirs = []
 
+          if Dir.glob(head, File::FNM_CASEFOLD).find{|dir| dir == head}
+            dirs << head + "/lib"
+          end
+
           if !Dir.glob(head + "-*", File::FNM_CASEFOLD).empty?
             dirs << head + "-#{ver}/lib" if !Dir.glob(head + "-[89].*", File::FNM_CASEFOLD).empty?
             dirs << head + "-#{ver.delete('.')}/lib" if !Dir.glob(head + "-[89][0-9]*", File::FNM_CASEFOLD).empty?
@@ -718,7 +824,7 @@
   path_list = check_NG_path(path_list)
   path_list.map!{|path| path.strip}
 
-  if !CROSS_COMPILING and is_win32?
+  if !CROSS_COMPILING and (is_win32? || is_macosx?)
     # exist-dir only
     path_list.delete_if{|path| Dir.glob(File.join(path, "*.{a,so,dll,lib}")).empty?}
   end
@@ -1031,29 +1137,52 @@
   have_tcl_h && have_tk_h
 end
 
-def setup_for_macosx_framework
-  # search directory of header files
-  if File.exist?(dir = File.join(TkLib_Config["tcltk-framework"], 
-                                 'Tcl.framework', 'Headers'))
-    TclConfig_Info['TCL_INCLUDE_SPEC'] = "-I#{dir} "
-    TkConfig_Info['TK_INCLUDE_SPEC'] = "-I#{File.join(TkLib_Config['tcltk-framework'], 'Tk.framework', 'Headers')} "
-  else
-    dir = Dir.glob(File.join(TkLib_Config["tcltk-framework"], 
-                             'Tcl.framework', '*', 'Headers'),
-                   File::FNM_CASEFOLD)
-    TclConfig_Info['TCL_INCLUDE_SPEC'] = "-I#{dir[0]} " unless dir.empty?
-    TkConfig_Info['TK_INCLUDE_SPEC'] = "-I#{Dir.glob(File.join(TkLib_Config['tcltk-framework'], 'Tk.framework', '*', 'Headers'), File::FNM_CASEFOLD)[0]} "
+def setup_for_macosx_framework(tclver, tkver)
+  # use framework, but no tclConfig.sh
+  unless $LDFLAGS.include?('-framework')
+    $LDFLAGS << ' -framework Tk -framework Tcl'
   end
 
-  $LDFLAGS << ' -framework Tk -framework Tcl'
+  if TkLib_Config["tcl-framework-header"]
+    TclConfig_Info['TCL_INCLUDE_SPEC'] <<
+      "-I#{TkLib_Config["tcl-framework-header"].quote} "
+  else
+    TclConfig_Info['TCL_INCLUDE_SPEC'] = ""
 
-  if TkLib_Config["tcl-framework-header"]
-    TclConfig_Info['TCL_INCLUDE_SPEC'] = 
-      "-I#{TkLib_Config["tcl-framework-header"]} "
+    tcl_base = File.join(TkLib_Config["tcltk-framework"], 'Tcl.framework')
+    if tclver
+      TclConfig_Info['TCL_INCLUDE_SPEC'] <<
+        "-I#{File.join(tcl_base, 'Versions', tclver, 'Headers').quote} "
+    end
+
+    TclConfig_Info['TCL_INCLUDE_SPEC'] << File.join(tcl_base, 'Headers')
+
+    unless tclver
+      dir = Dir.glob(File.join(tcl_base, 'Versions', '*', 'Headers'), 
+                     File::FNM_CASEFOLD).sort.reverse[0]
+      TclConfig_Info['TCL_INCLUDE_SPEC'] << "-I#{dir.quote} " if dir
+    end
   end
+
   if TkLib_Config["tk-framework-header"]
     TkConfig_Info['TK_INCLUDE_SPEC'] = 
-      "-I#{TkLib_Config["tk-framework-header"]} "
+      "-I#{TkLib_Config["tk-framework-header"].quote} "
+  else
+    TkConfig_Info['TK_INCLUDE_SPEC'] = ""
+
+    tk_base  = File.join(TkLib_Config["tcltk-framework"], 'Tk.framework')
+    if tkver
+      TkConfig_Info['TK_INCLUDE_SPEC'] <<
+        "-I#{File.join(tk_base, 'Versions', tkver, 'Headers').quote} "
+    end
+
+    TkConfig_Info['TK_INCLUDE_SPEC'] << File.join(tk_base, 'Headers')
+
+    unless tkver
+      dir = Dir.glob(File.join(tk_base, 'Versions', '*', 'Headers'), 
+                     File::FNM_CASEFOLD).sort.reverse[0]
+      TkConfig_Info['TK_INCLUDE_SPEC'] << "-I#{dir.quote} " if dir
+    end
   end
 end
 
@@ -1320,7 +1449,17 @@
 #if activeTcl = with_config("ActiveTcl")
 if activeTcl = with_config("ActiveTcl", true)
   puts("Use ActiveTcl libraries (if available).")
-  activeTcl = '/opt/ActiveTcl*/lib' unless activeTcl.kind_of? String
+  unless activeTcl.kind_of? String
+    # set default ActiveTcl path
+    if CROSS_COMPILING
+    elsif is_win32?
+      activeTcl = 'c:/Tcl*'
+    elsif is_macosx?
+      activeTcl = '/Library/Frameworks'
+    else
+      activeTcl = '/opt/ActiveTcl*'
+    end
+  end
 end
 TkLib_Config["ActiveTcl"] = activeTcl
 
@@ -1379,7 +1518,6 @@
 tk_ldir_list  = [tk_ldir,  tk_cfg_dir]
 tcl_ldir_list = [tcl_ldir, tcl_cfg_dir]
 
-
 # check tk_shlib_search_path
 check_shlib_search_path(with_config('tk-shlib-search-path'))
 
@@ -1391,7 +1529,25 @@
 # MacOS X Frameworks?
 if TkLib_Config["tcltk-framework"]
   puts("Use MacOS X Frameworks.")
-  setup_for_macosx_framework
+  if tcl_cfg_dir
+    $INCFLAGS << ' ' << TclConfig_Info['TCL_INCLUDE_SPEC']
+    $LDFLAGS  << ' ' << TclConfig_Info['TCL_LIBS']
+    if stubs
+      $LDFLAGS << ' ' << TclConfig_Info['TCL_STUB_LIB_SPEC']
+    else
+      $LDFLAGS << ' ' << TclConfig_Info['TCL_LIB_SPEC']
+    end
+  end
+  if tk_cfg_dir
+    $INCFLAGS << ' ' << TkConfig_Info['TK_INCLUDE_SPEC']
+    $LDFLAGS  << ' ' << TkConfig_Info['TK_LIBS']
+    if stubs
+      $LDFLAGS << ' ' << TkConfig_Info['TK_STUB_LIB_SPEC']
+    else
+      $LDFLAGS << ' ' << TkConfig_Info['TK_LIB_SPEC']
+    end
+  end
+  setup_for_macosx_framework(tclver, tkver) if tcl_cfg_dir && tk_cfg_dir
 end
 
 # name of  Tcl/Tk libraries

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]