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

WIP: Windows cross compilation via LLVM #72366

Draft
wants to merge 15 commits into
base: master
Choose a base branch
from

Conversation

Ericson2314
Copy link
Member

@Ericson2314 Ericson2314 commented Oct 31, 2019

Motivation for this change

LLVM can do a much better job than GCC via MinGW. In particular, it can do abi-compatable C++ with MSVC, and has more features implemented such proper C++ threads.

I want this because I want Nix to run on Windows, and am continuing @volth's port to make it do so (NixOS/nix#3185). However, I think it's important that we can purely build Nix for all supported platforms, and not ask developers to set up arcane stuff to test their PRs. Therefore I am making this as a self-imposed prerequisite. I need this to do so because Nix uses C++ threads.

Some of this stuff is rather rougher / and more patch heavy than I like my portability initiatives to be, and so I'll hold off trying to port many more packages until the far far future when the requisite tech debt is cleaned up and the portability is maintainable. But I can't do any less than this if I am to build Nix.

The base branch is very intentional, because I will want to merge to 19.09 in addition to master so Nix can use it from there in its CI.

This supports MinGW and Visual Studio headers and libs:

  • MinGW: { config = "x86_64-pc-mingw32"; useLLVM = true; }
  • MSVC: { config = "x86_64-pc-windows-msvc"; useLLVM = true; }
Things done
  • Tested using sandboxing (nix.useSandbox on NixOS, or option sandbox in nix.conf on non-NixOS linux)
  • Built on platform(s)
    • NixOS
    • macOS
    • other Linux distributions
  • Tested via one or more NixOS test(s) if existing and applicable for the change (look inside nixos/tests)
  • Tested compilation of all pkgs that depend on this change using nix-shell -p nix-review --run "nix-review wip"
  • Tested execution of all binary files (usually in ./result/bin/)
  • Determined the impact on package closure size (by running nix path-info -S before and after)
  • Ensured that relevant documentation is up to date
  • Fits CONTRIBUTING.md.
Notify maintainers

cc @angerman

@Ericson2314
Copy link
Member Author

@volth that's fair, and we could run MSVC in wine too, but I think Nix and all its dependencies, like chromium, should be robust enough to build with LLVM.

@@ -220,6 +220,16 @@ rec {
platform = {};
};

windowsLlvm32 = {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should add this to cross-trunk


for variant in ld.gold ld.bfd ld.lld; do
for variant in ld.gold ld.bfd ld.lld${optionalString (targetPlatform.useLLVM or false) " ld64.ldd"}; do
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this wasn’t actually necessary… let’s leave it out for now (perhaps later we can get macOS llvm cross working)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah it's not necessary; I was just too busy fixing other things to move it out yet.

@@ -339,6 +339,8 @@ stdenv.mkDerivation {
hardening_unsupported_flags+=" pic"
'' + optionalString targetPlatform.isMinGW ''
hardening_unsupported_flags+=" stackprotector"
'' + optionalString targetPlatform.isWindows ''
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have so many of these we should provably move these to some attrset (not necessary now)

@@ -1,4 +1,4 @@
{ lib, stdenvNoCC, curl }: # Note that `curl' may be `null', in case of the native stdenvNoCC.
{ lib, buildPackages ? { inherit stdenvNoCC; }, stdenvNoCC, curl }: # Note that `curl' may be `null', in case of the native stdenvNoCC.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems awkward?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed it is!

@@ -11,6 +11,12 @@ stdenv.mkDerivation rec {
sha256 = "0a7hi4crnc3j1j39qcnd44zqdfwzw1xghcf80marx5vdf1qdzy6p";
};

# It disables it with MSVC, but CMake doesn't realize that clang for windows,
# even with gcc-style flags, has the same semantic restrictions.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is aws manually adding fpic? Perhaps they have a flag to disable it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They are manually adding it for non-MSVC. CMake should have a better notion of MSVC / destinguish between MSVC the abi (which we are) and MSVC which we aren't since the wrappers just know gcc-style flags.

{ stdenvNoCC, fetchurl, lib, config, msitools, unzip, static ? false }:

#if !(config.microsoftVisualStudioLicenseAccepted or false)
if false
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Temporary while I get things to work. We should add another line of defense beyond things being broken and not part of the default jobs so @GrahamcOfBorg doesn't do anything with those.

@matthewbauer
Copy link
Member

Great work!!!

@veprbl veprbl added 6.topic: cross-compilation Building packages on a different sort platform than than they will be run on 6.topic: windows Running, or buiding, packages on Windows labels Nov 1, 2019
@Ericson2314
Copy link
Member Author

I drafted https://reviews.llvm.org/D69760 which hopefully will fix up some things. Next step might be making a windres-style CLI to llvm-rc, but hopefully that can be put off for a while.

@Ericson2314 Ericson2314 changed the title WIP: Windows cross compilattation via LLVM WIP: Windows cross compilation via LLVM Nov 3, 2019
@@ -66,7 +66,7 @@ in lib.init bootStages ++ [
(hostPlatform.isLinux && !buildPlatform.isLinux)
[ buildPackages.patchelf ]
++ lib.optional
(let f = p: !p.isx86 || p.libc == "musl" || p.libc == "wasilibc" || p.isiOS; in f hostPlatform && !(f buildPlatform))
(let f = p: !p.isx86 || p.libc == "musl" || p.libc == "wasilibc" || p.isiOS || p.isWindows; in f hostPlatform && !(f buildPlatform))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was wondering if we should just set this to stdenv.hostPlatform != stdenv.buildPlatform. It very rarely hurts anything (there could be some weird custom gnuconfig changes that break) to set it, we mostly just need it for weird platforms though.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh! I think I remembered some of the logic was to avoid adding it twice, if native already has it.

We should just do a mass rebuild so everywhere sets it, always.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don’t think it’s necessary for native. Besides costing a mass rebuild, it also could break some custom scripts.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@matthewbauer We should make a dontAutoreconf for that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer to not have an option for this. Status quo is probably okay. You can always add the hook yourself.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I meant dontUpdateAutotoolsGnuConfigScripts, which does exist. I we'll only need to add it in a few places.

@aszlig
Copy link
Member

aszlig commented Nov 3, 2019

@volth: It isn't my realm anymore (and never really has been), since it has been ages since I had anything to do with Windows (luckily :-D), so I can't really say anything on this PR.

@Ericson2314
Copy link
Member Author

Finally zlib builds! But now CMake things don't configure, however (with the switch from lld-link to ld.link). INFO:dialect_default[] it gets running strings on a built binary in both cases. In the lld-link case it doesn't care, presumably because there is a "simulating MSVC" thing and the rules are all different. In the lld.link / clang::toolchains::CrossWindows case it does care, presumably cause it thinks it's more GNU like / MinGW or whatever.

My response is to try going full MinGW, like mstorsjo/llvm-mingw#57, for now, so I am doing that's been done before and which is closer to what we've got.

@Ericson2314 Ericson2314 force-pushed the llvm-windows branch 2 times, most recently from dd9318a to 7766e03 Compare November 4, 2019 03:52
Ericson2314 added a commit to Ericson2314/llvm-project that referenced this pull request Nov 4, 2019
Summary:
Besides the Mingw toolchain, there is also the CrossWindows toolchain,
which means GNU-style cli but genuine windows headers + libraries. LLD's
MinGW driver is as good a fit as binutil's ld, but there is no easy way
to select it when lld was being rewritten to lld-link.

This makes lld always be the GNU-style one, consistent with the non-msvc
case. It's a small breaking change for Windows, but the only
straightforward way.

It may seem silly to worry about the gnu-style flags, but it is useful
for mixing software designed with MinGW in mind with "real" windows
software that needs a MSVC C++ ABI, C++ threads, etc.

Testing in conjunction with NixOS/nixpkgs#72366,
which might be the first fully automated way to cross compile to
Windows.  I haven't taught Nixpkgs to wrap clang-cl like it wraps clang,
so even for some packages that have separate MSVC and MinGW builds
systems (e.g. zlib, opensll), I seem to be having better luck with the
MinGW-style builds so am going with that.

Reviewers: ruiu, rnk, mstorsjo

Subscribers: mstorsjo, cfe-commits, llvm-commits

Tags: #clang, #llvm

Differential Revision: https://reviews.llvm.org/D69760
@ofborg ofborg bot removed the 6.topic: fetch label Nov 12, 2019
which might be the first fully automated way to cross compile to
Windows. I haven't taught Nixpkgs to wrap clang-cl like it wraps clang,
so even for some packages that have separate MSVC and MinGW builds
systems (e.g. zlib, opensll), I seem to be having better luck with the
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
systems (e.g. zlib, opensll), I seem to be having better luck with the
systems (e.g. zlib, openssl), I seem to be having better luck with the

@ryantm ryantm marked this pull request as draft October 23, 2020 03:04
@stale
Copy link

stale bot commented Oct 30, 2021

I marked this as stale due to inactivity. → More info

@stale stale bot added the 2.status: stale https://github.com/NixOS/nixpkgs/blob/master/.github/STALE-BOT.md label Oct 30, 2021
@cidkidnix
Copy link
Contributor

Heads up here, I'm intending to pick this PR up and get it in a working state against master (or staging-next/staging).
Currently tinkering with it atm, Would love to have llvm-mingw cross-compiling available.

@s1341
Copy link
Contributor

s1341 commented Apr 24, 2023

@cidkidnix did you pick this up?

@stale stale bot removed the 2.status: stale https://github.com/NixOS/nixpkgs/blob/master/.github/STALE-BOT.md label Apr 24, 2023
@cidkidnix
Copy link
Contributor

@s1341 Yeah I did, been super busy lately, but I had something roughly working in this branch: https://github.com/cidkidnix/nixpkgs/commits/dylang/llvm-mingw. Some logic is weird though. I plan to continue on this sometime soon (hopefully).

@s1341
Copy link
Contributor

s1341 commented Apr 25, 2023

@cidkidnix care for some collaboration? I really need this.

@Ericson2314
Copy link
Member Author

@s1341 I think neither of us would mind if you just started picking this up. We can worry about baton passes later.

Also btw check out #228374 (review). It is convenient that UEFI work is also going on concurrently!

@wegank wegank added the 2.status: stale https://github.com/NixOS/nixpkgs/blob/master/.github/STALE-BOT.md label Mar 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
2.status: merge conflict 2.status: stale https://github.com/NixOS/nixpkgs/blob/master/.github/STALE-BOT.md 2.status: work-in-progress 6.topic: cross-compilation Building packages on a different sort platform than than they will be run on 6.topic: stdenv Standard environment 6.topic: windows Running, or buiding, packages on Windows 8.has: package (new) 10.rebuild-darwin: 11-100 10.rebuild-linux: 11-100
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

10 participants