Skip to content

Commit 51d1ba4

Browse files
committed
CXX-Interop: Fix missing header deps edge
The custom target dependency was an order-only dependency edge. As a result, changing the swift file wouldn't result in the header getting regenerated at the right time because nothing actually depended on it being up-to-date. This patch should fix that and ties it into the `fibonacci` target a little more cleanly. The generated header is marked as being one of the target sources, so the target itself depends on the header getting built. This ensures that the C++ file gets rebuilt if the header changes. The header still depends on the Swift sources in the target. We're now extracting that list directly from the target itself instead of needing to pass it in explicitly. The module is also extracted from the target itself. We're also automatically adding the location of the header include directory so that dependees can find it as part of the target interface. Fixes #8
1 parent 7a86d39 commit 51d1ba4

File tree

2 files changed

+55
-53
lines changed

2 files changed

+55
-53
lines changed

3_bidirectional_cxx_interop/cmake/modules/AddSwift.cmake

Lines changed: 46 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,29 @@
55
#
66
# See https://swift.org/LICENSE.txt for license information
77

8-
include(CheckCompilerFlag)
9-
10-
# Generate bridging header from Swift to C++
11-
# NOTE: This logic will eventually be upstreamed into CMake
12-
function(_swift_generate_cxx_header_target target module header)
13-
cmake_parse_arguments(ARG "" "" "SOURCES;SEARCH_PATHS;DEPENDS" ${ARGN})
14-
if(NOT ARG_SOURCES)
15-
message(FATAL_ERROR "No sources provided to 'swift_generate_cxx_header_target'")
8+
9+
# Generate the bridging header from Swift to C++
10+
#
11+
# target: the name of the target to generate headers for.
12+
# This target must build swift source files.
13+
# header: the name of the header file to generate.
14+
#
15+
# NOTE: This logic will eventually be unstreamed into CMake.
16+
function(_swift_generate_cxx_header target header)
17+
if(NOT TARGET ${target})
18+
message(FATAL_ERROR "Target ${target} not defined.")
19+
endif()
20+
21+
if(NOT DEFINED CMAKE_Swift_COMPILER)
22+
message(WARNING "Swift not enabled in project. Cannot generate headers for Swift files.")
23+
return()
24+
endif()
25+
26+
cmake_parse_arguments(ARG "" "" "SEARCH_PATHS;MODULE_NAME" ${ARGN})
27+
28+
if(NOT ARG_MODULE_NAME)
29+
set(target_module_name $<TARGET_PROPERTY:${target},Swift_MODULE_NAME>)
30+
set(ARG_MODULE_NAME $<IF:$<BOOL:${target_module_name}>,${target_module_name},${target}>)
1631
endif()
1732

1833
if(ARG_SEARCH_PATHS)
@@ -23,27 +38,36 @@ function(_swift_generate_cxx_header_target target module header)
2338
set(SDK_FLAGS "-sdk" "${CMAKE_OSX_SYSROOT}")
2439
elseif(WIN32)
2540
set(SDK_FLAGS "-sdk" "$ENV{SDKROOT}")
41+
elseif(DEFINED ${CMAKE_SYSROOT})
42+
set(SDK_FLAGS "-sdk" "${CMAKE_SYSROOT}")
2643
endif()
2744

28-
add_custom_command(
29-
OUTPUT
30-
"${header}"
45+
cmake_path(APPEND CMAKE_CURRENT_BINARY_DIR include
46+
OUTPUT_VARIABLE base_path)
47+
48+
cmake_path(APPEND base_path ${header}
49+
OUTPUT_VARIABLE header_path)
50+
51+
set(_AllSources $<TARGET_PROPERTY:${target},SOURCES>)
52+
set(_SwiftSources $<FILTER:${_AllSources},INCLUDE,\\.swift$>)
53+
add_custom_command(OUTPUT ${header_path}
54+
DEPENDS ${_SwiftSources}
55+
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
3156
COMMAND
3257
${CMAKE_Swift_COMPILER} -frontend -typecheck
3358
${ARG_SEARCH_PATHS}
34-
${ARG_SOURCES}
59+
${_SwiftSources}
3560
${SDK_FLAGS}
36-
-module-name "${module}"
61+
-module-name "${ARG_MODULE_NAME}"
3762
-cxx-interoperability-mode=default
38-
-emit-clang-header-path "${header}"
39-
DEPENDS
40-
${ARG_DEPENDS}
63+
-emit-clang-header-path ${header_path}
4164
COMMENT
42-
"Generating '${header}'"
43-
)
65+
"Generating '${header_path}'"
66+
COMMAND_EXPAND_LISTS)
4467

45-
add_custom_target("${target}"
46-
DEPENDS
47-
"${header}"
48-
)
68+
# Added to public interface for dependees to find.
69+
target_include_directories(${target} PUBLIC ${base_path})
70+
# Added to the target to ensure target rebuilds if header changes and is used
71+
# by sources in the target.
72+
target_sources(${target} PRIVATE ${header_path})
4973
endfunction()

3_bidirectional_cxx_interop/lib/fibonacci/CMakeLists.txt

Lines changed: 9 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,38 +5,16 @@
55
#
66
# See https://swift.org/LICENSE.txt for license information
77

8-
9-
# Generate a C++ header from Swift sources
10-
#
11-
# This function is implemented in cmake/modules/AddSwift.cmake.
12-
#
13-
# _swift_generate_cxx_header_target(target-name,
14-
# SwiftModule/C++ namespace,
15-
# generated header path)
16-
_swift_generate_cxx_header_target(
17-
fibonacci_swift_h
18-
SwiftFibonacci
19-
"${CMAKE_CURRENT_BINARY_DIR}/include/fibonacci/fibonacci-swift.h"
20-
SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/fibonacci.swift"
21-
SEARCH_PATHS "${PINGPONG_INCLUDE_DIR}")
22-
23-
# 1. Create a library from the Swift and C++ sources.
24-
# 2. The library requires the Swift header in order to compile, so we create a
25-
# dependency between the library and the header target created above.
26-
# 3. This libraries, and users of this library, will need to find the
27-
# generated header, so we direct CMake to emit `PUBLIC` a public header
28-
# search path, ensuring that dependees of this library also pick up this
29-
# search path.
30-
# 4. Manually override the Swift module name to "SwiftFibonacci" to match the
31-
# name in the generated header header above.
32-
# 5. Enable C++ interoperability mode on all Swift compilations. Again, this is
33-
# required for users of this library, so we make it 'PUBLIC' to ensure the
34-
# flag is propagated to users of the library. Emitting the flag is gated by
35-
# the COMPILE_LANGUAGE cmake generator expression to ensure that the flag is
36-
# only passed to the Swift compiler and not the C++ compiler.
378
add_library(fibonacci STATIC fibonacci.swift fibonacci.cpp)
38-
add_dependencies(fibonacci fibonacci_swift_h)
39-
target_include_directories(fibonacci PUBLIC "${CMAKE_CURRENT_BINARY_DIR}/include")
409
set_target_properties(fibonacci PROPERTIES Swift_MODULE_NAME "SwiftFibonacci")
4110
target_compile_options(fibonacci PUBLIC
4211
"$<$<COMPILE_LANGUAGE:Swift>:-cxx-interoperability-mode=default>")
12+
13+
# Generate a C++ header from Swift sources. This is automatically added to the
14+
# fibonacci target. The target will regenerate the header file when any of the
15+
# Swift sources change. Clang detects that the C++ file depends on the header,
16+
# and tells Ninja about this dependency in the depfile.
17+
# This function is implemented in cmake/modules/AddSwift.cmake.
18+
_swift_generate_cxx_header(fibonacci
19+
fibonacci/fibonacci-swift.h
20+
SEARCH_PATHS "${PINGPONG_INCLUDE_DIR}")

0 commit comments

Comments
 (0)