Skip to content
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 & distribute release builds with Zig as stand-alone C compiler #659

Closed
wants to merge 16 commits into from

Conversation

Kha
Copy link
Member

@Kha Kha commented Sep 8, 2021

As they say, Zig is an obvious choice for what C compiler to ship with your language. In particular, this is a big step towards zero-setup native compilation on Windows.

We use Zig's cross-compilation feature to link the Linux build against the ancient glibc 2.15, obviating the previous workaround of using an older nixpkgs channel that combines a not-quite-recent glibc with a not-quite-recent clang. Other cross-compilation targets for platforms not supported by GH Actions would also be interesting, though I wasn't able to find one that works out of the box from Linux yet.

@Kha
Copy link
Member Author

Kha commented Sep 10, 2021

To give a bit more context and a progress update, this PR tries to build all of Lean with Zig, and then copy it to bin/ and have leanc use it as a portable C compiler. Conceptually this is the simplest approach and it opens up the possibility of using Zig for cross-compiling Lean, as this PR already does for glibc 2.15 as mentioned above. However, in practice there still seem to be many hurdles to overcome for (non-cross-)compiling a nontrivial C++ project like Lean with it on all our platforms, see below.

An alternative approach would be to keep using system/Nix clang for compiling Lean itself and ship Zig only for compiling user Lean programs. Since Lean produces C code, not C++, and of a quite limited variety, it should be much easier to ensure that Zig can cope with it. However, we would still need to link Lean programs with the C++ standard library used for compiling the Lean stdlib, so we would need to ship its static library with Lean. That should work I think, but we could still run into compiler mismatches in advanced cases, e.g. LTO. And we would not be able to cross-compile Lean.

So the first approach would be preferable. The solved and unsolved issues with it are:

  • zig c++ does not support exceptions anymore
  • zig ld does not support --whole-archive/-force_load for building shared libraries from static libraries
    • workaround: hackily gather & pass .o files manually
  • macOS: getopt.h seems to be missing
    • workaround: we already have a custom implementation for MSVC, use it on all platforms
  • Windows: pthread.h seems to be missing
    • workaround: turn off AUTO_THREAD_FINALIZATION on Windows
    • @leodemoura there's also an old comment saying that we should use C++11's thread_local when it's ready, which I hope it is by now
  • Windows: Zig's ntdef.h defines min/max macros, which mingw64 didn't
    • solution: #define NOMINMAX
  • Windows: mingw64 ccache does not like our zigcc/zigc++ bash wrapper scripts
    • not directly an issue with Zig
    • solution should be: use msys2 ccache, but it segfaults...
    • workaround: do not use ccache when building with Zig on Windows
    • will be solved by porting leanc to Lean
  • macOS: can't find utimensat
  • Windows: -out-implib is not supported
  • Windows: -lLean does not find libLean.a
  • Windows: when passing relative include path, clang may write drive-relative path such as \mingw64\... to dependency file, which confuses Zig's depfile lexer
    • workaround: use absolute paths only
  • Windows: leaninteractivetests sometimes fail with "R6016" on CI
  • macOS: cannot dlsym symbol from executable
    • -rdynamic does not seem to be implemented for MachO?
  • macOS: -Wl,-undefined,dynamic_lookup is not supported
  • macOS: unclear failure in any test case using leanmake. Is lean --deps failing?
  • macOS: random test failures while compiling libcxx like
    /Users/runner/work/lean4/lean4/build/zig/lib/libcxx/src/future.cpp:1:1: unable to build C object: unable to build C object: FileNotFound
    
    Race condition?
  • Zig's caching is not quite compatible with make
    • when restoring a compile target from Zig's cache, the mtime is not updated, so make will remake the target again on the next run
    • should not be an issue for CI
  • to be continued...?

And for the fun of it, let's try cross-compiling from x86_64-linux-gnu:

  • aarch64-linux-gnu: compiles at least! 🎉
  • aarch64-macos-gnu: building GMP works, linking libleanshared.so fails with error: InvalidCharacter :(
  • Emscripten: unclear to me what target to use, if any. wasm32-wasi-musl support looks much better, but AFAIK there are many features missing from WASI until it could run Lean
  • to be continued...?

@Kha
Copy link
Member Author

Kha commented Sep 10, 2021

I'll take the liberty to ping @andrewrk himself here in case he's interested in our little Zig experiment & progress :) ...

@leodemoura
Copy link
Member

@leodemoura there's also an old comment saying that we should use C++11's thread_local when it's ready, which I hope it is by now

I hope so too :)

@Kha
Copy link
Member Author

Kha commented Sep 22, 2021

Phew, good progress on Windows after many more fixes & workarounds (see above)! The test suite is now all green on my Windows machine, while on CI it randomly fails in the interactive tests with a single last error 🤔 .

Unfortunately, on macOS the tests uncovered many more linker issues that I don't see easy workarounds for/where the issue isn't even clear. I can open upstream issues for them, but unless someone is nice enough to specifically fix all of them for us, I think the only realistic solution is to ship without Zig on macOS for the time being.

@Kha
Copy link
Member Author

Kha commented Nov 15, 2021

Obsoleted by #795, which did not run into any of the above issues apart from the Windows headers (which apparently are from the clang64 toolchain)

@Kha Kha closed this Nov 15, 2021
ChrisHughes24 pushed a commit to ChrisHughes24/lean4 that referenced this pull request Dec 2, 2022
* `@[to_additive]` will now correctly guess names with `CoeTC`, `CoeT` and `CoeHTCT` in it
* rewrite function `targetName`. 
  - It will now warn the user if it gives a composite name that can be auto-generated (before `to_additive` would never warn if a composite name was given). 
  - the logic when `allowAutoName = true` now corresponds to the docstring
  - Fix a bug where declarations were silently allowed to translate to itself (maybe because the `return` statements returned a value for the whole function?)
  - Add some more tracing
  - The behavior of namespaces when giving a composite name has been changed. It will always generate a name with the same number of components. Example:
```lean
namespace MeasureTheory.MulMeasure
@[to_additive AddMeasure.myOperation] def myOperation := ...
-- before: generates `AddMeasure.myOperation` (and never gives a warning)
-- after: generates `MeasureTheory.AddMeasure.myOperation` (and probably warns that the name can be auto-generated)
end MeasureTheory.MulMeasure
```
* This should fix all problems in leanprover#659 other than leanprover#660

Minor changes:
* When applying `@[to_additive]` to a structure, add a trace message if no translation is inserted for a field.
* Define `Name.fromComponents` and `Name.splitAt`
* Reduce transitive imports of `Tactic/toAdditive`
* Move some auxiliary declarations from `Tactic/Simps` to more appropriate places 
  - swap arguments of `String.isPrefixOf?`
  - improve `Name.getString`

Co-authored-by: Scott Morrison <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants