SPM Using Prebuilt Libraries

Hello All,
I have a project that has several third-party packages that I do not have to source to. I know SPM prefers having the source distribution, but I don’t have that option. Some of these are delivered as Frameworks, some are a bunch of header files and a static library. From what I read about SPM, it has System Modules which let you link in system libraries, but I am unsure if that will work with these third party code libraries.

So I have three questions.

  • Should SPM find the frameworks if they are in the Source folder for the project? It seems that I must pass in the frameworks path to the build command to get them to link.
  • How do define my own wrapper for the loose library? I don’t think a system module will work because it must specify a fixed path in the module definition file. Is that correct?
  • Other modules I do have the source but it is in Objective-C. I am confused about how I tell SPM to build a Framework, and which files are the ones that should be exposed outside the module.

Thank you!

1 Like

Just to follow up on the last question, I created a simple Obj-C package with DeviceUtil. I use SPM to generate the Xcode project and change the IPHONEOS_DEPLOYMENT_TARGET=9.3, SDKROOT=β€œiphoneos” then build.

.
β”œβ”€β”€ DeviceUtil.xcodeproj
β”‚ β”œβ”€β”€ DeviceUtilTests_Info.plist
β”‚ β”œβ”€β”€ DeviceUtil_Info.plist
β”‚ β”œβ”€β”€ GeneratedModuleMap
β”‚ β”‚ └── DeviceUtil
β”‚ β”‚ └── module.modulemap
β”‚ β”œβ”€β”€ project.pbxproj
β”‚ β”œβ”€β”€ project.xcworkspace
β”‚ β”‚ β”œβ”€β”€ contents.xcworkspacedata
β”‚ β”‚ └── xcuserdata
β”‚ β”‚ └── possenb.xcuserdatad
β”‚ β”‚ └── UserInterfaceState.xcuserstate
β”‚ β”œβ”€β”€ xcshareddata
β”‚ β”‚ └── xcschemes
β”‚ β”‚ β”œβ”€β”€ DeviceUtil-Package.xcscheme
β”‚ β”‚ └── xcschememanagement.plist
β”‚ └── xcuserdata
β”‚ └── possenb.xcuserdatad
β”‚ └── xcschemes
β”‚ └── xcschememanagement.plist
β”œβ”€β”€ LICENSE.txt
β”œβ”€β”€ Package.resolved
β”œβ”€β”€ Package.swift
β”œβ”€β”€ README.md
β”œβ”€β”€ Rakefile
β”œβ”€β”€ Sources
β”‚ └── DeviceUtil
β”‚ β”œβ”€β”€ DeviceList.plist
β”‚ β”œβ”€β”€ DeviceUtil.m
β”‚ └── include
β”‚ └── DeviceUtil.h
└── Tests
└── DeviceUtilTests
└── DeviceUtilTests.swift

16 directories, 18 files

my Package.swift is this:

➜ DeviceUtil git:(SwiftPM) βœ— more Package.swift
// swift-tools-version:4.0
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
name: β€œDeviceUtil”,
products: [
// Products define the executables and libraries produced by a package, and make them visible to other packages.
.library(
name: β€œDeviceUtil”,
targets: [β€œDeviceUtil”]),
],
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: β€œDeviceUtil”,
dependencies: []),
publicHeadersPath: β€œDeviceUtil/include”),
.testTarget(
name: β€œDeviceUtilTests”,
dependencies: [β€œDeviceUtil”]),
]
)

I get a framework with the following:

.
β”œβ”€β”€ DeviceUtil.framework
β”‚ β”œβ”€β”€ DeviceUtil
β”‚ β”œβ”€β”€ Info.plist
β”‚ └── _CodeSignature
β”‚ └── CodeResources
β”œβ”€β”€ DeviceUtilPackageDescription.framework
β”‚ β”œβ”€β”€ Headers
β”‚ └── Modules
β”œβ”€β”€ DeviceUtilTests.swiftmodule
β”‚ β”œβ”€β”€ x86_64.swiftdoc
β”‚ └── x86_64.swiftmodule
└── DeviceUtilTests.xctest
β”œβ”€β”€ DeviceUtilTests
β”œβ”€β”€ Frameworks
β”‚ β”œβ”€β”€ libswiftCore.dylib
β”‚ β”œβ”€β”€ libswiftCoreAudio.dylib
β”‚ β”œβ”€β”€ libswiftCoreFoundation.dylib
β”‚ β”œβ”€β”€ libswiftCoreGraphics.dylib
β”‚ β”œβ”€β”€ libswiftCoreImage.dylib
β”‚ β”œβ”€β”€ libswiftCoreMedia.dylib
β”‚ β”œβ”€β”€ libswiftDarwin.dylib
β”‚ β”œβ”€β”€ libswiftDispatch.dylib
β”‚ β”œβ”€β”€ libswiftFoundation.dylib
β”‚ β”œβ”€β”€ libswiftMetal.dylib
β”‚ β”œβ”€β”€ libswiftObjectiveC.dylib
β”‚ β”œβ”€β”€ libswiftQuartzCore.dylib
β”‚ β”œβ”€β”€ libswiftSwiftOnoneSupport.dylib
β”‚ β”œβ”€β”€ libswiftUIKit.dylib
β”‚ β”œβ”€β”€ libswiftXCTest.dylib
β”‚ └── libswiftos.dylib
β”œβ”€β”€ Info.plist
β”œβ”€β”€ _CodeSignature
β”‚ └── CodeResources
└── libswiftRemoteMirror.dylib

9 directories, 25 files

I don’t see my public Header in the resulting framework.

Thanks,
– Paul

Ah, swift package generate-xcodeproj does not seem to add the Headers build phase and the defines module flag even though I added the publicHeadersPath.