Skip to content

[cxx-interop] Make test discovery compatible with C++ interop #7165

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

Merged
merged 1 commit into from
Dec 11, 2023

Conversation

egorzhdan
Copy link
Contributor

Motivation:

If a Swift module is built with C++ interop enabled, all of its dependencies must also be built with C++ interop enabled.

Swift packages that use test discovery get a synthesized "PackageDiscoveredTests" target which is built by SwiftPM when someone runs swift test command. This module is currently always built without C++ interop, which is causing issues for projects that rely on it.

Modifications:

This patch makes sure that the -cxx-interoperability-mode= command line flag gets propagated to the test discovery target.

Result:

Packages that use both C++ interop and test discovery can now be built successfully by SwiftPM.

rdar://117078320 / resolves #6990

// discovery target must enable C++ interop as well
switch testTargetRole {
case .discovery:
for dependency in try self.target.recursiveTargetDependencies() {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is somewhat ugly, but it should go away once we have a better story for mixing C-interop and C++-interop in a single project.

@egorzhdan
Copy link
Contributor Author

@swift-ci please test

for dependency in try self.target.recursiveTargetDependencies() {
let dependencyScope = self.buildParameters.createScope(for: dependency)
let dependencySwiftFlags = dependencyScope.evaluate(.OTHER_SWIFT_FLAGS)
if let interopModeFlag = dependencySwiftFlags.first(where: { $0.hasPrefix("-cxx-interoperability-mode=") }) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are we doing these kind of checks elsewhere in the code? should it be encapsulated behind something like dependencySwiftFlags.cxxInteropMode returning an optional?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 to this question

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't happening elsewhere in the code, no. We basically don't want to implicitly enable C++ interop unless is it really unavoidable, like it is in the case of a test discovery target, because parsing Objective-C headers in Objective-C++ language mode sometimes changes semantics/ABI.

I only see one other usage of extraSwiftFlags.first(where: ...) in UserToolchain.swift and one other usage of .evaluate(.OTHER_SWIFT_FLAGS). I can extract a common method for either, let me know if you think it's worth it.

Copy link
Contributor

@MaxDesiatov MaxDesiatov Dec 7, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generalizing extraSwiftFlags.first(where:) (preferably its replacement that isn't stringly-typed) makes sense to me, the other seems fine as is.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I just realized that the other usage of extraSwiftFlags.first operates on [String], not on flags/scopes. So I don't really see a way to simplify this.

@MaxDesiatov MaxDesiatov added build system Changes to interactions with build systems swift test Changes impacting `swift test` tool bug C++ interop labels Dec 6, 2023
Copy link
Contributor

@MaxDesiatov MaxDesiatov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall the change makes sense, but would be great to avoid the hackiness of adding this logic directly in SwiftTargetBuildDescription. Also, please cherry-pick it against release/5.10 after it's merged.

@hyp
Copy link
Contributor

hyp commented Dec 6, 2023

You also need to pass through the C++ standard as well, when C++ interop is enabled.

@egorzhdan egorzhdan force-pushed the egorzhdan/cxx-interop-test-discovery branch from e1b4410 to cb66df8 Compare December 7, 2023 17:01
@egorzhdan
Copy link
Contributor Author

@MaxDesiatov is there a more suitable place for this logic, perhaps BuildParameters? We'd need to have access to the type of the test module to see if it is a test discovery module to apply these flags.

@egorzhdan
Copy link
Contributor Author

@hyp thanks, done. We should now be passing -Xcc -std=... to the test discovery target.

@egorzhdan
Copy link
Contributor Author

@swift-ci please test

@MaxDesiatov
Copy link
Contributor

BuildParameters come from SwiftTool and are specified on the command line or via Swift SDKs and toolsets. I haven't worked with BuildSettings yet, but that seems like something manifest-specific, which is more appropriate here, isn't it? @neonichu can correct me if I'm wrong.

If a Swift module is built with C++ interop enabled, all of its dependencies must also be built with C++ interop enabled.

Swift packages that use test discovery get a synthesized "PackageDiscoveredTests" target which is built by SwiftPM when someone runs `swift test` command. This module is currently always built without C++ interop, which is causing issues for projects that rely on it.

This patch makes sure that the `-cxx-interoperability-mode=` command line flag gets propagated to the test discovery target.

rdar://117078320 / resolves #6990
@egorzhdan egorzhdan force-pushed the egorzhdan/cxx-interop-test-discovery branch from cb66df8 to 6a2278f Compare December 8, 2023 13:24
@egorzhdan
Copy link
Contributor Author

@swift-ci please test

@egorzhdan
Copy link
Contributor Author

@swift-ci please test Windows

Copy link
Contributor

@MaxDesiatov MaxDesiatov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realize that C++ options/flags code needs a larger refactoring to avoid the stringly-typed nature of it, but fine to merge this now to unblock interop adopters.

@egorzhdan egorzhdan merged commit d2eb0ca into main Dec 11, 2023
@egorzhdan egorzhdan deleted the egorzhdan/cxx-interop-test-discovery branch December 11, 2023 15:10
egorzhdan added a commit that referenced this pull request Dec 11, 2023
### Motivation:

If a Swift module is built with C++ interop enabled, all of its
dependencies must also be built with C++ interop enabled.

Swift packages that use test discovery get a synthesized
"PackageDiscoveredTests" target which is built by SwiftPM when someone
runs `swift test` command. This module is currently always built without
C++ interop, which is causing issues for projects that rely on it.
### Modifications:

This patch makes sure that the `-cxx-interoperability-mode=` command
line flag gets propagated to the test discovery target.

### Result:

Packages that use both C++ interop and test discovery can now be built
successfully by SwiftPM.

rdar://117078320 / resolves
#6990

(cherry picked from commit d2eb0ca)
egorzhdan added a commit that referenced this pull request Dec 11, 2023
### Motivation:

If a Swift module is built with C++ interop enabled, all of its
dependencies must also be built with C++ interop enabled.

Swift packages that use test discovery get a synthesized
"PackageDiscoveredTests" target which is built by SwiftPM when someone
runs `swift test` command. This module is currently always built without
C++ interop, which is causing issues for projects that rely on it. ###
Modifications:

This patch makes sure that the `-cxx-interoperability-mode=` command
line flag gets propagated to the test discovery target.

### Result:

Packages that use both C++ interop and test discovery can now be built
successfully by SwiftPM.

rdar://117078320 / resolves
#6990

Original PR: #7165

(cherry picked from commit d2eb0ca)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug build system Changes to interactions with build systems C++ interop swift test Changes impacting `swift test` tool
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Auto Generated *PackageDiscoveredTest Is Incompatible With C++ Interop
5 participants