-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[CMake] Windows stdlib cross-compilation fixes #13140
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
[CMake] Windows stdlib cross-compilation fixes #13140
Conversation
@compnerd This addresses most of the issues that I contacted you about. I haven't yet had a chance to look at what was causing the VFS overlay issue or the linking issues for the produced executables on x64, but will do so when I next get a chance. |
@compnerd The VFS overlay issue was it was only being applied to Swift sources and not the C++ sources in the runtime. Remaining issues are the lld-link arguments being wrong on x64 and the runtime assertion in |
This has been sitting here for a little while and I'm not sure who it falls under. @davezarzycki This may be of interest with regards to #12895. Could you take a look, and possibly cc in other relevant people? |
Hi @troughton – I'm not sure who to CC. You might want to consider emailing swift-dev at this point. |
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.
Please don't remove the hack in stdlib/public/SwiftRemoteMirror/CMakeLists.txt
. It is needed on Linux unified CMake builds.
Oh, I think I see what you're doing. I think that removing |
It needs to be passed as a linker flag for Swift libraries depending on the target SDK, not the host platform, and we don’t know what the target SDKs are until we’re in It’s definitely not a nice solution, but I’m not sure how to do it better. |
I still think that From my experience with Makefile based projects, one should get the defaults "right" at the top level and then have subordinate Makefiles or CMakeLists opt into non-default behavior as needed. |
@gottesmm I might pull out the C++14 part of it looks like the consensus is to shift Swift to C++14 on all platforms, but does the rest of this PR look okay? |
@troughton I would prefer if we just switch swift to c++14 as well. We should only add complexity to the build if we absolutely need to do so. Let me take a look real quick at the PR. |
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.
Some questions.
@@ -81,8 +81,20 @@ macro(swift_common_standalone_build_config_llvm product is_cross_compiling) | |||
# HACK: this ugly tweaking is to prevent the propagation of the flag from LLVM | |||
# into swift. The use of this flag pollutes all targets, and we are not able | |||
# to remove it on a per-target basis which breaks cross-compilation. | |||
# Therefore, we always remove it here and then selectively re-add it to the |
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 have noticed this hack making the rounds recently. What is going on here? Why doesn't LLVM run into these issues as well?
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 short version is Windows doesn't support -z,defs
as a linker flag, and CMAKE_SHARED_LINKER_FLAGS
get applied to all linker invocations, so we have to move where it gets added.
LLVM doesn't run into it because it uses the CMAKE_SYSTEM_NAME
method for cross-compiling (so this flag would never get inserted in the first place for Windows), whereas Swift has a custom scheme where we don't know the SDK targets until much later in the configuration process.
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 explanation should be added here. Also, it should be clear that this is due to windows.
string(REGEX REPLACE "-Wl,-z,defs" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}") | ||
|
||
if (LLVM_COMPILER_IS_GCC_COMPATIBLE) |
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 am assuming this will not be in the final version?
@@ -721,6 +721,7 @@ function(_add_swift_library_single target name) | |||
swift_windows_generate_sdk_vfs_overlay(SWIFTLIB_SINGLE_VFS_OVERLAY_FLAGS) | |||
foreach(flag ${SWIFTLIB_SINGLE_VFS_OVERLAY_FLAGS}) | |||
list(APPEND SWIFTLIB_SINGLE_SWIFT_COMPILE_FLAGS -Xcc;${flag}) | |||
list(APPEND SWIFTLIB_SINGLE_C_COMPILE_FLAGS ${flag}) |
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 this for?
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.
Windows is case-insensitive, so when you're cross-compiling from a case-sensitive filesystem a number of header paths don't resolve (since the Windows headers are very loose about case and the spellings vary between files).
The VFS overlay is a means to map between the differently-cased forms of the headers (e.g. windows.h
to Windows.h
). Previously, it wasn't passing the argument to use the VFS overlay to the C/C++ runtime sources correctly (so it was working for Swift import Msvcrt
only).
cmake/modules/AddSwift.cmake
Outdated
@@ -1151,6 +1152,10 @@ function(_add_swift_library_single target name) | |||
# import library targets when the library was added. Use that to adjust the | |||
# link libraries. | |||
if("${SWIFTLIB_SINGLE_SDK}" STREQUAL "WINDOWS") | |||
# We need to set the C++ standard from C++11 to C++14 on Windows | |||
# for compilers using the GCC driver. | |||
set_property(TARGET "${target}" PROPERTY CXX_STANDARD 14) |
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 am assuming this is gone?
cmake/modules/AddSwift.cmake
Outdated
@@ -1453,6 +1458,11 @@ function(add_swift_library name) | |||
continue() | |||
endif() | |||
|
|||
# TODO Support SwiftPrivate on Windows (SR-6489) |
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.
Can you add to the comment here to describe the problem. I think just saying something like this would be fine:
TODO: Currently SwiftPrivate runs into linker problems on Windows. See SR-6489.
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.
Done, thanks. That's definitely clearer.
cmake/modules/AddSwift.cmake
Outdated
if(NOT "${sdk}" STREQUAL "WINDOWS" AND NOT "${name}" STREQUAL "swiftRemoteMirror") | ||
# Add back the flags we removed from the call to HandleLLVMOptions | ||
# in SwiftSharedCMakeConfig.cmake. | ||
list(APPEND swiftlib_link_flags_all "-Wl,-z,defs") |
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 am assuming this goes away after c++14?
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 part doesn't. The flag is currently being unconditionally removed so Windows works, (#13209), so this adds it back for non-Windows targets. swiftRemoteMirror was also removing the flag manually, so I consolidated that change here.
I've removed all of the C++14 changes; they should be addressed in a separate PR (#13403 if it's Windows only, or something different again if it goes project-wide). |
This PR is a lot simpler now that the C++14 changes have been separately merged in. Does it look okay to merge? As a quick recap, this PR now:
|
@gottesmm Checking in about this PR - does it look okay to merge? |
@@ -81,8 +81,20 @@ macro(swift_common_standalone_build_config_llvm product is_cross_compiling) | |||
# HACK: this ugly tweaking is to prevent the propagation of the flag from LLVM | |||
# into swift. The use of this flag pollutes all targets, and we are not able | |||
# to remove it on a per-target basis which breaks cross-compilation. | |||
# Therefore, we always remove it here and then selectively re-add it to the |
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 explanation should be added here. Also, it should be clear that this is due to windows.
cmake/modules/AddSwift.cmake
Outdated
if(NOT "${sdk}" STREQUAL "WINDOWS" AND NOT "${name}" STREQUAL "swiftRemoteMirror") | ||
# Add back the flags we removed from the call to HandleLLVMOptions | ||
# in SwiftSharedCMakeConfig.cmake. | ||
list(APPEND swiftlib_link_flags_all "-Wl,-z,defs") |
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 really dislike all of the special cases in this function and additionally how this calls out windows but really you are working with the complement. The technical debt here makes me unhappy.
That being said, I think for now, this is fine.
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 certainly agree it's far from an ideal approach, but yes, addressing it would take a larger refactor, and I don't think this is much worse than what surrounds it.
# CMAKE_SHARED_LINKER_FLAGS are determined based on the host system and | ||
# then applied to all targets. | ||
# To work around this, we unconditionally remove the flag here and then | ||
# selectively add it to the per-target link flags in AddSwift.cmake. |
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.
Nice explanation! It is exactly what I was looking for. My biggest fear in general with cmake changes is that we lose
3 last knits:
- Can you fix the formatting on the text so it is 80 columns or proper paragraphs? I.e. I would do this:
# HACK: Windows doesn't support -z,defs as a linker flag.
#
# Normally, LLVM ...
- Can you say the function in AddSwift.cmake where it is (add_swift_library, I think it is?).
- I forgot if it is there, but in add_swift_library can you add a similar comment to this that points back at this code in words like you pointed at it in words here.
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.
Erm.
- knits => nits.
- What I meant to say is that my biggest fear with cmake changes is forgetting why hacks were added. That is why I am asking for so much here as such things have happened in the past.
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.
Does that look okay now? I've been editing on the GitHub web interface so gauging formatting is somewhat difficult; I don't think it exposes column width, for instance. I've also updated the comment in AddSwift.cmake so it's hopefully a little clearer.
Looks great to me! Can you squash the history? Then lets get this show started = ). |
a82c162
to
505c462
Compare
History squashed – sorry for the opening/closing PR noise. |
@swift-ci clean test and merge |
@swift-ci test and merge |
Disable SwiftPrivate, remove -Wl,-z,defs, and use the VFS overlay for compiling the runtime.
505c462
to
7c2230b
Compare
Tests passed on Linux but failed compiling for ARM from macOS. Apparently my assumption that this was Windows-only was wrong; it looks like the I've updated the condition to re-add it only for ELF targets and updated the comment accordingly. I'm going to run tests locally on a macOS host to check, but I'm fairly certain that should resolve the issue. One thing I’m not sure about is the LLVM CMake files do exempt e.g. FreeBSD from the flag (although I don’t know why), so perhaps it’s safer to only add the |
I don't think that LLVM's lack of |
In that case, do you think it’s appropriate to include the flag for FreeBSD in Swift, and if so, does the revised patch look otherwise okay? I don’t personally have a FreeBSD system to test on. |
I don't have an opinion about |
I don’t think that’s possible. You could potentially do something convoluted like caching whether the flag was added by LLVM, checking if the Swift SDK matches the host SDK, and then adding it back in that case, but then it wouldn’t be added for cross-compiling, and it seems fairly error-prone to me. I think that the cleanest option is to maintain our own list of targets for -z,defs. If that list can be simply “all ELF targets”, then great; otherwise, we can follow LLVM’s approach and just copy their long list of special-case exemptions. @gottesmm What approach do you want to take? If we go with the 'all ELF targets' it might break some untested targets, but it'd be simple enough for maintainers of those targets to patch the condition. |
@gottesmm If the changes look okay, could you please trigger CI again? If not, I think it might be worth splitting the |
@troughton Sorry I dropped this. The right person to review this right now is @Rostepher. Btw, have you considered asking for commit access? Then you wouldn't need to ask people to run CI testing ; ). |
Adding @Rostepher to the reviewers list based on @gottesmm's last comment. |
Is any of this still needed? I have most of the unit tests building and a good chunk of it passing even. |
It’s still useful, but it’s really not much. At this point, the patch just re-enables a warning on Linux and adds the VFS overlay as a flag to building th C libraries. |
Yeah, I think that is useful :-) |
@swift-ci please test and merge |
This PR contains a few changes that are needed to make the Windows stdlib cross-compile from Linux.
Namely, it:
-Wl,-z,defs
is only added for non-Windows (and non-RemoteMirror) targets-std=
C++ flag and instead use CMake'sCXX_STANDARD
so that we can build against the Visual Studio 2017 headers (which require C++14). If someone can suggest a more elegant implementation than just replacing the string inCMAKE_CXX_FLAGS
I'd be glad to hear it.