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] Add -cxx-interoperability-mode driver flag; deprecate `-… #64088

Merged
merged 6 commits into from
Mar 8, 2023
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
16 changes: 5 additions & 11 deletions docs/CppInteroperability/GettingStartedWithC++Interop.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,9 @@ module CxxTest {
Add the C++ module to the include path and enable C++ interop:
- Navigate to your project directory
- In `Project` navigate to `Build Settings` -> `Swift Compiler`
- Under `Custom Flags` -> `Other Swift Flags` add `-Xfrontend -enable-experimental-cxx-interop`
- Under `Custom Flags` -> `Other Swift Flags` add `-cxx-compatibility-mode=swift-5.9`
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Suggested change
- Under `Custom Flags` -> `Other Swift Flags` add `-cxx-compatibility-mode=swift-5.9`
- Under `Custom Flags` -> `Other Swift Flags` add `-cxx-interoperability-mode=swift-5.9`

Looks like this one got lost in the rebase.. oops

- Under `Search Paths` -> `Import Paths` add your search path to the C++ module (i.e, `./ProjectName/CxxTest`).

```
// Add to Other Swift Flags and Import Paths respectively
-Xfrontend -enable-experimental-cxx-interop
-I./ProjectName/CxxTest
```

- This should now allow your to import your C++ Module into any `.swift` file.

```
Expand Down Expand Up @@ -87,7 +81,7 @@ After creating your Swift package project, follow the steps [Creating a Module t
- Swift code will be in `Sources/CxxInterop` called `main.swift`
- C++ source code follows the example shown in [Creating a Module to contain your C++ source code](#creating-a-module-to-contain-your-c-source-code)
- Under targets, add the name of your C++ module and the directory containing the Swift code as a target.
- In the target defining your Swift target, add a`dependencies` to the C++ Module, the `path`, `source`, and `swiftSettings` with `unsafeFlags` with the source to the C++ Module, and enable `-enable-experimental-cxx-interop`
- In the target defining your Swift target, add a`dependencies` to the C++ Module, the `path`, `source`, and `swiftSettings` with `unsafeFlags` with the source to the C++ Module, and enable `-cxx-interoperability-mode=swift-5.9`

```
//In Package Manifest
Expand Down Expand Up @@ -117,7 +111,7 @@ let package = Package(
sources: [ "main.swift" ],
swiftSettings: [.unsafeFlags([
"-I", "Sources/CxxTest",
"-enable-experimental-cxx-interop",
"-cxx-interoperability-mode=swift-5.9",
])]
),
]
Expand Down Expand Up @@ -150,7 +144,7 @@ After creating your project follow the steps [Creating a Module to contain your
- Create a `CMakeLists.txt` file and configure for your project
- In`add_library` invoke `cxx-support` with the path to the C++ implementation file
- Add the `target_include_directories` with `cxx-support` and path to the C++ Module `${CMAKE_SOURCE_DIR}/Sources/CxxTest`
- Add the `add_executable` to the specific files/directory you would like to generate source, with`SHELL:-enable-experimental-cxx-interop`.
- Add the `add_executable` to the specific files/directory you would like to generate source, with`SHELL:-cxx-interoperability-mode=swift-5.9`.
- In the example below we will be following the file structure used in [Creating a Swift Package](#Creating-a-Swift-Package)

```
Expand All @@ -173,7 +167,7 @@ target_include_directories(cxx-support PUBLIC

add_executable(CxxInterop ./Sources/CxxInterop/main.swift)
target_compile_options(CxxInterop PRIVATE
"SHELL:-enable-experimental-cxx-interop"
"SHELL:-cxx-interoperability-mode=swift-5.9"
target_link_libraries(CxxInterop PRIVATE cxx-support)

```
Expand Down
15 changes: 15 additions & 0 deletions include/swift/AST/DiagnosticsFrontend.def
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,21 @@ REMARK(warning_in_access_notes_file,none,

WARNING(compiler_plugin_not_loaded,none,
"compiler plugin not loaded: %0; loader error: %1", (StringRef, StringRef))

ERROR(dont_enable_interop_and_compat,none,
"do not pass both -enable-experimental-cxx-interop and "
"-cxx-interoperability-mode. Remove -enable-experimental-cxx-interop.", ())

ERROR(invalid_interop_compat_mode,none,
"invalid option passed to -cxx-interoperability-mode. Please select either "
"'off' or 'swift-5.9'.", ())
NOTE(swift_will_maintain_compat,none,
"Swift will maintain source compatibility for imported APIs based on the "
"selected compatibility mode, so updating the Swift compiler will not "
"change how APIs are imported.", ())
WARNING(enable_interop_flag_deprecated,none,
"the -enable-experimental-cxx-interop flag is deprecated. Please pass "
"'-cxx-interoperability-mode=' instead.", ())

#define UNDEFINE_DIAGNOSTIC_MACROS
#include "DefineDiagnosticMacros.h"
8 changes: 7 additions & 1 deletion include/swift/Option/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -663,9 +663,15 @@ def enable_experimental_concise_pound_file : Flag<["-"],

def enable_experimental_cxx_interop :
Flag<["-"], "enable-experimental-cxx-interop">,
Flags<[FrontendOption, HelpHidden, ModuleInterfaceOption]>,
Flags<[NoDriverOption, FrontendOption, HelpHidden, ModuleInterfaceOption]>,
HelpText<"Enable experimental C++ interop code generation and config directives">;

def cxx_interoperability_mode :
Joined<["-"], "cxx-interoperability-mode=">,
Flags<[FrontendOption, ModuleInterfaceOption]>,
HelpText<"Enables C++ interoperability; requires compatbility version to be "
"specified.">;

def experimental_c_foreign_reference_types :
Flag<["-"], "experimental-c-foreign-reference-types">,
Flags<[FrontendOption, HelpHidden, ModuleInterfaceOption]>,
Expand Down
1 change: 1 addition & 0 deletions lib/Driver/ToolChains.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@ void ToolChain::addCommonFrontendArgs(const OutputInfo &OI,
inputArgs.AddLastArg(arguments, options::OPT_library_level);
inputArgs.AddLastArg(arguments, options::OPT_enable_bare_slash_regex);
inputArgs.AddLastArg(arguments, options::OPT_enable_experimental_cxx_interop);
inputArgs.AddLastArg(arguments, options::OPT_cxx_interoperability_mode);
inputArgs.AddLastArg(arguments, options::OPT_load_plugin_library);
inputArgs.AddLastArg(arguments, options::OPT_load_plugin_executable);
inputArgs.AddLastArg(arguments, options::OPT_enable_builtin_module);
Expand Down
35 changes: 34 additions & 1 deletion lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,20 @@ static void SaveModuleInterfaceArgs(ModuleInterfaceOptions &Opts,
}
}

enum class CxxCompatMode {
invalid,
enabled,
off
};

static CxxCompatMode validateCxxInteropCompatibilityMode(StringRef mode) {
if (mode == "off")
return CxxCompatMode::off;
if (mode == "swift-5.9")
return CxxCompatMode::enabled;
return CxxCompatMode::invalid;
}

static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
DiagnosticEngine &Diags,
const FrontendOptions &FrontendOpts) {
Expand Down Expand Up @@ -899,7 +913,26 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
Opts.ClangTarget = llvm::Triple(A->getValue());
}

Opts.EnableCXXInterop |= Args.hasArg(OPT_enable_experimental_cxx_interop);
if (Arg *A = Args.getLastArg(OPT_cxx_interoperability_mode)) {
if (Args.hasArg(OPT_enable_experimental_cxx_interop)) {
Diags.diagnose(SourceLoc(), diag::dont_enable_interop_and_compat);
}

auto interopCompatMode = validateCxxInteropCompatibilityMode(A->getValue());
Opts.EnableCXXInterop |= (interopCompatMode == CxxCompatMode::enabled);

if (interopCompatMode == CxxCompatMode::invalid) {
Diags.diagnose(SourceLoc(), diag::invalid_interop_compat_mode);
Diags.diagnose(SourceLoc(), diag::swift_will_maintain_compat);
}
}

if (Args.hasArg(OPT_enable_experimental_cxx_interop)) {
Diags.diagnose(SourceLoc(), diag::enable_interop_flag_deprecated);
Diags.diagnose(SourceLoc(), diag::swift_will_maintain_compat);
Opts.EnableCXXInterop |= true;
}

Opts.EnableObjCInterop =
Args.hasFlag(OPT_enable_objc_interop, OPT_disable_objc_interop,
Target.isOSDarwin());
Expand Down
19 changes: 19 additions & 0 deletions test/Interop/Cxx/driver/dont-enable-interop-compat.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// RUN: rm -rf %t
// RUN: split-file %s %t
// RUN: %target-swift-frontend -typecheck -I %t/Inputs %t/test.swift -enable-experimental-cxx-interop 2>&1 | %FileCheck %s

//--- Inputs/module.modulemap
module Test {
header "test.h"
requires cplusplus
}

//--- Inputs/test.h


//--- test.swift

import Test

// CHECK: warning: the -enable-experimental-cxx-interop flag is deprecated. Please pass '-cxx-interoperability-mode=' instead.
// CHECK: note: Swift will maintain source compatibility for imported APIs based on the selected compatibility mode, so updating the Swift compiler will not change how APIs are imported.
18 changes: 18 additions & 0 deletions test/Interop/Cxx/driver/enable-interop-flag-depr.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// RUN: rm -rf %t
// RUN: split-file %s %t
// RUN: not %target-swift-frontend -typecheck -I %t/Inputs %t/test.swift -enable-experimental-cxx-interop -cxx-interoperability-mode=swift-5.9 2>&1 | %FileCheck %s

//--- Inputs/module.modulemap
module Test {
header "test.h"
requires cplusplus
}

//--- Inputs/test.h

//--- test.swift

import Test

// CHECK: error: do not pass both -enable-experimental-cxx-interop and -cxx-interoperability-mode. Remove -enable-experimental-cxx-interop.
// CHECK: note: Swift will maintain source compatibility for imported APIs based on the selected compatibility mode, so updating the Swift compiler will not change how APIs are imported.
18 changes: 18 additions & 0 deletions test/Interop/Cxx/driver/invalid-interop-compat-mode.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// RUN: rm -rf %t
// RUN: split-file %s %t
// RUN: not %target-swift-frontend -typecheck -I %t/Inputs %t/test.swift -cxx-interoperability-mode=swift-5.8 2>&1 | %FileCheck %s

//--- Inputs/module.modulemap
module Test {
header "test.h"
requires cplusplus
}

//--- Inputs/test.h

//--- test.swift

import Test

// CHECK: error: invalid option passed to -cxx-interoperability-mode. Please select either 'off' or 'swift-5.9'.
// CHECK: note: Swift will maintain source compatibility for imported APIs based on the selected compatibility mode, so updating the Swift compiler will not change how APIs are imported.
6 changes: 3 additions & 3 deletions test/lit.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -727,8 +727,8 @@ elif swift_test_mode == 'with_cxx_interop':
config.available_features.add("nonexecutable_test")
config.available_features.add("executable_test")
config.available_features.add("with_cxx_interop")
config.swift_frontend_test_options += ' -enable-experimental-cxx-interop'
config.swift_driver_test_options += ' -Xfrontend -enable-experimental-cxx-interop'
config.swift_frontend_test_options += ' -cxx-interoperability-mode=swift-5.9'
config.swift_driver_test_options += ' -cxx-interoperability-mode=swift-5.9'
else:
lit_config.fatal("Unknown test mode %r" % swift_test_mode)

Expand Down Expand Up @@ -2381,7 +2381,7 @@ config.substitutions.insert(0, ('%check-cxx-header-in-clang',
config.substitutions.append(('%env-', config.target_env_prefix))

config.substitutions.append(('%target-clangxx', '%s -std=c++11' % config.target_clang))
config.substitutions.append(('%target-swiftxx-frontend', '%s -enable-experimental-cxx-interop' % config.target_swift_frontend))
config.substitutions.append(('%target-swiftxx-frontend', '%s -cxx-interoperability-mode=swift-5.9' % config.target_swift_frontend))

config.substitutions.append(('%target-runtime', config.target_runtime))

Expand Down