mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
Merge pull request #5563 from suetanvil-misc/project-bintest-emulator-4-flat
Added testing support for cross-MinGW builds.
This commit is contained in:
@@ -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
|
||||
Executable
+71
@@ -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()
|
||||
@@ -541,6 +541,23 @@ EOS
|
||||
end
|
||||
end
|
||||
|
||||
def run_bintest
|
||||
puts ">>> Bintest #{name} <<<"
|
||||
targets = @gems.select { |v| File.directory? "#{v.dir}/bintest" }.map { |v| filename v.dir }
|
||||
targets << filename(".") if File.directory? "./bintest"
|
||||
mrbc = @gems["mruby-bin-mrbc"] ? exefile("#{@build_dir}/bin/mrbc") : mrbcfile
|
||||
|
||||
emulator = @test_runner.command
|
||||
emulator = @test_runner.shellquote(emulator) if emulator
|
||||
|
||||
env = {
|
||||
"BUILD_DIR" => @build_dir,
|
||||
"MRBCFILE" => mrbc,
|
||||
"EMULATOR" => @test_runner.emulator,
|
||||
}
|
||||
sh env, "ruby test/bintest.rb#{verbose_flag} #{targets.join ' '}"
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def create_mrbc_build; end
|
||||
|
||||
@@ -363,6 +363,11 @@ module MRuby
|
||||
@flags = []
|
||||
end
|
||||
|
||||
def emulator
|
||||
return "" unless @command
|
||||
return [@command, *@flags].map{|c| shellquote(c)}.join(' ')
|
||||
end
|
||||
|
||||
def run(testbinfile)
|
||||
puts "TEST for " + @build.name
|
||||
_run runner_options, { :flags => [flags, verbose_flag].flatten.join(' '), :infile => testbinfile }
|
||||
|
||||
@@ -7,7 +7,7 @@ assert('Compiling multiple files without new line in last line. #2361') do
|
||||
b.write('module B; end')
|
||||
b.flush
|
||||
result = `#{cmd('mrbc')} -c -o #{out.path} #{a.path} #{b.path} 2>&1`
|
||||
assert_equal "#{cmd('mrbc')}:#{a.path}:Syntax OK", result.chomp
|
||||
assert_equal "#{cmd_bin('mrbc')}:#{a.path}:Syntax OK", result.chomp
|
||||
assert_equal 0, $?.exitstatus
|
||||
end
|
||||
|
||||
@@ -16,7 +16,7 @@ assert('parsing function with void argument') do
|
||||
a.write('f ()')
|
||||
a.flush
|
||||
result = `#{cmd('mrbc')} -c -o #{out.path} #{a.path} 2>&1`
|
||||
assert_equal "#{cmd('mrbc')}:#{a.path}:Syntax OK", result.chomp
|
||||
assert_equal "#{cmd_bin('mrbc')}:#{a.path}:Syntax OK", result.chomp
|
||||
assert_equal 0, $?.exitstatus
|
||||
end
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ require 'tempfile'
|
||||
require 'open3'
|
||||
|
||||
def assert_mruby(exp_out, exp_err, exp_success, args)
|
||||
out, err, stat = Open3.capture3(cmd("mruby"), *args)
|
||||
out, err, stat = Open3.capture3( *(cmd_list("mruby") + args))
|
||||
assert "assert_mruby" do
|
||||
assert_operator(exp_out, :===, out, "standard output")
|
||||
assert_operator(exp_err, :===, err, "standard error")
|
||||
@@ -87,7 +87,7 @@ assert('mruby -e option (no code specified)') do
|
||||
end
|
||||
|
||||
assert('mruby -h option') do
|
||||
assert_mruby(/\AUsage: #{Regexp.escape cmd("mruby")} .*/m, "", true, %w[-h])
|
||||
assert_mruby(/\AUsage: #{Regexp.escape cmd_bin("mruby")} .*/m, "", true, %w[-h])
|
||||
end
|
||||
|
||||
assert('mruby -r option') do
|
||||
|
||||
+16
-2
@@ -3,13 +3,27 @@ require 'test/assert.rb'
|
||||
|
||||
GEMNAME = ""
|
||||
|
||||
def cmd(s)
|
||||
def cmd_list(s)
|
||||
path = s == "mrbc" ? ENV['MRBCFILE'] : "#{ENV['BUILD_DIR']}/bin/#{s}"
|
||||
path = path.sub(/\.exe\z/, "")
|
||||
if /mswin(?!ce)|mingw|bccwin/ =~ RbConfig::CONFIG['host_os']
|
||||
path = "#{path}.exe".tr("/", "\\")
|
||||
end
|
||||
path
|
||||
|
||||
path_list = [path]
|
||||
|
||||
emu = ENV['EMULATOR']
|
||||
path_list.unshift emu if emu && !emu.empty?
|
||||
|
||||
path_list
|
||||
end
|
||||
|
||||
def cmd(s)
|
||||
return cmd_list(s).join(' ')
|
||||
end
|
||||
|
||||
def cmd_bin(s)
|
||||
return cmd_list(s).pop
|
||||
end
|
||||
|
||||
def shellquote(s)
|
||||
|
||||
Reference in New Issue
Block a user