SwiftPM can't build executable with dependencies on Linux/Win platforms

Hello,

I try to build cross platform package for iOS/OSX/Lin/Win platforms based on C++ & Swift code.
So I made simplest package with C++ library target, Swift executable, dependent on C++ library and C++ executable, dependent on C++ library.
And I can successfully build it with OSX. But when I try to build package with Linux or Windows swift it produce same error for cxxMain target:

main.cpp:3:10: fatal error: module 'cxxLibrary' is needed but has not been provided, and implicit use of module files is disabled
#include "cxxLibrary.h"

At the same time MyCli executable target (Swift) built and run well on all platforms. So it looks like something wrong with module search on Linux/Windows platforms for C++ targets.

Need help....

Package file is:

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

import PackageDescription

let package = Package(
    name: "MyCli",
    platforms: [.macOS("13.3"), .iOS("14.0")],
    products: [
        .library(
            name: "cxxLibrary",
            targets: ["cxxLibrary"]),
        .executable(
            name: "MyCli",
            targets: ["MyCli"]),
        .executable(
            name: "cxxMain",
            targets: ["cxxMain"])
    ],
    targets: [
        .target(
            name: "cxxLibrary",
            cxxSettings: [
              //.headerSearchPath("."),
              .unsafeFlags(["-std=c++2b"])
            ]),
        .executableTarget(
            name: "MyCli",
            dependencies: ["cxxLibrary"],
            swiftSettings: [.interoperabilityMode(.Cxx)]),
        .executableTarget(
            name: "cxxMain",
            dependencies: ["cxxLibrary"],
            cxxSettings: [
              //.headerSearchPath("."),
              .unsafeFlags(["-std=c++2b"])
            ]),
    ]
)

cxxLibrary files:

// cxxLibrary.h
#pragma once
void sayHello();

// cxxLibrary.cpp
#include "cxxLibrary.h"
#include <cstdio>

void sayHello() {
    printf("Hello from c++\n");
}

MyCli files:

// main.swift
import cxxLibrary

print("Hello, world 1!")
sayHello()

cxxMain files:

// main.cpp
#include <print>
#include "cxxLibrary.h" // Error is here !!!!!!!!!!!!!!!!

int main(int argc, char *argv[]) {
    std::print("cxxMain\n");
    sayHello();
}

Try to reproduce you issue here:

  1. Add a new DemoKit and update the layout and content as you describe.

Note: cxxLibrary.h need to be under include folder

├── Package.swift
└── Sources
    ├── MyCli
    │   └── main.swift
    ├── cxxLibrary
    │   ├── cxxLibrary.cpp
    │   └── include
    │       └── cxxLibrary.h
    └── cxxMain
        └── main.cpp
  1. Running swift run cxxMain works fine on macOS 14.5 + Swift 5.10 Toolchain.

On Ubuntu 22 + Swift, it will first fail to the missing print header.

kyle@ubuntu:/Users/kyle/tmp/DemoKit$ swift run cxxMain
Building for debugging...
/Users/kyle/tmp/DemoKit/Sources/cxxMain/main.cpp:2:10: fatal error: 'print' file not found
#include <print>
         ^~~~~~~
1 error generated.
[0/4] Compiling cxxLibrary cxxLibrary.cpp

Maybe my compiler toolchain on Ubuntu 22 does not support C++23. Anyway, this is not the main point here.

So I just comment the 2 unrelated line and run it again.

// main.cpp
// #include <print>
#include "cxxLibrary.h"

int main(int argc, char *argv[]) {
    // std::print("cxxMain\n");
    sayHello();
}
➜  DemoKit swift run cxxMain
Building for debugging...
[5/5] Applying cxxMain
Build complete! (0.40s)
Hello from c++

No issue on my side.

Could you file a SwiftPM issue on GitHub and provide more information on your Linux environment so that we can better reproduce it?

I suspect the Windows problem is also related (as long as the Swift toolchain is new but not latest development snapshots). On Windows the C++ standard supported is decided by Swift’s bundled Clang, and Swift 5.10 comes with Clang 15, which is pretty outdated (released in 2022).

1 Like

You saved my life - when I removed -std=c++2b:

cxxSettings: [
              //.unsafeFlags(["-std=c++2b"])
            ]

It starts to work!
But it's related to something else than just C++ standard support.
Looks like in c++2b (and probably c++23 for Swift 6) mode clang compiler process includes different from c++17. Probably clang expects dependency target library to be valid c++23 module. Because on Windows I installed Swift from main branch (6 beta) and sure it supports c++23 and have same error.

1 Like