Trying to import Swift code from one target to Objective C target in same library can't find Swift header

I came across a problem trying to import swift code from one target of a library into another objective-c based target in the same library, but I cannot get my objective-c code to find the generated "-Swift.h" file I need to import, is it a bug or am I doing something wrong/strange?

My package looks like so:

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

import PackageDescription

let package = Package(
    name: "ImportSwiftToObjC",
    products: [
        // Products define the executables and libraries a package produces, and make them visible to other packages.
        .library(
            name: "ImportSwiftToObjC",
            targets: [
                "SwiftExport",
                "ObjCImport",
                "Bridge"
            ]),
    ],
    dependencies: [
        // Dependencies declare other packages that this package depends on.
        // .package(url: /* package url */, from: "1.0.0"),
    ],
    targets: [
        // Targets are the basic building blocks of a package. A target can define a module or a test suite.
        // Targets can depend on other targets in this package, and on products in packages this package depends on.
        .target(
            name: "SwiftExport",
            dependencies: []
        ),
        .target(
            name: "ObjCImport",
            dependencies: ["SwiftExport"]
        ),
        .target(
            name: "Bridge",
            dependencies: ["ObjCImport"]
        ),
        .testTarget(
            name: "ImportSwiftToObjCTests",
            dependencies: ["ObjCImport"]),
    ]
)

Directory layout:

├── Package.swift
├── README.md
├── Sources
│   ├── Bridge
│   │   └── Export.swift
│   ├── ObjCImport
│   │   ├── ObjCImport.m
│   │   └── include
│   │       └── ObjCImport.h
│   └── SwiftExport
│       └── SwiftExport.swift
└── Tests
    └── ImportSwiftToObjCTests
        └── ImportSwiftToObjCTests.swift

I have some swift code in the 'SwiftExport' I want to use in the Objective C target 'ObjCImport'. I should be able to import the SwiftExport-Swift.h generated file into ObjCImport.m, but whatever I try, the header file is not found.. I see it has been generated in the build folder, and exported in the module map of SwiftExport, but that's as far as I get.

I would expect to be able to do something like this:

#import <Foundation/Foundation.h>
#import "ObjCImport.h"

// Where do I find the SwiftExport-Swift.h file? I see it in the build folder, it exists
#import <SwiftExport/SwiftExport-Swift.h>


@implementation ObjCImport

+ (NSString*)helloWorld {
    return @"Hello, World!";
    // Would like to return something from the swift package
    //return SwiftExport.helloWorld;
}

@end

Reason for doing this relate to another bug trying to import some dynamic libraries with resources and I thought I found a workaround, I'll start with this problem first...

Can anyone point me in the right direction?

Did you ever resolve this? I'm having the same issue.

I was able to hack around it and get it to compile by adding the following to the ObjC target:

cSettings: [.unsafeFlags(["-I./build/GeneratedModuleMaps-iphoneos"])]

however this is not great for a number of reasons, including the explicit iphoneos in the path (what if I wanted to build for another OS?) and the general usage of .unsafeFlags. It seems like SPM should be adding this line itself. I tried using .headerSearchPath to set this in a "safer" manner but that didn't work.

When I compile with xcodebuild, I can see that lots of -I args are getting added, just not one that lets it find the generated header file. It's even adding -fmodule-map-file arguments that point to generated module map files in that same directory, but it's not adding the -I to allow the compiler to find the header there.

I also took a look at the SPM source at https://github.com/apple/swift-package-manager/blob/main/Sources/Build/BuildPlan/BuildPlan%2BClang.swift#L23-L28 and it appears there's no code to add the -I flag for the generated Swift header when planning a ClangTarget if the underlying dependency target is a SwiftTarget.

Forgot about this, looking at the package now, it looks like I implemented a workaround. I seem to remember I was running into this issue : [SR-13560] swiftpm: SWIFTPM_MODULE_BUNDLE returning nil · Issue #4500 · apple/swift-package-manager · GitHub

I have a seperate target for resources to access for testing, and it looks like where the package is used, I set the resource path from the resource module back into the bridge module.

They say the bug is fixed, but I haven't tried again.