Skip to content
GitHub Repository Forum RSS-Newsfeed

Windows support in Crystal 1.9

HertzDevil

With the release of Crystal 1.9, the compiler and the standard library have made a big step towards tier 1 support for x64 Windows with the MSVC toolchain. While an official Windows release isn’t ready yet, only few outstanding issues remain and we expect them to be resolved in the following months. This post is a brief overview of what 1.9 has achieved and what else needs to be achieved.

GUI Installer

installer

For the first time, there is a GUI installer for Windows! It installs the compiler and all the third-party dependencies for the standard library. It also adds the compiler to the PATH environment variable, sets up file association, updates or uninstalls properly, and warns the user if the Windows SDK or Microsoft Visual Studio cannot be detected. This setup is expected to “just” work on new machines apart from installing those Microsoft components. It provides a more streamlined experience to Crystal users on Windows who are less familiar with command-line environments.

The upcoming 1.9 release will come with a download option for this GUI installer. A new installer will be built on GitHub Actions whenever a minor or patch release is available, so you normally won’t see installers for nightly builds like the screenshot above, although updating to or from a nightly version shouldn’t be any different. If you have a GitHub account, please take a try at the crystal-installer artifact from this CI run and report any issues you found. You could also try building the installer locally, using Inno Setup and following the Windows workflow instructions.

Dynamic linking

Much of the work in the past three months went into supporting load-time dynamic linking on Windows as seamlessly as possible. You can now use the -Dpreview_dll compile-time flag to opt in to experimental dynamic linking support. More details can be found in the reference manual (1.9, master). A brief summary is:

  • @[Link("foo")] will now instruct the compiler to search for foo-static.lib before foo.lib when linking statically, or foo-dynamic.lib before foo.lib when linking dynamically, allowing both libraries to be served side-by-side in the same directory.
  • Static linking implies /MT and dynamic linking implies /MD. Your own C libraries should be built with the appropriate MSVC linker flags.
  • If the compiler flag -Dpreview_win32_delay_load is supplied, the CRYSTAL_LIBRARY_RPATH build-time environment variable can be used to prepend DLL search paths to the default search order. It is inspired by DT_RPATH for ELF binaries, and likewise supports $ORIGIN, enabling relocatable, dynamically linked Windows binaries.

Static linking will remain the default linking mode for Windows on Crystal 1.9 and 1.10; the compiler flag -Dpreview_dll enables dynamic linking in these versions. Afterwards, dynamic linking will become the default and --static will be required for static linking, just like on other systems. Please add --static to your build scripts appropriately if they rely on that.

Other notable advancements

  • IO.pipe is now asynchronous (#13362). This enables concurrency in a few crucial features on Windows, most notably piping a Process’s streams to IOs, and async Log backends. Note that Files and standard streams like STDOUT are still synchronous at the moment.
  • timeout now works correctly inside select expressions (#13525).
  • Time::Location now respects IANA time zone names out of the box (#13517), and local time zones without daylight saving time transitions (#13516).
  • STDIN, STDOUT, and STDERR are now opened in binary mode, rather than text mode (#13397). This is necessary for the macro run to work with certain source files that contain CRLF line endings.
  • Unix sockets are now supported to the extent that Windows actually implements (#13493), as well as several other miscellaneous socket APIs (#13325, #13326, #13363, #13364).
  • Read-only files and directories can now be deleted properly (#13462, #13626).

What’s left

An ever-changing list of outstanding issues on Windows can be found in this GitHub project, and we hope to squash the “Todo” and “In progress” columns by the time an official Windows release is available. As of the time of writing this post, the main remaining issues are:

  • Behavior of Process.new(shell: true) (#9030)
  • Support for long paths in file APIs (#13420)
  • Platform-independent sprintf for floats (#12473)
  • Making /SUBSYSTEM:WINDOWS more usable (#13058, #13330)
  • Process#close inside Process.run (#13425)
  • crystal play (#13492) and crystal i (#12396)
  • Channels do not behave correctly under -Dpreview_mt

The number of specs in the standard library test suite tagged with pending_win32 has dropped from 35 to 8 since the previous minor release. This is a sign of rapid progress, and this progress shall be carried over into the next development cycle.