Should running C++ with swift test work? (Getting to hello world with C++ and Swift Package)

(XCode 15 beta 6, MacOS 14.0 Beta (23A5301h))

I have two projects:

module cxxLibrary {
    header "SimpleCxxFunctions.hpp"

    export *
}
Building for debugging...
ld: Undefined symbols:
  _myFavoriteNumber, referenced from:
      InteropLibrary.NumberMaker.currentNumber() -> Swift.Int in NumberMaker.swift.o
clang: error: linker command failed with exit code 1 (use -v to see invocation)
[5/6] Linking CxxInteropLibraryPa…
error: fatalError

Package file:

// swift-tools-version: 5.9
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
    name: "CxxInteropLibrary",
    products: [
        .library(
            name: "cxxLibrary",
            targets: ["cxxLibrary"]),
        .library(
            name: "InteropLibrary",
            targets: ["InteropLibrary"])
    ],
    targets: [
        .target(
            name: "cxxLibrary"),
        .target(
            name: "InteropLibrary",
            dependencies: ["cxxLibrary"]),
            //swiftSettings: [.interoperabilityMode(.Cxx)]), have tried it both ways. 
        .testTarget(
            name: "CxxInteropLibraryTests",
            dependencies: ["InteropLibrary", "cxxLibrary"],
            swiftSettings: [.interoperabilityMode(.Cxx)])
    ]
)

Neither XCode nor the VScode extension flag any problems before the build.

Before I keep banging my head against this, should I even expect this to work with XCTests? If so is there something obvious I've done wrong?

Thank you.

It appears your Swift InteropLibrary target is not enabling interop and thus it thinks it is calling a C function, not a C++ function. This modified package manifest works for me locally and fixes the link issue:

let package = Package(
    name: "CxxInteropLibrary",
    products: [
        .library(
            name: "cxxLibrary",
            targets: ["cxxLibrary"]),
        .library(
            name: "InteropLibrary",
            targets: ["InteropLibrary"])
    ],
    targets: [
        .target(
            name: "cxxLibrary"),
        .target(
            name: "InteropLibrary",
            dependencies: ["cxxLibrary"],
            swiftSettings: [.interoperabilityMode(.Cxx)]),
        .testTarget(
            name: "CxxInteropLibraryTests",
            dependencies: ["InteropLibrary", "cxxLibrary"],
            swiftSettings: [.interoperabilityMode(.Cxx)])
    ]
)

2 Likes

Thank you. Returning that swiftSettings line to the Interop library worked!

I could have sworn I had tried that both ways but I must not have cleaned out the build folder.