diff options
| author | Chris Reuter <[email protected]> | 2021-10-21 21:33:17 -0400 |
|---|---|---|
| committer | Chris Reuter <[email protected]> | 2021-10-21 21:58:45 -0400 |
| commit | 5c4273f944b538bc24ed98c52991ea8bf9044654 (patch) | |
| tree | 2d65523aa60dff53a4cedd95e92abf25b0755a39 /build_config | |
| parent | b6b4ac8270fcef135291cbde60d18f1c8a4c98e4 (diff) | |
| download | mruby-5c4273f944b538bc24ed98c52991ea8bf9044654.tar.gz mruby-5c4273f944b538bc24ed98c52991ea8bf9044654.zip | |
Added testing support for cross-MinGW builds.
This adds a build_config that will cross-build a Windows executable
using the MinGW cross-compiler and will also run the unit (i.e.
'rake test') using Wine.
For this to work, I made some modifications to the underlying test
scripts as well as some minor changes to a couple of the tests
themselves.
Diffstat (limited to 'build_config')
| -rw-r--r-- | build_config/cross-mingw-winetest.rb | 91 | ||||
| -rwxr-xr-x | build_config/helpers/wine_runner.rb | 71 |
2 files changed, 162 insertions, 0 deletions
diff --git a/build_config/cross-mingw-winetest.rb b/build_config/cross-mingw-winetest.rb new file mode 100644 index 000000000..fad06b265 --- /dev/null +++ b/build_config/cross-mingw-winetest.rb @@ -0,0 +1,91 @@ + +# Cross-compile using MinGW and test using Wine. +# +# Steps: +# +# 1. Install MinGW; 64-bit target seems to work best. +# +# 2. Install Wine. +# +# 3. Run command: +# +# wine cmd /c echo "Hello world"' +# +# This will confirm that Wine works and will trigger standard +# Wine setup, which is slow. +# +# 4. Confirm that drive 'z:' is mapped to your root filesystem. +# (This is supposed to be a default but it helps to +# double-check.) To confirm, run: +# +# wine cmd /c dir 'z:\\' +# +# This should give you a DOS-style equivalent of 'ls /'. If not, +# you'll need to fix that with winecfg or by adding a symlink to +# '~/.wine/dosdevices'. +# +# 5. You will likely need to tweak the settings below to work with +# your configuration unless it is exactly like one of the platforms +# I've tested on (Ubuntu 20.04 or macOS using brew.) +# +# 6. Run the build command: +# +# MRUBY_CONFIG=build_config/cross-mingw-winetest.rb rake test +# +# If all goes well, you should now have Windows executables and a +# set of passing tests. +# +# +# Caveats: +# +# 1. This works by using a helper script that rewrites test output +# to make it look *nix-like and then handing it back to the test +# cases. Some of the existing tests were (slightly) modified to +# make this easier but only for the 'full-core' gembox. Other +# gems' bintests may or may not work with the helper script and +# may or may not be fixable by extending the script. +# +# 2. MinGW and Wine are both complex and not very consistent so you +# will likely need to do some fiddling to get things to work. +# +# 3. This script assumes you are running it on a *nix-style OS. +# +# 4. I recommend building 64-bit targets only. Building a 32-bit +# Windows binary with i686-w64-mingw32 seems to work (at least, +# it did for me) but the resulting executable failed a number of +# unit tests due to small errors in some floating point +# operations. It's unclear if this indicates more serious problems. +# + + +MRuby::CrossBuild.new("cross-mingw-winetest") do |conf| + conf.toolchain :gcc + + conf.host_target = "x86_64-w64-mingw32" + + # Ubuntu 20 + conf.cc.command = "#{conf.host_target}-gcc-posix" + + # macOS+Wine from brew + #conf.cc.command = "#{conf.host_target}-gcc" + + conf.linker.command = conf.cc.command + conf.archiver.command = "#{conf.host_target}-gcc-ar" + conf.exts.executable = ".exe" + + # By default, we compile as static as possible to remove runtime + # MinGW dependencies; they are probably fixable but it gets + # complicated. + conf.cc.flags = ['-static'] + conf.linker.flags += ['-static'] + + conf.test_runner do |t| + thisdir = File.absolute_path( File.dirname(__FILE__) ) + t.command = File.join(thisdir, * %w{ helpers wine_runner.rb}) + end + + conf.gembox "full-core" + + conf.enable_bintest + conf.enable_test +end diff --git a/build_config/helpers/wine_runner.rb b/build_config/helpers/wine_runner.rb new file mode 100755 index 000000000..9a7eb46b0 --- /dev/null +++ b/build_config/helpers/wine_runner.rb @@ -0,0 +1,71 @@ +#!/usr/bin/env ruby + +# Wrapper for running tests for cross-compiled Windows builds in Wine. + +require 'open3' + +DOSROOT = 'z:' + +# Rewrite test output to replace DOS-isms with Unix-isms. +def clean(output, stderr = false) + ends_with_newline = !!(output =~ /\n$/) + executable = ARGV[0].gsub(/\.exe\z/i, '') + + # Fix line-ends + output = output.gsub(/\r\n/, "\n") + + # Strip out Wine messages + + + results = output.split(/\n/).map do |line| + # Fix file paths + if line =~ /#{DOSROOT}\\/i + line.gsub!(/#{DOSROOT}([^:]*)/i) { |path| + path.gsub!(/^#{DOSROOT}/i, '') + path.gsub!(%r{\\}, '/') + path + } + end + + # strip '.exe' off the end of the executable's name if needed + line.gsub!(/(#{Regexp.escape executable})\.exe/i, '\1') + + line + end + + result_text = results.join("\n") + result_text += "\n" if ends_with_newline + return result_text +end + + +def main + if ARGV.empty? || ARGV[0] =~ /^- (-?) (\?|help|h) $/x + puts "#{$0} <command-line>" + exit 0 + end + + # For simplicity, just read all of stdin into memory and pass that + # as an argument when invoking wine. (Skipped if STDIN was not + # redirected.) + if !STDIN.tty? + input = STDIN.read + else + input = "" + end + + # Disable all Wine messages so they don't interfere with the output + ENV['WINEDEBUG'] = 'err-all,warn-all,fixme-all,trace-all' + + # Run the program in wine and capture the output + output, errormsg, status = Open3.capture3('wine', *ARGV, :stdin_data => input) + + # Clean and print the results. + STDOUT.write clean(output) + STDERR.write clean(errormsg) + + exit(status.exitstatus) +end + + +main() |
