Windows support in Crystal 1.9
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
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 forfoo-static.lib
beforefoo.lib
when linking statically, orfoo-dynamic.lib
beforefoo.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, theCRYSTAL_LIBRARY_RPATH
build-time environment variable can be used to prepend DLL search paths to the default search order. It is inspired byDT_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 aProcess
’s streams toIO
s, and asyncLog
backends. Note thatFile
s and standard streams likeSTDOUT
are still synchronous at the moment.timeout
now works correctly insideselect
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
, andSTDERR
are now opened in binary mode, rather than text mode (#13397). This is necessary for the macrorun
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
insideProcess.run
(#13425)crystal play
(#13492) andcrystal 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.