Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 20 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,25 @@

cmake_minimum_required(VERSION 3.19.6)

if(POLICY CMP0157)
cmake_policy(SET CMP0157 NEW)
endif()

list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules)

project(SwiftSyntax LANGUAGES C Swift)

if(CMAKE_Swift_COMPILATION_MODE_DEFAULT)
# Modern way of doing split builds with CMake 3.29+. This allows us to get proper module
# dependencies and avoid the workaround in AddSwiftHostLibrary.cmake.
set(SWIFT_SYNTAX_USE_SPLIT_BUILD TRUE)
else()
# Legacy way of doing split builds, which is to build the module in a separate target and then
# link to it. This is necessary for CMake versions before 3.29, which don't have proper support
# for Swift module dependencies.
set(SWIFT_SYNTAX_USE_SPLIT_BUILD FALSE)
endif()

set(SWIFT_VERSION 5)
set(CMAKE_Swift_LANGUAGE_VERSION ${SWIFT_VERSION})

Expand All @@ -37,9 +52,11 @@ endif()

set(CMAKE_MACOSX_RPATH YES)

option(SWIFT_SYNTAX_ENABLE_WMO_PRE_3_26
"Enable Whole Module Optimization (WMO) - requires swift-driver"
$<IF:$<AND:$<NOT:$<CONFIG:Debug>>,$<PLATFORM_ID:Darwin>>,YES,NO>)
if(NOT SWIFT_SYNTAX_USE_SPLIT_BUILD)
option(SWIFT_SYNTAX_ENABLE_WMO_PRE_3_26
"Enable Whole Module Optimization (WMO) - requires swift-driver"
$<IF:$<AND:$<NOT:$<CONFIG:Debug>>,$<PLATFORM_ID:Darwin>>,YES,NO>)
endif()

include(AddSwiftHostLibrary)
include(SwiftCompilerCapability)
Expand Down
125 changes: 67 additions & 58 deletions cmake/modules/AddSwiftHostLibrary.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -26,26 +26,28 @@ function(target_link_swift_syntax_libraries TARGET)

target_link_libraries(${TARGET} ${link_type} ${dependencies})

# cmake generation for Swift adds an order only dependency, which matches how C-family languages
# works. In that case, however, ninja (and presumably other generators) will rebuild on header
# changes. That's not the case for Swift, and thus if A -> B, A is not being rebuilt when the
# ABI/API of B changes.
#
# For now workaround this by touching a file whenever B is rebuilt and then compiling that file as
# part of A. Ideally this file would be generated by each of the targets, but that dependency didn't
# seem to be being tracked.
#
# Remove once rdar://102202478 is fixed.
foreach(DEPENDENCY ${dependencies})
string(REGEX REPLACE [<>:\"/\\|?*] _ sanitized ${DEPENDENCY})
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/forced-${sanitized}-dep.swift
COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/forced-${sanitized}-dep.swift
DEPENDS ${DEPENDENCY}
)
target_sources(${TARGET} PRIVATE
${CMAKE_CURRENT_BINARY_DIR}/forced-${sanitized}-dep.swift
)
endforeach()
if(NOT SWIFT_SYNTAX_USE_SPLIT_BUILD)
# cmake generation for Swift adds an order only dependency, which matches how C-family languages
# work. In that case, however, ninja (and presumably other generators) will rebuild on header
# changes. That's not the case for Swift, and thus if A -> B, A is not being rebuilt when the
# ABI/API of B changes.
#
# For now workaround this by touching a file whenever B is rebuilt and then compiling that file as
# part of A. Ideally this file would be generated by each of the targets, but that dependency didn't
# seem to be being tracked.
#
# Remove once rdar://102202478 is fixed.
foreach(DEPENDENCY ${dependencies})
string(REGEX REPLACE [=[[<>:"/\|?*]]=] _ sanitized ${DEPENDENCY})
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/forced-${sanitized}-dep.swift
COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/forced-${sanitized}-dep.swift
DEPENDS ${DEPENDENCY}
)
target_sources(${TARGET} PRIVATE
${CMAKE_CURRENT_BINARY_DIR}/forced-${sanitized}-dep.swift
)
endforeach()
endif()
endfunction()

# Add a new host library with the given name.
Expand All @@ -67,22 +69,13 @@ function(add_swift_syntax_library name)
set(module_file "${module_base}/${SWIFT_HOST_MODULE_TRIPLE}.swiftmodule")
set(module_interface_file "${module_base}/${SWIFT_HOST_MODULE_TRIPLE}.swiftinterface")
set(module_private_interface_file "${module_base}/${SWIFT_HOST_MODULE_TRIPLE}.private.swiftinterface")
set(module_sourceinfo_file "${module_base}/${SWIFT_HOST_MODULE_TRIPLE}.swiftsourceinfo")

# Add a custom target to create the module directory.
add_custom_command(
TARGET ${target}
PRE_BUILD
COMMAND "${CMAKE_COMMAND}" -E make_directory ${module_base}
COMMENT "Generating module directory for ${target}")

# Configure the emission of the Swift module files.
target_compile_options("${target}" PRIVATE
$<$<COMPILE_LANGUAGE:Swift>:
-DRESILIENT_LIBRARIES;
-enable-library-evolution;
-emit-module-path;${module_file};
-emit-module-source-info-path;${module_sourceinfo_file};
-emit-module-interface-path;${module_interface_file};
-emit-private-module-interface-path;${module_private_interface_file}
>)
Expand All @@ -106,43 +99,64 @@ function(add_swift_syntax_library name)
else()
set(module_dir ${CMAKE_CURRENT_BINARY_DIR})
set(module_base "${module_dir}/${name}.swiftmodule")
set(module_file "${module_file}")
endif()

# Touch the library and objects to workaround their mtime not being updated
# when there are no real changes (eg. a file was updated with a comment).
# Ideally this should be done in the driver, which could only update the
# files that have changed.
add_custom_command(
TARGET ${target}
POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E touch_nocreate $<TARGET_FILE:${target}> "${module_base}"
COMMAND_EXPAND_LISTS
COMMENT "Update mtime of library outputs workaround")
add_custom_command(
TARGET ${target}
POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E touch_nocreate $<TARGET_OBJECTS:${target}>
COMMAND_EXPAND_LISTS
COMMENT "Update mtime of objcect files workaround")

set_target_properties(${target} PROPERTIES
Swift_MODULE_NAME ${name}
Swift_MODULE_DIRECTORY ${module_dir}
INTERFACE_INCLUDE_DIRECTORIES ${module_dir}
)

# Configure the emission of the Swift module files.
target_compile_options("${target}" PRIVATE
$<$<COMPILE_LANGUAGE:Swift>:
"SHELL:-module-name ${name}"
"SHELL:-Xfrontend -module-abi-name -Xfrontend ${SWIFT_MODULE_ABI_NAME_PREFIX}${name}"
"-no-emit-module-separately-wmo"
>)

if(NOT SWIFT_SYNTAX_USE_SPLIT_BUILD)
# Legacy build configuration.
if(SWIFTSYNTAX_EMIT_MODULE)
set(module_sourceinfo_file "${module_base}/${SWIFT_HOST_MODULE_TRIPLE}.swiftsourceinfo")

# Add a custom target to create the module directory.
add_custom_command(
TARGET ${target}
PRE_BUILD
COMMAND "${CMAKE_COMMAND}" -E make_directory ${module_base}
COMMENT "Generating module directory for ${target}")

# Configure the emission of the Swift module files.
target_compile_options("${target}" PRIVATE
$<$<COMPILE_LANGUAGE:Swift>:
-emit-module-source-info-path;${module_sourceinfo_file};
>)
endif()

# Touch the library and objects to workaround their mtime not being updated
# when there are no real changes (eg. a file was updated with a comment).
add_custom_command(
TARGET ${target}
POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E touch_nocreate $<TARGET_FILE:${target}> "${module_base}"
COMMAND_EXPAND_LISTS
COMMENT "Update mtime of library outputs workaround")
add_custom_command(
TARGET ${target}
POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E touch_nocreate $<TARGET_OBJECTS:${target}>
COMMAND_EXPAND_LISTS
COMMENT "Update mtime of object files workaround")

# Configure the emission of the Swift module files.
target_compile_options("${target}" PRIVATE
$<$<COMPILE_LANGUAGE:Swift>:
"SHELL:-module-name ${name}"
"-no-emit-module-separately-wmo"
>)

if(CMAKE_VERSION VERSION_LESS 3.26.0 AND SWIFT_SYNTAX_ENABLE_WMO_PRE_3_26)
target_compile_options(${target} PRIVATE
$<$<COMPILE_LANGUAGE:Swift>:-wmo>)
if(CMAKE_VERSION VERSION_LESS 3.26.0 AND SWIFT_SYNTAX_ENABLE_WMO_PRE_3_26)
target_compile_options(${target} PRIVATE
$<$<COMPILE_LANGUAGE:Swift>:-wmo>)
endif()
endif()

target_compile_options(${target} PRIVATE
Expand All @@ -155,11 +169,6 @@ function(add_swift_syntax_library name)
)
endif()

# NOTE: workaround for CMake not setting up include flags yet
set_target_properties(${target} PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES ${module_dir}
)

set_target_properties(${target} PROPERTIES
BUILD_WITH_INSTALL_RPATH YES
)
Expand Down
Loading