Skip to content
This repository

Add support for cross compiling for the x64-mingw32 platform. #976

Closed
wants to merge 1 commit into from

3 participants

Lars Kanis Juga Paazmaya Akinori MUSHA
Lars Kanis

This should fix #864.

Probably the most easy way to build the mingw gems is by using the rake-compiler-dev-box: https://github.com/tjschuck/rake-compiler-dev-box
There is an issue with the strip command in the box, so you probably need this patch, too: tjschuck/rake-compiler-dev-box#4

There are two more outstanding external issues, that are currently patched:
1. libxslt needs a patch for mingw-w64: https://bugzilla.gnome.org/show_bug.cgi?id=676511
2. patching done by mini_portile does not work in this context: luislavena/mini_portile#23

This patch moves all MiniPortile recipes into extconf.rb. That ensures that all depending libraries are build with the same compiler version as the C-ext.

I wondered, if it wouldn't be better to also build libxml2 and libxslt with --enable-static for natives builds, but noticed the corresponding issue just now: #923

If this patch is the way to go for you, then I would merge it with static_clean.

I've successfully tested the extension by running the unit tests on Windows-7 64-Bit with Ruby-x86 2.0.0-p0, Ruby-x64 2.0.0-p0 and Ruby-x86 1.9.3-p392.

Building the gem native on windows with the bundled libraries does not (yet) work, but requires probably only minor changes.

Lars Kanis Add support for cross compiling for the x64-mingw32 platform.
This moves all MiniPortile recipes into extconf.rb.
8d90991
Mathieu Doyon MathieuDoyon referenced this pull request in smdahlen/vagrant-hostmanager October 09, 2013
Closed

Windows Support #24

Juga Paazmaya

Great!

Lars Kanis

Is there something I can do, to get this reviewed/merged? May I rebase the pull request to branch static_clean ?

Akinori MUSHA
Owner
knu commented October 22, 2013

I've just merged the static_clean branch to master, so please rebase it on the latest master.

Lars Kanis

This is superseded by #989.

Lars Kanis larskanis closed this October 27, 2013
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 1 unique commit by 1 author.

Oct 07, 2013
Lars Kanis Add support for cross compiling for the x64-mingw32 platform.
This moves all MiniPortile recipes into extconf.rb.
8d90991
This page is out of date. Refresh to see the latest.
4  Gemfile
@@ -9,10 +9,10 @@ gem "hoe-bundler", ">=1.1", :group => [:development, :test]
9 9
 gem "hoe-debugging", ">=1.0.3", :group => [:development, :test]
10 10
 gem "hoe-gemspec", ">=1.0", :group => [:development, :test]
11 11
 gem "hoe-git", ">=1.4", :group => [:development, :test]
12  
-gem "mini_portile", ">=0.2.2", :group => [:development, :test]
  12
+gem "mini_portile", "~>0.5.0", :group => [:development, :test]
13 13
 gem "minitest", "~>2.2.2", :group => [:development, :test]
14 14
 gem "rake", ">=0.9", :group => [:development, :test]
15  
-gem "rake-compiler", "~>0.8.0", :group => [:development, :test]
  15
+gem "rake-compiler", "~>0.9.1", :group => [:development, :test]
16 16
 gem "racc", ">=1.4.6", :group => [:development, :test], :platform => :ruby
17 17
 gem "rexical", ">=1.0.5", :group => [:development, :test], :platform => :ruby
18 18
 gem "rdoc", "~>3.10", :group => [:development, :test]
1  Manifest.txt
@@ -210,7 +210,6 @@ lib/nokogiri/xslt.rb
210 210
 lib/nokogiri/xslt/stylesheet.rb
211 211
 lib/xercesImpl.jar
212 212
 lib/xsd/xmlparser/nokogiri.rb
213  
-tasks/cross_compile.rb
214 213
 tasks/nokogiri.org.rb
215 214
 tasks/test.rb
216 215
 test/css/test_nthiness.rb
66  Rakefile
@@ -38,6 +38,12 @@ HOE = Hoe.spec 'nokogiri' do
38 38
     'nokogiri.gemspec',
39 39
     'lib/nokogiri/nokogiri.{bundle,jar,rb,so}',
40 40
     'lib/nokogiri/{1.9,2.0}',
  41
+    'ports/*.installed',
  42
+    'ports/i686-w64-mingw32',
  43
+    'ports/x86_64-w64-mingw32',
  44
+    'ports/i586-mingw32msvc',
  45
+    'ports/libxml2',
  46
+    'ports/libxslt',
41 47
     # GENERATED_PARSER,
42 48
     # GENERATED_TOKENIZER
43 49
   ]
@@ -53,7 +59,7 @@ HOE = Hoe.spec 'nokogiri' do
53 59
     ["hoe-git",         ">= 1.4"],
54 60
     ["minitest",        "~> 2.2.2"],
55 61
     ["rake",            ">= 0.9"],
56  
-    ["rake-compiler",   "~> 0.8.0"],
  62
+    ["rake-compiler",   "~> 0.9.1"],
57 63
     ["racc",            ">= 1.4.6"],
58 64
     ["rexical",         ">= 1.0.5"]
59 65
   ]
@@ -78,7 +84,7 @@ def add_file_to_gem relative_path
78 84
   target_dir = File.dirname(target_path)
79 85
   mkdir_p target_dir unless File.directory?(target_dir)
80 86
   rm_f target_path
81  
-  ln relative_path, target_path
  87
+  safe_ln relative_path, target_path
82 88
   HOE.spec.files += [relative_path]
83 89
 end
84 90
 
@@ -103,7 +109,9 @@ if java?
103 109
 else
104 110
   mingw_available = true
105 111
   begin
106  
-    require 'tasks/cross_compile'
  112
+    require 'rake/extensioncompiler'
  113
+    # Ensure mingw compiler is installed
  114
+    Rake::ExtensionCompiler.mingw_host
107 115
   rescue
108 116
     puts "WARNING: cross compilation not available: #{$!}"
109 117
     mingw_available = false
@@ -132,16 +140,23 @@ else
132 140
     ext.config_options << ENV['EXTOPTS']
133 141
     if mingw_available
134 142
       ext.cross_compile  = true
135  
-      ext.cross_platform = ["x86-mswin32-60", "x86-mingw32"]
136  
-      ext.cross_config_options << "--with-xml2-include=#{File.join($recipes["libxml2"].path, 'include', 'libxml2')}"
137  
-      ext.cross_config_options << "--with-xml2-lib=#{File.join($recipes["libxml2"].path, 'lib')}"
138  
-      ext.cross_config_options << "--with-iconv-dir=#{$recipes["libiconv"].path}"
139  
-      ext.cross_config_options << "--with-xslt-dir=#{$recipes["libxslt"].path}"
140  
-      ext.cross_config_options << "--with-zlib-dir=#{CROSS_DIR}"
  143
+      ext.cross_platform = ["x86-mingw32", "x64-mingw32"]
  144
+      ext.cross_config_options << "--enable-cross-build"
141 145
     end
142 146
   end
143 147
 end
144 148
 
  149
+# To reduce the gem file size strip mingw32 dlls before packaging
  150
+ENV['RUBY_CC_VERSION'].to_s.split(':').each do |ruby_version|
  151
+  task "copy:nokogiri:x86-mingw32:#{ruby_version}" do |t|
  152
+    sh "i686-w64-mingw32-strip -S tmp/x86-mingw32/stage/lib/nokogiri/#{ruby_version[/^\d+\.\d+/]}/nokogiri.so"
  153
+  end
  154
+
  155
+  task "copy:nokogiri:x64-mingw32:#{ruby_version}" do |t|
  156
+    sh "x86_64-w64-mingw32-strip -S tmp/x64-mingw32/stage/lib/nokogiri/#{ruby_version[/^\d+\.\d+/]}/nokogiri.so"
  157
+  end
  158
+end
  159
+
145 160
 # ----------------------------------------
146 161
 
147 162
 desc "Generate css/parser.rb and css/tokenizer.rex"
@@ -213,37 +228,44 @@ end
213 228
 
214 229
 # ----------------------------------------
215 230
 
  231
+def verify_dll(dll, fformat)
  232
+  host = 'x86_64-w64-mingw32'
  233
+  dump = `#{host}-objdump -p #{dll.inspect}`
  234
+  raise "unexpected file format for generated dll #{dll}" unless dump =~ /file format #{fformat}\s/
  235
+  raise "export function Init_nokogiri not in dll #{dll}" unless dump =~ /Export Tables.*\sInit_nokogiri\s/mi
  236
+end
  237
+
216 238
 desc "build a windows gem without all the ceremony."
217 239
 task "gem:windows" => "gem" do
218  
-  cross_rubies = ["1.9.3-p194", "2.0.0-p0"]
219  
-  ruby_cc_version = cross_rubies.collect { |_| _.split("-").first }.join(":") # e.g., "1.8.7:1.9.2"
  240
+  cross_rubies = [
  241
+    ["x86-mingw32", "1.9.3-p448"],
  242
+    ["x86-mingw32", "2.0.0-p247"],
  243
+    ["x64-mingw32", "2.0.0-p247"],
  244
+  ]
  245
+  ruby_cc_version = cross_rubies.collect { |platform, version| version.split("-").first }.uniq.join(":") # e.g., "1.8.7:1.9.2"
220 246
   rake_compiler_config_path = "#{ENV['HOME']}/.rake-compiler/config.yml"
221 247
 
222 248
   unless File.exists? rake_compiler_config_path
223  
-    raise "rake-compiler has not installed any cross rubies. try running 'env --unset=HOST rake-compiler cross-ruby VERSION=#{cross_rubies.first}'"
  249
+    raise "rake-compiler has not installed any cross rubies. try running 'env --unset=HOST rake-compiler cross-ruby VERSION=#{cross_rubies.first.last}'"
224 250
   end
225 251
   rake_compiler_config = YAML.load_file(rake_compiler_config_path)
226 252
 
227 253
   # check that rake-compiler config contains the right patchlevels. see #279 for background,
228 254
   # and http://blog.mmediasys.com/2011/01/22/rake-compiler-updated-list-of-supported-ruby-versions-for-cross-compilation/
229 255
   # for more up-to-date docs.
230  
-  cross_rubies.each do |version|
  256
+  cross_rubies.each do |platform, version|
231 257
     majmin, patchlevel = version.split("-")
232  
-    rbconfig = "rbconfig-#{majmin}"
  258
+    rbconfig = "rbconfig-#{platform}-#{majmin}"
233 259
     unless rake_compiler_config.key?(rbconfig) && rake_compiler_config[rbconfig] =~ /-#{patchlevel}/
234 260
       raise "rake-compiler '#{rbconfig}' not #{patchlevel}. try running 'env --unset=HOST rake-compiler cross-ruby VERSION=#{version}'"
235 261
     end
236 262
   end
237 263
 
238  
-  # verify that --export-all is in the 1.9 rbconfig. see #279,#374,#375.
239  
-  rbconfig_19 = rake_compiler_config["rbconfig-1.9.3"]
240  
-  raise "rbconfig #{rbconfig_19} needs --export-all in its DLDFLAGS value" if File.read(rbconfig_19).split("\n").grep(/CONFIG\["DLDFLAGS"\].*--export-all/).empty?
241  
-
242  
-  rbconfig_20 = rake_compiler_config["rbconfig-2.0.0"]
243  
-  raise "rbconfig #{rbconfig_20} needs --export-all in its DLDFLAGS value" if File.read(rbconfig_20).split("\n").grep(/CONFIG\["DLDFLAGS"\].*--export-all/).empty?
  264
+  sh("env RUBY_CC_VERSION=#{ruby_cc_version} rake cross native gem") || raise("build failed!")
244 265
 
245  
-  pkg_config_path = %w[libxslt libxml2].collect { |pkg| File.join($recipes[pkg].path, "lib/pkgconfig") }.join(":")
246  
-  sh("env PKG_CONFIG_PATH=#{pkg_config_path} RUBY_CC_VERSION=#{ruby_cc_version} rake cross2 native gem") || raise("build failed!")
  266
+  verify_dll 'tmp/x86-mingw32/nokogiri/1.9.3/nokogiri.so', 'pei-i386'
  267
+  verify_dll 'tmp/x86-mingw32/nokogiri/2.0.0/nokogiri.so', 'pei-i386'
  268
+  verify_dll 'tmp/x64-mingw32/nokogiri/2.0.0/nokogiri.so', 'pei-x86-64'
247 269
 end
248 270
 
249 271
 # vim: syntax=Ruby
57  build_all
@@ -2,12 +2,17 @@
2 2
 #
3 3
 #  script to build gems for all relevant platforms:
4 4
 #  - MRI et al (standard gem)
5  
-#  - windows (x86-mingw32 and x86-mswin32-60)
  5
+#  - windows (x86-mingw32 and x64-mingw32)
6 6
 #  - jruby
7 7
 #
8 8
 #  here's what I recommend for building all the gems:
9 9
 #
10  
-#   1. set up a vagrant VM guest running ubuntu lucid 32-bit.
  10
+#  set up a rake-compiler-dev-box as described here:
  11
+#      https://github.com/tjschuck/rake-compiler-dev-box
  12
+#  It is prepared with all the necessary build environments.
  13
+#
  14
+#  or alternatively do:
  15
+#   1. Setup a ubuntu 12.04+ machine
11 16
 #   2. install rvm, and install 1.9.3, 2.0.0 and jruby.
12 17
 #   3. `sudo apt-get install mingw32`
13 18
 #
@@ -63,26 +68,46 @@ rm -rf gems
63 68
 mkdir -p gems
64 69
 
65 70
 # windows
66  
-platform=$(uname -i)
67  
-if [[ $platform =~ "64" ]] ; then
68  
-    echo ""
69  
-    echo "ERROR: You need to build the windows gem on a 32-bit machine!"
70  
-    echo ""
71  
-    exit 1
72  
-fi
73 71
 rvm_use 1.9.3
74  
-if [[ ! -a ${HOME}/.rake-compiler/ruby/ruby-1.9.3-p194/lib/ruby/1.9.1/x86_64-linux/rbconfig.rb ]] ; then
75  
-    bundle exec rake-compiler cross-ruby VERSION=1.9.3-p194
  72
+
  73
+# download and install mingw-w64 compilers
  74
+mingw32='i686-w64-mingw32-gcc-4.7.2-release-linux64_rubenvb.tar.xz'
  75
+mingw64='x86_64-w64-mingw32-gcc-4.7.2-release-linux64_rubenvb.tar.xz'
  76
+
  77
+mkdir -p ~/mingw
  78
+
  79
+if [ ! -f "$HOME/mingw/$mingw32" ]; then
  80
+    curl -L http://downloads.sourceforge.net/mingw-w64/$mingw32 -o ~/mingw/$mingw32
  81
+    tar -C ~/mingw -xf ~/mingw/$mingw32
76 82
 fi
77  
-if [[ ! -a ${HOME}/.rake-compiler/ruby/ruby-2.0.0-p0/lib/ruby/2.0.0/x86_64-linux/rbconfig.rb ]] ; then
78  
-    bundle exec rake-compiler cross-ruby VERSION=2.0.0-p0
  83
+
  84
+if [ ! -f "$HOME/mingw/$mingw64" ]; then
  85
+    curl -L http://downloads.sourceforge.net/mingw-w64/$mingw64 -o ~/mingw/$mingw64
  86
+    tar -C ~/mingw -xf ~/mingw/$mingw64
79 87
 fi
80  
-bundle exec rake cross
  88
+
  89
+# add mingw-w64 to the PATH
  90
+mingw_w64_paths="$HOME/mingw/mingw32/bin:$HOME/mingw/mingw64/bin"
  91
+
  92
+export PATH=$PATH:$mingw_w64_paths
  93
+
  94
+# Build 1.9.3 using 1.9.3 as base
  95
+rvm use 1.9.3
  96
+rake-compiler cross-ruby VERSION=1.9.3-p448 HOST=i586-mingw32msvc
  97
+
  98
+# Now build Ruby 2.0.0 too
  99
+rvm use 2.0.0
  100
+rake-compiler cross-ruby VERSION=2.0.0-p247 HOST=i686-w64-mingw32 debugflags="-g"
  101
+
  102
+# And the cherry of the cake: x64 Ruby
  103
+rake-compiler cross-ruby VERSION=2.0.0-p247 HOST=x86_64-w64-mingw32 debugflags="-g"
  104
+
  105
+
  106
+rvm use 1.9.3
81 107
 bundle exec rake gem:windows
82  
-cp -v pkg/nokogiri*x86-{mingw32,mswin32}*.gem gems
  108
+cp -v pkg/nokogiri*{x86,x64}-mingw32*.gem gems
83 109
 
84 110
 # MRI
85  
-rvm_use 1.9.3
86 111
 bundle exec rake clean
87 112
 bundle exec rake gem
88 113
 cp -v pkg/nokogiri*.gem gems # should only be one at this point in the script
237  ext/nokogiri/extconf.rb
@@ -89,9 +89,39 @@ def iconv_prefix
89 89
 end
90 90
 
91 91
 def process_recipe(name, version)
92  
-  MiniPortile.new(name, version).tap { |recipe|
  92
+  MiniPortile.new(name, version).tap do |recipe|
93 93
     recipe.target = File.join(ROOT, "ports")
94  
-    recipe.files = ["ftp://ftp.xmlsoft.org/libxml2/#{recipe.name}-#{recipe.version}.tar.gz"]
  94
+    recipe.host = RbConfig::CONFIG["host_alias"]
  95
+
  96
+    # Apply any bundled patches, that match the version to build
  97
+    recipe.patch_files += Dir[File.join(ROOT, "ports", "patches", "#{name}-#{version}-*")].sort
  98
+    class << recipe
  99
+      # Use patch instead of git-apply because git-apply does nothing
  100
+      # when it is run within another git checkout
  101
+      def patch
  102
+        @patch_files.each do |full_path|
  103
+          next unless File.exists?(full_path)
  104
+          output "Running patch with #{full_path}..."
  105
+          execute('patch', %Q(patch -p1 < #{full_path}))
  106
+        end
  107
+      end
  108
+
  109
+      def config_cross
  110
+        self.configure_options += [
  111
+          "--target=#{host}",
  112
+          "--host=#{host}",
  113
+          "--enable-static",
  114
+          "--disable-shared",
  115
+        ]
  116
+      end
  117
+
  118
+      def config_native
  119
+        self.configure_options += [
  120
+          "--enable-shared",
  121
+          "--disable-static",
  122
+        ]
  123
+      end
  124
+    end
95 125
 
96 126
     yield recipe
97 127
 
@@ -101,7 +131,7 @@ def process_recipe(name, version)
101 131
       FileUtils.touch checkpoint
102 132
     end
103 133
     recipe.activate
104  
-  }
  134
+  end
105 135
 end
106 136
 
107 137
 windows_p = RbConfig::CONFIG['target_os'] == 'mingw32' || RbConfig::CONFIG['target_os'] =~ /mswin/
@@ -116,7 +146,8 @@ def process_recipe(name, version)
116 146
 
117 147
 if RbConfig::MAKEFILE_CONFIG['CC'] =~ /mingw/
118 148
   $CFLAGS << " -DIN_LIBXML"
119  
-  $LIBS << " -lz" # TODO why is this necessary?
  149
+  # Mingw32 package is static linked
  150
+  $LIBS << " -lz -liconv"
120 151
 end
121 152
 
122 153
 if RbConfig::MAKEFILE_CONFIG['CC'] =~ /gcc/
@@ -124,108 +155,146 @@ def process_recipe(name, version)
124 155
   $CFLAGS << " -Wall -Wcast-qual -Wwrite-strings -Wconversion -Wmissing-noreturn -Winline"
125 156
 end
126 157
 
127  
-if windows_p
128  
-  message "Cross-building nokogiri.\n"
  158
+opt_header_dirs = [
  159
+  # First search /opt/local for macports
  160
+  '/opt/local/include',
129 161
 
130  
-  HEADER_DIRS = [INCLUDEDIR]
131  
-  LIB_DIRS = [LIBDIR]
132  
-  XML2_HEADER_DIRS = [File.join(INCLUDEDIR, "libxml2"), INCLUDEDIR]
  162
+  # Then check for OpenCSW packages
  163
+  '/opt/csw/include',
133 164
 
134  
-else
135  
-  opt_header_dirs = [
136  
-    # First search /opt/local for macports
137  
-    '/opt/local/include',
  165
+  # Then search /usr/local for people that installed from source
  166
+  '/usr/local/include',
138 167
 
139  
-    # Then check for OpenCSW packages
140  
-    '/opt/csw/include',
  168
+  # Check the ruby install locations
  169
+  INCLUDEDIR,
  170
+]
141 171
 
142  
-    # Then search /usr/local for people that installed from source
143  
-    '/usr/local/include',
  172
+if arg_config('--use-system-libraries', !!ENV['NOKOGIRI_USE_SYSTEM_LIBRARIES'])
  173
+  message "Building nokogiri using system libraries.\n"
144 174
 
145  
-    # Check the ruby install locations
146  
-    INCLUDEDIR,
  175
+  HEADER_DIRS = opt_header_dirs + [
  176
+    # Fall back to /usr
  177
+    '/usr/include',
  178
+    '/usr/include/libxml2',
147 179
   ]
148 180
 
149  
-  if arg_config('--use-system-libraries', !!ENV['NOKOGIRI_USE_SYSTEM_LIBRARIES'])
150  
-    message "Building nokogiri using system libraries.\n"
151  
-
152  
-    HEADER_DIRS = opt_header_dirs + [
153  
-      # Fall back to /usr
154  
-      '/usr/include',
155  
-      '/usr/include/libxml2',
156  
-    ]
  181
+  LIB_DIRS = [
  182
+    # First search /opt/local for macports
  183
+    '/opt/local/lib',
157 184
 
158  
-    LIB_DIRS = [
159  
-      # First search /opt/local for macports
160  
-      '/opt/local/lib',
  185
+    # Then check for OpenCSW packages
  186
+    '/opt/csw/lib',
161 187
 
162  
-      # Then check for OpenCSW packages
163  
-      '/opt/csw/lib',
  188
+    # Then search /usr/local for people that installed from source
  189
+    '/usr/local/lib',
164 190
 
165  
-      # Then search /usr/local for people that installed from source
166  
-      '/usr/local/lib',
  191
+    # Check the ruby install locations
  192
+    LIBDIR,
167 193
 
168  
-      # Check the ruby install locations
169  
-      LIBDIR,
  194
+    # Finally fall back to /usr
  195
+    '/usr/lib',
  196
+  ]
170 197
 
171  
-      # Finally fall back to /usr
172  
-      '/usr/lib',
173  
-    ]
  198
+  XML2_HEADER_DIRS = opt_header_dirs.map { |idir|
  199
+    File.join(idir, "libxml2")
  200
+  } + HEADER_DIRS
174 201
 
175  
-    XML2_HEADER_DIRS = opt_header_dirs.map { |idir|
176  
-      File.join(idir, "libxml2")
177  
-    } + HEADER_DIRS
  202
+  # If the user has homebrew installed, use the libxml2 inside homebrew
  203
+  brew_prefix = `brew --prefix libxml2 2> /dev/null`.chomp
  204
+  unless brew_prefix.empty?
  205
+    LIB_DIRS.unshift File.join(brew_prefix, 'lib')
  206
+    XML2_HEADER_DIRS.unshift File.join(brew_prefix, 'include/libxml2')
  207
+  end
178 208
 
179  
-    # If the user has homebrew installed, use the libxml2 inside homebrew
180  
-    brew_prefix = `brew --prefix libxml2 2> /dev/null`.chomp
181  
-    unless brew_prefix.empty?
182  
-      LIB_DIRS.unshift File.join(brew_prefix, 'lib')
183  
-      XML2_HEADER_DIRS.unshift File.join(brew_prefix, 'include/libxml2')
  209
+  pkg_config('libxslt')
  210
+  pkg_config('libxml-2.0')
  211
+else
  212
+  message "Building nokogiri using packaged libraries.\n"
  213
+
  214
+  require 'mini_portile'
  215
+  require 'yaml'
  216
+
  217
+  dependencies = YAML.load_file(File.join(ROOT, "dependencies.yml"))
  218
+
  219
+  cross_build = enable_config("cross-build")
  220
+  if cross_build
  221
+    zlib_recipe = process_recipe("zlib", dependencies["zlib"]) do |recipe|
  222
+      recipe.files = ["http://zlib.net/#{recipe.name}-#{recipe.version}.tar.gz"]
  223
+      class << recipe
  224
+        def configure
  225
+          Dir.chdir work_path do
  226
+            mk = File.read 'win32/Makefile.gcc'
  227
+            File.open 'win32/Makefile.gcc', 'wb' do |f|
  228
+              f.puts "BINARY_PATH = #{path}/bin"
  229
+              f.puts "LIBRARY_PATH = #{path}/lib"
  230
+              f.puts "INCLUDE_PATH = #{path}/include"
  231
+              f.puts mk.sub(/^PREFIX\s*=\s*$/, "PREFIX = #{host}-")
  232
+            end
  233
+          end
  234
+        end
  235
+
  236
+        def configured?
  237
+          Dir.chdir work_path do
  238
+            !! (File.read('win32/Makefile.gcc') =~ /^BINARY_PATH/)
  239
+          end
  240
+        end
  241
+
  242
+        def compile
  243
+          execute "compile", "make -f win32/Makefile.gcc"
  244
+        end
  245
+
  246
+        def install
  247
+          execute "install", "make -f win32/Makefile.gcc install"
  248
+        end
  249
+      end
184 250
     end
185 251
 
186  
-    pkg_config('libxslt')
187  
-    pkg_config('libxml-2.0')
188  
-  else
189  
-    message "Building nokogiri using packaged libraries.\n"
190  
-
191  
-    require 'mini_portile'
192  
-    require 'yaml'
193  
-
194  
-    dependencies = YAML.load_file(File.join(ROOT, "dependencies.yml"))
195  
-
196  
-    libxml2_recipe = process_recipe("libxml2", dependencies["libxml2"]) { |recipe|
  252
+    libiconv_recipe = process_recipe("libiconv", dependencies["libiconv"]) do |recipe|
  253
+      recipe.files = ["http://ftp.gnu.org/pub/gnu/libiconv/#{recipe.name}-#{recipe.version}.tar.gz"]
197 254
       recipe.configure_options = [
198  
-        "--enable-shared",
199  
-        "--disable-static",
200  
-        "--without-python",
201  
-        "--without-readline",
202  
-        "--with-iconv=#{iconv_prefix}",
203  
-        "--with-c14n",
204  
-        "--with-debug",
205  
-        "--with-threads"
  255
+        "CPPFLAGS='-Wall'",
  256
+        "CFLAGS='-O2 -g'",
  257
+        "CXXFLAGS='-O2 -g'",
  258
+        "LDFLAGS="
206 259
       ]
207  
-    }
  260
+      recipe.config_cross
  261
+    end
  262
+  end
208 263
 
209  
-    libxslt_recipe = process_recipe("libxslt", dependencies["libxslt"]) { |recipe|
210  
-      recipe.configure_options = [
211  
-        "--enable-shared",
212  
-        "--disable-static",
213  
-        "--without-python",
214  
-        "--without-crypto",
215  
-        "--with-debug",
216  
-        "--with-libxml-prefix=#{libxml2_recipe.path}"
217  
-      ]
218  
-    }
  264
+  libxml2_recipe = process_recipe("libxml2", dependencies["libxml2"]) do |recipe|
  265
+    recipe.files = ["ftp://ftp.xmlsoft.org/libxml2/#{recipe.name}-#{recipe.version}.tar.gz"]
  266
+    recipe.configure_options = [
  267
+      "--without-python",
  268
+      "--without-readline",
  269
+      "--with-iconv=#{cross_build ? libiconv_recipe.path : iconv_prefix}",
  270
+      "--with-c14n",
  271
+      "--with-debug",
  272
+      "--with-threads"
  273
+    ]
  274
+    cross_build ? recipe.config_cross : recipe.config_native
  275
+  end
219 276
 
220  
-    $LIBPATH = ["#{libxml2_recipe.path}/lib"] | $LIBPATH
221  
-    $LIBPATH = ["#{libxslt_recipe.path}/lib"] | $LIBPATH
  277
+  libxslt_recipe = process_recipe("libxslt", dependencies["libxslt"]) do |recipe|
  278
+    recipe.files = ["ftp://ftp.xmlsoft.org/libxml2/#{recipe.name}-#{recipe.version}.tar.gz"]
  279
+    recipe.configure_options = [
  280
+      "--without-python",
  281
+      "--without-crypto",
  282
+      "--with-debug",
  283
+      "--with-libxml-prefix=#{libxml2_recipe.path}"
  284
+    ]
  285
+    cross_build ? recipe.config_cross : recipe.config_native
  286
+  end
222 287
 
223  
-    $CFLAGS << " -DNOKOGIRI_USE_PACKAGED_LIBRARIES -DNOKOGIRI_LIBXML2_PATH='\"#{libxml2_recipe.path}\"' -DNOKOGIRI_LIBXSLT_PATH='\"#{libxslt_recipe.path}\"'"
  288
+  $LIBPATH = ["#{zlib_recipe.path}/lib"] | $LIBPATH if zlib_recipe
  289
+  $LIBPATH = ["#{libiconv_recipe.path}/lib"] | $LIBPATH if libiconv_recipe
  290
+  $LIBPATH = ["#{libxml2_recipe.path}/lib"] | $LIBPATH
  291
+  $LIBPATH = ["#{libxslt_recipe.path}/lib"] | $LIBPATH
224 292
 
225  
-    HEADER_DIRS = [libxml2_recipe, libxslt_recipe].map { |f| File.join(f.path, "include") }
226  
-    LIB_DIRS = [libxml2_recipe, libxslt_recipe].map { |f| File.join(f.path, "lib") }
227  
-    XML2_HEADER_DIRS = HEADER_DIRS + [File.join(libxml2_recipe.path, "include", "libxml2")]
228  
-  end
  293
+  $CFLAGS << " -DNOKOGIRI_USE_PACKAGED_LIBRARIES -DNOKOGIRI_LIBXML2_PATH='\"#{libxml2_recipe.path}\"' -DNOKOGIRI_LIBXSLT_PATH='\"#{libxslt_recipe.path}\"'"
  294
+
  295
+  HEADER_DIRS = [zlib_recipe, libiconv_recipe, libxml2_recipe, libxslt_recipe].compact.map { |f| File.join(f.path, "include") }
  296
+  LIB_DIRS = [zlib_recipe, libiconv_recipe, libxml2_recipe, libxslt_recipe].compact.map { |f| File.join(f.path, "lib") }
  297
+  XML2_HEADER_DIRS = HEADER_DIRS + [File.join(libxml2_recipe.path, "include", "libxml2")]
229 298
 end
230 299
 
231 300
 dir_config('zlib', HEADER_DIRS, LIB_DIRS)
12  lib/nokogiri.rb
@@ -2,9 +2,6 @@
2 2
 # Modify the PATH on windows so that the external DLLs will get loaded.
3 3
 
4 4
 require 'rbconfig'
5  
-ENV['PATH'] = [File.expand_path(
6  
-  File.join(File.dirname(__FILE__), "..", "ext", "nokogiri")
7  
-), ENV['PATH']].compact.join(';') if RbConfig::CONFIG['host_os'] =~ /(mswin|mingw)/i
8 5
 
9 6
 if defined?(RUBY_ENGINE) && RUBY_ENGINE == "jruby"
10 7
   # The line below caused a problem on non-GAE rack environment.
@@ -13,7 +10,7 @@
13 10
   # However, simply cutting defined?(JRuby::Rack::VERSION) off resulted in
14 11
   # an unable-to-load-nokogiri problem. Thus, now, Nokogiri checks the presense
15 12
   # of appengine-rack.jar in $LOAD_PATH. If Nokogiri is on GAE, Nokogiri
16  
-  # should skip loading xml jars. This is because those are in WEB-INF/lib and 
  13
+  # should skip loading xml jars. This is because those are in WEB-INF/lib and
17 14
   # already set in the classpath.
18 15
   unless $LOAD_PATH.to_s.include?("appengine-rack")
19 16
     require 'stringio'
@@ -25,7 +22,12 @@
25 22
   end
26 23
 end
27 24
 
28  
-require 'nokogiri/nokogiri'
  25
+begin
  26
+  RUBY_VERSION =~ /(\d+.\d+)/
  27
+  require "nokogiri/#{$1}/nokogiri"
  28
+rescue LoadError
  29
+  require 'nokogiri/nokogiri'
  30
+end
29 31
 require 'nokogiri/version'
30 32
 require 'nokogiri/syntax_error'
31 33
 require 'nokogiri/xml'
41  ports/patches/libxslt-1.1.28-fix-mkdir-for-mingw.patch
... ...
@@ -0,0 +1,41 @@
  1
+From a7ff3f0043f02d4ade966b6ac05b8be39166daa7 Mon Sep 17 00:00:00 2001
  2
+From: Lars Kanis <lars@greiz-reinsdorf.de>
  3
+Date: Sun, 6 Oct 2013 22:04:46 +0200
  4
+Subject: [PATCH] Use mkdir macro also in case if mingw32.
  5
+
  6
+This fixes bug 676511.
  7
+---
  8
+ libxslt/libxslt.h     | 6 ++++++
  9
+ libxslt/win32config.h | 1 -
  10
+ 2 files changed, 6 insertions(+), 1 deletion(-)
  11
+
  12
+diff --git a/libxslt/libxslt.h b/libxslt/libxslt.h
  13
+index 2f6f20d..e6d4c83 100644
  14
+--- a/libxslt/libxslt.h
  15
++++ b/libxslt/libxslt.h
  16
+@@ -27,4 +27,10 @@
  17
+ #endif
  18
+ #endif
  19
+ 
  20
++#if defined(_MSC_VER) || defined(__MINGW32__)
  21
++#include <io.h>
  22
++#include <direct.h>
  23
++#define mkdir(p,m) _mkdir(p)
  24
++#endif
  25
++
  26
+ #endif /* ! __XSLT_LIBXSLT_H__ */
  27
+diff --git a/libxslt/win32config.h b/libxslt/win32config.h
  28
+index 9f60e55..e1ceae1 100644
  29
+--- a/libxslt/win32config.h
  30
++++ b/libxslt/win32config.h
  31
+@@ -78,7 +78,6 @@ static int isnan (double d) {
  32
+ 
  33
+ #include <direct.h>
  34
+ #if defined(_MSC_VER) || defined(__MINGW32__)
  35
+-#define mkdir(p,m) _mkdir(p)
  36
+ #define snprintf _snprintf
  37
+ #if _MSC_VER < 1500
  38
+ #define vsnprintf(b,c,f,a) _vsnprintf(b,c,f,a)
  39
+-- 
  40
+1.8.3.2
  41
+
132  tasks/cross_compile.rb
... ...
@@ -1,132 +0,0 @@
1  
-gem 'rake-compiler'
2  
-require 'rake/extensioncompiler'
3  
-HOST = Rake::ExtensionCompiler.mingw_host
4  
-
5  
-require 'mini_portile'
6  
-dependencies = YAML.load_file("dependencies.yml")
7  
-$recipes = {}
8  
-%w[zlib libiconv libxml2 libxslt].each do |lib|
9  
-  $recipes[lib] = MiniPortile.new lib, dependencies[lib]
10  
-end
11  
-$recipes.each { |_, recipe| recipe.host = HOST }
12  
-
13  
-file "lib/nokogiri/nokogiri.rb" do
14  
-  File.open("lib/nokogiri/nokogiri.rb", 'wb') do |f|
15  
-    f.write %Q{require "nokogiri/\#{RUBY_VERSION.sub(/\\.\\d+$/, '')}/nokogiri"\n}
16  
-  end
17  
-end
18  
-
19  
-namespace :cross do
20  
-  task :zlib do
21  
-    recipe = $recipes["zlib"]
22  
-    recipe.files = ["http://zlib.net/#{recipe.name}-#{recipe.version}.tar.gz"]
23  
-    class << recipe
24  
-      def configure
25  
-        Dir.chdir work_path do
26  
-          mk = File.read 'win32/Makefile.gcc'
27  
-          File.open 'win32/Makefile.gcc', 'wb' do |f|
28  
-            f.puts "BINARY_PATH = #{CROSS_DIR}/bin"
29  
-            f.puts "LIBRARY_PATH = #{CROSS_DIR}/lib"
30  
-            f.puts "INCLUDE_PATH = #{CROSS_DIR}/include"
31  
-            f.puts mk.sub(/^PREFIX\s*=\s*$/, "PREFIX = #{HOST}-")
32  
-          end
33  
-        end
34  
-      end
35  
-
36  
-      def configured?
37  
-        Dir.chdir work_path do
38  
-          !! (File.read('win32/Makefile.gcc') =~ /^BINARY_PATH/)
39  
-        end
40  
-      end
41  
-
42  
-      def compile
43  
-        execute "compile", "make -f win32/Makefile.gcc"
44  
-      end
45  
-
46  
-      def install
47  
-        execute "install", "make -f win32/Makefile.gcc install"
48  
-      end
49  
-    end
50  
-
51  
-    checkpoint = "#{CROSS_DIR}/#{recipe.name}-#{recipe.version}-#{recipe.host}.installed"
52  
-    unless File.exist?(checkpoint)
53  
-      recipe.cook
54  
-      touch checkpoint
55  
-    end
56  
-    recipe.activate
57  
-  end
58  
-
59  
-  task :libiconv do
60  
-    recipe = $recipes["libiconv"]
61  
-    recipe.files = ["http://ftp.gnu.org/pub/gnu/libiconv/#{recipe.name}-#{recipe.version}.tar.gz"]
62  
-    recipe.configure_options = [
63  
-      "--host=#{HOST}",
64  
-      "--enable-static",
65  
-      "--disable-shared",
66  
-      "CPPFLAGS='-mno-cygwin -Wall'",
67  
-      "CFLAGS='-mno-cygwin -O2 -g'",
68  
-      "CXXFLAGS='-mno-cygwin -O2 -g'",
69  
-      "LDFLAGS=-mno-cygwin"
70  
-    ]
71  
-
72  
-    checkpoint = "#{CROSS_DIR}/#{recipe.name}-#{recipe.version}-#{recipe.host}.installed"
73  
-    unless File.exist?(checkpoint)
74  
-      recipe.cook
75  
-      touch checkpoint
76  
-    end
77  
-    recipe.activate
78  
-  end
79  
-
80  
-  task :libxml2 => ["cross:zlib", "cross:libiconv"] do
81  
-    recipe = $recipes["libxml2"]
82  
-    recipe.files = ["ftp://ftp.xmlsoft.org/libxml2/#{recipe.name}-#{recipe.version}.tar.gz"]
83  
-    recipe.configure_options = [
84  
-      "--host=#{HOST}",
85  
-      "--enable-static",
86  
-      "--disable-shared",
87  
-      "--with-zlib=#{CROSS_DIR}",
88  
-      "--with-iconv=#{$recipes["libiconv"].path}",
89  
-      "--without-python",
90  
-      "--without-readline",
91  
-      "CFLAGS='-DIN_LIBXML'"
92  
-    ]
93  
-
94  
-    checkpoint = "#{CROSS_DIR}/#{recipe.name}-#{recipe.version}-#{recipe.host}.installed"
95  
-    unless File.exist?(checkpoint)
96  
-      recipe.cook
97  
-      touch checkpoint
98  
-    end
99  
-    recipe.activate
100  
-  end
101  
-
102  
-  task :libxslt => ['cross:libxml2'] do
103  
-    recipe = $recipes["libxslt"]
104  
-    recipe.files = ["ftp://ftp.xmlsoft.org/libxml2/#{recipe.name}-#{recipe.version}.tar.gz"]
105  
-    recipe.configure_options = [
106  
-      "--host=#{HOST}",
107  
-      "--enable-static",
108  
-      "--disable-shared",
109  
-      "--with-libxml-prefix=#{$recipes["libxml2"].path}",
110  
-      "--without-python",
111  
-      "--without-crypto",
112  
-      "CFLAGS='-DIN_LIBXML'"
113  
-    ]
114  
-
115  
-    checkpoint = "#{CROSS_DIR}/#{recipe.name}-#{recipe.version}-#{recipe.host}.installed"
116  
-    unless File.exist?(checkpoint)
117  
-      recipe.cook
118  
-      touch checkpoint
119  
-    end
120  
-    recipe.activate
121  
-  end
122  
-
123  
-  task :file_list do
124  
-    add_file_to_gem "lib/nokogiri/nokogiri.rb"
125  
-  end
126  
-
127  
-end
128  
-
129  
-require 'rake/clean'
130  
-CLOBBER.include("#{CROSS_DIR}/*.installed", "#{CROSS_DIR}/#{HOST}", "tmp/#{HOST}")
131  
-
132  
-task :cross2 => ["cross:libxslt", "lib/nokogiri/nokogiri.rb", "cross", "cross:file_list"]
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.