1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
ruby--ruby/ext/tk/extconf.rb
nagai 5d639de5d3 * ext/tk/extconf.rb: better support for MinGW environment.
* ext/tk/README.tcltklib: add info of --with-tcltk-drive for Windows.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27562 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2010-04-30 06:41:01 +00:00

1654 lines
52 KiB
Ruby

##############################################################
# extconf.rb for tcltklib
# release date: 2010-04-30
##############################################################
require 'mkmf'
#$VERBOSE=true
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]
##############################################################
# use old extconf.rb ?
##############################################################
if with_config('tk-old-extconf')
require File.join(File.dirname(__FILE__), 'old-extconf.rb')
exit
end
##############################################################
# 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
current_configs = {'with'=>{}, 'enable'=>{}}
# 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
}
# 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
}
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
}
# 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
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.delete(*Dir.glob("*.#{$OBJEXT}"))
File.delete('Makefile') rescue nil
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
def win_drive
drive = with_config("windows-tcltk-drive", "c")
case(RUBY_PLATFORM)
when /cygwin/
["/cygdrive/#{drive}", "/cygdrive/[A-Za-z]"]
else
["#{drive}:", "[A-Za-z]:"]
end
end
def is_macosx?
/darwin/ =~ RUBY_PLATFORM
end
def check_tcltk_version(version)
return [nil, nil] unless version.kind_of? String
version = version.strip
tclver = version.dup
tkver = version.dup
dot = major = minor_dot = minor = plvl_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 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
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_dirs.concat Dir.glob(TkLib_Config["ActiveTcl"]).sort.reverse
end
if is_win32?
drive, drv_regexp = win_drive
if TkLib_Config["ActiveTcl"]
path_head.concat [
"#{drive}/ActiveTcl*", "#{drive}/Activetcl*",
"#{drive}/activeTcl*", "#{drive}/activetcl*",
"#{drive}/Program Files/ActiveTcl*",
"#{drive}/Program Files/Activetcl*",
"#{drive}/Program Files/activeTcl*",
"#{drive}/Program Files/activetcl*",
"/ActiveTcl*", "/Activetcl*", "/activeTcl*", "/activetcl*",
"/Program Files/ActiveTcl*", "/Program Files/Activetcl*",
"/Program Files/activeTcl*", "/Program Files/activetcl*"
]
end
path_head.concat [
"#{drive}/Tcl*", "#{drive}/tcl*",
"#{drive}/Program Files/Tcl*", "#{drive}/Program Files/tcl*",
"/Tcl*", "/tcl*", "/Program Files/Tcl*", "/Program Files/tcl*"
]
path_head.map!{|d|
[Dir.glob(d).sort.reverse,
Dir.glob(d.sub(%r|^(#{drv_regexp})?/([^/])|, '\1//\2')).sort.reverse]
}.flatten!
ENV['PATH'].split(File::PATH_SEPARATOR).each{|dir|
path_head << dir
path_head << File.expand_path(File.join(dir, '..'))
if dir.gsub!(/\\/, '/')
path_head << dir
path_head << File.expand_path(File.join(dir, '..'))
end
if dir.sub!(%r|^(#{drv_regexp})?/([^/])|, '\1//\2')
path_head << dir
path_head << File.expand_path(File.join(dir, '..'))
end
}
path_head |= path_head
path_head.each{|dir|
path_dirs << dir
dir = File.join(dir, "lib")
path_dirs << dir if File.directory?(dir)
}
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}/lib"
path_dirs << "#{dir}" unless Dir.glob("#{dir}/lib*.*").empty?
dirnames = []
if TkLib_Config["ActiveTcl"]
dirnames.concat ["ActiveTcl","activeTcl","Activetcl","activetcl"]
end
dirnames.concat ["TclTk","Tcl_Tk","Tcl-Tk","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_]*").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.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}.join(' ')
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
libpath = lib_spec.gsub(/(#{lib_flag}|-L)/, "").strip
end
def get_tclConfig_dirs
config_dir = []
if is_win32?
drive, drv_regexp = win_drive
if TkLib_Config["ActiveTcl"]
dirs = []
if TkLib_Config["ActiveTcl"].kind_of?(String)
dirs << TkLib_Config["ActiveTcl"]
end
dirs.concat [
"#{drive}/ActiveTcl*/lib", "#{drive}/Activetcl*/lib",
"#{drive}/activeTcl*/lib", "#{drive}/activetcl*/lib",
"#{drive}/Tcl*/lib", "#{drive}/tcl*/lib",
"#{drive}/Program Files/ActiveTcl*/lib",
"#{drive}/Program Files/Activetcl*/lib",
"#{drive}/Program Files/activeTcl*/lib",
"#{drive}/Program Files/activetcl*/lib",
"#{drive}/Program Files/Tcl*/lib", "#{drive}/Program Files/tcl*/lib",
"/ActiveTcl*/lib", "/Activetcl*/lib",
"/activeTcl*/lib", "/activetcl*/lib",
"/Tcl*/lib", "/tcl*/lib",
"/Program Files/ActiveTcl*/lib", "/Program Files/Activetcl*/lib",
"/Program Files/activeTcl*/lib", "/Program Files/activetcl*/lib",
"/Program Files/Tcl*/lib", "/Program Files/tcl*/lib"
]
else
dirs = [
"#{drive}/Tcl*/lib", "#{drive}/tcl*/lib",
"#{drive}/Program Files/Tcl*/lib", "#{drive}/Program Files/tcl*/lib",
"/Tcl*/lib", "/tcl*/lib",
"/Program Files/Tcl*/lib", "/Program Files/tcl*/lib"
]
end
dirs.map!{|d|
[Dir.glob(d).sort.reverse,
Dir.glob(d.sub(%r|^(#{drv_regexp})?/([^/])|, '\1//\2')).sort.reverse]
}.flatten!
ENV['PATH'].split(File::PATH_SEPARATOR).each{|dir|
dirs << File.expand_path(File.join(dir, '..', 'lib'))
dirs << dir
dirs << File.expand_path(File.join(dir, '..'))
if dir.gsub!(/\\/, '/')
dirs << File.expand_path(File.join(dir, '..', 'lib'))
dirs << dir
dirs << File.expand_path(File.join(dir, '..'))
end
if dir.sub!(%r|^(#{drv_regexp})?/([^/])|, '\1//\2')
dirs << File.expand_path(File.join(dir, '..', 'lib'))
dirs << dir
dirs << File.expand_path(File.join(dir, '..'))
end
}
dirs |= dirs
unless TkLib_Config["space-on-tk-libpath"]
dirs.delete_if{|path| path =~ / /}
end
config_dir.concat(dirs.zip(dirs))
elsif framework = find_macosx_framework()
config_dir.unshift(framework)
else
if activeTcl = TkLib_Config['ActiveTcl']
# check latest version at first
config_dir.concat(Dir.glob(activeTcl).sort.reverse)
end
config_dir.concat [
RbConfig::CONFIG['libdir'],
File.join(RbConfig::CONFIG['exec_prefix'], 'lib'),
File.join(RbConfig::CONFIG['prefix'], 'lib'),
"/usr/local/opt/lib", "/usr/local/pkg/lib", "/usr/local/share/lib",
"/usr/local/lib", "/usr/opt/lib", "/usr/pkg/lib",
"/usr/share/lib", "/usr/contrib/lib", "/usr/lib"
]
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,tcltk,Tcl,tcl,Tk,tk}[987]*/lib')
Dir.glob(dir + '/{TclTk,tcltk,Tcl,tcl,Tk,tk}[987]*')
Dir.glob(dir + '/{TclTk,tcltk,Tcl,tcl,Tk,tk}/lib')
Dir.glob(dir + '/{TclTk,tcltk,Tcl,tcl,Tk,tk}')
}.flatten!
ENV['PATH'].split(File::PATH_SEPARATOR).each{|dir|
config_dir << File.expand_path(File.join(dir, '..', 'lib'))
}
# for MacOS X
#config_dir << "~/Library/Tcl"
#config_dir.concat(Dir.glob("~/Library/Tcl/*").sort.reverse)
config_dir << "/Library/Tcl"
config_dir.concat(Dir.glob("/Library/Tcl/*").sort.reverse)
config_dir << "/Network/Library/Tcl"
config_dir.concat(Dir.glob("/Network/Library/Tcl/*").sort.reverse)
config_dir << "/System/Library/Tcl"
config_dir.concat(Dir.glob("/System/Library/Tcl/*").sort.reverse)
[
#"~/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'))]
}
end
config_dir
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
else
# fixed tclConfig
config_dir = []
paths.each{|path|
if path.kind_of?(Array)
config_dir << path
else
dirs = Dir.glob(path)
config_dir.concat(dirs.zip(dirs))
end
}
end
tclver, tkver = TkLib_Config['tcltkversion']
conf = nil
(config_dir | config_dir).map{|dir|
if dir.kind_of? Array
[dir[0].strip.chomp('/'), dir[1].strip.chomp('/')]
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
if enable_config("shared") == false
tails = ['Config.sh', 'config.sh', 'Config-shared.sh', 'config-shared.sh']
else
tails = ['Config-shared.sh', 'config-shared.sh', 'Config.sh', 'config.sh']
end
if File.file?(tcldir)
tclcfg_files = [tcldir] * tails.length
else
tclcfg_files = tails.map{|f| File.join(tcldir, 'tcl' << f)}
end
if File.file?(tkdir)
tkcfg_files = [tkdir] * tails.length
else
tkcfg_files = tails.map{|f| File.join(tcldir, 'tk' << f)}
end
tclcfg_files.zip(tkcfg_files).uniq.each{|tclpath, tkpath|
next if !File.exist?(tclpath) || !File.exist?(tkpath)
# parse tclConfig.sh/tkConfig.sh
tclconf = parse_tclConfig(tclpath)
next if tclver && tclver !~ /^#{tclconf['TCL_MAJOR_VERSION']}(\.?)#{tclconf['TCL_MINOR_VERSION']}/
tkconf = parse_tclConfig(tkpath)
next if tkver && tkver !~ /^#{tkconf['TK_MAJOR_VERSION']}(\.?)#{tkconf['TK_MINOR_VERSION']}/
# nativethread check
if !TkLib_Config["ruby_with_thread"] && tclconf['TCL_THREADS'] == '1'
puts "WARNIG: find #{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
# find tclConfig.sh & tkConfig.sh
conf = [tclconf, tkconf] unless conf
# check Tcl library
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']}*.*")).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']}*.*")).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 "WARNIG: find #{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
#return [tclpath, tkpath]
# print(" #{[tclpath, tkpath].inspect}");
TkLib_Config["tclConfig_paths"] << [tclpath, tkpath]
}
# print("\n");
}
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) && (tkConfig_file != false) &&
(tclConfig_dir != false) && (tkConfig_dir != false)
unless use_tclConfig
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
unless tclConfig_dir
if tclConfig_file
tclConfig_dir = File.dirname(tclConfig_file)
elsif tkConfig_dir
tclConfig_dir = tkConfig_dir
end
end
unless tkConfig_dir
if tkConfig_file
tkConfig_dir = File.dirname(tkConfig_file)
elsif tclConfig_dir
tkConfig_dir = tclConfig_dir
end
end
tkConfig_dir ||= tclConfig_dir
TkLib_Config["tclConfig-file"] = tclConfig_file
TkLib_Config["tkConfig-file"] = tkConfig_file
TkLib_Config["tclConfig-dir"] = tclConfig_dir
TkLib_Config["tkConfig-dir"] = tkConfig_dir
print("Search tclConfig.sh", (tclConfig_dir)? " (in #{tclConfig_dir})": "",
" and tkConfig.sh", (tkConfig_dir)? " (in #{tkConfig_dir})": "", ".")
if tclConfig_dir
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|
File.dirname(tclpath)
}
dirs |= dirs
puts("Valid tclConfig.sh and tkConfig.sh are found in #{dirs.inspect}")
puts("Use [tclConfig.sh,tkConfig.sh] == ['#{tclConfig}','#{tkConfig}']")
$LIBPATH |= [File.dirname(tclConfig)]
$LIBPATH |= [File.dirname(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_NG_path(path_list)
path_list.find_all{|path| not TkLib_Config["tcltk-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"]).sort.reverse
#end
if TkLib_Config["ActiveTcl"].kind_of?(String) # glob path
path_list.concat Dir.glob(TkLib_Config["ActiveTcl"]).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 + "-*").empty?
dirs << head + "-#{ver}/lib" if !Dir.glob(head + "-[987].*").empty?
dirs << head + "-#{ver.delete('.')}/lib" if !Dir.glob(head + "-[987][0-9]*").empty?
end
if !Dir.glob(head + "[_-]*").empty?
dirs << head + "_#{ver}/lib" if !Dir.glob(head + "_[987].*").empty?
dirs << head + "-#{ver}/lib" if !Dir.glob(head + "-[987].*").empty?
dirs << head + "_#{ver.delete('.')}/lib" if !Dir.glob(head + "_[987][0-9]*").empty?
dirs << head + "-#{ver.delete('.')}/lib" if !Dir.glob(head + "-[987][0-9]*").empty?
end
dirs
end
}
}.flatten!
path_list.concat path_dirs
else
# paths is a string with PATH environment style
path_list = paths.split(File::PATH_SEPARATOR)
#path_list = paths.split((is_win32?)? ';': ':')
end
path_list = check_NG_path(path_list)
if is_win32?
# exist-dir only
drive, drv_regexp = win_drive
path_list.each{|path|
path = path.strip;
#$LIBPATH |= [path] if File.directory?(path)
$LIBPATH |= [path.sub(%r|^(#{drv_regexp})?//|, '\1/')] unless Dir.glob(File.join(path, "*.{a,so,dll,lib}")).empty?
}
else
# keep paths for searching dynamic libs
path_list.each{|path| $LIBPATH |= [path.strip] }
end
end
def search_vers_on_path(vers, path, *heads)
if enable_config("shared") == false
exts = CONFIG['LIBEXT'] + ',' + CONFIG['DLEXT']
exts << ",lib,dll" if is_win32?
exts << ",bundle,dylib" if is_macosx? || /nextstep|openstep|rhapsody/ =~ RUBY_PLATFORM
else
exts = CONFIG['DLEXT'] + ',' + CONFIG['LIBEXT']
exts << ",dll,lib" if is_win32?
exts << ",dylib,bundle" if is_macosx? || /nextstep|openstep|rhapsody/ =~ RUBY_PLATFORM
end
files = Dir.glob(File.join(path, "*{#{heads.join(',')}}*.{#{exts}}"))
files |= files
vers.find_all{|ver| files.find{|f| f =~ /(#{ver}|#{ver.delete('.')})/} }
end
def find_tcl(tcllib, stubs, version, *opt_paths)
print "Search Tcl library"
if stubs
func = "Tcl_InitStubs"
lib = "tclstub"
else
func = "Tcl_FindExecutable"
lib = "tcl"
end
if version && ! version.empty?
versions = [version]
else
versions = TkLib_Config['search_versions']
end
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)}
if TkLib_Config["ActiveTcl"].kind_of?(String) # glob path
default_paths.concat Dir.glob(TkLib_Config["ActiveTcl"]).sort.reverse.map{|d| d << "/lib"}
end
if is_win32?
drive, drv_regexp = win_drive
if TkLib_Config["ActiveTcl"]
default_paths.concat [
"#{drive}/ActiveTcl*", "#{drive}/Activetcl*",
"#{drive}/activeTcl*", "#{drive}/activetcl*",
"#{drive}/Program Files/ActiveTcl*",
"#{drive}/Program Files/Activetcl*",
"#{drive}/Program Files/activeTcl*",
"#{drive}/Program Files/activetcl*",
"/ActiveTcl*", "/Activetcl*", "/activeTcl*", "/activetcl*",
"/Program Files/ActiveTcl*", "/Program Files/Activetcl*",
"/Program Files/activeTcl*", "/Program Files/activetcl*"
].map{|d| d << "/lib"}
end
default_paths.concat [
"#{drive}/Tcl*", "#{drive}/tcl*",
"#{drive}/Program Files/Tcl*", "#{drive}/Program Files/tcl*",
"/Tcl*", "/tcl*", "/Program Files/Tcl*", "/Program Files/tcl*",
].map{|d| d << "/lib"}
default_paths.map{|d|
[Dir.glob(d).sort.reverse,
Dir.glob(d.sub(%r|^(#{drv_regexp})?/([^/])|, '\1//\2')).sort.reverse]
}.flatten.find_all{|dir| File.directory?(dir)}
end
env_paths = []
ENV['PATH'].split(File::PATH_SEPARATOR).each{|dir|
env_paths << File.expand_path(File.join(dir, '..', 'lib'))
env_paths << dir
env_paths << File.expand_path(File.join(dir, '..'))
if is_win32?
if dir.gsub!(/\\/, '/')
env_paths << File.expand_path(File.join(dir, '..', 'lib'))
env_paths << dir
env_paths << File.expand_path(File.join(dir, '..'))
end
if dir.sub!(%r|^(#{drv_regexp})?/([^/])|, '\1//\2')
env_paths << File.expand_path(File.join(dir, '..', 'lib'))
env_paths << dir
env_paths << File.expand_path(File.join(dir, '..'))
end
end
}
if is_win32?
env_paths = env_paths.find_all{|d|
not (Dir.glob(File.join(d, "*[Tt]cl*")) | Dir.glob(File.join(d.sub(%r|^(#{drv_regexp})?/([^/])|, '\1//\2'), "*[Tt]cl*"))).empty?
}
else
env_paths = env_paths.find_all{|d|
not (Dir.glob(File.join(d, "*[Tt]cl*"))).empty?
}
end
default_paths.concat env_paths
default_paths |= default_paths
unless TkLib_Config["space-on-tk-libpath"]
default_paths.delete_if{|path| path =~ / /}
end
if (paths = opt_paths.compact).empty?
unless TclConfig_Info['config_file_path']
paths = check_NG_path(default_paths)
else
# use definisions on tclConfig.sh
TclConfig_Info['TCL_LIB_SPEC'].sub(TclConfig_Info['TCL_LIB_FLAG'],"").strip.sub("-L","") =~ /("|'|)([^"']+)\1/
$LIBPATH |= [$2] unless $2.empty?
if stubs
if TclConfig_Info['TCL_SUPPORTS_STUBS'] == '0' ||
TclConfig_Info['TCL_STUB_LIB_SPEC'].strip.empty?
print(".\n") # progress
puts "#{TclConfig_Info['config_file_path']} tells us that your Tcl/Tk library doesn't support stub."
return false
else
#*** Probably, TCL_LIBS is a subset of TK_LIBS. ***
unless is_win32? # ignore tclConfig on Windows
# $LDFLAGS << ' ' << TclConfig_Info['TCL_LIBS']
# $DLDFLAGS << ' ' << TclConfig_Info['TCL_LIBS']
$LDFLAGS << ' ' << TclConfig_Info['TCL_STUB_LIB_SPEC']
end
end
else
#*** Probably, TCL_LIBS is a subset of TK_LIBS. ***
unless is_win32? # ignore tclConfig on Windows
# $LDFLAGS << ' ' << TclConfig_Info['TCL_LIBS']
# $DLDFLAGS << ' ' << TclConfig_Info['TCL_LIBS']
$LDFLAGS << ' ' << TclConfig_Info['TCL_LIB_SPEC']
end
end
paths = [File.dirname(TclConfig_Info['config_file_path'])]
versions = [TclConfig_Info['TCL_VERSION']]
end
end
ret = paths.find{|path|
if tcllib
print(".")
find_library(tcllib, func, path)
else
search_vers_on_path(versions, path, lib, 'tcl').find{|ver|
(print(".");find_library("#{lib}#{ver}", func, path)) or
(print(".");find_library("#{lib}#{ver.delete('.')}", func, path)) or
(print(".");find_library("#{lib}#{ver}g", func, path)) or
(print(".");find_library("#{lib}#{ver.delete('.')}g", func, path)) or
(print(".");find_library("tcl#{ver}", func, path)) or
(print(".");find_library("tcl#{ver.delete('.')}", func, path)) or
(print(".");find_library("tcl#{ver}g", func, path)) or
(print(".");find_library("tcl#{ver.delete('.')}g", func, path))
} || (!version && (print(".");find_library(lib, func, path)))
end
}
print("\n") # progress
print("Found a Tcl library at #{ret}.\n") if ret
ret
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)
print "Search Tk library"
if stubs
func = "Tk_InitStubs"
lib = "tkstub"
else
func = "Tk_Init"
lib = "tk"
end
if version && ! version.empty?
versions = [version]
else
versions = TkLib_Config['search_versions']
end
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)}
if TkLib_Config["ActiveTcl"].kind_of?(String) # glob path
default_paths.concat Dir.glob(TkLib_Config["ActiveTcl"]).sort.reverse.map{|d| d << "/lib"}
end
if is_win32?
drive, drv_regexp = win_drive
if TkLib_Config["ActiveTcl"]
default_paths.concat [
"#{drive}/ActiveTcl*", "#{drive}/Activetcl*",
"#{drive}/activeTcl*", "#{drive}/activetcl*",
"#{drive}/Program Files/ActiveTcl*",
"#{drive}/Program Files/Activetcl*",
"#{drive}/Program Files/activeTcl*",
"#{drive}/Program Files/activetcl*",
"/ActiveTcl*", "/Activetcl*", "/activeTcl*", "/activetcl*",
"/Program Files/ActiveTcl*", "/Program Files/Activetcl*",
"/Program Files/activeTcl*", "/Program Files/activetcl*"
].map{|d| d << "/lib"}
end
default_paths.concat [
"#{drive}/Tcl*", "#{drive}/tcl*",
"#{drive}/Program Files/Tcl*", "#{drive}/Program Files/tcl*",
"/Tcl*", "/tcl*", "/Program Files/Tcl*", "/Program Files/tcl*",
].map{|d| d << "/lib"}
default_paths.map{|d|
[Dir.glob(d).sort.reverse,
Dir.glob(d.sub(%r|^(#{drv_regexp})?/([^/])|, '\1//\2')).sort.reverse]
}.flatten.find_all{|dir| File.directory?(dir)}
end
env_paths = []
ENV['PATH'].split(File::PATH_SEPARATOR).each{|dir|
env_paths << File.expand_path(File.join(dir, '..', 'lib'))
env_paths << dir
env_paths << File.expand_path(File.join(dir, '..'))
if is_win32?
if dir.gsub!(/\\/, '/')
env_paths << File.expand_path(File.join(dir, '..', 'lib'))
env_paths << dir
env_paths << File.expand_path(File.join(dir, '..'))
end
if dir.sub!(%r|^(#{drv_regexp})?/([^/])|, '\1//\2')
env_paths << File.expand_path(File.join(dir, '..', 'lib'))
env_paths << dir
env_paths << File.expand_path(File.join(dir, '..'))
end
end
}
if is_win32?
env_paths = env_paths.find_all{|d|
not (Dir.glob(File.join(d, "*[Tt]k*")) | Dir.glob(File.join(d.sub(%r|^(#{drv_regexp})?/([^/])|, '\1//\2'), "*[Tt]k*"))).empty?
}
else
env_paths = env_paths.find_all{|d|
not (Dir.glob(File.join(d, "*[Tt]k*"))).empty?
}
end
default_paths.concat env_paths
default_paths |= default_paths
unless TkLib_Config["space-on-tk-libpath"]
default_paths.delete_if{|path| path =~ / /}
end
if (paths = opt_paths.compact).empty?
unless TkConfig_Info['config_file_path']
paths = check_NG_path(default_paths)
else
# use definisions on tkConfig.sh
TkConfig_Info['TK_LIB_SPEC'].sub(TkConfig_Info['TK_LIB_FLAG'],"").strip.sub("-L","") =~ /("|'|)([^"']+)\1/
$LIBPATH |= [$2] unless $2.empty?
if stubs
if TkConfig_Info['TK_STUB_LIB_SPEC'].strip.empty?
print(".\n") # progress
puts "#{TkConfig_Info['config_file_path']} tells us that your Tcl/Tk library doesn't support stub."
return false
else
unless is_win32? # ignore tclConfig on Windows
# $LDFLAGS << ' ' << parse_TK_LIBS(TkConfig_Info['TK_LIBS'])
$LDFLAGS << ' ' << TkConfig_Info['TK_LIBS']
# $DLDFLAGS << ' ' << parse_TK_LIBS(TkConfig_Info['TK_LIBS'])
$LDFLAGS << ' ' << TkConfig_Info['TK_STUB_LIB_SPEC']
end
end
else
unless is_win32? # ignore tclConfig on Windows
# $LDFLAGS << ' ' << parse_TK_LIBS(TkConfig_Info['TK_LIBS'])
$LDFLAGS << ' ' << TkConfig_Info['TK_LIBS'] unless is_win32?
# $DLDFLAGS << ' ' << parse_TK_LIBS(TkConfig_Info['TK_LIBS'])
$LDFLAGS << ' ' << TkConfig_Info['TK_LIB_SPEC'] unless is_win32?
end
end
paths = [File.dirname(TkConfig_Info['config_file_path'])]
versions = [TkConfig_Info['TK_VERSION']]
end
end
ret = paths.find{|path|
if tklib
print(".")
find_library(tklib, func, path)
else
search_vers_on_path(versions, path, lib, 'tk').find{|ver|
(print(".");find_library("#{lib}#{ver}", func, path)) or
(print(".");find_library("#{lib}#{ver.delete('.')}", func, path)) or
(print(".");find_library("#{lib}#{ver}g", func, path)) or
(print(".");find_library("#{lib}#{ver.delete('.')}g", func, path)) or
(print(".");find_library("tk#{ver}", func, path)) or
(print(".");find_library("tk#{ver.delete('.')}", func, path)) or
(print(".");find_library("tk#{ver}g", func, path)) or
(print(".");find_library("tk#{ver.delete('.')}g", func, path))
} || (!version && (print(".");find_library(lib, func, path)))
end
}
print("\n") # progress
print("Found a Tk library at #{ret}.\n") if ret
ret
end
def find_tcltk_library(tcllib, tklib, stubs, tclversion, tkversion,
tcl_opt_paths, tk_opt_paths)
unless find_tcl(tcllib, stubs, tclversion, *tcl_opt_paths)
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.")
return false
end
unless find_tk(tklib, stubs, tkversion, *tk_opt_paths)
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.")
return false
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)}
if TkLib_Config["ActiveTcl"].kind_of?(String) # glob path
base_dir.concat Dir.glob(TkLib_Config["ActiveTcl"]).sort.reverse.map{|d| d << "/include"}
end
if is_win32?
drive, drv_regexp = win_drive
if TkLib_Config["ActiveTcl"]
base_dir.concat [
"#{drive}/ActiveTcl*", "#{drive}/Activetcl*",
"#{drive}/activeTcl*", "#{drive}/activetcl*",
"#{drive}/Program Files/ActiveTcl*",
"#{drive}/Program Files/Activetcl*",
"#{drive}/Program Files/activeTcl*",
"#{drive}/Program Files/activetcl*",
"/ActiveTcl*", "/Activetcl*", "/activeTcl*", "/activetcl*",
"/Program Files/ActiveTcl*", "/Program Files/Activetcl*",
"/Program Files/activeTcl*", "/Program Files/activetcl*"
].map{|d| d << "/include"}
end
base_dir.concat [
"#{drive}/Tcl*/include", "#{drive}/tcl*/include",
"#{drive}/Program Files/Tcl*/include",
"#{drive}/Program Files/tcl*/include",
"/Tcl*/include", "/tcl*/include",
"/Program Files/Tcl*/include", "/Program Files/tcl*/include",
]
base_dir.map{|d|
[Dir.glob(d).sort.reverse,
Dir.glob(d.sub(%r|^(#{drv_regexp})?/([^/])|, '\1//\2')).sort.reverse]
}.flatten.find_all{|dir| File.directory?(dir)}
ENV['PATH'].split(File::PATH_SEPARATOR).each{|dir|
base_dir << File.expand_path(File.join(dir, '..', 'include'))
base_dir << dir
base_dir << File.expand_path(File.join(dir, '..'))
if dir.gsub!(/\\/, '/')
base_dir << File.expand_path(File.join(dir, '..', 'include'))
base_dir << dir
base_dir << File.expand_path(File.join(dir, '..'))
end
if dir.sub!(%r|^(#{drv_regexp})?/([^/])|, '\1//\2')
base_dir << File.expand_path(File.join(dir, '..', 'include'))
base_dir << dir
base_dir << File.expand_path(File.join(dir, '..'))
end
}
end
base_dir |= base_dir
unless TkLib_Config["space-on-tk-libpath"]
base_dir.delete_if{|path| path =~ / /}
end
if TclConfig_Info['TCL_INCLUDE_SPEC'] &&
have_tcl_h = try_cpp('tcl.h', TclConfig_Info['TCL_INCLUDE_SPEC'])
$INCFLAGS << " " << TclConfig_Info['TCL_INCLUDE_SPEC']
elsif have_tcl_h = have_header('tcl.h')
# find
else
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.delete('.')]
}.flatten)
}
have_tcl_h = find_header('tcl.h', *paths)
end
if TkConfig_Info['TK_INCLUDE_SPEC'] &&
have_tk_h = try_cpp('tk.h', TkConfig_Info['TK_INCLUDE_SPEC'])
$INCFLAGS << " " << TkConfig_Info['TK_INCLUDE_SPEC']
elsif have_tk_h = have_header('tk.h')
# find
else
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.delete('.')]
}.flatten)
}
have_tk_h = find_header('tk.h', *paths)
end
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'))
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'))[0]} "
end
$LDFLAGS << ' -framework Tk -framework Tcl'
if TkLib_Config["tcl-framework-header"]
TclConfig_Info['TCL_INCLUDE_SPEC'] =
"-I#{TkLib_Config["tcl-framework-header"]} "
end
if TkLib_Config["tk-framework-header"]
TkConfig_Info['TK_INCLUDE_SPEC'] =
"-I#{TkLib_Config["tk-framework-header"]} "
end
end
def find_X11(*opt_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('/')))}
defaults.compact.each{|path| paths.concat(Dir.glob(path.strip.chomp('/')))}
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 search_X_libraries
if TkConfig_Info['config_file_path']
# use definitions on tkConfig.sh
if TkConfig_Info['TK_XINCLUDES'] && TkConfig_Info['TK_XLIBSW'] &&
!TkConfig_Info['TK_XINCLUDES'].strip.empty? &&
!TkConfig_Info['TK_XLIBSW'].strip.empty?
#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 use_X
puts("Use X11 libraries.")
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. So, can't make tcltklib.so which is required by Ruby/Tk.")
exit
end
if TkConfig_Info['TK_XINCLUDES'] &&
!TkConfig_Info['TK_XINCLUDES'].strip.empty?
$INCFLAGS << " " << TkConfig_Info['TK_XINCLUDES'].strip
end
end
use_X
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_Info['config_file_path']
if tcl_enable_thread == true
puts("Warning: definiton of tclConfig.sh is ignored, because --enable-tcl-thread option is given.")
elsif tcl_enable_thread == false
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
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
# 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
tclConfig = false
end
end
end
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); }")
rescue Exception
# cannot try_run. Is CROSS-COMPILE environment?
puts(%Q'\
*****************************************************************************
**
** NATIVETHREAD SUPPORT CHECK WARNING:
**
** 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.
**
*****************************************************************************
')
return true
end
end
if tcl_enable_thread == nil
# tcl-thread is unknown
if try_run(<<EOF)
#include <tcl.h>
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(<<EOF)
#include <tcl.h>
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 (TkLib_Config["ruby_with_thread"])
# ruby -> enable
unless tcl_enable_thread
# ruby -> enable && tcl -> disable
puts(%Q'\
*****************************************************************************
**
** NATIVETHREAD SUPPORT MODE WARNING:
**
** Ruby is compiled with --enable-pthread, but your Tcl/Tk library
** 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 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).
**
*****************************************************************************
')
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'\
*****************************************************************************
**
** NATIVETHREAD SUPPORT MODE ERROR:
**
** 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 nativethread 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
##############################################################
# 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 += ' -D_WIN32' if /cygwin/ =~ RUBY_PLATFORM
# Does ruby have nativethread ?
TkLib_Config["ruby_with_thread"] =
macro_defined?('HAVE_NATIVETHREAD', '#include "ruby.h"')
#---------------------------------------------------
# check requirement of Tcl/tk version
tcltk_version = with_config("tcltkversion")
tclver, tkver =
TkLib_Config["tcltkversion"] = check_tcltk_version(tcltk_version)
puts("Specified Tcl/Tk version is #{[tclver, tkver].inspect}") if tclver&&tkver
# use ActiveTcl ?
#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
end
TkLib_Config["ActiveTcl"] = activeTcl
# 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 += ' -DUSE_TCL_STUBS -DUSE_TK_STUBS'
end
# directory configuration of Tcl/Tk libraries
tk_idir, tk_ldir = dir_config("tk")
tcl_idir, tcl_ldir = dir_config("tcl")
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
# get tclConfig.sh/tkConfig.sh
TkLib_Config["tcltk-NG-path"] = []
tclcfg, tkcfg = get_tclConfig(with_config("tclConfig-file", true),
with_config("tkConfig-file", true),
with_config("tclConfig-dir", tcl_ldir || true),
with_config("tkConfig-dir", tk_ldir || true))
TclConfig_Info = TkLib_Config["tclConfig_info"] || {}
TkConfig_Info = TkLib_Config["tkConfig_info"] || {}
TclConfig_Info['config_file_path'] = tclcfg
TkConfig_Info['config_file_path'] = tkcfg
TclConfig_Info['TCL_INCLUDE_SPEC'] = "-I#{tcl_idir.quote}" if tcl_idir
TkConfig_Info['TK_INCLUDE_SPEC'] = "-I#{tk_idir.quote}" if tk_idir
tk_cfg_dir = File.dirname(TkConfig_Info['config_file_path']) rescue nil
tcl_cfg_dir = File.dirname(TclConfig_Info['config_file_path']) rescue nil
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'))
# set TCL_DEFS and TK_DEFS
# $CPPFLAGS += " #{TclConfig_Info['TCL_DEFS']}"
# $CPPFLAGS += " #{TkConfig_Info['TK_DEFS']}"
$CPPFLAGS += collect_tcltk_defs(TclConfig_Info['TCL_DEFS'], TkConfig_Info['TK_DEFS'])
# MacOS X Frameworks?
if TkLib_Config["tcltk-framework"]
puts("Use MacOS X Frameworks.")
setup_for_macosx_framework
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
$CPPFLAGS << %[ -DRUBY_VERSION=\\"#{RUBY_VERSION}\\"]
$CPPFLAGS << %[ -DRUBY_RELEASE_DATE=\\"#{RUBY_RELEASE_DATE}\\"]
create_makefile("tcltklib")
puts "Find Tcl/Tk libraries. Make tcltklib.so which is required by Ruby/Tk."
else
puts "Can't find proper Tcl/Tk libraries. So, can't make tcltklib.so which is required by Ruby/Tk."
end