-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Build with Mingw-w64 #6170
Comments
I'm all for this because I like the idea of being able to build windows binaries without windows, but not to the detriment / timeliness of the current windows development being done. That said, maybe this will make windows CI easier? or no? |
Of course, Mingw64 should be supported. It doesn't feel like a pressing issue to me, though. I don't no much about the practical differences between MSVC and Mingw64 in regards to Crystal supporting it. But, as I alread said in #5430 (comment), the current effort should focus on porting the stdlib to Win32 API. That needs to be done anyway and still requires a lot of work. Supporting an alternate tool chain doesn't gain anything until that is at least somewhat matured.
Windows CI needs to run on windows anyway, so there is no point in cross compiling from a different platform. |
Azure CI looks very interesting. It supports Windows, Linux and Mac and is free fpr Open Source Projects: https://azure.microsoft.com/en-us/blog/announcing-azure-pipelines-with-unlimited-ci-cd-minutes-for-open-source/ @bcardiff @RX14 👀 |
travis-ci has also announced windows support: https://blog.travis-ci.com/2018-10-11-windows-early-release That should be fairly easy to integrate into the CI setup |
Since Crystal is maturing support towards MSVC and Win32 APIs directly instead of mingw-w64 (#26 (comment)), Is this still relevant? |
Technically yes. Mingw-w64 is a different target than msvc and supporting it is still a goal I think. Although it's not actively driven at the moment due to low importance. |
Exactly. The Crystal team can always re-open the issue if there is enough demand for it. |
correct. which is the reason language like Rust offer a MSVC and GNU build for Windows, the latter being MinGW-w64.
how is it not actionable? wouldn't adding support for it be an action?
please dont do that. you have over 1000 issues open, no harm in leaving this open. closing by a maintainer sends a strong signal that this is essentially WONTFIX, regardless of any reason given.
both of these items are false. Native Win32 support is only marginally useful, as developing with that environment requires an install of Visual Studio, which is at least 100 times the install size of MSYS2 and similar options. secondly, WSL has no impact on MinGW/MSYS2, because WSL is a Linux emulator, so you take a huge performance hit using that option, whereas MSYS2 offers native Windows output. |
Actionable means to have a clear path what's necessary to achieve this, or at least the intention to discuss that and determine a path.
Yes, we'd like to reduce that number. There's not much value in having lots of stale issues. We know that Mingw is not supported and that support for it would be welcome. But no need to keep an issue around that does nothing.
Sorry, I have a hard time making any sense of "Native Win32 support is only marginally useful". I also beg to differ that "WSL has no impact on MinGW/MSYS2". MSYS2 is a tool for using Unix programs on Windows. I used that myself back in the day. But I've long moved to WSL because it's a much more complete Unix environment with an actual Linux kernel interface that offers a lot more possibilities. Sure, WSL is not a replacement for all use cases of MSYS2. But for me, it is a much better one. And I'm pretty sure for many others as well. |
I get the desire to want to close issues, but closing them doesn't fix anything, it just makes you feel better. they should be closed when they are actually fixed, or when they decision is made that they will never be fixed.
sorry I was just using your language. a better comment would be "MSVC support is only marginally useful". Windows developers use MSVC when its the only option. Ideally MSYS2 support would also exist, as it has several benefits over MSVC.
MSYS2 is able to produce native Windows programs: https://packages.msys2.org/base/mingw-w64-gcc
its not a replacement at all. WSL "programs" are linux programs that work on Windows via an emulator. MSYS2 produces native Windows programs that rely on the Windows API. the two couldn't be more different. |
Keeping it open also does nothing towards getting it resolved. Closing issues with no forseeable activity helps to keep the amount of currently relevant issues manageable. |
To be clear, there are a few different toolchains possible on Windows:
MSYS is the "MSYS" environment of MSYS2, as indicated by While the majority of our MSVC toolchain work is completed, some deserves extra attention regarding what happens if other Windows toolchains are going to be supported, such as the meaning of "default shell". There is also the issue that MinGW-w64's license will always be more permissive than MSVC's, and that could be a deal breaker for some people. So I think now is a good time to revisit those alternative toolchains. |
I see little value in supporting Cygwin or MSYS-2.0 since we support the official Windows API: there shouldn't be any portability issues of crystal code. I can see value in MinGW-w64 as an alternative to MSVC, especially if we could link an EXE from linux or macos (though I'm not sure about the runtime in that case). |
+1
What? 😮 |
Sure. Linking against msys we wouldn't need any Windows system libraries, so it should be entirely feasible to cross-link executables. |
Ah, right, thanks for clarifying 🙇 |
You can cross-link Windows executables straight from non-Windows systems using
Anyway, here is a worked example of using MinGW-w64 stand-alone on Windows:
We can supposedly symlink |
This issue has been mentioned on Crystal Forum. There might be relevant details there: |
Apart from cross-compilation, it is also possible to build and distribute Crystal itself using crystal/src/openssl/lib_crypto.cr Lines 3 to 20 in 991f9d0
On MSYS2, assuming a non-portable Crystal installation, there is probably no need for an
They could actually be fixed by wrapping them in {% from_libressl = (`sh -c 'hash pkg-config 2> /dev/null || printf %s false'` != "false") &&
(`sh -c 'test -f $(pkg-config --silence-errors --variable=includedir libcrypto)/openssl/opensslv.h || printf %s false'` != "false") &&
(`sh -c 'printf "#include <openssl/opensslv.h>\nLIBRESSL_VERSION_NUMBER" | ${CC:-cc} $(pkg-config --cflags --silence-errors libcrypto || true) -E -'`.chomp.split('\n').last != "LIBRESSL_VERSION_NUMBER") %}
{% ssl_version = `sh -c 'hash pkg-config 2> /dev/null && pkg-config --silence-errors --modversion libcrypto || printf %s 0.0.0'`.split.last.gsub(/[^0-9.]/, "") %} Yet now the initial cross-compilation to |
Resolves part of #6170. These series of patches allow `--cross-compile --target=x86_64-windows-gnu` to mostly work: * The `@[ThreadLocal]` annotation and its corresponding LLVM attribute seem to break when targetting `x86_64-windows-gnu`, so Win32 TLS is used instead. This is only needed for `Thread.current`. * Since MinGW uses `libgcc`, and Crystal relies on the underlying C++ ABI to raise exceptions, we use the Itanium ABI's `_Unwind_*` functions, along with a thin personality function wrapper. ([GCC itself does the same](https://github.com/gcc-mirror/gcc/blob/68afc7acf609be2b19ec05c8393c2ffc7f4adb4a/libgcc/unwind-c.c#L238-L246). See also [Language-specific handler](https://learn.microsoft.com/en-us/cpp/build/exception-handling-x64?view=msvc-170#language-specific-handler) from the Windows x64 ABI docs.) * MinGW binaries now come with DWARF debug information, so they work under GDB, maybe under LLDB, and probably poorly under the Visual Studio Debugger. * There is no need to mangle symbol names the same way MSVC binaries do. * `--cross-compile` now prints ld-style linker flags, rather than MSVC ones. This is still incomplete and includes remnants of the MSVC toolchain like the `/ENTRY` flag; they will be fixed later once we get to native compiler builds. * `src/lib_c/x86_64-windows-gnu` is now a symlink to `src/lib_c/x86_64-windows-msvc`, since both toolchains are targetting the same Win32 APIs. (This is not Cygwin nor MSYS2's MSYS environment.) * Lib funs now use the Win32 C ABI, instead of the SysV ABI. * On MinGW we use GMP proper, and there is no need for MPIR. After building a local compiler, `bin\crystal build --cross-compile --target=x86_64-windows-gnu` will generate an object file suitable for linking under MinGW-w64. At a minimum, this object file depends on Boehm GC and libiconv, although they can be skipped using `-Dgc_none` and `-Dwithout_iconv` respectively. Then we could use MSYS2's UCRT64 environment to link the final executable: ``` $ pacman -Sy mingw-w64-ucrt-x86_64-gc mingw-w64-ucrt-x86_64-pcre2 mingw-w64-ucrt-x86_64-libiconv mingw-w64-ucrt-x86_64-gmp $ cc test.obj `pkg-config bdw-gc iconv libpcre2-8 gmp --libs` -lDbgHelp -lole32 ``` Stack traces do not work correctly yet. Also note that MSYS2's DLL names are different from the ones distributed with MSVC Crystal, and that cross-compilation never copies the DLL dependencies to the output directory. To make the executable run outside MSYS2, use `dumpbin /dependents` from the MSVC developer prompt to obtain the dependencies, then copy them manually from the MSYS2 `/ucrt64/bin` folder.
LLVM is similar, if we assume that a MinGW-w64-based compiler is only portable within an MSYS2 shell. First the {% llvm_config = env("LLVM_CONFIG") || `sh #{__DIR__}/ext/find-llvm-config`.stringify %} This is somewhat related to #9030 and shows that we probably shouldn't assume If {% llvm_version = `#{llvm_config.id} --version`.stringify %} This is not a parsing issue, but simply because if [ "$LLVM_CONFIG" ]; then
case "$(uname -s)" in
MSYS_NT*|MINGW32_NT*|MINGW64_NT*)
printf "%s" "$(cygpath -w "$LLVM_CONFIG")"
;;
*)
printf "%s" "$LLVM_CONFIG"
;;
esac
else
# ...
fi or alternatively, as described above, wrap each macro backtick invocation within |
This is a continuation of #15070 that allows a compiler built with MinGW-w64 to itself build programs correctly. Resolves part of #6170. * Because linker flags for GCC may now be executed on a Windows environment, we use the correct form of argument quoting. We also drop `-rdynamic` since that only makes sense for ELF executables. * Targetting `x86_64-windows-gnu`, including normal compilations from such a Crystal compiler, will not copy dependent DLLs to the output directory. Crystal itself and programs built under MSYS2 will just work as long as the proper environment is used. You are on your own here, although `ldd` exists on MSYS2 so that you don't need the MSVC build tools for this. * The correct GCC compiler flag to select `wmain` over `main` as the C entry point is `-municode`. (The system entry point is presumably `_start` now.) * `legacy_stdio_definitions.obj` doesn't exist on MinGW-w64, so we disable it outside MSVC. * For build command lines that are too long on Windows, we use GCC's response file support. To build a MinGW-w64 compiler: ```cmd @Rem on the MSVC developer prompt make -fMakefile.win crystal bin\crystal build --cross-compile --target=x86_64-windows-gnu src\compiler\crystal.cr -Dwithout_interpreter ``` ```sh # on MSYS2's UCRT64 environment pacman -Sy \ mingw-w64-ucrt-x86_64-gc mingw-w64-ucrt-x86_64-pcre2 mingw-w64-ucrt-x86_64-libiconv \ mingw-w64-ucrt-x86_64-zlib mingw-w64-ucrt-x86_64-openssl mingw-w64-ucrt-x86_64-llvm cc crystal.obj -o crystal \ $(pkg-config bdw-gc libpcre2-8 iconv zlib openssl --libs) \ $(llvm-config --libs --system-libs --ldflags) \ -lDbgHelp -lole32 -lWS2_32 export CRYSTAL_PATH='lib;$ORIGIN\src' export CRYSTAL_LIBRARY_PATH='' ``` Now you can run or build a considerable number of files from here, such as `./crystal.exe samples/2048.cr` and `./crystal.exe spec spec/std/regex_spec.cr`. Notable omissions are OpenSSL and LLVM, as fixing their version detection macros is a bit complicated. The interpreter is not supported. Most likely, `Crystal::Loader` would have a GCC-style `.parse`, but the rest of the functionality would be identical to the MSVC `LoadLibraryExW`-based loader. ~~Also, some invocations like `./crystal.exe spec spec/std/json` will fail since the whole command line string is too long. Similar to MSVC, [GCC also handles response files starting with `@`](https://gcc.gnu.org/onlinedocs/gcc/Overall-Options.html), so this can be implemented later; a workaround is to use `--single-module`.~~ For reference, here are all the useful MSYS2 packages and their corresponding pkg-config names: | MSYS2 package name | pkg-config name | |-|-| | mingw-w64-ucrt-x86_64-gc | bdw-gc | | mingw-w64-ucrt-x86_64-pcre2 | libpcre2-8 | | mingw-w64-ucrt-x86_64-libiconv | iconv | | mingw-w64-ucrt-x86_64-gmp | gmp | | mingw-w64-ucrt-x86_64-zlib | zlib | | mingw-w64-ucrt-x86_64-libxml2 | libxml-2.0 | | mingw-w64-ucrt-x86_64-libyaml | yaml-0.1 | | mingw-w64-ucrt-x86_64-openssl | openssl | | mingw-w64-ucrt-x86_64-libffi | libffi | | mingw-w64-ucrt-x86_64-llvm | _(use llvm-config instead)_ |
Currently, MSYS2 only provides a Cygwin-based Git, which unlike Git for Windows doesn't handle Windows symlinks correctly. That means when attempting to check out this repository, one of the following things will happen:
This could be a problem for Shards as well. |
Cross-compiles a MinGW-w64-based Crystal compiler from Ubuntu, then links it on MSYS2's UCRT64 environment. Resolves part of #6170. The artifact includes the compiler, all dependent DLLs, and the source code only. It is not a complete installation since it is missing e.g. the documentation and the licenses, but it is sufficient for bootstrapping further native compiler builds within MSYS2. The resulting binary is portable within MSYS2 and can be executed from anywhere inside an MSYS2 shell, although compilation requires `mingw-w64-ucrt-x86_64-cc`, probably `mingw-w64-ucrt-x86_64-pkgconf`, plus the respective development libraries listed in #15077. The DLLs bundled under `bin/` are needed to even start Crystal since they are dynamically linked at load time; they are not strictly needed if Crystal is always run only within MSYS2, but that is the job of an actual `PKGBUILD` file.
Introduces new methods for extracting COFF debug information from programs in the PE format, integrating them into Crystal's existing DWARF parsing functionality. Resolves part of #6170. It is questionable whether reusing `src/exception/call_stack/elf.cr` for MinGW-w64 is appropriate, since nothing here is in the ELF format, but this PR tries to avoid moving existing code around, save for the old `Exception::CallStack.setup_crash_handler` as it remains the only common portion between MSVC and MinGW-w64.
I suppose we could work with |
While we have been using the UCRT64 environment so far, the same cross-compilation also works for CLANG64 and MINGW64, but an even faster alternative is to download the "portable" artifact and do
The CLANGARM64 environment is only meaningful on an ARM64 Windows host, but it should make porting to ARM64 relatively straightforward. The MSYS environment is a bit different. LLVM never officially supports MSYS, so if you ever see an |
Crystal is in the process of supporting Visual Studio. However Mingw-w64 should
be supported as well.
http://mingw-w64.org
The text was updated successfully, but these errors were encountered: