From: nobuyoshi nakada Date: 2005-11-04T20:55:22+09:00 Subject: [ruby-dev:27636] Re: [win32] replaced symbols なかだです。 At Tue, 1 Nov 2005 07:58:51 +0900, H.Yamamoto wrote in [ruby-dev:27614]: > >1.9専用にしてみました。 > > 試してみたのですが、 > > ../ruby/win32/win32.h(488) : fatal error C1070: ソ-ス ファイル '../ruby/win32/win32.h' > 中で #if に対応する #endif が見つかりません。 > NMAKE : fatal error U1077: 'cl' : リターン コード '0x2' > Stop. > > というエラーが出てコンパイルできませんでした。見た感じ、パッチを当てたあとの > win32/win32.h の 87 行目の > > #ifdef RUBY_EXPORT > > が閉じてないように見えます。(そしてどこで閉じればいいかわからない(汗)) 他にもいろいろ問題がありましたが、これで一応bcc,mingw,mswinとも に動いているように見えます。 [ruby-dev:27610]からの差分です。 diff -U2 configure.in configure.in --- configure.in 28 Oct 2005 10:48:15 -0000 +++ configure.in 4 Nov 2005 08:19:28 -0000 @@ -980,5 +980,5 @@ cygwin*|mingw*) : ${LDSHARED="${CC} -shared -s"} XLDFLAGS="$XLDFLAGS -Wl,--stack,0x02000000" - DLDFLAGS="${DLDFLAGS} -Wl,--enable-auto-import" + DLDFLAGS="${DLDFLAGS} -Wl,--enable-auto-import,--export-all" : ${LIBPATHENV=""} rb_cv_dlopen=yes ;; --- bcc32/Makefile.sub 27 Oct 2005 03:52:56 -0000 +++ bcc32/Makefile.sub 25 Oct 2005 16:59:17 -0000 1.84 @@ -433,3 +433,3 @@ $(RUBYDEF): $(LIBRUBY_A) $(PREP) - $(MINIRUBY) $(srcdir)win32/mkexports.rb -output=$@ -base=$(RUBY_SO_NAME) $(LIBRUBY_A) + $(MINIRUBY) $(srcdir)bcc32/mkexports.rb -output=$@ -base=$(RUBY_SO_NAME) $(LIBRUBY_A) diff -U2 cygwin/GNUmakefile.in cygwin/GNUmakefile.in --- cygwin/GNUmakefile.in 31 Oct 2005 08:06:14 -0000 +++ cygwin/GNUmakefile.in 2 Nov 2005 10:19:27 -0000 @@ -6,9 +6,7 @@ ifeq (@target_os@,cygwin) DLL_BASE_NAME := $(subst .dll,,$(LIBRUBY_SO)) - WIN32H = else DLL_BASE_NAME := $(RUBY_SO_NAME) DLLWRAP += -mno-cygwin - WIN32H = win32/win32.h VPATH += $(srcdir)/win32 endif @@ -35,11 +33,4 @@ rubyw: $(WPROGRAM) -ifeq ($(WIN32H),) - DLDFLAGS += -Wl,--export-all -else - DLDFLAGS += -Wl,--enable-stdcall-fixup - DLDOBJS += ruby.def -endif - $(LIBRUBY): $(RUBY_EXP) $(LIBRUBY_SO) $(RUBY_EXP) $(LIBRUBY_SO): $(DLL_BASE_NAME).res.@OBJEXT@ @@ -69,11 +60,22 @@ GNUmakefile: $(srcdir)/cygwin/GNUmakefile.in -$(OBJS) $(MAINOBJ): $(WIN32H) +ifeq (@target_os@,mingw32) +$(OBJS) $(MAINOBJ): win32/win32.h + +DLDFLAGS += ruby.def -$(LIBRUBY_SO): $(if $(WIN32H),ruby.def) +$(LIBRUBY_SO): ruby.def ruby.def: $(LIBRUBY_A) $(PREP) $(RBCONFIG) - $(MINIRUBY) $(srcdir)/win32/mkexports.rb -output=$@ \ - $(if $(WIN32H),-win32h=$(WIN32H)) $(LIBRUBY_A) + $(MINIRUBY) $(srcdir)/win32/mkexports.rb -output=$@ $(LIBRUBY_A) +endif + +ifeq (@target_os@,cygwin) +cygwin-$(RUBY_INSTALL_NAME)$(MAJOR)$(MINOR).dll: $(LIBRUBY_A) + @NM@ --extern --defined $(LIBRUBY_A) | \ + $(MINIRUBY) -ne 'BEGIN{puts "EXPORTS"}; puts $$1+"=cyg$(RUBY_INSTALL_NAME)$(MAJOR)$(MINOR)."+$$1 if / [CDT] _(.*)$$/' >rubydll.def + @DLLWRAP@ -s --def=rubydll.def -o $@ + @rm -f rubydll.def +endif clean-local:: --- win32/Makefile.sub 31 Oct 2005 08:20:32 -0000 +++ win32/Makefile.sub 25 Oct 2005 16:59:17 -0000 1.105 @@ -462,3 +462,3 @@ $(RUBYDEF): $(LIBRUBY_A) $(PREP) - $(MINIRUBY) $(srcdir)/win32/mkexports.rb -output=$@ -win32h=$(srcdir)/win32/win32.h $(LIBRUBY_A) + $(MINIRUBY) $(srcdir)/win32/mkexports.rb -output=$@ $(LIBRUBY_A) diff -U2 win32/win32.c win32/win32.c --- win32/win32.c 28 Oct 2005 08:26:48 -0000 +++ win32/win32.c 1 Nov 2005 05:26:47 -0000 @@ -3446,9 +3446,9 @@ rb_w32_sleep(unsigned long msec) { - return rb_w32_msleep(msec); + return rb_w32_Sleep(msec); } int WINAPI -rb_w32_msleep(unsigned long msec) +rb_w32_Sleep(unsigned long msec) { DWORD ret; diff -U2 win32/win32.h win32/win32.h --- win32/win32.h 28 Oct 2005 08:34:18 -0000 +++ win32/win32.h 1 Nov 2005 06:41:54 -0000 @@ -21,8 +21,7 @@ // #include conflict with varargs.h? // There is function-name conflitct, so we rename it -#if !defined(IN) && !defined(FLOAT) +#if !defined(WSAAPI) #define OpenFile WINAPI_OpenFile #include -#include #undef OpenFile #endif @@ -96,6 +95,6 @@ #define fclose(f) rb_w32_fclose(f) #define getpid() rb_w32_getpid() -#define sleep(x) rb_w32_msleep((x)*1000) -#define Sleep(msec) (void)rb_w32_msleep(msec) +#define sleep(x) rb_w32_Sleep((x)*1000) +#define Sleep(msec) (void)rb_w32_Sleep(msec) #ifdef __BORLANDC__ #define creat(p, m) _creat(p, m) @@ -132,4 +131,5 @@ #undef unlink #define unlink(p) rb_w32_unlink(p) +#endif #define strcasecmp(s1, s2) stricmp(s1, s2) @@ -473,5 +473,5 @@ int rb_w32_fclose(FILE*); int rb_w32_utime(const char *, const struct utimbuf *); -int WINAPI rb_w32_msleep(unsigned long msec); +int WINAPI rb_w32_Sleep(unsigned long msec); /* --- wince/Makefile.sub 26 Oct 2005 00:40:31 -0000 +++ wince/Makefile.sub 25 Oct 2005 16:59:18 -0000 1.45 @@ -444,3 +444,3 @@ @echo. $(DLDOBJS) - $(LDSHARED) $(INITOBJS) $(DLDOBJS) $(LIBRUBY_A) \ + $(LDSHARED) $(MAINOBJ) $(DLDOBJS) $(LIBRUBY_A) \ $(RUBY_SO_NAME).res $(LIBS) -Fe$@ $(LDFLAGS) \ only in patch2: --- bcc32/mkexports.rb 3 Oct 2002 11:20:31 -0000 1.3 +++ bcc32/mkexports.rb 2 Nov 2005 10:48:55 -0000 @@ -2,24 +2,23 @@ -SYM = {} -STDIN.reopen(open("nul")) -ARGV.each do |obj| - IO.foreach("|tdump -q -oiPUBDEF -oiPUBD32 #{obj.tr('/', '\\')}") do |l| - next unless /(?:PUBDEF|PUBD32)/ =~ l - SYM[$1] = true if /'(.*?)'/ =~ l - end -end +$:.unshift(File.expand_path("../..", __FILE__)) +require 'win32/mkexports' -exports = [] -if $name - exports << "Name " + $name -elsif $library - exports << "Library " + $library -end -exports << "Description " + $description.dump if $description -exports << "EXPORTS" << SYM.keys.sort +class Exports::Bcc < Exports + Forwards = /^rb_w32_(\w+)/ -if $output - open($output, 'w') {|f| f.puts exports.join("\n")} -else - puts exports.join("\n") + def forwarding(internal, export) + internal[/\A_?/]+export + end + + def each_export(objs) + objs.each do |obj| + opt = /\.(?:so|dll)\z/i =~ obj ? "-ee" : "-oiPUBDEF -oiPUBD32" + IO.foreach("|tdump -q #{opt} #{obj.tr('/', '\\')} < nul") do |l| + next unless /(?:PUBDEF|PUBD32|EXPORT)/ =~ l + yield $1 if /'(.*?)'/ =~ l + end + end + yield "_strcasecmp", "_stricmp" + yield "_strncasecmp", "_strnicmp" + end end only in patch2: --- win32/mkexports.rb 18 Jun 2002 10:23:31 -0000 1.4 +++ win32/mkexports.rb 4 Nov 2005 07:16:08 -0000 @@ -2,29 +2,133 @@ -SYM = {} +module Config + autoload :CONFIG, "rbconfig" +end + +class Exports + @subclass = [] + def self.inherited(klass) + @subclass << [/#{klass.name.sub(/.*::/, '').downcase}/i, klass] + end + + def self.create(*args, &block) + platform = RUBY_PLATFORM + pat, klass = @subclass.find {|pat, klass| pat =~ platform} + unless klass + raise ArgumentError, "unsupported platform: #{platform}" + end + klass.new(*args, &block) + end + + def self.extract(objs, *rest) + create(objs).exports(*rest) + end + + def self.output(output = $output, &block) + if output + open(output, 'w', &block) + else + yield STDOUT + end + end + + def initialize(objs) + syms = {} + winapis = {} + internal = export = nil + each_export(objs) do |internal, export| + syms[internal] = export + winapis[$1] = internal if /^_?(rb_w32_\w+)(?:@\d+)?$/ =~ internal + end + win32h = File.join(File.dirname(__FILE__), "win32.h") + IO.foreach(win32h) do |line| + if /^#define (\w+)\((.*?)\)\s+(?:\(void\))?(rb_w32_\w+)\((.*?)\)\s*$/ =~ line and + $2.delete(" ") == $4.delete(" ") + export, internal = $1, $3 + if syms[internal] or internal = winapis[internal] + syms[forwarding(internal, export)] = internal + end + end + end + @syms = syms + end + + def exports(name = $name, library = $library, description = $description) + exports = [] + if name + exports << "Name " + name + elsif library + exports << "Library " + library + end + exports << "Description " + description.dump if description + k = v = nil + exports << "EXPORTS" << symbols() + exports + end + + private + def forwarding(internal, export) + internal.sub(/^[^@]+/, "\\1#{export}") + end -objs = ARGV.collect {|s| s.tr('/', '\\')} -IO.foreach("|dumpbin -symbols " + objs.join(' ')) do |l| - next if /^[0-9A-F]+ 0+ UNDEF / =~ l - next unless l.sub!(/.*\sExternal\s+\|\s+/, '') - if l.sub!(/^_/, '') - next if /@.*@/ =~ l || /@[0-9a-f]{16}$/ =~ l - elsif !l.sub!(/^(\S+) \([^@?\`\']*\)$/, '\1') - next + def each_export(objs) + end + + def symbols() + @syms.sort.collect {|k, v| v ? "#{k}=#{v}" : k} end - SYM[l.strip] = true end -exports = [] -if $name - exports << "Name " + $name -elsif $library - exports << "Library " + $library +class Exports::Mswin < Exports + def each_export(objs) + noprefix = ($arch and /^sh/ !~ $arch) + objs = objs.collect {|s| s.tr('/', '\\')} + filetype = nil + IO.popen(%w"dumpbin -symbols -exports" + objs) do |f| + f.each do |l| + if (filetype = l[/^File Type: (.+)/, 1])..(/^\f/ =~ l) + case filetype + when /OBJECT/, /LIBRARY/ + next if /^[[:xdigit:]]+ 0+ UNDEF / =~ l + next unless l.sub!(/.*\sExternal\s+\|\s+/, '') + if noprefix or l.sub!(/^_/, '') + next if /@.*@/ =~ l || /@[[:xdigit:]]{16}$/ =~ l + l.sub!(/^/, '_') if /@\d+$/ =~ l + elsif !l.sub!(/^(\S+) \([^@?\`\']*\)$/, '\1') + next + end + when /DLL/ + next unless l.sub!(/^\s*\d+\s+[[:xdigit:]]+\s+[[:xdigit:]]+\s+/, '') + else + next + end + yield l.strip + end + end + end + yield "strcasecmp", "msvcrt.stricmp" + yield "strncasecmp", "msvcrt.strnicmp" + end end -exports << "Description " + $description.dump if $description -exports << "EXPORTS" << SYM.keys.sort -if $output - open($output, 'w') {|f| f.puts exports.join("\n")} -else - puts exports.join("\n") +class Exports::Mingw < Exports + def self.nm + @@nm ||= Config::CONFIG["NM"] + end + + def each_export(objs) + IO.popen([self.class.nm, "--extern", "--defined", *objs]) do |f| + f.each {|l| yield $1 if / [[:upper:]] _(.*)$/ =~ l} + end + yield "strcasecmp", "_stricmp" + yield "strncasecmp", "_strnicmp" + end + + def symbols() + @syms.select {|k, v| v}.sort.collect {|k, v| "#{k}=#{v}"} + end end + +END { + exports = Exports.extract(ARGV) + Exports.output {|f| f.puts exports} +} -- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦