Xcode SPM mixed languages

I am working on a branch of my PBPopupController framework to support SPM. The code consists of sources written in Swift and Objective-C.

I reorganised the structure of the project so that the code written in Swift was separated from the code written in Objective-C, by creating two sub-directories (Swift and ObjC).

Now when I try to import <PBPopupController/PBPopupController-Swift.h> , Xcode gives me an error: "file not found" .

You can view the project at: https://github.com/iDevelopper/PBPopupController/tree/spm-support

Here is my package.swift code:

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

import PackageDescription

let package = Package(
    name: "PBPopupController",
    platforms: [
        .iOS(.v11),
        .macOS(.v10_15)
    ],
    products: [
        // Products define the executables and libraries produced by a package, and make them visible to other packages.
        .library(
            name: "PBPopupController",
            targets: ["PBPopupController"]),
    ],
    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 which this package depends on.
        .target(
            name: "PBPopupController_ObjC",
            dependencies: [],
            path: "PBPopupController",
            exclude: [
                "PBPopupController/Swift",
                "Assets",
                "PBPopupController/Info.plist"
            ],
            publicHeadersPath: "include",
            
            cSettings: [
                .headerSearchPath("."),
                .headerSearchPath("ObjC"),
                .define("MY_SWIFT_PACKAGE")
                    
            ]
            
        ),
        .target(
            name: "PBPopupController",
            dependencies: ["PBPopupController_ObjC"],
            path: "PBPopupController",
            exclude: [
                "PBPopupController/ObjC",
                "Assets",
                "PBPopupController/Info.plist"
            ],
            
            cSettings: [
                .define("MY_SWIFT_PACKAGE"),
                //.headerSearchPath("."),
                //.headerSearchPath("ObjC")
            ],
            
            swiftSettings: [.define("MY_SWIFT_PACKAGE")]
        )
    ]
)

This is the UIViewController.Private.h

#import <UIKit/UIKit.h>

@class PBPopupBar;
@class PBPopupController;

@interface UIViewController (Private)

UIEdgeInsets _PBPopupSafeAreaInsets(id self);

void _LNPopupSupportFixInsetsForViewController(UIViewController* controller, BOOL layout, UIEdgeInsets additionalSafeAreaInsets);

- (void)_configurePopupBarFromBottomBar;

@end

@interface UINavigationController (Private)

- (void)pb_viewDidLayoutSubviews;

@end

And the .m, where I can't import the generated -Swift.h

#import "PBPopupController.h"

#ifdef MY_SWIFT_PACKAGE
#import "PBPopupController-Swift.h"
#else
#import <PBPopupController/PBPopupController-Swift.h>
#endif

...
1 Like

This looks like a question about using SPM, not developing SPM; I've moved it into the correct forum category.

You have to use @import when using SPM, e.g.

@import PBPopupController

But it looks like you have circular dependencies, which I think won't work.

Did you read the question correctly? Here, we are in the framework (the module) which is made with sources written in Swift and Objective-C. I want to be able to import moduleName-Swift.h (eg PBPopupController-Swift.h) generated by Xcode into the .m (eg UIViewController+Private.m) which is part of the framework.

You can't mix languages in targets with Objective-C, they need to be in their own targets (and currently cross-target dependencies won't work). See the SwiftPM docs for more information on creating C language targets. SwiftPM also won't generate a bridging header automatically as well.

i have a target for Objective-c code and another one for Swift code.

Do you mean I have to manually create PBPopuController.Swift.h or grab the PBPopuController.Swift.h generated when I compile without SPM and put it in the / include directory?

I know we cannot mix mixed language in a target, but I have two, one for ObjC and another for Swift.

I guess so.