mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
3976eb12ff
* lib/mkmf.rb (have_framework): should append framework options to $LIBS, not $LDFLAGS. the former is propagated to exts.mk when enable-static-linked-ext. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@43277 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2051 lines
66 KiB
Ruby
2051 lines
66 KiB
Ruby
##############################################################
|
|
# extconf.rb for tcltklib
|
|
# release date: 2010-07-30
|
|
##############################################################
|
|
require 'mkmf'
|
|
|
|
TkLib_Config = {}
|
|
TkLib_Config['search_versions'] =
|
|
# %w[8.9 8.8 8.7 8.6 8.5 8.4 8.3 8.2 8.1 8.0 7.6 4.2]
|
|
# %w[8.7 8.6 8.5 8.4 8.3 8.2 8.1 8.0]
|
|
# %w[8.7 8.6 8.5 8.4 8.0] # to shorten search steps
|
|
%w[8.5 8.4] # At present, Tcl/Tk8.6 is not supported.
|
|
|
|
TkLib_Config['major_nums'] = '87'
|
|
|
|
|
|
##############################################################
|
|
# 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::FNM_CASEFOLD))
|
|
File.delete(*Dir.glob("*.#{$OBJEXT}", File::FNM_CASEFOLD))
|
|
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 is_macosx?
|
|
/darwin/ =~ RUBY_PLATFORM
|
|
end
|
|
|
|
def maybe_64bit?
|
|
/64|universal|s390x/ =~ RUBY_PLATFORM
|
|
end
|
|
|
|
def check_tcltk_version(version)
|
|
return [nil, nil] unless version.kind_of? String
|
|
|
|
tclver, tkver = version.split(',')
|
|
tclver = tclver.strip
|
|
return [tclver, tkver.strip] if tkver
|
|
|
|
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 tclver =~ /^(\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
|
|
tkver = tclver
|
|
tclver = "7" + ((dot)? ".": "") + ((minor.empty)? "": "6") + ext
|
|
end
|
|
|
|
tkver = tclver unless tkver
|
|
|
|
[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_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.exist?(File.join(dir, "Tcl.framework", "Headers"))
|
|
next unless File.directory?(tcldir = File.join(dir, "Tcl.framework"))
|
|
next unless File.exist?(File.join(dir, "Tk.framework", "Headers"))
|
|
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?
|
|
|
|
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"
|
|
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)} 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
|
|
|
|
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
|
|
|
|
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_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"
|
|
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)} 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
|
|
($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. 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
|
|
version_check = proc {|code|
|
|
code << ("#if TCL_MAJOR_VERSION != #{major} || TCL_MINOR_VERSION != #{minor}\n" \
|
|
"#error VERSION does not match\n" \
|
|
"#endif")
|
|
}
|
|
else
|
|
version_check = nil
|
|
end
|
|
have_tcl_h = have_header('tcl.h', &version_check)
|
|
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
|
|
|
|
if major || minor
|
|
version_check = proc {|code|
|
|
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
|
|
code
|
|
}
|
|
else
|
|
version_check = nil
|
|
end
|
|
have_tcl_h = paths.find{|path|
|
|
print(".") # progress
|
|
inc_opt = " -I#{path.quote}"
|
|
if try_header("tcl", inc_opt, &version_check)
|
|
($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
|
|
version_check = proc {|code|
|
|
code << ("#if TK_MAJOR_VERSION != #{major} || TK_MINOR_VERSION != #{minor}\n" \
|
|
"#error VERSION does not match\n" \
|
|
"#endif")
|
|
}
|
|
else
|
|
version_check = nil
|
|
end
|
|
have_tk_h = have_header('tk.h')
|
|
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
|
|
|
|
if major || minor
|
|
version_check = proc {|code|
|
|
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
|
|
code
|
|
}
|
|
else
|
|
version_check = nil
|
|
end
|
|
have_tk_h = paths.find{|path|
|
|
print(".") # progress
|
|
inc_opt = " -I#{path.quote}"
|
|
if try_header(%w'tcl.h tk.h', inc_opt, &version_check)
|
|
($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 $LIBS && $LIBS.include?('-framework')
|
|
($LIBS ||= "") << ' -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
|
|
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('/'), 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. 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
|
|
|
|
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
|
|
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("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"])
|
|
$CPPFLAGS ||= ""
|
|
|
|
# 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.")
|
|
|
|
%w"ruby_native_thread_p rb_errinfo rb_safe_level rb_hash_lookup
|
|
rb_proc_new rb_obj_untrust rb_obj_taint rb_set_safe_level_force
|
|
rb_sourcefile rb_thread_alive_p rb_thread_check_trap_pending".each do |func|
|
|
have_func(func, "ruby.h")
|
|
print(".") # progress
|
|
end
|
|
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
|
|
|
|
# check requirement of Tcl/tk version
|
|
tcltk_version = with_config("tcltkversion")
|
|
TkLib_Config["tcltkversion"] = check_tcltk_version(tcltk_version)
|
|
|
|
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
|
|
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
|
|
|
|
# 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
|
|
activeTcl = '/opt/ActiveTcl*'
|
|
end
|
|
end
|
|
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 ||= ""; $CPPFLAGS += ' -DUSE_TCL_STUBS -DUSE_TK_STUBS'
|
|
end
|
|
|
|
# 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
|
|
|
|
# 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
|
|
|
|
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].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"]
|
|
|
|
libs = ''
|
|
if tcl_cfg_dir
|
|
TclConfig_Info['TCL_LIBS'] ||= ""
|
|
($INCFLAGS ||= "") << ' ' << TclConfig_Info['TCL_INCLUDE_SPEC']
|
|
libs << ' ' << 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?
|
|
libs << ' ' << TclConfig_Info['TCL_BUILD_STUB_LIB_SPEC']
|
|
else
|
|
libs << ' ' << 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?
|
|
libs << ' ' << TclConfig_Info['TCL_BUILD_LIB_SPEC']
|
|
else
|
|
libs << ' ' << TclConfig_Info['TCL_LIB_SPEC']
|
|
end
|
|
end
|
|
end
|
|
|
|
libs << " -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']
|
|
libs << ' ' << 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?
|
|
libs << ' ' << TkConfig_Info['TK_BUILD_STUB_LIB_SPEC']
|
|
else
|
|
libs << ' ' << 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?
|
|
libs << ' ' << TkConfig_Info['TK_BUILD_LIB_SPEC']
|
|
else
|
|
libs << ' ' << TkConfig_Info['TK_LIB_SPEC']
|
|
end
|
|
end
|
|
end
|
|
$LDFLAGS << ' ' << libs
|
|
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}\\"]
|
|
|
|
# remove harmful definitions.
|
|
$defs.delete_if{|x|/^-Du?intptr_t=/ =~ x}
|
|
|
|
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."
|
|
puts "If you have Tcl/Tk libraries on your environment, you may be able to use them with configure options (see ext/tk/README.tcltklib)."
|
|
puts "At present, Tcl/Tk8.6 is not supported. Although you can try to use Tcl/Tk8.6 with configure options, it will not work correctly. I recommend you to use Tcl/Tk8.5 or 8.4."
|
|
end
|