Skip to content

v0.5.10

Latest

Choose a tag to compare

@github-actions github-actions released this 08 Sep 23:08
· 8 commits to main since this release
v0.5.10
c4767d6

Unofficial community build. Not affiliated with Modular or Qualcomm.

The release where there is a mojo.exe. Not in this archive, and not one you can use for anything yet, but the compiler now compiles for a Windows target with zero failing compile actions, links with zero undefined symbols, and the binary that comes out runs on the machine that built it. Nine changes land here, six of them are the road to that, and the last of them moves the pin 145 commits.

Pinned to upstream modular/v25.7.0-29887-g2b47eeef01, commit 2b47eeef01fd2d85269184ced847dc75d2c5040a.

Download mojo-windows-runtime-0.5.10-x86_64.zip, unpack it, run bin\hello.exe. Nothing to install first. Windows 10 version 1809 or later, x64.

The compiler builds

#300 opened with 44 files failing to compile the moment the compiler sources were pointed at a Windows target for the first time. Five changes took that to zero, and they are worth reading in order because each one was hiding the next.

#301 is the one that accounts for 35 of the 44 and has nothing to do with the compiler. curl's BUILD file lists its own source directory in includes, and includes propagates, so every target that reaches curl anywhere in its graph was compiling with -isystem external/curl+/lib on the command line. That is harmless until the header names start colliding, and the CRT and the Windows SDK between them own a few thousand short generic names. share.h is one. Microsoft's <xiosbase> says #include <share.h> and means the CRT's, got curl's, and curl's pulls in curl_setup.h and so winsock2.h and so the whole of windows.h. The visible symptom was that including <sstream> defined IGNORE in every translation unit in the compiler, and 35 files then failed to parse an enumerator by that name. The directory is a -iquote copt now, which reaches curl and nothing else.

#303 and #304 are the ordinary porting work underneath. Four places passed a std::filesystem::path where a std::string was wanted and let the implicit conversion do it, which only exists where path::value_type is char, and on Windows it is wchar_t. Two files were getting <string> and <deque> handed to them by some other header, which libstdc++ and libc++ both do and Microsoft's STL does not. And three files included headers Windows has never had. <dlfcn.h> was unused and simply went. <unistd.h> in the interpreter's write folder became <io.h> and _write. The signal handler is the real one and it now keeps the LLVM half, which is the stack trace and the host machine info, and loses the detail block that names the signal and the faulting address, because producing that on Windows means a vectored exception handler and that is separate work.

#305 is the last four, and both of them are a constant rather than an API. kExprDestOperandIdx is ~1ULL in an enum with no fixed underlying type, and the implementation picks the type: the Itanium ABI picks an unsigned one, the Microsoft ABI picks int, which cannot hold it. Clang warns, carries on with -2, and the first braced initializer for a size_t turns that into an error. The enum says enum : size_t now. The other is four InsertValueOp::create calls with a position of zero, where create is overloaded on ArrayRef<int64_t> and on DenseI64ArrayAttr and mlir::Attribute has an implicit constructor from a pointer. Under -fms-compatibility clang keeps the pre C++11 rule that any constant expression evaluating to zero is a null pointer constant, so the attribute overload became viable and neither candidate won. Only the zeroes failed, which is why a position of one sitting on the next line compiled fine.

#307 is the link. Init and AsyncRT:Runtime are both plain static libraries and both declared functions with MODULAR_CXX_EXPORT, which is dllexport when MODULAR_BUILDING_LIBRARY is defined and dllimport when it is not. The only thing that defines it is modular_shared_library, and neither of these is one, so every caller was being sent to an import table entry that no import library has, while lld-link pointed out that the definition was in an object file it already had. This is the same mistake Support:Context made in v0.5.9 and it gets the same answer, MODULAR_CXX_STATIC_VISIBLE, which is default visibility on ELF and Mach-O and nothing at all on Windows, because there is no DLL boundary here for either word to be about. On Linux and macOS this changes nothing.

With that in, //Mojo/tools/mojo builds natively on Windows: 0 failing compile actions, 0 undefined symbols, bazel-bin/Mojo/tools/mojo/mojo.exe produced and it starts. What it cannot do yet is the point of the next section.

Three other things

#297 finishes off #207, which asked how widespread the #201 problem is rather than assuming. A value whose last use is an argument of a raising call is destroyed on the way out of that call, and naming it in the except block does not count as a use, so the handler reads a slot something else now owns. Linux usually gets the right answer by luck because the old bytes are still there, and the Windows allocator scrubs them. scripts/find-dead-handler-values.py counts it: 2003 Mojo files, 23 sites in 17 files, and reading all 23 leaves two real ones. io/file.mojo puts a destroyed directory name into an error message. tempfile/tempfile.mojo uses a destroyed path to clean up after a failed write, so on Windows the cleanup looks at a scrubbed path, finds nothing, and leaves the temporary file behind. Both are fixed. Two sites is not enough to justify carrying a compiler change in the overlay, and the compiler change is not ours to make, so what this leaves behind is the script and a number that can be re-run against a new pin.

#298 closes #230 the long way round. Two GPU codegen tests fail to build on every platform, and the issue framed it as a choice: either the released mojo from the wheel builds them, in which case our LLVM configuration is wrong and this is a build setting, or it does not, in which case they belong behind a constraint. The released one does build them, so the first branch looked right. Adding AMDGPU and NVPTX to the LLVM configuration is a one line change through an extra_targets hook nothing was using, and it was made, and 2721 actions ran over 22 minutes, and the error did not move by a byte. It does not move because the triple is not served by an LLVM backend, it is served by a Mojo TargetBackend, and HostBackend is the only one in this tree. amdgcn-amd-amdhsa appears in no C++ source here at all. Both tests take a constraint now, each with a comment saying why the obvious fix does not work, so nobody spends the same 22 minutes.

#299 closes #115. All thirteen @modular_wheel aliases are selects over the three platforms Modular publishes the MAX wheel for, Windows is not one, and nothing was checking that the default arm which makes that survivable is still there. The failure mode is why it matters: a select with no matching arm fails in whatever reaches it rather than in the file that lost the arm, and one standard library test importing DeviceContext takes its whole package's lit aggregate down, which is where most of the old analysis allowlist came from. The check names the aliases directly now. The audit came out clean, all thirteen analyze for Windows, and the compiler does not reach the wheel at all.

The pin

#308 is the first pin move since M5, 145 commits, and it closed #302. Two of the 225 overlay files needed a real merge. The one that conflicted was our rules_mypy patch meeting upstream's own version of the same fix, and theirs turned out to be ours plus a second bug we did not have, so ours was dropped and theirs taken. The other was a test added to a lit list and it merged without comment. The bump also turned up that the lock had been recording the string main as its tag, because branch mode used the branch name where tag and commit modes both use git describe, and that tag is exactly what release notes and issues quote. Branch mode describes now, which is why the tag above reads the way it does.

What is different in the archive

The four binaries all changed, and this time one of them changed in a way you can see from outside.

KGENCompilerRTShared.lib no longer exports AsyncRT::getOrCreateCPUDevice. That is #307 arriving: the function lives in a static library, it was marked for export anyway, and so it was being published out of a DLL that had no business publishing it. MSupportGlobals.lib and AsyncRTRuntimeGlobals.lib are byte for byte what they were in v0.5.9, so nothing else about what these DLLs offer has moved, and the rest of the difference in the binaries is 145 commits of upstream plus whatever the relink stamped into them.

example/hello.mojo, LICENSE and NOTICE are unchanged. README.txt differs only in the version number. upstream.lock names the new pin.

Test results

Linux tier 0 is 237 pass and 2 skipped of 239. Linux tier 1 is 76 pass and 2 skipped of 78, with the usual nonzero exit because //Mojo/stdlib/test/os:test_trap_gpu.mojo fails to build for a target this machine does not have. Windows tier 0 is 233 pass and 6 skipped of 239. Windows tier 1 is 75 pass and 3 skipped of 78. Windows ABI conformance is 13 of 13.

Both tier 0 totals are one higher than v0.5.9 because the pin move brought in a new compile-fail test and the merge put it in the list. Everything else is exactly what it was before the bump, which was the point of running all five suites twice.

The kgen and mojo-tool lit suites were not re-run. They were 321 of 321 in v0.5.8 and that number is now two pin moves old, so treat it as a reason to expect a result rather than as a result.

Manual acceptance

This exact archive was unpacked on a Windows machine into a clean directory and bin\hello.exe run from where it landed, printing Hello from Mojo and built for Windows: True and exiting zero.

The rest of the v0.5.6 record stands and is in docs/acceptance.md, covering non ASCII paths, paths with spaces, crash output for an access violation and a stack overflow, an import table with nothing unexpected in it, and a Defender scan that left everything alone. Those were checked against a runtime that has been relinked twice since, which is worth knowing when reading them. Item 1 is still not applicable because there is no mojo.exe in the archive to start a REPL with. Items 2 and 5 still need a person at a real console, one to judge how the colours read and one to press Ctrl-C, and nobody has done either yet.

What still does not work

The archive is a runtime and one example program. It does not contain mojo.exe and nothing in this release puts one there. A compiler that builds and links is a long way from a compiler that ships: it has never compiled a Mojo program on Windows, the standard library it would need beside it is not packaged, and until #31 lands it has no COFF JIT, which means no REPL and no mojo run whatever else is true.

MLIR type identity still does not survive a module boundary on Windows, which is #294 and was the price of the v0.5.9 link fix. The MAX wheel still has no Windows build, and #299 settled that as far as it can be settled: the aliases resolve, the compiler does not reach them, and the tests that genuinely need MAX come back skipped, which is the accurate answer for a platform MAX does not build for.

The debug archive nearly did not get built at all, which is #310. .pdb files are not declared outputs of a link action, so a cached link produces the DLL and not the symbols, and with path mapping on the link is forced into the sandbox which throws undeclared outputs away. The archive here is correct, but it took two flags applied by hand and a full rebuild to get it, and the script does not know about them yet.

Files

The overlay archives are built by CI from the tag and carry a provenance attestation. The Windows archives are cross compiled from Linux by hand and carry checksums only, because CI cannot build them and attesting them there would sign a claim that is false. docs/releasing.md explains that at more length.

Verify what you downloaded before using it:

sha256sum -c SHA256SUMS
sha256sum -c SHA256SUMS-windows
gh attestation verify <file> --repo tamnd/mojo.windows

The Windows binaries are unsigned, so Windows will warn about them the first time you run one from Explorer. That is expected. docs/downloading.md says what the warning looks like, what decides whether you see it at all, and how to get past it.