Sourcekit lsp breaks when cmake generates a compile_commands.json with the swift compiler at /usr/bin/swiftc, logging stuff like No language service for 'file:\/\/\/...
Seems like this is not the actual swiftc binary, possibly a wrapper that points to the path produced by xcrun --find swiftc
This can be solved by setting the correct swift compiler binary in cmake
if(APPLE)
# Find the actual compiler binary, /usr/bin/swiftc doesn't work with sourcekit-lsp
execute_process(
COMMAND xcrun --find swiftc
OUTPUT_VARIABLE SWIFTC_PATH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if(NOT CMAKE_Swift_COMPILER)
set(CMAKE_Swift_COMPILER "${SWIFTC_PATH}" CACHE FILEPATH "Swift compiler path" FORCE)
endif()
endif()
But this breaks compilation with errors like
<unknown>:0: error: unable to load standard library for target 'arm64-apple-macosx26.0'
ninja: build stopped: subcommand failed.
possibly because unlike /usr/bin/swiftc, the real binary at xcrun --find swiftc needs a -sdk flag even for the default macos sdk.
This can be fixed either by populating $SDKROOT or setting CMAKE_OSX_SYSROOT in cmake.
if(APPLE)
# Find the macOS SDK path, /usr/bin/swiftc compiles without a -sdk flag but the actual compiler still needs it
execute_process(
COMMAND xcrun --sdk macosx --show-sdk-path
OUTPUT_VARIABLE MACOS_SDK_PATH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
# Find the actual compiler binary, /usr/bin/swiftc doesn't work with sourcekit-lsp
execute_process(
COMMAND xcrun --find swiftc
OUTPUT_VARIABLE SWIFTC_PATH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if(NOT CMAKE_OSX_SYSROOT)
set(CMAKE_OSX_SYSROOT "${MACOS_SDK_PATH}" CACHE STRING "macOS SDK path" FORCE)
endif()
if(NOT CMAKE_Swift_COMPILER)
set(CMAKE_Swift_COMPILER "${SWIFTC_PATH}" CACHE FILEPATH "Swift compiler path" FORCE)
endif()
endif()
While the workaround is relatively straightforward, SourceKit-LSP should ideally work with /usr/bin/swiftc or .swiftly/bin/swiftc as they are the standard ways of invoking command line tools on Apple platforms.