From 46ae2d907e592e6f0cd14f309cf13181853bfb38 Mon Sep 17 00:00:00 2001 From: shyouhei Date: Sun, 26 Jun 2011 08:47:36 +0000 Subject: * ext/tk/extconf.rb: copy from trunk, as requested by Hidetoshi NAGAI. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8_7@32233 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 4 + ext/tk/config_list.in | 41 + ext/tk/extconf.rb | 2001 ++++++++++++++++++++++++++++++++++++++++++++----- ext/tk/old-extconf.rb | 440 +++++++++++ version.h | 2 +- 5 files changed, 2295 insertions(+), 193 deletions(-) create mode 100644 ext/tk/config_list.in create mode 100644 ext/tk/old-extconf.rb diff --git a/ChangeLog b/ChangeLog index a8aefe3637..d9137c8eda 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +Sun Jun 26 17:46:43 2011 URABE Shyouhei + + * ext/tk/extconf.rb: copy from trunk, as requested by Hidetoshi NAGAI. + Thu Jun 23 18:38:43 2011 Hiroshi Nakamura backported r26281 from ruby_1_8 diff --git a/ext/tk/config_list.in b/ext/tk/config_list.in new file mode 100644 index 0000000000..143a7b5df6 --- /dev/null +++ b/ext/tk/config_list.in @@ -0,0 +1,41 @@ +############################################## +# configure options for Ruby/Tk +# release date: 2011-06-05 +############################################## +with tk-old-extconf +with ActiveTcl +with tk-shlib-search-path +enable tcltk-stubs +with tcltkversion +enable tcl-h-ver-check +enable tk-h-ver-check +with tcl-build-dir +with tk-build-dir +with tcl-config +with tk-config +with tclConfig-dir +with tkConfig-dir +with tclConfig-file +with tkConfig-file +with tcllib +with tklib +with tcl-dir +with tk-dir +with tcl-include +with tk-include +with tcl-lib +with tk-lib +enable mac-tcltk-framework +enable tcltk-framework +with tcltk-framework +with tcl-framework-dir +with tk-framework-dir +with tcl-framework-header +with tk-framework-header +with X11 +with X11-dir +with X11-include +with X11-lib +enable pthread +enable tcl-thread +enable space-on-tk-libpath diff --git a/ext/tk/extconf.rb b/ext/tk/extconf.rb index 4807ea7b40..1f4f37a215 100644 --- a/ext/tk/extconf.rb +++ b/ext/tk/extconf.rb @@ -1,81 +1,137 @@ +############################################################## # extconf.rb for tcltklib - +# release date: 2010-07-30 +############################################################## require 'mkmf' -#is_win32 = (/mswin32|mingw|cygwin|bccwin32/ =~ RUBY_PLATFORM) -is_win32 = (/mswin|mingw|cygwin|bccwin|wince/ =~ RUBY_PLATFORM) -#is_macosx = (/darwin/ =~ RUBY_PLATFORM) +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.0] # to shorten search steps -def find_framework(tcl_hdr, tk_hdr) - if framework_dir = with_config("tcltk-framework") - paths = [framework_dir] - else - unless tcl_hdr || tk_hdr || - enable_config("tcltk-framework", false) || - enable_config("mac-tcltk-framework", false) - return false - end - paths = ["/Library/Frameworks", "/System/Library/Frameworks"] - end +TkLib_Config['major_nums'] = '87' - checking_for('Tcl/Tk Framework') { - paths.find{|dir| - dir.strip! - dir.chomp!('/') - (tcl_hdr || FileTest.directory?(dir + "/Tcl.framework/") ) && - (tk_hdr || FileTest.directory?(dir + "/Tk.framework/") ) - } - } -end -tcl_framework_header = with_config("tcl-framework-header") -tk_framework_header = with_config("tk-framework-header") +############################################################## +# use old extconf.rb ? +############################################################## +if with_config('tk-old-extconf') + require File.join(File.dirname(__FILE__), 'old-extconf.rb') + exit +end -tcltk_framework = find_framework(tcl_framework_header, tk_framework_header) -unless is_win32 - have_library("nsl", "t_open") - have_library("socket", "socket") - have_library("dl", "dlopen") - have_library("m", "log") +############################################################## +# check configs +############################################################## +($cleanfiles ||= "") << 'config_list' +config_list_file = 'config_list' +config_list_file_source = File.join(File.dirname(__FILE__),'config_list.in') +if !File.exist?(config_list_file) || + File.ctime(config_list_file_source) > File.ctime(config_list_file) + old_config_list_file = config_list_file_source +else + old_config_list_file = config_list_file end -tk_idir, tk_ldir = dir_config("tk") -tcl_idir, tcl_ldir = dir_config("tcl") -x11_idir, x11_ldir = dir_config("X11") +current_configs = {'with'=>{}, 'enable'=>{}} -tk_ldir2 = with_config("tk-lib") -tcl_ldir2 = with_config("tcl-lib") -x11_ldir2 = with_config("X11-lib") +# setup keys by config_list.in +IO.foreach(config_list_file_source){|line| + line.chomp! + line.lstrip! + next if line.empty? || line =~ /^\#/ # + mode, key, value = line.split(/\s+/, 3) + value ||= "" + current_configs[mode][key] = value rescue nil +} -tk_ldir_list = [tk_ldir2, tk_ldir] -tcl_ldir_list = [tcl_ldir2, tcl_ldir] +# define current value of keys +IO.foreach(old_config_list_file){|line| + line.chomp! + line.lstrip! + next if line.empty? || line =~ /^\#/ # + mode, key, value = line.split(/\s+/, 3) + value ||= "" + if current_configs[mode] && current_configs[mode].has_key?(key) + current_configs[mode][key] = value + end +} -tklib = with_config("tklib") -tcllib = with_config("tcllib") -stubs = enable_config("tcltk_stubs") || with_config("tcltk_stubs") +update_flag = false +current_configs['with'].each_key{|key| + if (value = with_config(key).to_s) != current_configs['with'][key] + update_flag = true + current_configs['with'][key] = value + end +} +current_configs['enable'].each_key{|key| + if (value = enable_config(key).to_s) != current_configs['enable'][key] + update_flag = true + current_configs['enable'][key] = value + end +} -tcltk_version = with_config("tcltkversion") +# update current_configs +if update_flag || !File.exist?(config_list_file) + open(config_list_file, 'w'){|fobj| + fobj.print("# values of current configure options (generated by extconf.rb)\n"); + ['with', 'enable'].each{|mode| + current_configs[mode].each_key{|key| + fobj.print("#{mode} #{key} #{current_configs[mode][key]}\n") + } + } + } +end -use_X = with_config("X11", (! is_win32)) +if update_flag + puts "Configure options for Ruby/Tk may be updated." + puts "So, delete files which depend on old configs." + File.delete(*Dir.glob("*.#{CONFIG['DLEXT']}", File::FNM_CASEFOLD)) + File.delete(*Dir.glob("*.#{$OBJEXT}", File::FNM_CASEFOLD)) + File.delete('Makefile') rescue nil -def check_tcltk_version(version) - return [nil, nil] unless version +else + makefile = 'Makefile' + if File.exist?(makefile) && + File.ctime(config_list_file) > File.ctime(makefile) + # no need to update Makefile + exit + end +end + + +############################################################## +# fuctions +############################################################## +def is_win32? + /mswin|mingw|cygwin|bccwin/ =~ RUBY_PLATFORM +end - version = version.strip +def is_macosx? + /darwin/ =~ RUBY_PLATFORM +end + +def maybe_64bit? + /64|universal/ =~ RUBY_PLATFORM +end - tclver = version.dup - tkver = version.dup +def check_tcltk_version(version) + return [nil, nil] unless version.kind_of? String - major = dot = minor = dot = plvl = ext = nil + tclver, tkver = version.split(',') + tclver = tclver.strip + return [tclver, tkver.strip] if tkver - if version =~ /^(\d)(\.?)(\d)(\.?)(\d*)(.*)$/ - major = $1; minor_dot = $2; minor = $3; plvl_dot = $4; plvl = $5; ext = $6 + dot = major = minor_dot = minor = plvl_dot = plvl = ext = nil + if tclver =~ /^(\d)(\.?)(\d)(\.?)(\d*)(.*)$/ + major = $1; minor_dot = $2; minor = $3; plvl_dot = $4; plvl = $5; ext = $6 dot = ! minor_dot.empty? if plvl_dot.empty? && ! plvl.empty? minor << plvl end - elsif version =~ /^(\d)(\.?)(\d?)(.*)$/ + elsif tclver =~ /^(\d)(\.?)(\d?)(.*)$/ major = $1; minor_dot = $2; minor = $3; ext = $4 dot = ! minor_dot.empty? else # unknown -> believe user @@ -88,19 +144,891 @@ def check_tcltk_version(version) tkver = "4" + ((dot)? ".": "") + ((minor.empty)? "": "2") + ext elsif major == "4" # Tk4.2 ( not support Tkversion < 4.2 ) # Tcl7.6 + tkver = tclver tclver = "7" + ((dot)? ".": "") + ((minor.empty)? "": "6") + ext end + tkver = tclver unless tkver + [tclver, tkver] end -def find_tcl(tcllib, stubs, version, *opt_paths) - default_paths = ["/usr/local/lib", "/usr/pkg/lib", "/usr/lib"] - default_paths << "/Tcl/lib" # default for ActiveTcl +def get_shlib_versions(major = 8, minor_max = 9, minor_min = 0, ext = "") + if tclcfg = TkLib_Config["tclConfig_info"] + major = tclcfg['TCL_MAJOR_VERSION'].to_i + minor_min = tclcfg['TCL_MINOR_VERSION'].to_i - if (paths = opt_paths.compact).empty? - paths = default_paths + elsif TkLib_Config["tcltkversion"] + tclver, tkver = TkLib_Config["tcltkversion"] + if tclver =~ /8\.?(\d)(.*)/ + minor_min = $1.to_i + ext = $2 + else + # unsupported version + return [""] + end + end + + # if disable-stubs, version is fixed. + minor_max = minor_min unless TkLib_Config["tcltk-stubs"] + + vers = [] + minor_max.downto(minor_min){|minor| + vers << "#{major}.#{minor}#{ext}" unless ext.empty? + vers << "#{major}.#{minor}" + } + + vers << "" +end + +def get_shlib_path_head + path_head = [] + path_dirs = [] + + if TkLib_Config["ActiveTcl"].kind_of?(String) # glob path + # 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 + elsif is_win32? + if TkLib_Config["ActiveTcl"] + path_head.concat ["c:/ActiveTcl", "c:/Program Files/ActiveTcl", + "c:/Program Files (x86)/ActiveTcl"] + end + path_head.concat [ + "c:/Tcl", "c:/Program Files/Tcl", "c:/Program Files (x86)/Tcl", + "/Tcl", "/Program Files/Tcl", "/Program Files (x86)/Tcl" + ] + path_head.uniq! + #path_head.each{|dir| path_dirs << dir.dup if File.directory? dir} + path_head.each{|dir| path_dirs << File.expand_path(dir) if File.directory? dir} + + # for MinGW + ["/usr/local/lib64", "/usr/lib64", "/usr/local/lib", "/usr/lib"].each{|dir| + #path_dirs << dir if File.directory? dir + path_dirs << File.expand_path(dir) if File.directory? dir + } + path_dirs |= ENV['LIBRARY_PATH'].split(';').find_all{|dir| File.directory? dir}.map{|dir| File.expand_path(dir)} if ENV['LIBRARY_PATH'] + path_dirs |= ENV['PATH'].split(';').find_all{|dir| File.directory? dir}.map{|dir| File.expand_path(dir)} if ENV['PATH'] + + else + [ + '/opt', '/pkg', '/share', + '/usr/local/opt', '/usr/local/pkg', '/usr/local/share', '/usr/local', + '/usr/opt', '/usr/pkg', '/usr/share', '/usr/contrib', '/usr' + ].each{|dir| + next unless File.directory?(dir) + + path_dirs << "#{dir}/lib64" if maybe_64bit? + path_dirs << "#{dir}/lib" + path_dirs << "#{dir}" unless Dir.glob("#{dir}/lib*.*", File::FNM_CASEFOLD).empty? + + dirnames = [] + if TkLib_Config["ActiveTcl"] + dirnames.concat ["ActiveTcl"] + end + dirnames.concat ["TclTk","Tcl_Tk","Tcl-Tk"] + + dirnames.each{|name| + path_dirs << "#{dir}/#{name}" if File.directory?("#{dir}/#{name}") + path_head << "#{dir}/#{name}" unless Dir.glob("#{dir}/#{name}[-89_]*", File::FNM_CASEFOLD).empty? + } + } + end + + unless TkLib_Config["space-on-tk-libpath"] + path_head.delete_if{|path| path =~ / /} + path_dirs.delete_if{|path| path =~ / /} + end + + [path_head, path_dirs] +end + +def find_macosx_framework + use_framework = is_macosx? && TkLib_Config["ActiveTcl"] + + use_framework ||= (tcl_hdr = with_config("tcl-framework-header")) + use_framework ||= (tk_hdr = with_config("tk-framework-header")) + tcl_hdr = nil unless tcl_hdr.kind_of? String + tk_hdr = nil unless tk_hdr.kind_of? String + TkLib_Config["tcl-framework-header"] = tcl_hdr + TkLib_Config["tk-framework-header"] = tk_hdr + + use_framework ||= (tcl_dir = with_config("tcl-framework-dir")) + tcl_dir = nil unless tcl_dir.kind_of? String + if !tcl_dir && tcl_hdr + # e.g. /Library/Frameworks/Tcl.framework/Headers + # ==> /Library/Frameworks/Tcl.framework + tcl_dir = File.dirname(tcl_hdr.strip.chomp('/')) + end + TkLib_Config["tcl-framework-dir"] = tcl_dir + + use_framework ||= (tk_dir = with_config("tk-framework-dir")) + tk_dir = nil unless tk_dir.kind_of? String + if !tk_dir && tk_hdr + # e.g. /Library/Frameworks/Tk.framework/Headers + # ==> /Library/Frameworks/Tk.framework + tk_dir = File.dirname(tk_hdr.strip.chomp('/')) + end + TkLib_Config["tk-framework-dir"] = tk_dir + + if tcl_dir && !tk_dir + tk_dir = File.join(File.dirname(tcl_dir), 'Tk.framework') + TkLib_Config["tk-framework-dir"] = tk_dir + elsif !tcl_dir && tk_dir + tcl_dir = File.join(File.dirname(tk_dir), 'Tcl.framework') + TkLib_Config["tcl-framework-dir"] = tcl_dir + end + if tcl_dir && tk_dir + TkLib_Config["tcltk-framework"] = File.dirname(tcl_dir) unless TkLib_Config["tcltk-framework"] + return [tcl_dir, tk_dir] + end + + # framework is disabled? + if with_config("tcltk-framework") == false || + enable_config("tcltk-framework") == false + return false + end + + use_framework ||= (framework_dir = with_config("tcltk-framework")) + if framework_dir.kind_of? String + TkLib_Config["tcltk-framework"] = framework_dir.strip.chomp('/') + return [File.join(TkLib_Config["tcltk-framework"], 'Tcl.framework'), + File.join(TkLib_Config["tcltk-framework"], 'Tk.framework')] + end + + unless enable_config("tcltk-framework", use_framework) || + enable_config("mac-tcltk-framework", use_framework) + TkLib_Config["tcltk-framework"] = false + return false + end + + paths = [ + #"~/Library/Frameworks", + "/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")) + next unless File.directory?(tkdir = File.join(dir, "Tk.framework")) + TkLib_Config["tcltk-framework"] = dir + return [tcldir, tkdir] + } + + nil +end + +def collect_tcltk_defs(tcl_defs_str, tk_defs_str) + conflicts = [ + 'PACKAGE_NAME', 'PACKAGE_TARNAME', 'PACKAGE_VERSION', + 'PACKAGE_STRING', 'PACKAGE_BUGREPORT' + ] + + begin + # Ruby 1.9.x or later + arch_config_h = RbConfig.expand($arch_hdrdir + "/ruby/config.h") + if File.exist?(arch_config_h) + keys = [] + IO.foreach(arch_config_h){|line| + if line =~ /^#define +([^ ]+)/ + keys << $1 + end + } + conflicts = keys + end + rescue + # ignore, use default + end + + if tcl_defs_str + tcl_defs = tcl_defs_str.split(/ ?-D/).map{|s| + s =~ /^([^=]+)(.*)$/ + [$1, $2] + } + else + tcl_defs = [] + end + + if tk_defs_str + tk_defs = tk_defs_str.split(/ ?-D/).map{|s| + s =~ /^([^=]+)(.*)$/ + [$1, $2] + } + else + tk_defs = [] + end + + defs = tcl_defs | tk_defs + + defs.delete_if{|name,value| + conflicts.include?(name) || + ( (vtcl = tcl_defs.assoc(name)) && (vtk = tk_defs.assoc(name)) && + vtcl != vtk ) + } + + defs.map{|ary| s = ary.join(''); (s.strip.empty?)? "": "-D" << s} +end + +def parse_tclConfig(file) + # check tclConfig.sh/tkConfig.sh + tbl = Hash.new{|h,k| h[k] = ""} + return tbl unless file + IO.foreach(file){|line| + line.strip! + next if line !~ /^([^\#=][^=]*)=(['"]|)(.*)\2$/ + key, val = $1, $3 + tbl[key] = val.gsub(/\$\{([^}]+)\}/){|s| + subst = $1 + (tbl[subst])? tbl[subst]: s + } rescue nil + } + tbl +end + +def get_libpath(lib_flag, lib_spec) + # get libpath from {TCL,Tk}_LIB_FLAG and {TCL,Tk}_LIB_SPEC + lib_spec.gsub(/(#{lib_flag}|-L)/, "").strip +end + +def get_tclConfig_dirs + config_dir = [] + + if CROSS_COMPILING + elsif is_win32? + if TkLib_Config["ActiveTcl"] + dirs = [] + if TkLib_Config["ActiveTcl"].kind_of?(String) + dirs << File.join(TkLib_Config["ActiveTcl"], 'lib') + end + dirs.concat [ + "c:/ActiveTcl*/lib", "c:/Tcl*/lib", + "c:/Program Files*/ActiveTcl*/lib", "c:/Program Files*/Tcl*/lib", + "/ActiveTcl*/lib", "/Tcl*/lib", + "/Program Files*/ActiveTcl*/lib", "/Program Files*/Tcl*/lib" + ] + else + dirs = [ + "c:/Tcl*/lib", "c:/Program Files*/Tcl*/lib", + "/Tcl*/lib", "/Program Files*/Tcl*/lib" + ] + end + dirs = dirs.collect{|d| Dir.glob(d, File::FNM_CASEFOLD)}.flatten.uniq + + dirs |= ENV['LIBRARY_PATH'].split(';') if ENV['LIBRARY_PATH'] + dirs |= ENV['PATH'].split(';') if ENV['PATH'] + + exeext = RbConfig::CONFIG['EXEEXT'] + ENV['PATH'].split(File::PATH_SEPARATOR).each{|dir| + dir.tr!(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR + next if Dir.glob(File.join(dir, "{tclsh,wish}*#{exeext}"), File::FNM_CASEFOLD).empty? + dirs << File.expand_path(File.join(dir, '..', 'lib')) + dirs << dir + # dirs << File.expand_path(File.join(dir, '..')) + } + + unless TkLib_Config["space-on-tk-libpath"] + dirs.delete_if{|path| path =~ / /} + end + + config_dir.concat(dirs.zip(dirs)) + + else + if framework = find_macosx_framework() + config_dir.unshift(framework) + end + + if activeTcl = TkLib_Config['ActiveTcl'] + # check latest version at first + 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 << RbConfig::CONFIG['libdir'] + + ((maybe_64bit?)? ['lib64', 'lib']: ['lib']).each{|dir| + config_dir.concat [ + File.join(RbConfig::CONFIG['exec_prefix'], dir), + File.join(RbConfig::CONFIG['prefix'], dir), + "/usr/local/opt/#{dir}", "/usr/local/pkg/#{dir}", + "/usr/local/share/#{dir}", "/usr/local/#{dir}", + "/usr/opt/#{dir}", "/usr/pkg/#{dir}", "/usr/share/#{dir}", + "/usr/contrib/#{dir}", "/usr/#{dir}" + ] + } + + config_dir.concat [ + '/opt', '/pkg', '/share', + '/usr/local/opt', '/usr/local/pkg', '/usr/local/share', '/usr/local', + '/usr/opt', '/usr/pkg', '/usr/share', '/usr/contrib', '/usr' + ].map{|dir| + Dir.glob(dir + "/{tcltk,tcl,tk}[#{TkLib_Config['major_nums']}*/lib", + File::FNM_CASEFOLD) + Dir.glob(dir + "/{tcltk,tcl,tk}[#{TkLib_Config['major_nums']}*", + File::FNM_CASEFOLD) + Dir.glob(dir + '/{tcltk,tcl,tk}/lib', File::FNM_CASEFOLD) + Dir.glob(dir + '/{tcltk,tcl,tk}', File::FNM_CASEFOLD) + }.flatten! + + exeext = RbConfig::CONFIG['EXEEXT'] + ENV['PATH'].split(File::PATH_SEPARATOR).each{|dir| + dir.tr!(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR + next if Dir.glob(File.join(dir, "{tclsh,wish}*#{exeext}"), File::FNM_CASEFOLD).empty? + config_dir << File.expand_path(File.join(dir, '..', 'lib')) + } + + # for MacOS X + 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" + ] + paths.reverse! unless TkLib_Config["ActiveTcl"] + + paths.each{|frmwk| + base = File.expand_path(frmwk) + 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 get_ext_list() + exts = [CONFIG['DLEXT']] + exts.concat %w(dll lib) if is_win32? + exts.concat %w(bundle dylib) if is_macosx? || /nextstep|openstep|rhapsody/ =~ RUBY_PLATFORM + + if enable_config("shared") == false + [CONFIG['LIBEXT'], "a"].concat exts + else + exts.concat [CONFIG['LIBEXT'], "a"] + end + + if is_win32? + exts.map!{|ext| [ext.downcase, ext.upcase]}.flatten! + end + + exts +end + +def libcheck_for_tclConfig(tcldir, tkdir, 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 + + incflags = ($INCFLAGS ||= "").dup + libpath = ($LIBPATH ||= []).dup + libs_param = ($libs ||= "").dup + tcllibs = nil + mkmf_param = nil + + tclver, tkver = TkLib_Config["tcltkversion"] + exts = "(" + get_ext_list.join('|') + ")" + + if tclver + tcl_glob = "*tcl#{stub}#{tclver}.*" + tcl_regexp = /^.*(tcl#{stub}#{tclver}.*)\.(#{exts}).*$/ + elsif tclconf + tcl_glob = "*tcl#{stub}#{tclconf['TCL_MAJOR_VERSION']}{.,}#{tclconf['TCL_MINOR_VERSION']}*.*" + tcl_regexp = /^.*(tcl#{stub}#{tclconf['TCL_MAJOR_VERSION']}(?:\.|)#{tclconf['TCL_MINOR_VERSION']}.*)\.(#{exts}).*$/ + end + if tkver + tk_glob = "*tk#{stub}#{tkver}.*" + tk_regexp = /^.*(tk#{stub}#{tkver}.*)\.(#{exts}).*$/ + elsif tkconf + tk_glob = "*tk#{stub}#{tkconf['TK_MAJOR_VERSION']}{.,}#{tkconf['TK_MINOR_VERSION']}*.*" + tk_regexp = /^.*(tk#{stub}#{tkconf['TK_MAJOR_VERSION']}(?:\.|)#{tkconf['TK_MINOR_VERSION']}.*)\.#{exts}.*$/ + end + + tcllib_ok ||= !tclconf || Dir.glob(File.join(tcldir, tcl_glob), File::FNM_CASEFOLD).find{|file| + if file =~ tcl_regexp + libname = $1 + ext = $2.downcase + begin + $INCFLAGS = incflags.dup << " " << tclconf["TCL_INCLUDE_SPEC"] + #puts "check #{file} #{$1} #{tclfunc} #{tcldir}" + #find_library($1, tclfunc, tcldir) + if (tclconf && tclconf["TCL_SHARED_BUILD"] == "0") || + (ext != CONFIG['DLEXT'] && ext == CONFIG['LIBEXT']) || ext == "a" + # static link + tcllibs = $libs + " -DSTATIC_BUILD " + file.quote + + # FIX ME: avoid pathname trouble (fail to find) on MinGW. + # e.g. TCL_INCLUDE_SPEC describes "-I/usr/local/include", + # but compiler can find "-IC:/msys/1.0/local/include" only. + $INCFLAGS << " -I" << File.join(File.dirname(File.dirname(file)),"include") if is_win32? + else + tcllibs = append_library($libs, libname) + tcllibs = "-L#{tcldir.quote} -Wl,-R#{tcldir.quote} " + tcllibs + + # FIX ME: avoid pathname trouble (fail to find) on MinGW. + $INCFLAGS << " -I" << File.join(File.dirname(tcldir),"include") if is_win32? + end + + $LIBPATH = libpath | [tcldir] + try_func(tclfunc, tcllibs, ["tcl.h"]) || + ( try_func(tclfunc, tcllibs << " " << tclconf['TCL_LIBS'], ["tcl.h"]) if tclconf['TCL_LIBS'] ) + + ensure + mkmf_param = { + 'PATH' => file, + 'LIBNAME' => libname, + 'libs' => tcllibs.dup, + 'INCFLAGS' => $INCFLAGS.dup, + 'LIBPATH' => $LIBPATH.dup, + } + $LIBPATH = libpath.dup + $libs = libs_param.dup + end + end + } + tclconf['MKMF_PARAMS'] = mkmf_param if tclconf && tcllib_ok + + tklib_ok ||= !tkconf || Dir.glob(File.join(tkdir, tk_glob), File::FNM_CASEFOLD).find{|file| + if file =~ tk_regexp + libname = $1 + ext = $2.downcase + begin + #puts "check #{file} #{$1} #{tkfunc} #{tkdir}" + # find_library($1, tkfunc, tkdir) + if (tkconf && tkconf["TCL_SHARED_BUILD"] == "0") || + (ext != CONFIG['DLEXT'] && ext == CONFIG['LIBEXT']) || ext == "a" + # static link + tklibs = " -DSTATIC_BUILD " + file.quote + + # FIX ME: avoid pathname trouble (fail to find) on MinGW. + $INCFLAGS << " -I" << File.join(File.dirname(File.dirname(file)),"include") if is_win32? + else + tklibs = append_library("", libname) + #tklibs = append_library("", $1) + tklibs = "-L#{tkdir.quote} -Wl,-R#{tkdir.quote} " + tklibs + + # FIX ME: avoid pathname trouble (fail to find) on MinGW. + $INCFLAGS << " -I" << File.join(File.dirname(tcldir),"include") if is_win32? + end + + tklibs << " " << tcllibs if tcllibs + tmp_tklibs = tklibs.dup + $LIBPATH = libpath | [tkdir] + try_func(tkfunc, tklibs, ["tcl.h", "tk.h"]) || + ( try_func(tkfunc, tklibs << " " << tkconf['TK_LIBS'], ["tcl.h", "tk.h"]) if tkconf['TK_LIBS'] ) || + ( try_func(tkfunc, (tklibs = tmp_tklibs.dup) << " " << tkconf['TK_XLIBSW'], ["tcl.h", "tk.h"]) if tkconf['TK_XLIBSW'] ) || + ( try_func(tkfunc, tklibs << " " << tkconf['TK_LIBS'], ["tcl.h", "tk.h"]) if tkconf['TK_LIBS'] ) + + ensure + mkmf_param = { + 'PATH' => file, + 'LIBNAME' => libname, + 'libs' => tklibs.dup, + 'INCFLAGS' => $INCFLAGS.dup, + 'LIBPATH' => $LIBPATH.dup, + } + $LIBPATH = libpath.dup + $libs = libs_param.dup + end + end + } + + $INCFLAGS = incflags.dup + tkconf['MKMF_PARAMS'] = mkmf_param if tkconf && tklib_ok + + [tcllib_ok, tklib_ok] +end + +def search_tclConfig(*paths) # libdir list or [tcl-libdir|file, tk-libdir|file] + TkLib_Config["tclConfig_paths"] = [] + + paths.compact! + if paths.empty? + config_dir = get_tclConfig_dirs + elsif paths.length == 1 && !paths[0][0] && !paths[0][1] + config_dir = get_tclConfig_dirs.map{|dir| + if dir.kind_of? Array + [ (paths[0][0] == false)? nil: dir[0], + (paths[0][1] == false)? nil: dir[1] ] + else + [ (paths[0][0] == false)? nil: dir, + (paths[0][1] == false)? nil: dir ] + end + } + else + # fixed tclConfig + config_dir = [] + paths.each{|path| + if path.kind_of?(Array) + config_dir << path + else + dirs = Dir.glob(path, File::FNM_CASEFOLD) + config_dir.concat(dirs.zip(dirs)) + end + } + end + + tclver, tkver = TkLib_Config['tcltkversion'] + if tclver && tclver =~ /^\D*(\d)\.?(\d)?/ # ignore PATCH_LEVEL + tclver_major = $1 + tclver_minor = $2 + else + tclver_major = nil + tclver_minor = nil + end + if tkver && tkver =~ /^\D*(\d)\.?(\d)?/ # ignore PATCH_LEVEL + tkver_major = $1 + tkver_minor = $2 + else + tkver_major = nil + tkver_minor = nil + end + + conf = nil + + config_dir.uniq! + config_dir.map{|dir| + if dir.kind_of? Array + [ (dir[0])? dir[0].strip.chomp('/'): nil, + (dir[1])? dir[1].strip.chomp('/'): nil ] + else + dir.strip.chomp('/') + end + }.each{|dir| + print(".") # progress + # print("check #{dir} ==>"); + if dir.kind_of? Array + tcldir, tkdir = dir + else + tcldir = tkdir = dir + end + + tails = ['Config-shared.sh', 'config-shared.sh', 'Config.sh', 'config.sh'] + + if tcldir + if File.file?(tcldir) + tclcfg_files = [tcldir] * tails.length + else + tclcfg_files = tails.map{|f| File.join(tcldir, 'tcl' << f)} + end + else + tclcfg_files = [nil] * tails.length + end + + if tkdir + if File.file?(tkdir) + tkcfg_files = [tkdir] * tails.length + else + tkcfg_files = tails.map{|f| File.join(tkdir, 'tk' << f)} + end + else + tkcfg_files = [nil] * tails.length + end + + tclcfg_files.zip(tkcfg_files).map{|tclpath, tkpath| + [ (tclpath && File.exist?(tclpath))? File.expand_path(tclpath): tclpath, + (tkpath && File.exist?(tkpath))? File.expand_path(tkpath): tkpath ] + }.uniq.each{|tclpath, tkpath| + next if tclpath && !File.exist?(tclpath) + next if tkpath && !File.exist?(tkpath) + + # parse tclConfig.sh/tkConfig.sh + tclconf = (tclpath)? parse_tclConfig(tclpath): nil + next if tclconf && tclver && ((tclver_major && tclver_major != tclconf['TCL_MAJOR_VERSION']) || (tclver_minor && tclver_minor != tclconf['TCL_MINOR_VERSION'])) + + tkconf = (tkpath)? parse_tclConfig(tkpath): nil + next if tkconf && tkver && ((tkver_major && tkver_major != tkconf['TK_MAJOR_VERSION']) || (tkver_minor && tkver_minor != tkconf['TK_MINOR_VERSION'])) + + # nativethread check + if !TkLib_Config["ruby_with_thread"] + if tclconf + if tclconf['TCL_THREADS'] == '1' + puts "\nWARNING: found #{tclpath.inspect}, but it WITH nativethread-support under ruby WITHOUT nativethread-support. So, ignore it." + TkLib_Config["tcl-NG-path"] << File.dirname(tclpath) + next + end + else + puts "\nWARNING: When not refer tclConfig.sh, cannot check native-thread support on Tcl/Tk libraries. Ruby, which is used now, does NOT support native-thread. So, if Tcl/Tk libraries support native-thread, it will NOT work properly." + end + end + + # find tclConfig.sh & tkConfig.sh + conf = [tclconf, tkconf] unless conf + + # check Tcl library + if is_macosx? && TkLib_Config["tcltk-framework"] + # if use framework, not check (believe it is installed properly) + tcllib_ok = tklib_ok = true + else + tcllib_ok, tklib_ok = + libcheck_for_tclConfig((tclpath)? File.dirname(tclpath): nil, + (tkpath)? File.dirname(tkpath): nil, + tclconf, tkconf) + end + + unless tcllib_ok && tklib_ok + unless tcllib_ok + puts "\nWARNING: found #{tclpath.inspect}, but cannot find valid Tcl library for the tclConfig.sh. So, ignore it." + TkLib_Config["tcl-NG-path"] << File.dirname(tclpath) + end + unless tklib_ok + puts "\nWARNING: found #{tkpath.inspect}, but cannot find valid Tk library for the tkConfig.sh. So, ignore it." + TkLib_Config["tk-NG-path"] << File.dirname(tkpath) + end + next + end + + #return [tclpath, tkpath] + # print(" #{[tclpath, tkpath].inspect}"); + TkLib_Config["tclConfig_paths"] << [tclpath, tkpath] + } + + # 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 + # find tclConfig.sh and tkConfig.sh + TkLib_Config["tclConfig_info"], TkLib_Config["tkConfig_info"] = conf + TkLib_Config["tclConfig_paths"][0] + end +end + +def get_tclConfig(tclConfig_file, tkConfig_file, tclConfig_dir, tkConfig_dir) + use_tclConfig = tclConfig_file != false && tclConfig_dir != false + use_tkConfig = tkConfig_file != false && tkConfig_dir != false + + unless use_tclConfig || use_tkConfig + puts("Don't use [tclConfig.sh, tkConfig.sh]") + return [nil, nil] + end + + tclConfig_file = nil unless tclConfig_file.kind_of? String + tkConfig_file = nil unless tkConfig_file.kind_of? String + tclConfig_dir = nil unless tclConfig_dir.kind_of? String + tkConfig_dir = nil unless tkConfig_dir.kind_of? String + + if use_tclConfig && !tclConfig_dir + if tclConfig_file + tclConfig_dir = File.dirname(tclConfig_file) + elsif tkConfig_dir + tclConfig_dir = tkConfig_dir + end + end + if use_tkConfig && !tkConfig_dir + if tkConfig_file + tkConfig_dir = File.dirname(tkConfig_file) + elsif tclConfig_dir + tkConfig_dir = tclConfig_dir + end end + tkConfig_dir ||= tclConfig_dir + + if use_tclConfig + TkLib_Config["tclConfig-file"] = tclConfig_file + TkLib_Config["tclConfig-dir"] = tclConfig_dir + else + tclConfig_file = false + tclConfig_dir = false + end + if use_tkConfig + TkLib_Config["tkConfig-file"] = tkConfig_file + TkLib_Config["tkConfig-dir"] = tkConfig_dir + else + tkConfig_file = false + tkConfig_dir = false + end + + print ("Don't use tclConfig.sh (specified by configure option).\n") unless use_tclConfig + print ("Don't use tkConfig.sh (specified by configure option).\n") unless use_tkConfig + print("Search ") + print("tclConfig.sh", (tclConfig_dir)? " (in #{tclConfig_dir})": "") if use_tclConfig + print((use_tclConfig)? " and ": "", "tkConfig.sh", (tkConfig_dir)? " (in #{tkConfig_dir})": "") if use_tkConfig + print(".") + + if tclConfig_dir || tkConfig_dir || !use_tclConfig || !use_tkConfig + tclConfig, tkConfig = + search_tclConfig([ ((tclConfig_file)? tclConfig_file: tclConfig_dir), + ((tkConfig_file)? tkConfig_file: tkConfig_dir) ]) + else + tclConfig, tkConfig = search_tclConfig() + end + print("\n") + # TclConfig_Info = TkLib_Config["tclConfig_info"] + # TkConfig_Info = TkLib_Config["tkConfig_info"] + + if tclConfig || tkConfig + dirs = TkLib_Config["tclConfig_paths"].map{|tclpath, tkpath| + [ (tclpath)? File.dirname(tclpath): nil, + (tkpath)? File.dirname(tkpath): nil ] + } + dirs |= dirs + puts("Valid [tclConfig.sh, tkConfig.sh] are found in #{dirs.inspect}") + puts("Use [tclConfig.sh, tkConfig.sh] == #{[tclConfig, tkConfig].inspect}") + $LIBPATH ||= [] + $LIBPATH |= [File.dirname(tclConfig)] if tclConfig + $LIBPATH |= [File.dirname(tkConfig)] if tkConfig + #TkLib_Config["tclConfig_paths"].each{|tclcfg, tkcfg| + # $LIBPATH |= [File.dirname(tclcfg)] | [File.dirname(tkcfg)] + #} + else + puts("Fail to find [tclConfig.sh, tkConfig.sh]") + end + + [tclConfig, tkConfig] +end + +def check_tcl_NG_path(path_list) + path_list.find_all{|path| not TkLib_Config["tcl-NG-path"].include?(path) } +end + +def check_tk_NG_path(path_list) + path_list.find_all{|path| not TkLib_Config["tk-NG-path"].include?(path) } +end + +def check_NG_path(path_list) + path_list.find_all{|path| + not (TkLib_Config["tcl-NG-path"].include?(path) && + TkLib_Config["tk-NG-path"].include?(path)) + } +end + +def check_shlib_search_path(paths) + if !paths || paths.empty? + path_list = [] + + #if TkLib_Config["ActiveTcl"] + # path_list.concat Dir.glob(TkLib_Config["ActiveTcl"], File::FNM_CASEFOLD).sort.reverse + #end + if TkLib_Config["ActiveTcl"].kind_of?(String) # glob path + path_list.concat Dir.glob(TkLib_Config["ActiveTcl"], File::FNM_CASEFOLD).sort.reverse + end + + vers = get_shlib_versions + path_head, path_dirs = get_shlib_path_head + + path_list.concat vers.map{|ver| + path_head.map{|head| + if ver.empty? + head + "/lib" + 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? + 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}/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? + dirs << head + "-#{ver.delete('.')}/lib" if !Dir.glob(head + "-[89][0-9]*", File::FNM_CASEFOLD).empty? + end + + dirs + end + } + }.flatten! + + path_list.concat path_dirs + + else + # paths is a string with PATH environment style + path_list = paths.split((is_win32?)? ';': ':') + end + + path_list = check_NG_path(path_list) + path_list.map!{|path| path.strip} + + 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 + + # keep paths for searching dynamic libs + #$LIBPATH |= path_list + path_list.uniq +end + +def search_vers_on_path(vers, path, *heads) + exts = get_ext_list.join(',') + files = Dir.glob(File.join(path, "*{#{heads.join(',')}}*.{#{exts}}"), File::FNM_CASEFOLD) + vers.find_all{|ver| files.find{|f| f =~ /(#{ver}|#{ver.delete('.')})/} } +end + +def find_tcl(tcllib, stubs, version, *opt_paths) + if TclConfig_Info['MKMF_PARAMS'] + # already checked existence of tcl library based on tclConfig.sh + ($INCFLAGS ||= "") << " " << TclConfig_Info['MKMF_PARAMS']['INCFLAGS'] + $LIBPATH ||= []; $LIBPATH |= TclConfig_Info['MKMF_PARAMS']['LIBPATH'] + ($libs ||= "") << " " << TclConfig_Info['MKMF_PARAMS']['libs'] + return [true, nil, nil, nil] + end + # else, no available tclConfig.sh on the system + + print "Search Tcl library" if stubs func = "Tcl_InitStubs" @@ -113,38 +1041,139 @@ def find_tcl(tcllib, stubs, version, *opt_paths) if version && ! version.empty? versions = [version] else - versions = %w[8.6 8.5 8.4 8.3 8.2 8.1 8.0 7.6] + versions = TkLib_Config['search_versions'] end - if tcllib - st = find_library(tcllib, func, *paths) - else - st = versions.find { |ver| - find_library("#{lib}#{ver}", func, *paths) or - find_library("#{lib}#{ver.delete('.')}", func, *paths) or - find_library("#{lib}#{ver}g", func, *paths) or - find_library("#{lib}#{ver.delete('.')}g", func, *paths) or - find_library("tcl#{ver}", func, *paths) or - find_library("tcl#{ver.delete('.')}", func, *paths) or - find_library("tcl#{ver}g", func, *paths) or - find_library("tcl#{ver.delete('.')}g", func, *paths) - } || (!version && find_library(lib, func, *paths)) + default_paths = [] + + default_paths.concat [ + RbConfig::CONFIG['libdir'], + File.join(RbConfig::CONFIG['exec_prefix'], 'lib'), + File.join(RbConfig::CONFIG['prefix'], 'lib'), + "/usr/local/lib", "/usr/pkg/lib", "/usr/contrib/lib", "/usr/lib" + ].find_all{|dir| File.directory?(dir)} unless CROSS_COMPILING + + if TkLib_Config["ActiveTcl"].kind_of?(String) # glob path + default_paths.concat Dir.glob(TkLib_Config["ActiveTcl"]).sort.reverse.map{|d| d << "/lib"} end - unless st - puts("Warning:: cannot find Tcl library. tcltklib will not be compiled (tcltklib is disabled on your Ruby == Ruby/Tk will not work). Please check configure options.") + if !CROSS_COMPILING and is_win32? + default_paths.concat [ + "c:/Tcl/lib","c:/Program Files/Tcl/lib","c:/Program Files (x86)/Tcl/lib", + "/Tcl/lib","/Program Files/Tcl/lib","/Program Files (x86)/Tcl/lib" + ].find_all{|dir| File.directory?(dir)}.map{|dir| File.expand_path(dir)} + + # for MinGW + ["/usr/local/lib64", "/usr/lib64", "/usr/local/lib", "/usr/lib"].each{|dir| + default_paths << File.expand_path(dir) if File.directory? dir + } + + default_paths |= ENV['LIBRARY_PATH'].split(';').find_all{|dir| File.directory? dir}.map{|dir| File.expand_path(dir)} if ENV['LIBRARY_PATH'] + default_paths |= ENV['PATH'].split(';').find_all{|dir| File.directory? dir}.map{|dir| File.expand_path(dir)} if ENV['PATH'] end - st -end -def find_tk(tklib, stubs, version, *opt_paths) - default_paths = ["/usr/local/lib", "/usr/pkg/lib", "/usr/lib"] - default_paths << "/Tcl/lib" # default for ActiveTcl + default_paths |= TkLib_Config["checked_shlib_dirs"] + + unless TkLib_Config["space-on-tk-libpath"] + default_paths.delete_if{|path| path =~ / /} + end if (paths = opt_paths.compact).empty? - paths = default_paths + paths = check_tcl_NG_path(default_paths) end + incflags = ($INCFLAGS ||= "").dup + libpath = ($LIBPATH ||= []).dup + libs_param = ($libs ||= "").dup + tcllibs = nil + + exts = "(" + get_ext_list.join('|') + ")" + + paths.map{|path| + lib_w_sufx = lib + begin + $LIBPATH |= [path] + inc = [File.join(File.dirname(path),"include"), File.dirname(path)] + inc.each{|f| $INCFLAGS << " -I" << f } + + if tcllib + print(".") + if have_library(tcllib, func, ["tcl.h"]) + return [true, path, lib_w_sufx, nil, *inc] + end + else + sufx_list = ['', 't', 'g', 's', 'x'] + search_vers_on_path(versions, path, lib, 'tcl').find{|ver| + dir_enum = Dir.foreach(path) + no_dot_ver = ver.delete('.') + libnames = ["#{lib}#{ver}", "#{lib}#{no_dot_ver}"] + libnames << "tcl#{ver}" << "tcl#{no_dot_ver}" if lib != "tcl" + libnames.find{|libname| + sufx_list.find{|sufx| + print(".") + dir_enum.map{|fname| + if fname =~ /^.*(#{libname}.*#{sufx})\.(#{exts}).*$/ + [fname, $1, $2] + end + }.compact.find{|fname, lib_w_sufx, ext| + ext.downcase! + if (ext != CONFIG['DLEXT'] && ext == CONFIG['LIBEXT']) || + ext == "a" + # static link + tcllibs = libs_param + " -DSTATIC_BUILD " + fname.quote + else + tcllibs = append_library($libs, lib_w_sufx) + tcllibs = "-L#{path.quote} -Wl,-R#{path.quote} " + tcllibs + end + if try_func(func, tcllibs, ["tcl.h"]) + return [true, path, nil, tcllibs, *inc] + end + } + } + } + } + if (!version && (print(".");try_func(func, libs_param, ["tcl.h"]))) + return [true, path, lib_w_sufx, nil, *inc] + end + end + ensure + $LIBPATH = libpath.dup + $libs = libs_param.dup + $INCFLAGS = incflags.dup + end + } + + print("\n") # progress + [false, nil, nil, nil] +end + +def parse_TK_LIBS(tklibs) + sfx = "lib|shlib|dll|so" + re = /(("|')[^"']+\.(#{sfx})\2|[^"' ]+\.(#{sfx})|-l("|')[^"']+\5|-l[^" ]+)/#' + + tklibs.scan(re).map{|lib,| + if lib =~ /^("|')([^"]+)\.(#{sfx})\1/ + "\"-l#{$2}\"" + elsif lib =~ /([^" ]+)\.(#{sfx})/ + "-l#{$1}" + else + lib + end + }.join(' ') +end + +def find_tk(tklib, stubs, version, *opt_paths) + if TkConfig_Info['MKMF_PARAMS'] + # already checked existence of tcl library based on tkConfig.sh + ($INCFLAGS ||= "") << " " << TkConfig_Info['MKMF_PARAMS']['INCFLAGS'] + $LIBPATH ||= []; $LIBPATH |= TkConfig_Info['MKMF_PARAMS']['LIBPATH'] + ($libs ||= "") << " " << TkConfig_Info['MKMF_PARAMS']['libs'] + return [true, nil, nil, nil] + end + # else, no available tkConfig.sh on the system + + print "Search Tk library" + if stubs func = "Tk_InitStubs" lib = "tkstub" @@ -156,40 +1185,382 @@ def find_tk(tklib, stubs, version, *opt_paths) if version && ! version.empty? versions = [version] else - versions = %w[8.6 8.5 8.4 8.3 8.2 8.1 8.0 4.2] + versions = TkLib_Config['search_versions'] end - if tklib - st = find_library(tklib, func, *paths) + default_paths = [] + + default_paths.concat [ + RbConfig::CONFIG['libdir'], + File.join(RbConfig::CONFIG['exec_prefix'], 'lib'), + File.join(RbConfig::CONFIG['prefix'], 'lib'), + "/usr/local/lib", "/usr/pkg/lib", "/usr/contrib/lib", "/usr/lib" + ].find_all{|dir| File.directory?(dir)} unless CROSS_COMPILING + + if !CROSS_COMPILING and is_win32? + default_paths.concat [ + "c:/Tcl/lib","c:/Program Files/Tcl/lib","c:/Program Files (x86)/Tcl/lib", + "/Tcl/lib","/Program Files/Tcl/lib","/Program Files (x86)/Tcl/lib" + ].find_all{|dir| File.directory?(dir)} + + # for MinGW + ["/usr/local/lib64", "/usr/lib64", "/usr/local/lib", "/usr/lib"].each{|dir| + default_paths << File.expand_path(dir) if File.directory? dir + } + + default_paths |= ENV['LIBRARY_PATH'].split(';').find_all{|dir| File.directory? dir}.map{|dir| File.expand_path(dir)} if ENV['LIBRARY_PATH'] + default_paths |= ENV['PATH'].split(';').find_all{|dir| File.directory? dir}.map{|dir| File.expand_path(dir)} if ENV['PATH'] + end + + default_paths |= TkLib_Config["checked_shlib_dirs"] + + unless TkLib_Config["space-on-tk-libpath"] + default_paths.delete_if{|path| path =~ / /} + end + + if (paths = opt_paths.compact).empty? + paths = check_tk_NG_path(default_paths) + end + + incflags = ($INCFLAGS ||= "").dup + libpath = ($LIBPATH ||= []).dup + libs_param = ($libs ||= "").dup + tcllibs = nil + + exts = "(" + get_ext_list.join('|') + ")" + + paths.map{|path| + lib_w_sufx = lib + begin + $LIBPATH |= [path] + inc = [File.join(File.dirname(path),"include"), File.dirname(path)] + inc.each{|f| $INCFLAGS << " -I" << f } + + if tklib + print(".") + if have_library(tklib, func, ["tcl.h", "tk.h"]) + return [true, path, lib_w_sufx, nil, *inc] + end + else + sufx_list = ['', 't', 'g', 's', 'x'] + search_vers_on_path(versions, path, lib, 'tk').find{|ver| + dir_enum = Dir.foreach(path) + no_dot_ver = ver.delete('.') + libnames = ["#{lib}#{ver}", "#{lib}#{no_dot_ver}"] + libnames << "tk#{ver}" << "tk#{no_dot_ver}" if lib != "tk" + libnames.find{|libname| + sufx_list.find{|sufx| + print(".") + dir_enum.map{|fname| + if fname =~ /^.*(#{libname}.*#{sufx})\.(#{exts}).*$/ + [fname, $1, $2] + end + }.compact.find{|fname, lib_w_sufx, ext| + if (ext != CONFIG['DLEXT'] && ext == CONFIG['LIBEXT']) || + ext == "a" + # static link + tklibs = libs_param + " -DSTATIC_BUILD " + fname.quote + else + tklibs = append_library($libs, lib_w_sufx) + tklibs = "-L#{path.quote} -Wl,-R#{path.quote} " + tklibs + end + if try_func(func, tklibs, ["tcl.h", "tk.h"]) + return [true, path, nil, tklibs, *inc] + end + } + } + } + } + if (!version && (print(".");try_func(func, libs_param, ["tcl.h", "tk.h"]))) + return [true, path, lib_w_sufx, nil, *inc] + end + end + ensure + $LIBPATH = libpath + $libs = libs_param + $INCFLAGS = incflags.dup + end + } + + print("\n") # progress + [false, nil, nil, nil] +end + +def find_tcltk_library(tcllib, tklib, stubs, tclversion, tkversion, + tcl_opt_paths, tk_opt_paths) + st,path,lib,libs,*inc = find_tcl(tcllib, stubs, tclversion, *tcl_opt_paths) + unless st + puts("Warning:: cannot find Tcl library. tcltklib will not be compiled (tcltklib is disabled on your Ruby. That is, Ruby/Tk will not work). Please check configure options.") + return false else - st = versions.find { |ver| - find_library("#{lib}#{ver}", func, *paths) or - find_library("#{lib}#{ver.delete('.')}", func, *paths) or - find_library("#{lib}#{ver}g", func, *paths) or - find_library("#{lib}#{ver.delete('.')}g", func, *paths) or - find_library("tk#{ver}", func, *paths) or - find_library("tk#{ver.delete('.')}", func, *paths) or - find_library("tk#{ver}g", func, *paths) or - find_library("tk#{ver.delete('.')}g", func, *paths) - } || (!version && find_library(lib, func, *paths)) + ($LIBPATH ||= []; $LIBPATH |= [path]) if path + $libs = append_library($libs, lib) if lib + ($libs ||= "") << " " << libs if libs + $INCFLAGS ||= "" + inc.each{|f| $INCFLAGS << " -I" << f} end + st,path,lib,libs,*inc = find_tk(tklib, stubs, tkversion, *tk_opt_paths) unless st - puts("Warning:: cannot find Tk library. tcltklib will not be compiled (tcltklib is disabled on your Ruby == Ruby/Tk will not work). Please check configure options.") + puts("Warning:: cannot find Tk library. tcltklib will not be compiled (tcltklib is disabled on your Ruby. That is, Ruby/Tk will not work). Please check configure options.") + return false + else + ($LIBPATH ||= []; $LIBPATH |= [path]) if path + $libs = append_library($libs, lib) if lib && !lib.empty? + ($libs ||= "") << " " << libs if libs + $INCFLAGS ||= "" + inc.each{|f| $INCFLAGS << " -I" << f} + end + + true +end + +def find_tcltk_header(tclver, tkver) + base_dir = [] + + base_dir.concat [ + File.join(RbConfig::CONFIG['prefix'], 'include'), + "/usr/local/include", "/usr/pkg/include", "/usr/contrib/include", + "/usr/include" + ].find_all{|dir| File.directory?(dir)}.map{|dir| File.expand_path(dir)} + + if !CROSS_COMPILING && is_win32? + base_dir.concat [ + "c:/Tcl/include","c:/Program Files/Tcl/include", + "c:/Program Files (x86)/Tcl/include", + "/Tcl/include","/Program Files/Tcl/include", + "/Program Files (x86)/Tcl/include" + ].find_all{|dir| File.directory?(dir)}.map{|dir| File.expand_path(dir)} + + if ENV['CPATH'] + base_dir |= ENV['CPATH'].split(';').find_all{|dir| File.directory?(dir)}.map{|dir| File.expand_path(dir)} + end + end + + base_dir |= TkLib_Config["checked_shlib_dirs"] + + unless TkLib_Config["space-on-tk-libpath"] + base_dir.delete_if{|path| path =~ / /} + end + + # tcl.h + if TclConfig_Info['MKMF_PARAMS'] + # already checked existence of tcl headers based on tclConfig.sh + have_tcl_h = true + else + print "\nSearch tcl.h" + if enable_config("tcl-h-ver-check", true) && + tclver && tclver =~ /^\D*(\d)\.?(\d)/ + major = $1; minor = $2 + else + major = minor = nil + end + print(".") # progress + if major && minor + # version check on tcl.h + have_tcl_h = try_cpp("#include \n#if TCL_MAJOR_VERSION != #{major} || TCL_MINOR_VERSION != #{minor}\n#error VERSION does not match\n#endif") + else + have_tcl_h = have_header('tcl.h') + end + unless have_tcl_h + if tclver && ! tclver.empty? + versions = [tclver] + else + versions = TkLib_Config['search_versions'] + end + paths = base_dir.dup + (versions + [""]).each{|ver| + paths.concat(base_dir.map{|dir| + [ + dir + '/tcl' + ver, + dir + '/tcl' + ver + '/include', + dir + '/tcl' + ver.delete('.'), + dir + '/tcl' + ver.delete('.') + '/include' + ] + }.flatten) + } + paths = paths.map{|dir| + (File.directory?(dir))? File.expand_path(dir): nil + }.compact.uniq + + code = "#include \n" + code << "#if TCL_MAJOR_VERSION != #{major}\n#error MAJOR_VERSION does not match\n#endif\n" if major + code << "#if TCL_MINOR_VERSION != #{minor}\n#error MINOR_VERSION does not match\n#endif\n" if minor + have_tcl_h = paths.find{|path| + print(".") # progress + inc_opt = " -I#{path.quote}" + if try_cpp(code, inc_opt) + ($INCFLAGS ||= "") << inc_opt + true + else + false + end + } + end + end + + # tk.h + if TkConfig_Info['MKMF_PARAMS'] + # already checked existence of tk headers based on tkConfig.sh + have_tk_h = true + else + print "\nSearch tk.h" + if enable_config("tk-h-ver-check", true) && + tkver && tkver =~ /^\D*(\d)\.?(\d)/ + major = $1; minor = $2 + else + major = minor = nil + end + print(".") # progress + if major && minor + # version check on tk.h + have_tk_h = try_cpp("#include \n#if TK_MAJOR_VERSION != #{major} || TK_MINOR_VERSION != #{minor}\n#error VERSION does not match\n#endif") + else + have_tk_h = have_header('tk.h') + end + unless have_tk_h + if tkver && ! tkver.empty? + versions = [tkver] + else + versions = TkLib_Config['search_versions'] + end + paths = base_dir.dup + (versions + [""]).each{|ver| + paths.concat(base_dir.map{|dir| + [ + dir + '/tk' + ver, + dir + '/tk' + ver + '/include', + dir + '/tk' + ver.delete('.'), + dir + '/tk' + ver.delete('.') + '/include' + ] + }.flatten) + } + paths = paths.map{|dir| + (File.directory?(dir))? File.expand_path(dir): nil + }.compact.uniq + + code = "#include \n#include \n" + code << "#if TK_MAJOR_VERSION != #{major}\n#error MAJOR_VERSION does not match\n#endif\n" if major + code << "#if TK_MINOR_VERSION != #{minor}\n#error MINOR_VERSION does not match\n#endif\n" if minor + have_tk_h = paths.find{|path| + print(".") # progress + inc_opt = " -I#{path.quote}" + if try_cpp(code, inc_opt) + ($INCFLAGS ||= "") << inc_opt + true + else + false + end + } + end + end + + puts "Can't find \"tcl.h\"." unless have_tcl_h + puts "Can't find \"tk.h\"." unless have_tk_h + have_tcl_h && have_tk_h +end + +def setup_for_macosx_framework(tclver, tkver) + # use framework, but no tclConfig.sh + unless $LDFLAGS && $LDFLAGS.include?('-framework') + ($LDFLAGS ||= "") << ' -framework Tk -framework Tcl' + end + + if TkLib_Config["tcl-framework-header"] + TclConfig_Info['TCL_INCLUDE_SPEC'][0,0] = + " -I#{TkLib_Config["tcl-framework-header"].quote} " + else + 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'][0,0] = + " -I#{TkLib_Config["tk-framework-header"].quote} " + else + 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 - st end def find_X11(*opt_paths) - default_paths = - [ "/usr/X11/lib", "/usr/lib/X11", "/usr/X11R6/lib", "/usr/openwin/lib" ] - paths = opt_paths.compact.concat(default_paths) + defaults = + [ "/usr/X11*/lib", "/usr/lib/X11*", "/usr/local/X11*", "/usr/openwin/lib" ] + paths = [] + opt_paths.compact.each{|path| paths.concat(Dir.glob(path.strip.chomp('/'), File::FNM_CASEFOLD))} + defaults.compact.each{|path| paths.concat(Dir.glob(path.strip.chomp('/'), File::FNM_CASEFOLD))} st = find_library("X11", "XOpenDisplay", *paths) unless st - puts("Warning:: cannot find X11 library. tcltklib will not be compiled (tcltklib is disabled on your Ruby == Ruby/Tk will not work). Please check configure options. If your Tcl/Tk don't require X11, please try --without-X11.") + puts("Warning:: cannot find X11 library. tcltklib will not be compiled (tcltklib is disabled on your Ruby. That is, Ruby/Tk will not work). Please check configure options. If your Tcl/Tk don't require X11, please try --without-X11.") end st -end +end + +def search_X_libraries + use_tkConfig = false + if TkConfig_Info['config_file_path'] + # use definitions on tkConfig.sh + if (TkConfig_Info['TK_XINCLUDES'] && + !TkConfig_Info['TK_XINCLUDES'].strip.empty?) || + (TkConfig_Info['TK_XLIBSW'] && !TkConfig_Info['TK_XLIBSW'].strip.empty?) + use_tkConfig = true + #use_X = true && with_config("X11", ! is_win32?) + use_X = with_config("X11", true) + else + #use_X = false || with_config("X11", false) + use_X = with_config("X11", false) + end + else + # depend on configure options + use_X = with_config("X11", !(is_win32? || TkLib_Config["tcltk-framework"])) + end + + if TkConfig_Info['TK_XINCLUDES'] && + !TkConfig_Info['TK_XINCLUDES'].strip.empty? + ($INCFLAGS ||= "") << " " << TkConfig_Info['TK_XINCLUDES'].strip + end + + if use_X + puts("Use X11 libraries (or use TK_XINCLUDES/TK_XLIBSW information on tkConfig.sh).") + x11_idir, x11_ldir = dir_config("X11") + x11_ldir2 = with_config("X11-lib") + unless find_X11(x11_ldir2, x11_ldir) + puts("Can't find X11 libraries. ") + if use_tkConfig && + TkConfig_Info['TK_XLIBSW'] && !TkConfig_Info['TK_XLIBSW'].strip.empty? + puts("But, try to use TK_XLIBSW information (believe tkCOnfig.sh).") + ($libs ||= "") << " " << TkConfig_Info['TK_XLIBSW'] << " " + else + puts("So, can't make tcltklib.so which is required by Ruby/Tk.") + exit + end + end + end + + use_X +end def pthread_check() tcl_major_ver = nil @@ -205,74 +1576,50 @@ def pthread_check() tcl_enable_thread = nil end - if (tclConfig = with_config("tclConfig-file")) + if TclConfig_Info['config_file_path'] if tcl_enable_thread == true - puts("Warning: --with-tclConfig-file option is ignored, because --enable-tcl-thread option is given.") + puts("Warning: definiton of tclConfig.sh is ignored, because --enable-tcl-thread option is given.") elsif tcl_enable_thread == false - puts("Warning: --with-tclConfig-file option is ignored, because --disable-tcl-thread option is given.") + puts("Warning: definition of tclConfig.sh is ignored, because --disable-tcl-thread option is given.") else # tcl-thread is unknown and tclConfig.sh is given - begin - open(tclConfig, "r") do |cfg| - while line = cfg.gets() - if line =~ /^\s*TCL_THREADS=(0|1)/ - tcl_enable_thread = ($1 == "1") - break - end - - if line =~ /^\s*TCL_MAJOR_VERSION=("|')(\d+)\1/ - tcl_major_ver = $2 - if tcl_major_ver =~ /^[1-7]$/ - tcl_enable_thread = false - break - end - if tcl_major_ver == "8" && tcl_minor_ver == "0" - tcl_enable_thread = false - break - end - end - - if line =~ /^\s*TCL_MINOR_VERSION=("|')(\d+)\1/ - tcl_minor_ver = $2 - if tcl_major_ver == "8" && tcl_minor_ver == "0" - tcl_enable_thread = false - break - end - end - end + if TclConfig_Info['TCL_THREADS'] + tcl_enable_thread = (TclConfig_Info['TCL_THREADS'] == "1") + else + tcl_major_ver = TclConfig_Info['TCL_MAJOR_VERSION'].to_i + tcl_minor_ver = TclConfig_Info['TCL_MINOR_VERSION'].to_i + if tcl_major_ver < 8 || (tcl_major_ver == 8 && tcl_minor_ver == 0) + tcl_enable_thread = false end + end - if tcl_enable_thread == nil - # not find definition - if tcl_major_ver - puts("Warning: '#{tclConfig}' doesn't include TCL_THREADS definition.") - else - puts("Warning: '#{tclConfig}' may not be a tclConfig file.") - end - tclConfig = false + if tcl_enable_thread == nil + # cannot find definition + if tcl_major_ver + puts("Warning: '#{TclConfig_Info['config_file_path']}' doesn't include TCL_THREADS definition.") + else + puts("Warning: '#{TclConfig_Info['config_file_path']}' may not be a tclConfig file.") end - rescue Exception - puts("Warning: fail to read '#{tclConfig}'!! --> ignore the file") - tclConfig = false + #tclConfig = false end end end - if tcl_enable_thread == nil && !tclConfig + if tcl_enable_thread == nil && !TclConfig_Info['config_file_path'] # tcl-thread is unknown and tclConfig is unavailable begin - try_run_available = try_run("int main() { exit(0); }") + try_run("int main() { exit(0); }") rescue Exception # cannot try_run. Is CROSS-COMPILE environment? puts(%Q'\ ***************************************************************************** ** -** PTHREAD SUPPORT CHECK WARNING: +** NATIVETHREAD SUPPORT CHECK WARNING: ** -** We cannot check the consistency of pthread support between Ruby -** and the Tcl/Tk library in your environment (are you perhaps -** cross-compiling?). If pthread support for these 2 packages is -** inconsistent you may find you get errors when running Ruby/Tk +** We cannot check the consistency of nativethread support between +** Ruby and the Tcl/Tk library in your environment (are you perhaps +** cross-compiling?). If nativethread support for these 2 packages +** is inconsistent you may find you get errors when running Ruby/Tk ** (e.g. hangs or segmentation faults). We strongly recommend ** you to check the consistency manually. ** @@ -286,7 +1633,7 @@ def pthread_check() # tcl-thread is unknown if try_run(< -int main() { +int main() { Tcl_Interp *ip; ip = Tcl_CreateInterp(); exit((Tcl_Eval(ip, "set tcl_platform(threaded)") == TCL_OK)? 0: 1); @@ -305,26 +1652,29 @@ EOF end # check pthread mode - if (macro_defined?('HAVE_NATIVETHREAD', '#include "ruby.h"')) + if (TkLib_Config["ruby_with_thread"]) + $CPPFLAGS ||= "" + # ruby -> enable unless tcl_enable_thread # ruby -> enable && tcl -> disable puts(%Q'\ ***************************************************************************** ** -** PTHREAD SUPPORT MODE WARNING: +** NATIVETHREAD SUPPORT MODE WARNING: ** ** Ruby is compiled with --enable-pthread, but your Tcl/Tk library -** seems to be compiled without pthread support. Although you can -** create the tcltklib library, this combination may cause errors -** (e.g. hangs or segmentation faults). If you have no reason to -** keep the current pthread support status, we recommend you reconfigure -** and recompile the libraries so that both or neither support pthreads. +** seems to be compiled without nativethread support. Although you can +** create the tcltklib library, this combination may cause errors (e.g. +** hangs or segmentation faults). If you have no reason to keep the +** current nativethread support status, we recommend you reconfigure and +** recompile the libraries so that both or neither support nativethreads. ** -** If you want change the status of pthread support, please recompile -** Ruby without "--enable-pthread" configure option or recompile Tcl/Tk -** with "--enable-threads" configure option (if your Tcl/Tk is later -** than or equal to Tcl/Tk 8.1). +** If you want change the status of nativethread support, please recompile +** Ruby without "--enable-pthread" configure option (If you use Ruby 1.9.x +** or later, you cannot remove this option, because it requires native- +** thread support.) or recompile Tcl/Tk with "--enable-threads" configure +** option (if your Tcl/Tk is later than or equal to Tcl/Tk 8.1). ** ***************************************************************************** ') @@ -346,13 +1696,13 @@ EOF puts(%Q'\ ***************************************************************************** ** -** PTHREAD SUPPORT MODE ERROR: +** NATIVETHREAD SUPPORT MODE ERROR: ** -** Ruby is not compiled with --enable-pthread, but your Tcl/Tk -** library seems to be compiled with pthread support. This +** Ruby is not compiled with --enable-pthread, but your Tcl/Tk +** library seems to be compiled with nativethread support. This ** combination may cause frequent hang or segmentation fault ** errors when Ruby/Tk is working. We recommend that you NEVER -** create the library with such a combination of pthread support. +** create the library with such a combination of nativethread support. ** ** Please recompile Ruby with the "--enable-pthread" configure option ** or recompile Tcl/Tk with the "--disable-threads" configure option. @@ -369,44 +1719,311 @@ EOF end end -tclver, tkver = check_tcltk_version(tcltk_version) +############################################################## +# main +############################################################## +# check header file +print("check functions.") +have_func("ruby_native_thread_p", "ruby.h") +print(".") # progress +have_func("rb_errinfo", "ruby.h") +print(".") # progress +have_func("rb_safe_level", "ruby.h") +print(".") # progress +have_func("rb_hash_lookup", "ruby.h") +print(".") # progress +have_func("rb_proc_new", "ruby.h") +print(".") # progress +have_func("rb_obj_untrust", "ruby.h") +print(".") # progress +have_func("rb_obj_taint", "ruby.h") +print(".") # progress +have_func("rb_set_safe_level_force", "ruby.h") +print(".") # progress +have_func("rb_sourcefile", "ruby.h") +print("\n") # progress + +print("check struct members.") +have_struct_member("struct RArray", "ptr", "ruby.h") +print(".") # progress +have_struct_member("struct RArray", "len", "ruby.h") +print("\n") # progress + +# check libraries +unless is_win32? + print("check libraries.") + have_library("nsl", "t_open") + print(".") # progress + have_library("socket", "socket") + print(".") # progress + have_library("dl", "dlopen") + print(".") # progress + have_library("m", "log", "math.h") + print("\n") # progress +end +$CPPFLAGS ||= "" +$CPPFLAGS += ' -D_WIN32' if /cygwin/ =~ RUBY_PLATFORM + +# Does ruby have nativethread ? +TkLib_Config["ruby_with_thread"] = + macro_defined?('HAVE_NATIVETHREAD', '#include "ruby.h"') + + +#--------------------------------------------------- +TclConfig_Info = {} +TkConfig_Info = {} + +# use Tcl/Tk build dir? (has highest priority) +TkLib_Config["tcl-build-dir"] = with_config("tcl-build-dir") +TkLib_Config["tk-build-dir"] = with_config("tk-build-dir") +if TkLib_Config["tcl-build-dir"] + puts("use Tcl build (pre-install) dir \"#{TkLib_Config["tcl-build-dir"]}\"") + TkLib_Config["tcl-build-dir"] = File.expand_path(TkLib_Config["tcl-build-dir"]) + base = File.dirname(TkLib_Config["tcl-build-dir"]) + ($INCFLAGS ||= "") << " -I#{File.join(base, "generic").quote} -I#{TkLib_Config["tcl-build-dir"].quote}" + $LIBPATH ||= []; $LIBPATH |= [TkLib_Config["tcl-build-dir"]] +end +if TkLib_Config["tk-build-dir"] + puts("use Tk build (pre-install) dir \"#{TkLib_Config["tk-build-dir"]}\"") + TkLib_Config["tk-build-dir"] = File.expand_path(TkLib_Config["tk-build-dir"]) + base = File.dirname(TkLib_Config["tk-build-dir"]) + ($INCFLAGS ||= "") << " -I#{File.join(base, "generic").quote} -I#{TkLib_Config["tk-build-dir"].quote}" + $LIBPATH ||= []; $LIBPATH |= [TkLib_Config["tk-build-dir"]] +end -if have_header("tcl.h") && have_header("tk.h") && - ( tcltk_framework || - ( ( !use_X || find_X11(x11_ldir2, x11_ldir) ) && - find_tcl(tcllib, stubs, tclver, *tcl_ldir_list) && - find_tk(tklib, stubs, tkver, *tk_ldir_list) ) ) - $CPPFLAGS += ' -DUSE_TCL_STUBS -DUSE_TK_STUBS' if stubs - $CPPFLAGS += ' -D_WIN32' if /cygwin/ =~ RUBY_PLATFORM +# check requirement of Tcl/tk version +tcltk_version = with_config("tcltkversion") +TkLib_Config["tcltkversion"] = check_tcltk_version(tcltk_version) - if tcltk_framework - if tcl_framework_header - $CPPFLAGS += " -I#{tcl_framework_header}" +if TkLib_Config["tcl-build-dir"] + if (cfgfile = with_config("tclConfig-file", Dir.glob(File.join(TkLib_Config["tcl-build-dir"], "tclConfig*.sh"), File::FNM_CASEFOLD)[0])) + TclConfig_Info['config_file_path'] = cfgfile + TkLib_Config["tclConfig_info"] = cfginfo = parse_tclConfig(cfgfile) + if tclver = TkLib_Config["tcltkversion"][0] + TkLib_Config["tcltkversion"][0].sub!(/\d(\.?)\d/, "#{cfginfo['TCL_MAJOR_VERSION']}\\1#{cfginfo['TCL_MINOR_VERSION']}") + else + TkLib_Config["tcltkversion"][0] = "#{cfginfo['TCL_MAJOR_VERSION']}.#{cfginfo['TCL_MINOR_VERSION']}" + end + end +end +if TkLib_Config["tk-build-dir"] + if (cfgfile = with_config("tkConfig-file", Dir.glob(File.join(TkLib_Config["tk-build-dir"], "tkConfig*.sh"), File::FNM_CASEFOLD)[0])) + TkConfig_Info['config_file_path'] = cfgfile + TkLib_Config["tkConfig_info"] = cfginfo = parse_tclConfig(cfgfile) + if TkLib_Config["tcltkversion"][1] + TkLib_Config["tcltkversion"][1].sub!(/\d(\.?)\d/, "#{cfginfo['TK_MAJOR_VERSION']}\\1#{cfginfo['TK_MINOR_VERSION']}") else - $CPPFLAGS += " -I#{tcltk_framework}/Tcl.framework/Headers" + TkLib_Config["tcltkversion"][1] = "#{cfginfo['TK_MAJOR_VERSION']}.#{cfginfo['TK_MINOR_VERSION']}" end + end +end + +tclver, tkver = TkLib_Config["tcltkversion"] +puts("Specified Tcl/Tk version is #{[tclver, tkver].inspect}") if tclver||tkver - if tk_framework_header - $CPPFLAGS += " -I#{tk_framework_header}" +# use ActiveTcl ? +#if activeTcl = with_config("ActiveTcl") +#if activeTcl = with_config("ActiveTcl", true) +if activeTcl = with_config("ActiveTcl", !(TkLib_Config["tcl-build-dir"] && TkLib_Config["tk-build-dir"])) + puts("Use ActiveTcl libraries (if available).") + 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 - $CPPFLAGS += " -I#{tcltk_framework}/Tk.framework/Headers" + activeTcl = '/opt/ActiveTcl*' end + end +end +TkLib_Config["ActiveTcl"] = activeTcl - $LDFLAGS += ' -framework Tk -framework Tcl' +# allow space chars on a libpath +TkLib_Config["space-on-tk-libpath"] = + enable_config("space-on-tk-libpath", ! is_win32?) + +# enable Tcl/Tk stubs? +=begin +if TclConfig_Info['TCL_STUB_LIB_SPEC'] && TkConfig_Info['TK_STUB_LIB_SPEC'] && + !TclConfig_Info['TCL_STUB_LIB_SPEC'].strip.empty? && + !TkConfig_Info['TK_STUB_LIB_SPEC'].strip.empty? + stubs = true + unless (st = enable_config("tcltk-stubs")).nil? + stubs &&= st + end + unless (st = with_config("tcltk-stubs")).nil? + stubs &&= st end +else + stubs = enable_config("tcltk-stubs") || with_config("tcltk-stubs") +end +=end +stubs = enable_config("tcltk-stubs") || with_config("tcltk-stubs") +if (TkLib_Config["tcltk-stubs"] = stubs) + puts("Compile with Tcl/Tk stubs.") + $CPPFLAGS ||= ""; $CPPFLAGS += ' -DUSE_TCL_STUBS -DUSE_TK_STUBS' +end - if stubs or pthread_check - # create Makefile +# directory configuration of Tcl/Tk libraries +if TkLib_Config["tcl-build-dir"] + tcl_idir = File.join(File.dirname(TkLib_Config["tcl-build-dir"]),"generic") + tcl_ldir = TkLib_Config["tcl-build-dir"] +else + tcl_idir, tcl_ldir = dir_config("tcl") +end +if TkLib_Config["tk-build-dir"] + tk_idir = File.join(File.dirname(TkLib_Config["tk-build-dir"]),"generic") + tk_ldir = TkLib_Config["tk-build-dir"] +else + tk_idir, tk_ldir = dir_config("tk") +end + +tcl_idir = tk_idir unless tcl_idir +tcl_ldir = tk_ldir unless tcl_ldir +tk_idir = tcl_idir unless tk_idir +tk_ldir = tcl_ldir unless tk_ldir + +TclConfig_Info['TCL_INCLUDE_SPEC'] ||= "" +TkConfig_Info['TK_INCLUDE_SPEC'] ||= "" +TclConfig_Info['TCL_INCLUDE_SPEC'][0,0] = "-I#{tcl_idir.quote} " if tcl_idir +TkConfig_Info['TK_INCLUDE_SPEC'][0,0] = "-I#{tk_idir.quote} " if tk_idir - # for SUPPORT_STATUS - $INSTALLFILES ||= [] - $INSTALLFILES << ["lib/tkextlib/SUPPORT_STATUS", "$(RUBYLIBDIR)", "lib"] +# get tclConfig.sh/tkConfig.sh +TkLib_Config["tcl-NG-path"] = [] +TkLib_Config["tk-NG-path"] = [] +tclcfg, tkcfg = + get_tclConfig( + TclConfig_Info['config_file_path'] || with_config("tclConfig-file", true), + TkConfig_Info['config_file_path'] || with_config("tkConfig-file", true), + (TclConfig_Info['config_file_path'])? + File.dirname(TclConfig_Info['config_file_path']) : + with_config("tclConfig-dir", tcl_ldir || true), + (TkConfig_Info['config_file_path'])? + File.dirname(TkConfig_Info['config_file_path']) : + with_config("tkConfig-dir", tk_ldir || true) + ) +TclConfig_Info.merge!(TkLib_Config["tclConfig_info"]) if TkLib_Config["tclConfig_info"] +TkConfig_Info.merge!(TkLib_Config["tkConfig_info"]) if TkLib_Config["tkConfig_info"] +TclConfig_Info['config_file_path'] ||= tclcfg +TkConfig_Info['config_file_path'] ||= tkcfg - have_func("rb_hash_lookup", "ruby.h") +tk_cfg_dir = File.dirname(TkConfig_Info['config_file_path']) rescue nil +tcl_cfg_dir = File.dirname(TclConfig_Info['config_file_path']) rescue nil - # create - $defs << %[-DRUBY_VERSION=\\"#{RUBY_VERSION}\\"] - $defs << %[-DRUBY_RELEASE_DATE=\\"#{RUBY_RELEASE_DATE}\\"] - create_makefile("tcltklib") +tk_ldir_list = [tk_ldir, tk_cfg_dir].uniq +tcl_ldir_list = [tcl_ldir, tcl_cfg_dir].uniq + +if TkConfig_Info['config_file_path'] + if TkLib_Config["tk-build-dir"] + spec_dir = get_libpath(TkConfig_Info['TK_LIB_FLAG'], TkConfig_Info['TK_BUILD_LIB_SPEC']) + else + spec_dir = get_libpath(TkConfig_Info['TK_LIB_FLAG'], TkConfig_Info['TK_LIB_SPEC']) end + tk_ldir_list << spec_dir if File.directory?(spec_dir) +end +if TclConfig_Info['config_file_path'] + if TkLib_Config["tcl-build-dir"] + spec_dir = get_libpath(TclConfig_Info['TCL_LIB_FLAG'], TclConfig_Info['TCL_BUILD_LIB_SPEC']) + else + spec_dir = get_libpath(TclConfig_Info['TCL_LIB_FLAG'], TclConfig_Info['TCL_LIB_SPEC']) + end + tcl_ldir_list << spec_dir if File.directory?(spec_dir) +end + +# check tk_shlib_search_path +TkLib_Config["checked_shlib_dirs"] = + check_shlib_search_path(with_config('tk-shlib-search-path')) + +# set TCL_DEFS and TK_DEFS +$CPPFLAGS ||= "" +# $CPPFLAGS += " #{TclConfig_Info['TCL_DEFS']}" +# $CPPFLAGS += " #{TkConfig_Info['TK_DEFS']}" +$defs += collect_tcltk_defs(TclConfig_Info['TCL_DEFS'], TkConfig_Info['TK_DEFS']) + +# MacOS X Frameworks? +if TkLib_Config["tcltk-framework"] + puts("Use MacOS X Frameworks.") + ($LDFLAGS ||= "") << " -L#{TkLib_Config["tcl-build-dir"].quote} -Wl,-R#{TkLib_Config["tcl-build-dir"].quote}" if TkLib_Config["tcl-build-dir"] + + if tcl_cfg_dir + TclConfig_Info['TCL_LIBS'] ||= "" + ($INCFLAGS ||= "") << ' ' << TclConfig_Info['TCL_INCLUDE_SPEC'] + $LDFLAGS << ' ' << TclConfig_Info['TCL_LIBS'] + if stubs + if TkLib_Config["tcl-build-dir"] && + TclConfig_Info['TCL_BUILD_STUB_LIB_SPEC'] && + !TclConfig_Info['TCL_BUILD_STUB_LIB_SPEC'].strip.empty? + $LDFLAGS << ' ' << TclConfig_Info['TCL_BUILD_STUB_LIB_SPEC'] + else + $LDFLAGS << ' ' << TclConfig_Info['TCL_STUB_LIB_SPEC'] + end + else + if TkLib_Config["tcl-build-dir"] && + TclConfig_Info['TCL_BUILD_LIB_SPEC'] && + !TclConfig_Info['TCL_BUILD_LIB_SPEC'].strip.empty? + $LDFLAGS << ' ' << TclConfig_Info['TCL_BUILD_LIB_SPEC'] + else + $LDFLAGS << ' ' << TclConfig_Info['TCL_LIB_SPEC'] + end + end + end + + $LDFLAGS << " -L#{TkLib_Config["tk-build-dir"].quote} -Wl,-R#{TkLib_Config["tk-build-dir"].quote}" if TkLib_Config["tk-build-dir"] + + if tk_cfg_dir + TkConfig_Info['TK_LIBS'] ||= "" + ($INCFLAGS ||= "") << ' ' << TkConfig_Info['TK_INCLUDE_SPEC'] + $LDFLAGS << ' ' << TkConfig_Info['TK_LIBS'] + if stubs + if TkLib_Config["tk-build-dir"] && + TclConfig_Info['TK_BUILD_STUB_LIB_SPEC'] && + !TclConfig_Info['TK_BUILD_STUB_LIB_SPEC'].strip.empty? + $LDFLAGS << ' ' << TkConfig_Info['TK_BUILD_STUB_LIB_SPEC'] + else + $LDFLAGS << ' ' << TkConfig_Info['TK_STUB_LIB_SPEC'] + end + else + if TkLib_Config["tk-build-dir"] && + TclConfig_Info['TK_BUILD_LIB_SPEC'] && + !TclConfig_Info['TK_BUILD_LIB_SPEC'].strip.empty? + $LDFLAGS << ' ' << TkConfig_Info['TK_BUILD_LIB_SPEC'] + else + $LDFLAGS << ' ' << TkConfig_Info['TK_LIB_SPEC'] + end + end + end + setup_for_macosx_framework(tclver, tkver) if tcl_cfg_dir && tk_cfg_dir +end + +# name of Tcl/Tk libraries +tklib = with_config("tklib") +tcllib = with_config("tcllib") + +# search X libraries +use_X = search_X_libraries + + +#--------------------------------------------------- +if (TkLib_Config["tcltk-framework"] || + ( find_tcltk_header(tclver, tkver) && + find_tcltk_library(tcllib, tklib, stubs, tclver, tkver, + tcl_ldir_list, tk_ldir_list) ) ) && + (stubs || pthread_check()) + # create Makefile + + # for SUPPORT_STATUS + $INSTALLFILES ||= [] + $INSTALLFILES << ["lib/tkextlib/SUPPORT_STATUS", "$(RUBYLIBDIR)", "lib"] + + # create + $defs << %[-DRUBY_VERSION=\\"#{RUBY_VERSION}\\"] + $defs << %[-DRUBY_RELEASE_DATE=\\"#{RUBY_RELEASE_DATE}\\"] + + create_makefile("tcltklib") + + puts "\nFind Tcl/Tk libraries. Make tcltklib.so which is required by Ruby/Tk." +else + puts "\nCan't find proper Tcl/Tk libraries. So, can't make tcltklib.so which is required by Ruby/Tk." end diff --git a/ext/tk/old-extconf.rb b/ext/tk/old-extconf.rb new file mode 100644 index 0000000000..ebc83a0c0b --- /dev/null +++ b/ext/tk/old-extconf.rb @@ -0,0 +1,440 @@ +# extconf.rb for tcltklib + +require 'mkmf' + +is_win32 = (/mswin|mingw|cygwin|bccwin/ =~ RUBY_PLATFORM) +#is_macosx = (/darwin/ =~ RUBY_PLATFORM) + +have_func("ruby_native_thread_p", "ruby.h") +have_func("rb_errinfo", "ruby.h") +have_func("rb_safe_level", "ruby.h") +have_struct_member("struct RArray", "ptr", "ruby.h") +have_struct_member("struct RArray", "len", "ruby.h") + +def find_framework(tcl_hdr, tk_hdr) + if framework_dir = with_config("tcltk-framework") + paths = [framework_dir] + else + unless tcl_hdr || tk_hdr || + enable_config("tcltk-framework", false) || + enable_config("mac-tcltk-framework", false) + return false + end + paths = ["/Library/Frameworks", "/System/Library/Frameworks"] + end + + checking_for('Tcl/Tk Framework') { + paths.find{|dir| + dir.strip! + dir.chomp!('/') + (tcl_hdr || FileTest.directory?(dir + "/Tcl.framework/") ) && + (tk_hdr || FileTest.directory?(dir + "/Tk.framework/") ) + } + } +end + +tcl_framework_header = with_config("tcl-framework-header") +tk_framework_header = with_config("tk-framework-header") + +tcltk_framework = find_framework(tcl_framework_header, tk_framework_header) + +unless is_win32 + have_library("nsl", "t_open") + have_library("socket", "socket") + have_library("dl", "dlopen") + have_library("m", "log") +end + +tk_idir, tk_ldir = dir_config("tk") +tcl_idir, tcl_ldir = dir_config("tcl") +x11_idir, x11_ldir = dir_config("X11") + +tk_ldir2 = with_config("tk-lib") +tcl_ldir2 = with_config("tcl-lib") +x11_ldir2 = with_config("X11-lib") + +tk_ldir_list = [tk_ldir2, tk_ldir] +tcl_ldir_list = [tcl_ldir2, tcl_ldir] + +tklib = with_config("tklib") +tcllib = with_config("tcllib") +stubs = enable_config("tcltk_stubs") || with_config("tcltk_stubs") + +tcltk_version = with_config("tcltkversion") + +use_X = with_config("X11", (! is_win32)) + +def parse_tclConfig(file) + # check tclConfig.sh/tkConfig.sh + tbl = {} + IO.foreach(file){|line| + line.strip! + next if line !~ /^([^\#=][^=]*)=(['"]|)(.*)\2$/ + key, val = $1, $3 + tbl[key] = val.gsub(/\$\{([^}]+)\}/){|s| tbl[$1]} rescue nil + } + tbl +end + +def check_tcltk_version(version) + return [nil, nil] unless version + + version = version.strip + + tclver = version.dup + tkver = version.dup + + major = dot = minor = dot = plvl = ext = nil + + if version =~ /^(\d)(\.?)(\d)(\.?)(\d*)(.*)$/ + major = $1; minor_dot = $2; minor = $3; plvl_dot = $4; plvl = $5; ext = $6 + dot = ! minor_dot.empty? + if plvl_dot.empty? && ! plvl.empty? + minor << plvl + end + elsif version =~ /^(\d)(\.?)(\d?)(.*)$/ + major = $1; minor_dot = $2; minor = $3; ext = $4 + dot = ! minor_dot.empty? + else # unknown -> believe user + return [tclver, tkver] + end + + # check Tcl7.6 / Tk4.2 ? + if major == "7" # Tcl7.6 ( not support Tclversion < 7.6 ) + # Tk4.2 + tkver = "4" + ((dot)? ".": "") + ((minor.empty)? "": "2") + ext + elsif major == "4" # Tk4.2 ( not support Tkversion < 4.2 ) + # Tcl7.6 + tclver = "7" + ((dot)? ".": "") + ((minor.empty)? "": "6") + ext + end + + [tclver, tkver] +end + +def find_tcl(tcllib, stubs, version, *opt_paths) + default_paths = ["/usr/local/lib", "/usr/pkg/lib", "/usr/lib"] + default_paths << "/Tcl/lib" # default for ActiveTcl + + if (paths = opt_paths.compact).empty? + paths = default_paths + end + + if stubs + func = "Tcl_InitStubs" + lib = "tclstub" + else + func = "Tcl_FindExecutable" + lib = "tcl" + end + + if version && ! version.empty? + versions = [version] + else + versions = %w[8.7 8.6 8.5 8.4 8.3 8.2 8.1 8.0 7.6] + end + + if tcllib + st = find_library(tcllib, func, *paths) + else + st = versions.find { |ver| + find_library("#{lib}#{ver}", func, *paths) or + find_library("#{lib}#{ver.delete('.')}", func, *paths) or + find_library("#{lib}#{ver}g", func, *paths) or + find_library("#{lib}#{ver.delete('.')}g", func, *paths) or + find_library("tcl#{ver}", func, *paths) or + find_library("tcl#{ver.delete('.')}", func, *paths) or + find_library("tcl#{ver}g", func, *paths) or + find_library("tcl#{ver.delete('.')}g", func, *paths) + } || (!version && find_library(lib, func, *paths)) + end + + unless st + puts("Warning:: cannot find Tcl library. tcltklib will not be compiled (tcltklib is disabled on your Ruby == Ruby/Tk will not work). Please check configure options.") + end + st +end + +def find_tk(tklib, stubs, version, *opt_paths) + default_paths = ["/usr/local/lib", "/usr/pkg/lib", "/usr/lib"] + default_paths << "/Tcl/lib" # default for ActiveTcl + + if (paths = opt_paths.compact).empty? + paths = default_paths + end + + if stubs + func = "Tk_InitStubs" + lib = "tkstub" + else + func = "Tk_Init" + lib = "tk" + end + + if version && ! version.empty? + versions = [version] + else + versions = %w[8.7 8.6 8.5 8.4 8.3 8.2 8.1 8.0 4.2] + end + + if tklib + st = find_library(tklib, func, *paths) + else + st = versions.find { |ver| + find_library("#{lib}#{ver}", func, *paths) or + find_library("#{lib}#{ver.delete('.')}", func, *paths) or + find_library("#{lib}#{ver}g", func, *paths) or + find_library("#{lib}#{ver.delete('.')}g", func, *paths) or + find_library("tk#{ver}", func, *paths) or + find_library("tk#{ver.delete('.')}", func, *paths) or + find_library("tk#{ver}g", func, *paths) or + find_library("tk#{ver.delete('.')}g", func, *paths) + } || (!version && find_library(lib, func, *paths)) + end + + unless st + puts("Warning:: cannot find Tk library. tcltklib will not be compiled (tcltklib is disabled on your Ruby == Ruby/Tk will not work). Please check configure options.") + end + st +end + +def find_tcltk_header(tclver, tkver) + base_dir = ['/usr/local/include', '/usr/pkg/include', '/usr/include'] + base_dir << '/Tcl/include' # default for ActiveTcl + + unless have_tcl_h = have_header('tcl.h') + if tclver && ! tclver.empty? + versions = [tclver] + else + versions = %w[8.7 8.6 8.5 8.4 8.3 8.2 8.1 8.0 7.6] + end + paths = base_dir.dup + versions.each{|ver| paths.concat(base_dir.map{|dir| dir + '/tcl' + ver})} + have_tcl_h = find_header('tcl.h', *paths) + end + + unless have_tk_h = have_header("tk.h") + if tkver && ! tkver.empty? + versions = [tkver] + else + versions = %w[8.7 8.6 8.5 8.4 8.3 8.2 8.1 8.0 4.2] + end + paths = base_dir.dup + versions.each{|ver| paths.concat(base_dir.map{|dir| dir + '/tk' + ver})} + have_tk_h = find_header('tk.h', *paths) + end + + have_tcl_h && have_tk_h +end + +def find_X11(*opt_paths) + default_paths = + [ "/usr/X11/lib", "/usr/lib/X11", "/usr/X11R6/lib", "/usr/openwin/lib" ] + paths = opt_paths.compact.concat(default_paths) + st = find_library("X11", "XOpenDisplay", *paths) + unless st + puts("Warning:: cannot find X11 library. tcltklib will not be compiled (tcltklib is disabled on your Ruby == Ruby/Tk will not work). Please check configure options. If your Tcl/Tk don't require X11, please try --without-X11.") + end + st +end + +def pthread_check() + tcl_major_ver = nil + tcl_minor_ver = nil + + # Is tcl-thread given by user ? + case enable_config("tcl-thread") + when true + tcl_enable_thread = true + when false + tcl_enable_thread = false + else + tcl_enable_thread = nil + end + + if (tclConfig = with_config("tclConfig-file")) + if tcl_enable_thread == true + puts("Warning: --with-tclConfig-file option is ignored, because --enable-tcl-thread option is given.") + elsif tcl_enable_thread == false + puts("Warning: --with-tclConfig-file option is ignored, because --disable-tcl-thread option is given.") + else + # tcl-thread is unknown and tclConfig.sh is given + begin + tbl = parse_tclConfig(tclConfig) + if tbl['TCL_THREADS'] + tcl_enable_thread = (tbl['TCL_THREADS'] == "1") + else + tcl_major_ver = tbl['TCL_MAJOR_VERSION'].to_i + tcl_minor_ver = tbl['TCL_MINOR_VERSION'].to_i + if tcl_major_ver < 8 || (tcl_major_ver == 8 && tcl_minor_ver == 0) + tcl_enable_thread = false + end + end + + if tcl_enable_thread == nil + # cannot find definition + if tcl_major_ver + puts("Warning: '#{tclConfig}' doesn't include TCL_THREADS definition.") + else + puts("Warning: '#{tclConfig}' may not be a tclConfig file.") + end + tclConfig = false + end + rescue Exception + puts("Warning: fail to read '#{tclConfig}'!! --> ignore the file") + tclConfig = false + end + end + end + + if tcl_enable_thread == nil && !tclConfig + # tcl-thread is unknown and tclConfig is unavailable + begin + try_run_available = try_run("int main() { exit(0); }") + rescue Exception + # cannot try_run. Is CROSS-COMPILE environment? + puts(%Q'\ +***************************************************************************** +** +** PTHREAD SUPPORT CHECK WARNING: +** +** We cannot check the consistency of pthread support between Ruby +** and the Tcl/Tk library in your environment (are you perhaps +** cross-compiling?). If pthread support for these 2 packages is +** inconsistent you may find you get errors when running Ruby/Tk +** (e.g. hangs or segmentation faults). We strongly recommend +** you to check the consistency manually. +** +***************************************************************************** +') + return true + end + end + + if tcl_enable_thread == nil + # tcl-thread is unknown + if try_run(< +int main() { + Tcl_Interp *ip; + ip = Tcl_CreateInterp(); + exit((Tcl_Eval(ip, "set tcl_platform(threaded)") == TCL_OK)? 0: 1); +} +EOF + tcl_enable_thread = true + elsif try_run(< +static Tcl_ThreadDataKey dataKey; +int main() { exit((Tcl_GetThreadData(&dataKey, 1) == dataKey)? 1: 0); } +EOF + tcl_enable_thread = true + else + tcl_enable_thread = false + end + end + + # check pthread mode + if (macro_defined?('HAVE_NATIVETHREAD', '#include "ruby.h"')) + # ruby -> enable + unless tcl_enable_thread + # ruby -> enable && tcl -> disable + puts(%Q'\ +***************************************************************************** +** +** PTHREAD SUPPORT MODE WARNING: +** +** Ruby is compiled with --enable-pthread, but your Tcl/Tk library +** seems to be compiled without pthread support. Although you can +** create the tcltklib library, this combination may cause errors +** (e.g. hangs or segmentation faults). If you have no reason to +** keep the current pthread support status, we recommend you reconfigure +** and recompile the libraries so that both or neither support pthreads. +** +** If you want change the status of pthread support, please recompile +** Ruby without "--enable-pthread" configure option or recompile Tcl/Tk +** with "--enable-threads" configure option (if your Tcl/Tk is later +** than or equal to Tcl/Tk 8.1). +** +***************************************************************************** +') + end + + # ruby -> enable && tcl -> enable/disable + if tcl_enable_thread + $CPPFLAGS += ' -DWITH_TCL_ENABLE_THREAD=1' + else + $CPPFLAGS += ' -DWITH_TCL_ENABLE_THREAD=0' + end + + return true + + else + # ruby -> disable + if tcl_enable_thread + # ruby -> disable && tcl -> enable + puts(%Q'\ +***************************************************************************** +** +** PTHREAD SUPPORT MODE ERROR: +** +** Ruby is not compiled with --enable-pthread, but your Tcl/Tk +** library seems to be compiled with pthread support. This +** combination may cause frequent hang or segmentation fault +** errors when Ruby/Tk is working. We recommend that you NEVER +** create the library with such a combination of pthread support. +** +** Please recompile Ruby with the "--enable-pthread" configure option +** or recompile Tcl/Tk with the "--disable-threads" configure option. +** +***************************************************************************** +') + $CPPFLAGS += ' -DWITH_TCL_ENABLE_THREAD=1' + return false + else + # ruby -> disable && tcl -> disable + $CPPFLAGS += ' -DWITH_TCL_ENABLE_THREAD=0' + return true + end + end +end + +tclver, tkver = check_tcltk_version(tcltk_version) + +if ( tcltk_framework || + ( find_tcltk_header(tclver, tkver) && + ( !use_X || find_X11(x11_ldir2, x11_ldir) ) && + find_tcl(tcllib, stubs, tclver, *tcl_ldir_list) && + find_tk(tklib, stubs, tkver, *tk_ldir_list) ) ) + $CPPFLAGS += ' -DUSE_TCL_STUBS -DUSE_TK_STUBS' if stubs + $CPPFLAGS += ' -D_WIN32' if /cygwin/ =~ RUBY_PLATFORM + + if tcltk_framework + if tcl_framework_header + $CPPFLAGS += " -I#{tcl_framework_header}" + else + $CPPFLAGS += " -I#{tcltk_framework}/Tcl.framework/Headers" + end + + if tk_framework_header + $CPPFLAGS += " -I#{tk_framework_header}" + else + $CPPFLAGS += " -I#{tcltk_framework}/Tk.framework/Headers" + end + + $LDFLAGS += ' -framework Tk -framework Tcl' + end + + if stubs or pthread_check + # create Makefile + + # for SUPPORT_STATUS + $INSTALLFILES ||= [] + $INSTALLFILES << ["lib/tkextlib/SUPPORT_STATUS", "$(RUBYLIBDIR)", "lib"] + + have_func("rb_hash_lookup", "ruby.h") + + # create + $defs << %[-DRUBY_VERSION=\\"#{RUBY_VERSION}\\"] + $defs << %[-DRUBY_RELEASE_DATE=\\"#{RUBY_RELEASE_DATE}\\"] + create_makefile("tcltklib") + end +end diff --git a/version.h b/version.h index 39b949da9a..49affc1877 100644 --- a/version.h +++ b/version.h @@ -2,7 +2,7 @@ #define RUBY_RELEASE_DATE "2011-06-26" #define RUBY_VERSION_CODE 187 #define RUBY_RELEASE_CODE 20110626 -#define RUBY_PATCHLEVEL 349 +#define RUBY_PATCHLEVEL 350 #define RUBY_VERSION_MAJOR 1 #define RUBY_VERSION_MINOR 8 -- cgit v1.2.3