Skip to content

Commit

Permalink
Autogenerate win32_std_spec
Browse files Browse the repository at this point in the history
  • Loading branch information
straight-shoota committed Jan 10, 2020
1 parent 6c25fa3 commit cfd3d1f
Show file tree
Hide file tree
Showing 3 changed files with 320 additions and 136 deletions.
87 changes: 87 additions & 0 deletions spec/generate_windows_spec.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#! /usr/bin/env bash
set +x

# This script iterates through each spec file and tries to cross compiler and
# run it on win32 platform.
#
# * `failed codegen` annotates specs that error in the compiler.
# This is mostly caused by some API not being ported to win32 (either the spec
# target itself or some tools used by the spec).
# * `failed linking` annotats specs that compile but don't link (at least not on
# basis of the libraries from *Porting to Windows* guide).
# Most failers are caused by missing libraries (libxml2, libyaml, libgmp,
# libllvm, libz, libssl), but there also seem to be some incompatibilities
# with the existing libraries.
# * `failed to run` annotates specs that compile and link but don't properly
# execute.
#
# PREREQUISITES:
#
# This script requires a working win32 build environment as described in
# the [*Porting to Windows* guide]()https://github.com/crystal-lang/crystal/wiki/Porting-to-Windows
#
# * LINKER points to a program that executes the linker command on win32 platform
# but does not run the compiled binary.
# * RUNNER points to a program that executes the compiled binary on win32 platform.
# When running on WSL, this can just be a shell because WSL can run win32
# binaries directly. When using a remote win32 environment, the program needs to
# make sure it reuses the previously compiled program.
#
# The defaults for both tools work on WSL, the linker only requires
# MSVC_BUILD_TOOLS to be set appropriately.
#
# USAGE:
#
# For std spec:
# $ spec/generate_windows_spec.cr > spec/win32_std_spec.cr
# For compiler spec:
# $ spec/generate_windows_spec.cr compiler > spec/win32_compiler_spec.cr

SPEC_SUITE=${1:-std}
LINKER=${LINKER:-crystal-windows-wsl}
RUNNER=${RUNNER:-/bin/sh -c}

function crystal-windows-wsl {
cmd.exe /S /c "${MSVC_BUILD_TOOLS} amd64 && cd /D %CD% && ${*//\"/} user32.lib"
return $?
}

if [ "$LINKER" == "crystal-windows-wsl" ] && [ -z "$MSVC_BUILD_TOOLS" ]; then
echo "Missing environemnt variable MSVC_BUILD_TOOLS" >&2
exit 1
fi

if [ -f "bin/crystal" ]; then
CRYSTAL_BIN=${CRYSTAL_BIN:-bin/crystal}
else
CRYSTAL_BIN=${CRYSTAL_BIN:-crystal}
fi

command="$0 $*"
echo "# This file is autogenerated by \`${command% }\`"
echo "# $(date --rfc-3339 seconds)"
echo

for spec in $(find "spec/$SPEC_SUITE" -type f -iname "*_spec.cr" | sort); do
require="require \"./${spec##spec/}\""

if ! linker_command=$($CRYSTAL_BIN build --cross-compile --target x86_64--windows-msvc "$spec" 2>/dev/null); then
echo "# $require (failed codegen)"
continue
fi

if ! $LINKER "$linker_command" >/dev/null 2>/dev/null; then
echo "# $require (failed linking)"
continue
fi

binary_path="./$(echo "$linker_command" | grep -oP '(?<="/Fe)(.*)(?=")').exe"

$RUNNER "$binary_path" > /dev/null; exit=$?

if [ $exit -eq 0 ] || [ $exit -eq 1 ]; then
echo "$require"
else
echo "# $require (failed to run)"
fi
done
141 changes: 5 additions & 136 deletions spec/std_spec.cr
Original file line number Diff line number Diff line change
@@ -1,140 +1,9 @@
require "spec"
{% unless flag?(:win32) %}
require "./std/**"
require "./std/**"
{% else %}
# This list gives an overview over which specs are currently working on win32
# and what not.
#
# There are different levels of not-working:
#
# * Specs that error at compile time are completely commented out. This is
# mostly caused by some API not being ported to win32 (either the spec target or
# the spec uses non-ported features).
# * Specs that compile but don't link (at least not on basis of the *Porting to
# Windows* guide) are guarded by the `require_nolink` macro. When passing
#`-Dwin32_nolink` they can be enabled for testing codegen. Most of are just
# caused by missing libraries (libxml2, libyaml, libgmp, libllvm, libz, libssl),
# but there also seem to be some incompatibilities with the existing libraries.
# * Some of the `require_nolink` specs are annotated as `# execution breaks`,
# which means linking is fine but they break the entire spec suite at runtime.

private macro require_nolink(path)
{% if flag?(:win32_nolink) %}
require {{ path }}
{% end %}
end

require_nolink "./std/adler32_spec.cr"
require "./std/array_spec.cr"
require "./std/atomic_spec.cr"
require "./std/base64_spec.cr"
# require "./std/benchmark_spec.cr"
require_nolink "./std/big/**"
require "./std/bit_array_spec.cr"
require "./std/bool_spec.cr"
require "./std/box_spec.cr"
# require "./std/callstack_spec.cr"
# require "./std/channel_spec.cr"
require "./std/char/**"
require "./std/char_spec.cr"
require "./std/class_spec.cr"
require "./std/colorize_spec.cr"
require_nolink "./std/comparable_spec.cr" # execution breaks
require_nolink "./std/complex_spec.cr"
require_nolink "./std/concurrent/**" # execution breaks
require "./std/concurrent_spec.cr"
require_nolink "./std/crc32_spec.cr"
require_nolink "./std/crypto/**"
require_nolink "./std/crystal/**"
require "./std/csv/**"
require "./std/deque_spec.cr"
require_nolink "./std/digest/**"
require "./std/dir_spec.cr"
require "./std/double_spec.cr"
require "./std/ecr/**"
require "./std/enumerable_spec.cr"
require "./std/enum_spec.cr"
require "./std/env_spec.cr"
require "./std/exception_spec.cr"
# require "./std/file/**"
# require "./std/file_spec.cr"
# require "./std/file_utils_spec.cr"
require_nolink "./std/flate/**"
require "./std/float_printer/**"
require_nolink "./std/float_spec.cr"
require "./std/gc_spec.cr"
require_nolink "./std/gzip/**"
require "./std/hash_spec.cr"
require "./std/html_spec.cr"
# require "./std/http/**"
require "./std/humanize_spec.cr"
require "./std/indexable_spec.cr"
require "./std/ini_spec.cr"
require_nolink "./std/int_spec.cr"
# require "./std/io/**"
require "./std/iterator_spec.cr"
require_nolink "./std/json/**"
# require "./std/kernel_spec.cr"
require "./std/levenshtein_spec.cr"
require_nolink "./std/llvm/**"
# require "./std/logger_spec.cr"
require "./std/match_data_spec.cr"
require_nolink "./std/math_spec.cr"
# require "./std/mime/**"
require "./std/mime_spec.cr"
# require "./std/mutex_spec.cr"
require "./std/named_tuple_spec.cr"
require_nolink "./std/number_spec.cr"
# require "./std/oauth/**"
# require "./std/oauth2/**"
require "./std/object_spec.cr"
# require "./std/openssl/**"
require "./std/option_parser_spec.cr"
require "./std/path_spec.cr"
require "./std/pointer_spec.cr"
require "./std/pp_spec.cr"
require "./std/pretty_print_spec.cr"
# require "./std/process_spec.cr"
require "./std/proc_spec.cr"
require "./std/raise_spec.cr"
require "./std/random/**"
require_nolink "./std/random_spec.cr"
require_nolink "./std/range_spec.cr"
require "./std/record_spec.cr"
require "./std/reference_spec.cr"
require "./std/regex_spec.cr"
require "./std/semantic_version_spec.cr"
require "./std/set_spec.cr"
# require "./std/signal_spec.cr"
require "./std/slice_spec.cr"
# require "./std/socket/**"
require "./std/spec/context_spec.cr"
require "./std/spec/expectations_spec.cr"
require "./std/spec/filters_spec.cr"
require_nolink "./std/spec/junit_formatter_spec.cr"
require "./std/spec/tap_formatter_spec.cr"
require "./std/spec_spec.cr"
require "./std/static_array_spec.cr"
require "./std/string/**"
require "./std/string_builder_spec.cr"
require "./std/string_pool_spec.cr"
require "./std/string_scanner_spec.cr"
# require "./std/string_spec.cr"
require_nolink "./std/struct_spec.cr"
require "./std/symbol_spec.cr"
# require "./std/system/**"
# require "./std/system_spec.cr"
# require "./std/thread/**"
# require "./std/thread_spec.cr"
require "./std/time/**"
require "./std/tuple_spec.cr"
require "./std/uint_spec.cr"
require "./std/uri/**"
require "./std/uri_spec.cr"
require "./std/uuid_spec.cr"
require "./std/weak_ref_spec.cr"
require_nolink "./std/xml/**"
require_nolink "./std/yaml/**"
require_nolink "./std/zip/**"
require_nolink "./std/zlib/**"
# This list gives an overview over which specs are currently working on win32.
#
# See spec/generate_windows_spec.sh for details.
require "./win32_std_spec.cr"
{% end %}
Loading

0 comments on commit cfd3d1f

Please sign in to comment.