Index: cmake/platforms/WinMsvc.cmake =================================================================== --- cmake/platforms/WinMsvc.cmake +++ cmake/platforms/WinMsvc.cmake @@ -8,6 +8,7 @@ # -DMSVC_BASE=/path/to/MSVC/system/libraries/and/includes # -DWINSDK_BASE=/path/to/windows-sdk # -DWINSDK_VER=windows sdk version folder name +# -DWINSDK_CASE_SENSITIVE=[YES|NO] # # LLVM_NATIVE_TOOLCHAIN: # *Absolute path* to a folder containing the toolchain which will be used to @@ -74,20 +75,22 @@ # kernel32.lib # etc # -# IMPORTANT: In order for this to work, you will need a valid copy of the Windows -# SDK and C++ STL headers and libraries on your host. Additionally, since the -# Windows libraries and headers are not case-correct, you will need to have these -# mounted in a case-insensitive mount. This requires one command to set up. +# WINSDK_CASE_SENSITIVE: +# The Windows SDK headers and libraries are not case-correct. You can mount +# the SDK in a case-insensitive mount to work around this. Run the following +# commands to set the mount up, and then copy the SDK headers and libraries to +# the winsdk.icase folder and use *that* folder as the path when configuring +# CMake. # -# ~/src: mkdir winsdk -# ~/src: mkdir winsdk.icase -# ~/src: ciopfs winsdk/ winsdk.icase +# ~/src: mkdir winsdk +# ~/src: mkdir winsdk.icase +# ~/src: ciopfs winsdk/ winsdk.icase # -# Now copy or otherwise install your headers and libraries to the winsdk.icase folder -# and use *that* folder as the path when configuring CMake. -# -# TODO: We could also provide a CMake option -DUSE_ICASE_VFS_OVERLAY=ON/OFF that would -# make this optional. For now, we require ciopfs. +# Alternatively, you can set WINSDK_CASE_SENSITIVE to YES, in which case this +# toolchain file will assume the SDK is hosted on a case-sensitive filesystem, +# and will create a case-insensitive clang VFS overlay for the SDK headers and +# case-correcting symlinks for the libraries. WINSDK_CASE_SENSITIVE defaults +# to OFF; i.e., the default assumption is a case-insensitive mount. # When configuring CMake with a toolchain file against a top-level CMakeLists.txt, @@ -106,6 +109,49 @@ endif() endfunction() +function(generate_winsdk_vfs_overlay winsdk_include_dir output_path) + set(include_dirs) + file(GLOB_RECURSE entries LIST_DIRECTORIES true "${winsdk_include_dir}/*") + foreach(entry ${entries}) + if(IS_DIRECTORY "${entry}") + list(APPEND include_dirs "${entry}") + endif() + endforeach() + + file(WRITE "${output_path}" "version: 0\n") + file(APPEND "${output_path}" "case-sensitive: false\n") + file(APPEND "${output_path}" "roots:\n") + + foreach(dir ${include_dirs}) + file(GLOB headers RELATIVE "${dir}" "${dir}/*.h") + if(NOT headers) + continue() + endif() + + file(APPEND "${output_path}" " - name: \"${dir}\"\n") + file(APPEND "${output_path}" " type: directory\n") + file(APPEND "${output_path}" " contents:\n") + + foreach(header ${headers}) + file(APPEND "${output_path}" " - name: \"${header}\"\n") + file(APPEND "${output_path}" " type: file\n") + file(APPEND "${output_path}" " external-contents: \"${dir}/${header}\"\n") + endforeach() + endforeach() +endfunction() + +function(generate_winsdk_lib_symlinks winsdk_um_lib_dir output_dir) + execute_process(COMMAND "${CMAKE_COMMAND}" -E make_directory "${output_dir}") + file(GLOB libraries RELATIVE "${winsdk_um_lib_dir}" "${winsdk_um_lib_dir}/*") + foreach(library ${libraries}) + string(TOLOWER "${library}" symlink_name) + execute_process(COMMAND "${CMAKE_COMMAND}" + -E create_symlink + "${winsdk_um_lib_dir}/${library}" + "${output_dir}/${symlink_name}") + endforeach() +endfunction() + # FIXME: We should support target architectures other than x64 set(CMAKE_SYSTEM_NAME Windows) set(CMAKE_SYSTEM_VERSION 10.0) @@ -115,6 +161,7 @@ init_user_prop(MSVC_BASE) init_user_prop(WINSDK_BASE) init_user_prop(WINSDK_VER) +init_user_prop(WINSDK_CASE_SENSITIVE) set(MSVC_INCLUDE "${MSVC_BASE}/include") set(MSVC_LIB "${MSVC_BASE}/lib") @@ -170,6 +217,18 @@ -imsvc "${WINSDK_INCLUDE}/um" -imsvc "${WINSDK_INCLUDE}/winrt") +if (WINSDK_CASE_SENSITIVE) + # Ensure all sub-configures use the top-level VFS overlay instead of generating their own. + init_user_prop(winsdk_vfs_overlay_path) + if(NOT winsdk_vfs_overlay_path) + set(winsdk_vfs_overlay_path "${CMAKE_BINARY_DIR}/winsdk_vfs_overlay.yaml") + generate_winsdk_vfs_overlay("${WINSDK_BASE}/Include/${WINSDK_VER}" "${winsdk_vfs_overlay_path}") + init_user_prop(winsdk_vfs_overlay_path) + endif() + list(APPEND COMPILE_FLAGS + -Xclang -ivfsoverlay -Xclang "${winsdk_vfs_overlay_path}") +endif() + string(REPLACE ";" " " COMPILE_FLAGS "${COMPILE_FLAGS}") # We need to preserve any flags that were passed in by the user. However, we @@ -193,6 +252,18 @@ -libpath:"${WINSDK_LIB}/ucrt/x64" -libpath:"${WINSDK_LIB}/um/x64") +if(WINSDK_CASE_SENSITIVE) + # Ensure all sub-configures use the top-level symlinks dir instead of generating their own. + init_user_prop(winsdk_lib_symlinks_dir) + if(NOT winsdk_lib_symlinks_dir) + set(winsdk_lib_symlinks_dir "${CMAKE_BINARY_DIR}/winsdk_lib_symlinks") + generate_winsdk_lib_symlinks("${WINSDK_BASE}/Lib/${WINSDK_VER}/um/x64" "${winsdk_lib_symlinks_dir}") + init_user_prop(winsdk_lib_symlinks_dir) + endif() + list(APPEND LINK_FLAGS + -libpath:"${winsdk_lib_symlinks_dir}") +endif() + string(REPLACE ";" " " LINK_FLAGS "${LINK_FLAGS}") # See explanation for compiler flags above for the _INITIAL variables.