-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Windows: Support building stage3, and bootstrapping via MSVC #13514
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
Conversation
build.zig
Outdated
@@ -292,10 +293,12 @@ pub fn build(b: *Builder) !void { | |||
artifact.addCSourceFiles(&optimized_c_sources, &[_][]const u8{ "-std=c99", "-O3" }); | |||
|
|||
artifact.linkLibrary(softfloat); | |||
artifact.linkLibCpp(); | |||
if (artifact.target.getOs().tag != .windows or artifact.target.getAbi() != .msvc) { | |||
artifact.linkLibCpp(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why don't we want to link against libc++
when targeting .msvc
ABI? Is this circumventing Zig wanting to use its own-built libc++.a
when linkLibCpp
is specified?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was to handle this problem: #12703 (comment)
I tried just not building/linking libcxxabi
at first, which gets you as far as linking (diffs I tried in the comment there).
The problem is that libc++ once built/linked under the msvc-built zig, conflicts with libcmt.lib (which comes from the msvc-built llvm that links with it):
lld-link : error : duplicate symbol: void * __cdecl operator new(unsigned __int64) [C:\cygwin64\home\kcbanner\kit\zig\build-release\stage3.vcxproj]
>>> defined at d:\a01\_work\12\s\src\vctools\crt\vcstartup\src\heap\new_scalar.cpp:32
>>> libcmt.lib(new_scalar.obj)
>>> defined at C:\cygwin64\home\kcbanner\kit\zig\lib\libcxx\src/new.cpp
>>> libc++.lib(new.obj)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, I think I was too hasty here. This might only be necessary during bootstrap - when we're linking against an msvc-built llvm (and not a zig-built one).
I'm going to attempt bootstrapping with this check in place, then removing it when building self-hosted. It might be that the solution is a build arg like -Duse-native-libcxx
to gate this behavior might be the real solution.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated this flow to use a new -Ddisable-libcpp
flag passed in by the bootstrapping script when building on a *-windows-msvc
host.
@@ -639,10 +644,15 @@ fn addStaticLlvmOptionsToExe(exe: *std.build.LibExeObjStep) !void { | |||
} | |||
|
|||
exe.linkSystemLibrary("z"); | |||
exe.linkSystemLibrary("zstd"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ls zstd
not supported when targeting windows-msvc
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just checked this again, and I think removing this conditionally was actually unnecessary. The key part of the zstd change was adding the ZIG_ENABLE_ZSTD
flag to the cmake script - since the initial LLVM built during bootstrapping on the host is build without ZSTD enabled (since we haven't built it for the host yet), we don't want to require it during the build:
if(ZIG_STATIC_ZSTD AND ZIG_ENABLE_ZSTD)
list(REMOVE_ITEM LLVM_SYSTEM_LIBRARIES "-lzstd")
find_library(ZSTD NAMES libzstd.a libzstdstatic.a zstd NAMES_PER_DIR)
list(APPEND LLVM_LIBRARIES "${ZSTD}")
endif()
Will remove -Ddisable-zstd and the change to this function.
CMakeLists.txt
Outdated
if (MSVC) | ||
list(REMOVE_ITEM LLVM_SYSTEM_LIBRARIES "z.lib") | ||
else() | ||
list(REMOVE_ITEM LLVM_SYSTEM_LIBRARIES "-lz") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the difference between LLVM_LIBRARIES
and LLVM_SYSTEM_LIBRARIES
? Will this change not potentially break other targets linking against system version of LLVM such as macOS?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is possible to link statically against a system provided LLVM e.g., Homebrew provided LLVM on macOS, in which case, I am wondering if this change doesn't break it as now we are removing -lz
from LLVM_SYSTEM_LIBRARIES
rather than LLVM_LIBRARIES
, assuming they are not the same.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added LLVM_SYSTEM_LIBRARIES
to hold the result of llvm-config.exe --system-libs
, instead of adding it to LLVM_LIBRARIES
. The reason for breaking it out into it's own variable was to handle this difference:
e:\dev\zig-bootstrap\out-win\host\bin>llvm-config.exe --system-libs
psapi.lib shell32.lib ole32.lib uuid.lib advapi32.lib z.lib
$ ./llvm-config.exe --system-libs
-lpsapi -lshell32 -lole32 -luuid -ladvapi32 -lz
The problem was that addCMakeLibraryList
requires a -l
prefix in order to pass the library to exe.linkSystemLibrary
instead of exe.addObjectFile
. There is no -l
prefix in the msvc --system-libs
case. What was happening was ie. uuid.lib
would be passed to exe.addObjectFile
which would generate a path like c:\path\to\zig\uuid.lib
when linking, which would fail.
For comparison the --libfiles
result on msvc vs msys2/mingw:
e:\dev\zig-bootstrap\out-win\host\bin>llvm-config.exe --libfiles
e:\dev\zig-bootstrap\out-win\host\lib\LLVMWindowsManifest.lib e:\dev\zig-bootstrap\out-win\host\lib\LLVMWindowsDriver.lib ... snip
$ ./llvm-config.exe --libfiles
E:/dev/zig-bootstrap/out/build-llvm-host/lib/libLLVMWindowsManifest.a E:/dev/zig-bootstrap/out/build-llvm-host/lib/libLLVMWindowsDriver.a ... snip
In this case, you do want to pass the full lib path, so I couldn't just check for a .lib extension to make the distinction.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To answer your second question, I believe -lz
should be in LLVM_SYSTEM_LIBARIES
in the ZIG_STATIC_LLVM
case on macOS, but I don't have access to a macOS system to check if -lz
should up in the llvm-config --libfiles
result or the llvm-config --system-libs
result.
Updated:
I also investigated the ability to build an The cmake platform code for Windows-Clang (which is selected when it detects your using Clang with an MSVC target) passes So, building -msvc isn't possible yet - but it sounds like that once we stop using lld-link, that we could support this case with our own COFF linker. With that being said, some of the changes I made during this investigation might be useful that point, so I included them. |
9c2a548
to
9194831
Compare
9194831
to
ce58f23
Compare
ce58f23
to
c43d345
Compare
Would you mind rebasing and fixing conflicts? |
c43d345
to
b1482f8
Compare
Will do, however I'm going to convert this back to a draft until I resolve the CBE issues with MSVC. This was ready to go until those changes landed. |
903dd83
to
fa89cc6
Compare
83d95c6
to
b70d439
Compare
b70d439
to
b803f32
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Place the result of llvm-config --system-libs into it's own list, so it can be handled separately. On windows, the list of libraries is returned like kernel32.lib uuid.lib instead of -lkernel32 -luuid. This would cause addCMakeLibraryList to link them as object files, which would produce incorrect paths. This list now makes it's way to addCMakeSystemLibraryList which handles this case correctly.
Wouldn't the same possibilities also affect the main llvm/clang/lld libraries? For example, LLVMCore.lib
rather than -lLLVMCore
.
It seems like rather than changing all this stuff, the logic inside parseConfigH
and/or addCMakeLibraryList
could be improved to handle both -lfoo
and foo.lib
.
Actually, I'm not sure what the problem is with exe.addObjectFile("foo.lib")
. I don't see this new addCMakeSystemLibraryList
function doing anything new.
CMakeLists.txt
Outdated
set(ZIG_ENABLE_ZSTD on CACHE BOOL "Enable linking zstd") | ||
set(ZIG_ENABLE_LIBCPP on CACHE BOOL "Enable linking libcpp") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to avoid adding these if possible. It looks like ZIG_ENABLE_LIBCPP
is unused and can simply be deleted.
As for ZIG_ENABLE_ZSTD
, it will confuse package maintainers and users into believing that Zig depends on zstd, which is not the case. In reality, it is a transitive dependency that we only have to care about when LLVM is built statically, and is built with zstd enabled. In such case, the user must pass -DZIG_STATIC_ZSTD=ON
. In all other cases, the user can leave the defaults as-is.
I don't see the purpose of an additional option.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The purpose of ZIG_ENABLE_ZSTD
was to get around ZIG_STATIC
enabling ZIG_STATIC_ZSTD
, which would cause a find_library search, which would then fail in cases where it didn't exist (like building zig for the host during bootstrapping).
I changed the way that the defaults were set to allow ZIG_STATIC_ZSTD
to be set explicitly off when ZIG_STATIC
is enabled. The build.bat
script will set this to OFF
explicitly when building for the host.
b803f32
to
4939d23
Compare
The problem was that libraries such as I could instead have |
945fb64
to
e4c4731
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really excellent work. The only problem I see is a couple missing cache hash lines (potentially would cause a subsequent compilation that added these new linker args to think it did not need to re-run the linker).
With those added, this is ready to land.
…s themselves, to fix path issues on windows
…/Debug subfolders)
- add support for passing through .def files to the linker, required for building libLTO.dll in LLVM - fixup libcpp linking conditionals - add option to skip linking zstd for use in bootstrapping (when building against an LLVM with LLVM_ENABLE_ZSTD=OFF)
Using zig cc with CMake on Windows was failing during compiler detection. -nostdinc was causing the crt not to be linked, and Coff/lld.zig assumed that wWinMainCRTStartup would be present in this case. -nostdlib did not prevent the default behaviour of linking libc++ when zig c++ was used. This caused libc++ to be built when CMake ran ABI detection using zig c++, which fails as libcxxabi cannot compile under MSVC. - Change the behaviour of COFF -nostdinc to set /entry to the function that the default CRT method for the specified subsystem would have called. - Fix -ENTRY being passed twice if it was specified explicitly and -nostdlib was present. - Add support for /pdb, /version, /implib, and /subsystem as linker args (passed by CMake) - Remove -Ddisable-zstd, no longer needed - Add -Ddisable-libcpp for use when bootstrapping on msvc
…s zig cc on Windows-Clang
…rt as well as libcmpt
- Remove ZIG_ENABLE_ZSTD in favour of allowing ZIG_STATIC_ZSTD to be toggled off explicitly when ZIG_STATIC is on - Remove ZIG_ENABLE_LIBCPP (now unused)
- Revert the addition of CLANG_SYSTEM_LIBARIES and LLVM_SYSTEM_LIBRARIES - Change addCMakeLibraryList to parse non-absolute path .lib dependencies as system libraries
e4c4731
to
7fe6247
Compare
Thanks! Hash inputs have been added. |
These are changes to support bootstrapping zig on Windows using MSVC. This closes #12703
The corresponding bootstrap script is here: ziglang/zig-bootstrap#140
Summary of changes:
llvm-config --system-libs
into it's own list, so it can be handled separately. On windows, the list of libraries is returned likekernel32.lib uuid.lib
instead of-lkernel32 -luuid
. This would causeaddCMakeLibraryList
to link them as object files, which would produce incorrect paths. This list now makes it's way toaddCMakeSystemLibraryList
which handles this case correctly.version.lib
)ZIG_ENABLE_ZSTD
: This controls whetherzstd
is linked in build.zig. This is done via a new argument,-Ddisable-zstd
. This is to support building zig when it links against and MSVC-built LLVM built withLLVM_ENABLE_ZSTD=OFF
.FileNotFound
followed byUnable to dump stack trace: InvalidPEMagic
#12703 (comment)-DEF:<filename>
. This is to handle this case: https://reviews.llvm.org/D134165. Specifically, building libLTO.dll during bootstrapping.I'm opening this as a draft, as I'm not not sure about one of the changes in
lld.zig
, specifically:This change was to support linking system libraries without needing to build the .lib for them (during the first zig build with msvc) however I'm not sure if this should take precedence over the
if (comp.crt_files.get(lib_basename)) |crt_file| {
branch.