-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Add support for building Swift on Windows with clang-cl and MSVC #5904
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
cmake/modules/AddSwift.cmake
Outdated
set(dep "${CMARK_LIBRARY_DIR}/cmark.lib") | ||
else() | ||
set(dep "${CMARK_LIBRARY_DIR}/lib${dep}.a") | ||
endif() |
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 seems wrong. We already adjust the library prefix appropriately. Please adjust the conditions for that.
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'm not sure we adjust the prefix accordingly: the layout of the cmark build directory on Windows is as follows:
- cmark.dll
- cmark.exe
- cmark.exp
- cmark.ilk
- cmark.lib
- cmark.pdb
- cmark_dll.pdb
- cmark_export.h
- cmark_static.lib
- libcmark.pc
There is no such file "libcmark.a", so we do in fact need to adjust the depency for Windows.
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.
Right, on windows, the library would be cmark.lib
or libcmark.lib
(in the vein of libcmt.lib
). Sounds like I missed that when I first setup the windows support. We should fix that generically, not specifically for building with cl
.
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 generic, and specific to Windows;
elseif("${dep}" STREQUAL "cmark")
if ("${SWIFT_HOST_VARIANT_SDK}" STREQUAL "WINDOWS")
set(dep "${CMARK_LIBRARY_DIR}/${dep}.lib")
else()
set(dep "${CMARK_LIBRARY_DIR}/lib${dep}.a")
endif()
cmake/modules/AddSwift.cmake
Outdated
@@ -1085,7 +1092,7 @@ function(_add_swift_library_single target name) | |||
# libraries are only associated with shared libraries, so add an | |||
# additional check for that as well. | |||
set(import_library ${library}) | |||
if(TARGET ${library}) | |||
if(TARGET ${library} AND NOT "${CMAKE_SYSTEM_NAME}" STREQUAL "Windows") |
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 import library path is needed on windows too. Why is this being changed?
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.
Ah yeah I forgot to put this in the discussion point section in the PR description.
Basically, if we leave this code on Windows, I get the following error immediately when running the cmake build:
could not find dependency 'swiftCore_IMPLIB-NOTFOUND'
When this is commented out, everything seems to work.
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.
Interesting. The problem is that when cross-compiling from Linux or macOS to Windows, you dont get the import library substitution behavior. As a result, we need to handle it manually. The import library property is manually set, so that should be present. It sounds like I may have gotten the condition wrong on that.
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.
Okay, I assume that means we keep the system name check, or should I nerf this for cross compilation?
cmake/modules/AddSwift.cmake
Outdated
@@ -1833,7 +1840,21 @@ function(_add_swift_executable_single name) | |||
BINARY_DIR ${SWIFT_RUNTIME_OUTPUT_INTDIR} | |||
LIBRARY_DIR ${SWIFT_LIBRARY_OUTPUT_INTDIR}) | |||
|
|||
# On Windows, libraries are prefixed with "lib", so we need to adjust FAT_LIBRARIES for this. |
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 doesnt support fat libraries.
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.
Interesting - I'm fairly sure it just links as a library. Without this change, I get an error that goes something like cannot find library swiftReflection.lib
. However, libSwiftReflection.lib
does exist, and everything links correctly.
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 output name should be swiftReflection.lib
not libSwiftReflection.lib
. Windows doesn't use the lib
prefix on most libraries.
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.
Odd: every single library built at the end of the swift build process has the prefix lib
That said, LLVM's built libraries don't have the lib
prefix, so perhaps I just haven't ifdefed the place we add lib
as a prefix to be non-Windows
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've removed the "lib" prefix from libraries, so this code can go as well.
cmake/modules/AddSwift.cmake
Outdated
# On Windows, we need to link rpcrt4.lib for UUIDs and mincore.lib for various file system APIs | ||
if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows") | ||
target_link_libraries("${name}" "mincore.lib" "rpcrt4.lib") | ||
endif() |
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 libraries need this additional linkage? I added support for target specific linking. Ive never seen this need to be added. I think that this may be masking something else.
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'm linking rpcrt4.lib for creation of UUIDs that doesn't rely on libuuid which is tricky to build on Windows.
I'm linking mincore.lib in order to fix some unresolved symbol errors when linking Clang libraries, as Clang uses file system APIs found in mincore
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 mincore
linkage looks wrong, as that should be in the interface libraries for the clang library depending on it. The rpcrt4 linkage makes sense, but we should handle it as a replacement for uuid, and create a variable for uuid vs rpcrt4.
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.
Right. Let me get back to you on what happens if i don't link mincore.lib (I'll run an entire build :) )
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 get the following link errors:
clangDriver.lib(MSVCToolChain.cpp.obj) : error LNK2001: unresolved external symbol GetFileVersionInfoSizeW
clangDriver.lib(MSVCToolChain.cpp.obj) : error LNK2001: unresolved external symbol GetFileVersionInfoW
clangDriver.lib(MSVCToolChain.cpp.obj) : error LNK2001: unresolved external symbol VerQueryValueW
bin\swift-ide-test.exe : fatal error LNK1120: 3 unresolved externals
cmake/modules/AddSwift.cmake
Outdated
${${CFLAGS_RESULT_VAR_NAME}} | ||
"-target" "${SWIFT_SDK_${CFLAGS_SDK}_ARCH_${CFLAGS_ARCH}_TRIPLE}") | ||
# MSVC doesn't understand the option -target | ||
if (NOT "${CMAKE_C_COMPILER_ID}" STREQUAL "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.
Change this to:
if ("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang")
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
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.
Wait, hang on, what about GCC?
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've fixed these checks to be not MSVC
cmake/modules/AddSwift.cmake
Outdated
list(APPEND result "--sysroot=${SWIFT_SDK_${CFLAGS_SDK}_PATH}") | ||
endif() | ||
elseif(NOT "${SWIFT_SDK_${CFLAGS_SDK}_PATH}" STREQUAL "/") | ||
list(APPEND result "--sysroot=${SWIFT_SDK_${CFLAGS_SDK}_PATH}") | ||
endif() |
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 simplification, however, I think that you will need to complicate this with a ${CMAKE_C_COMPILER_ID}
check.
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.
Fixed, thanks
cmake/modules/AddSwift.cmake
Outdated
if("${CFLAGS_SDK}" STREQUAL "WINDOWS") | ||
# MSVC doesn't understand -fms-compatibility-version. Also, these definitions should not be added here | ||
# for MSVC, as the linker and compiler have different command line options | ||
if("${CFLAGS_SDK}" STREQUAL "WINDOWS" AND NOT "${CMAKE_C_COMPILER_ID}" STREQUAL "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.
Please check the compiler ID against Clang
instead.
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.
Fixed, thanks
cmake/modules/AddSwift.cmake
Outdated
list(APPEND result "-DLLVM_ON_WIN32") | ||
list(APPEND result "-D_CRT_SECURE_NO_WARNINGS") | ||
# TODO(compnerd) handle /MT | ||
list(APPEND result "-D_DLL") |
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.
These are shared across MSVC and clang. This should be based on the target, not the compiler.
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 issue here was that I get many warnings when linking using MSVC. Something like
no such option -DLLVM_ON_WIN32
no such option -D_CRT_SECURE_NO_WARNINGS
no such option -D_DLL
However, if we add these to the compiler flags instead of both the compiler and linker flags, we remove these warnings.
This should be based on the target
I don't fully understand this, sorrry
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 spelling is /DLLVM_ON_WIN32 /D_CRT_SECURE_NO_WARNINGS /D_DLL
with cl.
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 doesn't matter if you use "-" or "/" in cl.exe. The problem that I'm mentioning is that the linker gets these flags as well as the compiler, when actually we only want the compiler to have these flags passed to it.
cmake/modules/AddSwift.cmake
Outdated
endif() | ||
else() | ||
list(APPEND result "-O0") | ||
endif() |
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 think that splitting this out may make it more readable. We have similar behavior with different spellings. The difference is really the compiler id.
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 haven't split this out, but I've tried to make this a bit more readable - let me know if you want me to split it out: I found it was too complicated and slightly confusing as you have to pass multiple variables etc. etc. Maybe that's because I'm not a CMake expert tho...
cmake/modules/AddSwift.cmake
Outdated
|
||
if(NOT "${SWIFT_${LFLAGS_SDK}_ICU_I18N}" STREQUAL "") | ||
list(APPEND result "-L${SWIFT_${sdk}_ICU_I18N}") | ||
endif() | ||
endif() |
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 would invert the conditions here, pushing the MSVC check inside the two clauses since the difference is the spelling.
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, this is slightly different, so can't be done.
The MSVC check is: if(NOT "${SWIFT_${LFLAGS_SDK}_ICU_UC_LIBRARIES}" STREQUAL "")
The Clang check is: if(NOT "${SWIFT_${LFLAGS_SDK}_ICU_UC}" STREQUAL "")
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 variable should be the same, so something is wrong 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.
You're right - I'm an idiot :D
cmake/modules/AddSwift.cmake
Outdated
("${SWIFTLIB_SINGLE_SDK}" STREQUAL "WINDOWS" AND | ||
NOT "${CMAKE_SYSTEM_NAME}" STREQUAL "WINDOWS")) | ||
list(APPEND link_flags "-fuse-ld=lld") | ||
endif() |
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.
Hmm, I think that you may be breaking cross-compilation on Windows to Linux.
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.
How would MSVC understand -fuse-ld=lld
even if we're cross-compiling to Linux?
I've changed this code BTW to:
# MSVC doesn't recognise -fuse-ld.
if ("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang")
if(SWIFT_ENABLE_GOLD_LINKER AND
"${SWIFT_SDK_${SWIFTLIB_SINGLE_SDK}_OBJECT_FORMAT}" STREQUAL "ELF")
list(APPEND link_flags "-fuse-ld=gold")
endif()
if(SWIFT_ENABLE_LLD_LINKER OR
("${SWIFTLIB_SINGLE_SDK}" STREQUAL "WINDOWS" AND
NOT "${CMAKE_SYSTEM_NAME}" STREQUAL "WINDOWS"))
list(APPEND link_flags "-fuse-ld=lld")
endif()
endif()
Perhaps this addresses the cross-compilation concerns?
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.
Using clang on Windows to target Linux would be cross-compilation, which would use the -fuse-ld=gold
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.
Yeah, so this now works, surely, as we have the if ("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang")
check?
cmake/modules/AddSwift.cmake
Outdated
else() | ||
set_property(TARGET "${target}" APPEND_STRING PROPERTY | ||
LINK_FLAGS " ${link_flags} -L${SWIFTLIB_DIR}/${SWIFTLIB_SINGLE_SUBDIR} -L${SWIFT_NATIVE_SWIFT_TOOLS_PATH}/../lib/swift/${SWIFTLIB_SINGLE_SUBDIR} -L${SWIFT_NATIVE_SWIFT_TOOLS_PATH}/../lib/swift/${SWIFT_SDK_${SWIFTLIB_SINGLE_SDK}_LIB_SUBDIR}") | ||
endif() |
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 combine the paths to use link_directories
.
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, cheers
cmake/modules/AddSwift.cmake
Outdated
else() | ||
list(APPEND link_flags | ||
"-L${SWIFTLIB_DIR}/${SWIFT_SDK_${SWIFTEXE_SINGLE_SDK}_LIB_SUBDIR}") | ||
endif() |
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.
Similar.
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, cheers
cmake/modules/AddSwift.cmake
Outdated
("${SWIFTLIB_SINGLE_SDK}" STREQUAL "WINDOWS" AND | ||
NOT "${CMAKE_SYSTEM_NAME}" STREQUAL "WINDOWS")) | ||
list(APPEND link_flags "-fuse-ld=lld") | ||
endif() |
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.
Again, cross-compiling from Windows to Linux.
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.
See the comment 2 above:
How would MSVC understand -fuse-ld=lld even if we're cross-compiling to Linux?
I've changed this code BTW to:
# MSVC doesn't recognise -fuse-ld.
if ("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang")
if(SWIFT_ENABLE_GOLD_LINKER AND
"${SWIFT_SDK_${SWIFTLIB_SINGLE_SDK}_OBJECT_FORMAT}" STREQUAL "ELF")
list(APPEND link_flags "-fuse-ld=gold")
endif()
if(SWIFT_ENABLE_LLD_LINKER OR
("${SWIFTLIB_SINGLE_SDK}" STREQUAL "WINDOWS" AND
NOT "${CMAKE_SYSTEM_NAME}" STREQUAL "WINDOWS"))
list(APPEND link_flags "-fuse-ld=lld")
endif()
endif()
Perhaps this addresses the cross-compilation concerns?
endif() | ||
|
||
# MSVC can't include directories at this point - we need to wait until _add_swift_library_single | ||
if (NOT "${CMAKE_C_COMPILER_ID}" STREQUAL "Windows") |
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.
ITYM 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.
Keen eyes, good spot. Doesn't affect anything, as cmake just ignores the call, but thanks :)
CMakeLists.txt
Outdated
@@ -467,6 +469,12 @@ else() | |||
set(SWIFT_HOST_VARIANT_ARCH_default "armv6") | |||
elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "armv7l") | |||
set(SWIFT_HOST_VARIANT_ARCH_default "armv7") | |||
elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "AMD64") | |||
set(SWIFT_HOST_VARIANT_ARCH_default "x86_64") | |||
elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "IA64") |
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.
IA64
is itanium, not x86_64
.
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.
Cheers, fixed
CMakeLists.txt
Outdated
set(SWIFT_PRIMARY_VARIANT_ARCH_default "x86_64") | ||
|
||
elseif("${SWIFT_HOST_VARIANT_SDK}" STREQUAL "WINDOWS") | ||
configure_sdk_windows(WINDOWS "Windows" "pc" "msvc" "${SWIFT_HOST_VARIANT_ARCH}") |
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 use the pc
vendor? unknown
should be 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.
Right. Once we get to the awesome point of compiling the stdlib and the compiler, I ran swiftc helloworld.swift
, and got an error that goes something like this:
could not find stdlib x86_64-pc-windows-msvc
updating unknown
to pc
fixes this
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.
That would be because we didnt setup the resource dir correctly. Fixing that would address this I believe.
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 do you mean by resource dir? Thanks!
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 resource dir is a special directory that has compiler resources (headers, libraries). It is controlled via the -resource-dir
parameter which IIRC we explicitly pass to the compiler in the build system
CMakeLists.txt
Outdated
elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "IA64") | ||
set(SWIFT_HOST_VARIANT_ARCH_default "x86_64") | ||
elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86") | ||
set(SWIFT_HOST_VARIANT_ARCH_default "x86") |
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 we not rewrite this as i686
internally rather than propagating x86
?
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.
Sure - I was unfamiliar with this kinda arch stuff, so it's great to have another set of eyes on this!
I haven't tested on x86 as I don't have an x86 PC!
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.
Heh. Apple platforms prefer (require?) i386
. Not sure what the right thing to do here is.
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.
We should split this out and get it merged first.
.gitignore
Outdated
#==============================================================================# | ||
8 | ||
4 | ||
SortedCFDatabase.def |
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.
Missing newline.
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.
Fixed
else() | ||
set(gyb_tool_command ${gyb_tool}) | ||
endif() | ||
|
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.
You can always run it this way irrespective of the platform. I think having a single way to run it is better.
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.
Fixed, thanks
# On Windows (using Visual Studio), the generated project files assume that the | ||
# generated GYB files will be in the source, not binary directory. | ||
# TODO: when we use Ninja as a generator, this may be unecessary. | ||
IF (WIN32) |
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.
Lowercase if
, no space after it. Doesnt this mean that you are no longer doing an out-of-source compilation?
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.
Yes, and I've just fixed this for Ninja. For some reason Visual Studio's generated project assume the generated GYB files are in the source directory. Ninja doesn't care, so I've nerfed VS and left the old out of source compilation for Ninja.
tools/SourceKit/tools/CMakeLists.txt
Outdated
# Also, see FIXME in Repl.cpp: | ||
# FIXME: Support REPL on non-Apple platforms. Ubuntu 14.10's editline does not | ||
# include the wide character entry points needed by the REPL yet. | ||
if(NOT "${CMAKE_SYSTEM_NAME}" STREQUAL "Windows") |
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 should be handled similar to libxml2 with a SWIFT_HAVE_LIBEDIT
.
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.
Good idea, thanks
tools/driver/CMakeLists.txt
Outdated
# CMake doesn't support create_symlink on Windows: http://cmake.3232098.n2.nabble.com/cmake-E-create-symlink-for-Windows-td4151271.html | ||
# TODO(hughbe/Windows): Windows does not support libedit currently. See the TODO in tools/SourceKit/tools/CMakeLists.txt |
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 don't think that this comment adds anything.
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.
You're right - removed
tools/swift-ide-test/CMakeLists.txt
Outdated
@@ -12,7 +12,9 @@ add_swift_host_tool(swift-ide-test | |||
) | |||
|
|||
# If libxml2 is available, make it available for swift-ide-test. | |||
if(SWIFT_HAVE_LIBXML) |
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 think that setting SWIFT_HAVE_LIBXML
should work for this guard. Consider cross-compilation.
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.
Fixed, thanks
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 is because clang is required: you need modules. There are module definitions that need to be pulled into the system SDK.
How do we overcome this? |
I'm gonna also tag some Apple folks so they can chip in (no excuses now that Thanksgiving is over ;) ) |
@@ -42,6 +42,10 @@ function(handle_gyb_source_single dependency_out_var_name) | |||
${GYB_SINGLE_FLAGS}) | |||
|
|||
set(gyb_tool "${SWIFT_SOURCE_DIR}/utils/gyb") | |||
|
|||
# GYB needs to be run via Python | |||
set(gyb_tool_command "python" ${gyb_tool}) |
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.
Should this be ${PYTHON_EXECUTABLE}
? The executable name could be something other than "python"
, I think.
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.
Interesting suggestion, I didn't know about this. Quick question: how does this interact with multiple python versions?
I found that you can't actually compile several gyb files if you use python 3 as they rely on python 2 code (e.g. maketrans/capitalize)
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.
@hughbe that works by allowing you to specify the path to the python interpreter at the cmake configuration time (i.e. -DPYTHON_EXECUTABLE=/usr/x86_64-pc-linux-gnu/bin/python2.7).
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 folks
@@ -42,6 +42,10 @@ function(handle_gyb_source_single dependency_out_var_name) | |||
${GYB_SINGLE_FLAGS}) | |||
|
|||
set(gyb_tool "${SWIFT_SOURCE_DIR}/utils/gyb") | |||
|
|||
# GYB needs to be run via Python | |||
set(gyb_tool_command "python" ${gyb_tool}) |
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.
Should this be ${PYTHON_EXECUTABLE}
? The executable name could be something other than "python"
, I think.
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
stdlib/public/runtime/CMakeLists.txt
Outdated
@@ -84,7 +84,7 @@ add_swift_library(swiftRuntime OBJECT_LIBRARY TARGET_LIBRARY | |||
C_COMPILE_FLAGS ${swift_runtime_library_compile_flags} | |||
LINK_FLAGS ${swift_runtime_linker_flags} | |||
INSTALL_IN_COMPONENT never_install | |||
TARGET_SDKS ANDROID CYGWIN FREEBSD LINUX) | |||
TARGET_SDKS ANDROID CYGWIN FREEBSD LINUX WINDOWS) |
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.
As part of a separate PR, I think a cleaner way to do this would be to define lists named OBJC_INTEROP_PLATFORMS
and NO_OBJC_INTEROP_PLATFORMS
, and use them instead of ALL_APPLE_PLATFORMS
.
Here's a zany idea: to support projects like mulle-objc, we allow the OBJC_INTEROP_PLATFORMS
and NO_OBJC_INTEROP_PLATFORMS
lists to be configurable via the build script and CMake. It would be really cool if I could compile for macOS without Objective-C support enabled, or compile for Linux with Objective-C interop:
$ utils/build-script --target-no-objc-sdks macos
$ utils/build-script --target-objc-sdks linux,freebsd
If this sounds like something the core team would be interested in, I'd love to submit a PR for it! /cc @gottesmm
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.
Take a look at: #5942
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.
Thanks! I also sent an email to the swift-dev mailing list.
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.
@modocache mulle-objc is unlikely to work with the objc-interop. There are hardcoded assumptions in the compiler about the ObjC ABI that is being used. It MUST be the non-fragile iOS ABI that is used.
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.
Let's discuss on-list to keep this pull request focused on just Windows. :) Even if mulle-objc doesn't work 100%, I think it's a good idea to allow Objective-C interop to be turned on or off for any given target.
@hughbe as to how to overcome the modules issue: simple, dont use MSVC until such a day as it actually supports modules. You already must build clang to build swift. So you already have clang. You can use the just built clang to build the runtime. That said, it seems that if you are sufficiently clever, you should be able to just copy the module maps into the appropriate SDK locations, and then use cl to build swiftc and the runtime and then use swift to build just the stdlib, which would use clang, which would allow you to use modules. Although, since the swift compilation is done manually .... this may actually be easier in practice than it appears at first glance. |
The runtime will eventually require that it be built with Clang once we enable the Swift calling convention too. |
I had a feeling that would happen - basically this gets us building with MSVC, but that's not really the complete goal. Once this is merged, I'll add support for clang-cl which should get the runtime working in the long run for a long time. This would be a rather simple task, as it should be as easy as adding CMAKE_CXX_SIMULATE_ID checks for clang-cl as this lays the groundwork. |
cmake/modules/AddSwift.cmake
Outdated
@@ -820,6 +820,9 @@ function(_add_swift_library_single target name) | |||
if(NOT "${SWIFT_${SWIFTLIB_SINGLE_SDK}_ICU_I18N_INCLUDE}" STREQUAL "${SWIFT_${SWIFTLIB_SINGLE_SDK}_ICU_UC_INCLUDE}") | |||
include_directories("${SWIFT_${SWIFTLIB_SINGLE_SDK}_ICU_I18N_INCLUDE}") | |||
endif() | |||
|
|||
# We need to include cmark at this point (not in swift_common_standalone_build_config_cmark) using 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.
Why?
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.
My understanding is that, at the point at which CMark was included before this change, there was no target that we were adding these flags. For other compilers, this is fine. However, CMake's MSVC generator understands this as a nop and doesn't do anything.
stdlib/public/core/CMakeLists.txt
Outdated
# the second, it causes errors when the system libraries are told to | ||
# include everything). The best way to get it in there, according to the | ||
# documentation, is to put the flags in the target_link_libraries setting. | ||
# With the GNU linker the equivalent of -all_load is to tell the linker |
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 the extra indentation 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.
No clue, reverted.
@@ -79,13 +79,20 @@ else() # NOT SWIFT_BUILT_STANDALONE | |||
set(clang_headers_location "${LLVM_LIBRARY_DIR}/clang/${CLANG_VERSION}") | |||
endif() | |||
|
|||
# CMake doesn't support create_symlink on Windows: http://cmake.3232098.n2.nabble.com/cmake-E-create-symlink-for-Windows-td4151271.html | |||
if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows") | |||
set(symlink_command "mklink") |
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 indent.
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
tools/driver/CMakeLists.txt
Outdated
@@ -13,18 +13,38 @@ add_swift_host_tool(swift | |||
) | |||
|
|||
target_link_libraries(swift edit) | |||
# CMake doesn't support create_symlink on Windows: http://cmake.3232098.n2.nabble.com/cmake-E-create-symlink-for-Windows-td4151271.html |
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.
Should we factor this out into a helper in cmake/modules/?
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 we wait on this? The reason why I ask is that I'm going to submit a PR fixing some symlink issues on Windows, and this code will go.
The problem is that there is no good way to check if a symlink exists on Windows using CMake, and mklink
reports an error which breaks/stops the build.
The fix would be to create a windows specific (or Xplat python script) that checks if a symlink exists before creating it.
cmake/modules/SwiftSource.cmake
Outdated
# Python utility script (line-directive-file), which reads the list of file paths, | ||
# passing them to the old Python utility script (line-directive) | ||
# TODO: we should move non-Windows builds to use this code at some point to | ||
# remove code duplication |
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 think we should just do that now, before landing the patch.
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
cmake/modules/AddSwift.cmake
Outdated
@@ -294,8 +294,12 @@ function(_add_variant_swift_compile_flags | |||
sdk arch build_type enable_assertions result_var_name) | |||
set(result ${${result_var_name}}) | |||
|
|||
# On Windows, we don't set SWIFT_SDK_WINDOWS_PATH, so don't include it |
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 compiler behaves differently when there's an SDK provided and when there isn't. Is there nothing reasonable to default this to?
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, never mind. Most of those differences have been removed.
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 is actually a dead comment, I have removed it
EDIT: I'm wrong
CMakeLists.txt
Outdated
|
||
# We don't have a build script for Windows currently (build-script-impl is a bash script), so temporarily shortens and simplifies the build | ||
# command for Swift on Windows - we only need to define 1 CMAKE variable (-DSWIFT_WINDOWS_ICU), rather than 8 (that are all the same anyway!) | ||
# We also want to avoid a dependency on PkgConfig (find_package), which is not easily available on Windows. |
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.
Uh... This is not the right way to handle this. find_package
doesn't require PkgConfig. The more correct solution would be to implement a "FindICU.cmake" module and have that module support overriding the ICU directory in a more universal way (it doesn't need to be Windows-specific).
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.
Right - we have a FindICU.cmake module already, but we can see about fixing that file
cmake/modules/AddSwift.cmake
Outdated
${${CFLAGS_RESULT_VAR_NAME}} | ||
"-target" "${SWIFT_SDK_${CFLAGS_SDK}_ARCH_${CFLAGS_ARCH}_TRIPLE}") | ||
# MSVC doesn't understand the option -target | ||
if ("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang") |
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.
Again, what about GCC?
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 didn't see that part of your review, but have addressed it and the other parts just now - sorry!
cmake/modules/AddSwift.cmake
Outdated
if("${CFLAGS_ARCH}" STREQUAL "i386" OR "${CFLAGS_ARCH}" STREQUAL "x86_64") | ||
list(APPEND result "-momit-leaf-frame-pointer") | ||
if("${CFLAGS_ARCH}" STREQUAL "i386" OR "${CFLAGS_ARCH}" STREQUAL "i686" OR "${CFLAGS_ARCH}" STREQUAL "x86_64") | ||
if ("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang") |
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.
Yeah, this definitely needs to be a test for MSVC. More compilers are GCC-like than MSVC-like.
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.
Make sense, fixed
Okay, thanks all for your comments. I've addressed all of them hopefully. I've had to rebase due to merge conflicts. I also ran a Clang build on my Linux VM and that seems to be working (had to fix the new line-directive-file-script for python using bash). |
CMakeLists.txt
Outdated
@@ -148,6 +148,10 @@ set(SWIFT_TOOLS_ENABLE_LTO OFF CACHE STRING "Build Swift tools with LTO. One | |||
set(SWIFT_PARALLEL_LINK_JOBS "" CACHE STRING | |||
"Define the maximum number of linker jobs for swift.") | |||
|
|||
option(SWIFT_HAVE_LIBEDIT | |||
"Enable linking to BSD's libedit. This is necessary to support the REPL and SourceKit, but is optional." |
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.
Nitpick: let's change "the REPL and SourceKit" to "the testing REPLs for swiftc and SourceKit". The real Swift REPL is in LLDB, and the rest of SourceKit should work fine without sourcekitd-test.
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.
Fixed, thanks Jordan
cmake/modules/AddSwift.cmake
Outdated
@@ -356,10 +393,11 @@ function(_add_variant_link_flags) | |||
endif() | |||
|
|||
if(NOT "${SWIFT_${LFLAGS_SDK}_ICU_UC}" STREQUAL "") | |||
list(APPEND result "-L${SWIFT_${sdk}_ICU_UC}") | |||
link_directories("${SWIFT_${sdk}_ICU_UC}") |
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.
If I'm reading the docs right, this adds these link directories to every target in the file, not just the one currently being edited (and same for include_directories
below). While that's probably not harmful, it's not correct to do within _add_variant_link_flags
either. Either we should set this all up initially, or we should leave it the way it is using manual flags.
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 had no idea, but I think you're right.
and same for include_directories below
I think target_include_directories
addresses this concern
I'm checking out the equivilent for link_directories
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.
Unfortunately, we have to resort to an CMAKE_C_COMPILER_ID
check for linking directories and do it manually with -L
or /LIBPATH
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.
Yeah, I see why you did it. Oh 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.
I actually think these might just be dead code, as we parse an absolute path to target_link_libraries or whatever it is, so these flags may be unecessary, but that's for another cleanup PR
target_link_libraries(swift-remoteast-test edit) | ||
|
||
# TODO(hughbe/Windows): Windows does not support libedit currently. See the TODO in tools/SourceKit/tools/CMakeLists.txt | ||
if(NOT "${CMAKE_SYSTEM_NAME}" STREQUAL "Windows") |
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.
SWIFT_HAVE_LIBEDIT?
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.
missed that, fixed
utils/line-directive
Outdated
@@ -244,8 +245,15 @@ def run(): | |||
dashes = sys.argv.index('--') | |||
sources = sys.argv[1:dashes] | |||
|
|||
# subprocess.Popen doesn't normalise paths on Windows (e.g. C:/swift/./lib) | |||
# and instead reports file/directory not found errors. Therefore, we need | |||
# to manually nromalise the path to the script to invoke. The rest will be |
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.
Typo: nromalise
.
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.
fixed
That's all of my comments, but @compnerd and @llvm-beanz might still have more. (And yes, in the long-term we definitely should be building the runtime with the just-built Clang.) |
I still think you should change how you're handling finding ICU and move the code into the FindICU.cmake file so that you're within CMake's convention. |
You're right - I don't really know where I was coming from in my previous attempt!! So ugly, unconventional and unecessary. Its probably most easily reviewed with |
That commit doesn't seem to be part of the PR, and when I click the link for it nothing shows up. |
My bad, I fixed some comment typos so had to rebase again: 1a8d539 |
cmake/modules/FindICU.cmake
Outdated
HINTS ${PC_ICU_${MODULE}_LIBDIR} ${PC_ICU_${MODULE}_LIBRARY_DIRS}) | ||
set(ICU_${MODULE}_LIBRARIES ${ICU_${MODULE}_LIBRARY}) | ||
|
||
if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows") |
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 think you're still not approaching this correctly.
Instead of having the if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")
, why not allow the ICU paths to be overridden on all platforms? Then the PkgConfig code path can run whenever an override value isn't specified on any platform, and raise errors if it fails.
It is worth noting that the PkgConfig functions in CMake return not-found if the user doesn't have pkg-config installed, so you don't need to avoid calling those functions on Windows (or any other platform).
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.
Yeah you're right. The reason why I was avoiding all of this way because you now have to pass 6 command line variables to CMake, whereas before you only had to pass 1. I guess this is fine, because when we have a build-script it will be simpler.
Take a look at the Simplify ICU package resolution...
commit: its a lot smaller, and only invokes certain behaviour if you can't find PkgConfig. I had to add two CMake variables (ICU_UC_LIB_NAME and ICU_I18N_LIB_NAME), because the library names for ICU on Windows and non-Windows are different. This way its user-configurable though.
I've updated the documentation accordingly.
Thanks
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.
LGTM 👍
Okay - I've applied some knife cutting to this PR, and have changed several commits and extracted them to their own PRs. This PR is now limited to clang-cl and MSVC specific functionality. E.g. compiler arguments, and linker errors. |
@swift-ci please clean smoke test |
1 similar comment
@swift-ci please clean smoke test |
Caveat
Please note: this PR on its own does not constitute actual support for building on Windows upon merging this PR.
For this, apple/swift-clang#45 and apple/swift-llvm#33 will have to be merged.
After this, I will break up my branch: https://github.com/hughbe/swift/tree/improve-win-instructions (that has a fully building Swift compiler) into multiple PRs (20 or so - 1 for each sub-project) and submit them.
If this is merged and you try to build Swift on Windows with MSVC, expect many thousands of build errors - many are duplicates, and all have been addressed in my branch above.
This could take a while, so hold your horses :)
Discussion