Skip to content
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

CXX-Interop: Fix missing header deps edge #9

Merged
merged 1 commit into from
Apr 29, 2024
Merged
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
68 changes: 46 additions & 22 deletions 3_bidirectional_cxx_interop/cmake/modules/AddSwift.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,29 @@
#
# See https://swift.org/LICENSE.txt for license information

include(CheckCompilerFlag)

# Generate bridging header from Swift to C++
# NOTE: This logic will eventually be upstreamed into CMake
function(_swift_generate_cxx_header_target target module header)
cmake_parse_arguments(ARG "" "" "SOURCES;SEARCH_PATHS;DEPENDS" ${ARGN})
if(NOT ARG_SOURCES)
message(FATAL_ERROR "No sources provided to 'swift_generate_cxx_header_target'")

# Generate the bridging header from Swift to C++
#
# target: the name of the target to generate headers for.
# This target must build swift source files.
# header: the name of the header file to generate.
#
# NOTE: This logic will eventually be unstreamed into CMake.
function(_swift_generate_cxx_header target header)
if(NOT TARGET ${target})
message(FATAL_ERROR "Target ${target} not defined.")
endif()

if(NOT DEFINED CMAKE_Swift_COMPILER)
message(WARNING "Swift not enabled in project. Cannot generate headers for Swift files.")
return()
endif()

cmake_parse_arguments(ARG "" "" "SEARCH_PATHS;MODULE_NAME" ${ARGN})

if(NOT ARG_MODULE_NAME)
set(target_module_name $<TARGET_PROPERTY:${target},Swift_MODULE_NAME>)
set(ARG_MODULE_NAME $<IF:$<BOOL:${target_module_name}>,${target_module_name},${target}>)
endif()

if(ARG_SEARCH_PATHS)
Expand All @@ -23,27 +38,36 @@ function(_swift_generate_cxx_header_target target module header)
set(SDK_FLAGS "-sdk" "${CMAKE_OSX_SYSROOT}")
elseif(WIN32)
set(SDK_FLAGS "-sdk" "$ENV{SDKROOT}")
elseif(DEFINED ${CMAKE_SYSROOT})
set(SDK_FLAGS "-sdk" "${CMAKE_SYSROOT}")
endif()

add_custom_command(
OUTPUT
"${header}"
cmake_path(APPEND CMAKE_CURRENT_BINARY_DIR include
OUTPUT_VARIABLE base_path)

cmake_path(APPEND base_path ${header}
OUTPUT_VARIABLE header_path)

set(_AllSources $<TARGET_PROPERTY:${target},SOURCES>)
set(_SwiftSources $<FILTER:${_AllSources},INCLUDE,\\.swift$>)
add_custom_command(OUTPUT ${header_path}
DEPENDS ${_SwiftSources}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMAND
${CMAKE_Swift_COMPILER} -frontend -typecheck
${ARG_SEARCH_PATHS}
${ARG_SOURCES}
${_SwiftSources}
${SDK_FLAGS}
-module-name "${module}"
-module-name "${ARG_MODULE_NAME}"
-cxx-interoperability-mode=default
-emit-clang-header-path "${header}"
DEPENDS
${ARG_DEPENDS}
-emit-clang-header-path ${header_path}
COMMENT
"Generating '${header}'"
)
"Generating '${header_path}'"
COMMAND_EXPAND_LISTS)

add_custom_target("${target}"
DEPENDS
"${header}"
)
# Added to public interface for dependees to find.
target_include_directories(${target} PUBLIC ${base_path})
# Added to the target to ensure target rebuilds if header changes and is used
# by sources in the target.
target_sources(${target} PRIVATE ${header_path})
endfunction()
40 changes: 9 additions & 31 deletions 3_bidirectional_cxx_interop/lib/fibonacci/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,38 +5,16 @@
#
# See https://swift.org/LICENSE.txt for license information


# Generate a C++ header from Swift sources
#
# This function is implemented in cmake/modules/AddSwift.cmake.
#
# _swift_generate_cxx_header_target(target-name,
# SwiftModule/C++ namespace,
# generated header path)
_swift_generate_cxx_header_target(
fibonacci_swift_h
SwiftFibonacci
"${CMAKE_CURRENT_BINARY_DIR}/include/fibonacci/fibonacci-swift.h"
SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/fibonacci.swift"
SEARCH_PATHS "${PINGPONG_INCLUDE_DIR}")

# 1. Create a library from the Swift and C++ sources.
# 2. The library requires the Swift header in order to compile, so we create a
# dependency between the library and the header target created above.
# 3. This libraries, and users of this library, will need to find the
# generated header, so we direct CMake to emit `PUBLIC` a public header
# search path, ensuring that dependees of this library also pick up this
# search path.
# 4. Manually override the Swift module name to "SwiftFibonacci" to match the
# name in the generated header header above.
# 5. Enable C++ interoperability mode on all Swift compilations. Again, this is
# required for users of this library, so we make it 'PUBLIC' to ensure the
# flag is propagated to users of the library. Emitting the flag is gated by
# the COMPILE_LANGUAGE cmake generator expression to ensure that the flag is
# only passed to the Swift compiler and not the C++ compiler.
add_library(fibonacci STATIC fibonacci.swift fibonacci.cpp)
add_dependencies(fibonacci fibonacci_swift_h)
target_include_directories(fibonacci PUBLIC "${CMAKE_CURRENT_BINARY_DIR}/include")
set_target_properties(fibonacci PROPERTIES Swift_MODULE_NAME "SwiftFibonacci")
target_compile_options(fibonacci PUBLIC
"$<$<COMPILE_LANGUAGE:Swift>:-cxx-interoperability-mode=default>")

# Generate a C++ header from Swift sources. This is automatically added to the
# fibonacci target. The target will regenerate the header file when any of the
# Swift sources change. Clang detects that the C++ file depends on the header,
# and tells Ninja about this dependency in the depfile.
# This function is implemented in cmake/modules/AddSwift.cmake.
_swift_generate_cxx_header(fibonacci
fibonacci/fibonacci-swift.h
SEARCH_PATHS "${PINGPONG_INCLUDE_DIR}")