swiftlang / swift-package-manager

The Package Manager for the Swift Programming Language
Apache License 2.0
9.71k stars 1.33k forks source link

Binary Target infer default header search path #7626

Open pyretttt opened 3 months ago

pyretttt commented 3 months ago

Description

Yet multi target targets are available. There is necessity to create middleware obc++ target to bridge c++ interfaces and other code under development. Despite getting swift - c++ interop. Sometimes we still forced to use objc++ mostly because of legacy.

Having said that I suppose that there should be some option to specify search path of c++ binary target. Structure of our xcframework is following:

- A.xcframework
  - ios-arm64
    - A.framework
      - Headers
      - Info.plist
      - A
      ...
  - ios-arm64_x86_64-simulator
    ....
  - Info.plist

Expected behavior

Considering

    targets: [
        .target(
            name: "sdk",
            dependencies: [.target(name: "sdk-objc++")]
        ),
        .target(
            name: "sdk-objc++",
            dependencies: [.targetItem(name: "LibCpp", condition: .none)],
            cxxSettings: [
                .headerSearchPath("../../LibCpp.xcframework/ios-arm64/LibCpp.framework/Headers"),
            ]
        ),
        .binaryTarget(
            name: "LibCpp",
            path: "LibCpp.xcframework"
        )
    ],
    cxxLanguageStandard: .cxx14

I expect specifying of .targetItem(name: "LibCpp", condition: .none) would by default infer path to default headers path for Darwin frameworks (ie ../../LibCpp.xcframework/ios-arm64/LibCpp.framework/Headers) or path of dependency specified with URL.

Actual behavior

Forced to specify local dependency headers path. I'm also not sure is there an option to specify searchPath for remote dependency.

Now only option to work with c++ headers is embedding them into modulemap.map I suppose. But it won't help in case any of imported headers has include of another header, because it expects well known directory structure.

Steps to reproduce

  1. Try to build package with similar manifest.
    let package = Package(
    name: "sdk",
    products: [
        // Products define the executables and libraries a package produces, making them visible to other packages.
        .library(
            name: "sdk",
            targets: ["sdk"]),
    ],
    targets: [
        .target(
            name: "sdk",
            dependencies: [.target(name: "sdk-objc++")]
        ),
        .target(
            name: "sdk-objc++",
            dependencies: [.targetItem(name: "LibCpp", condition: .none)],
            cxxSettings: [
                .headerSearchPath("../../LibCpp.xcframework/ios-arm64/LibCpp.framework/Headers"),
            ]
        ),
        .binaryTarget(
            name: "LibCpp",
            path: "LibCpp.xcframework"
        )
    ],
    cxxLanguageStandard: .cxx14
    )

Where LibCpp some c++ framework with Headers dir.

Swift Package Manager version/commit hash

swift-tools-version: 5.9

Swift & OS version (output of swift --version && uname -a)

swift-driver version: 1.87.3 Apple Swift version 5.9.2 (swiftlang-5.9.2.2.56 clang-1500.1.0.2.5) Target: arm64-apple-macosx13.0 Darwin s-a-bakulin-x 22.6.0 Darwin Kernel Version 22.6.0: Fri Sep 15 13:41:28 PDT 2023; root:xnu-8796.141.3.700.8~1/RELEASE_ARM64_T6000 arm64

ryansburgoyne commented 3 weeks ago

I have run into this as well. The only workaround I found was to copy the headers into LibCppHeaders at the root of the package and use .headerSearchPath("../../LibCppHeaders").