Is it possible to produce an XCFramework from a Swift Package with dependencies? - swift

I want to be able to take an internal SPM package, which depends on several other internal (and one external) SPM packages, and compile it into an XCFramework, using a series of xcodebuild like you would for a framework project. For example, I have PackageB, which references PackageA, and I'm trying to build PackageB.xcframework. The first step would be:
xcodebuild -scheme PackageB -destination "generic/platform=iOS" -configuration Release ARCHS="arm64" BUILD_DIR="./Build
The tool's output indicates that the dependency packages are being resolved, but they are then not recognized by the compiler (i.e. code in PackageB which references PackageA will not compile because PackageA is unknown at that point).
Thanks for any pointers.

You can create xcframework from swift package by using swift-create-xcframework command line tool, there is also GitHub action available for this.
If you don't want to use this tool, you can generate Xcode project by using swift package generate-xcodeproj command:
OVERVIEW: Generates an Xcode project. This command will be deprecated soon.
USAGE: swift package generate-xcodeproj
OPTIONS:
--xcconfig-overrides
Path to xcconfig file
--output Path where the Xcode project should be generated
--legacy-scheme-generator
Use the legacy scheme generator
--watch Watch for changes to the Package manifest to
regenerate the Xcode project
--skip-extra-files Do not add file references for extra files to the
generated Xcode project
--version Show the version.
-h, -help, --help Show help information.
and then create xcframework with the generated Xcode project.

Related

Is it possible to get Xcode to build dylibs for a SwiftPM project?

I am building a library using SwiftPM, and it is important for my use case that I link dynamically, so I have a dylib product.
.library(name: "ExampleLib", type: .dynamic, targets: ["ExampleLib"])
When I build the library with swift build, there is a libExampleLib.dylib produced in the .build folder.
However, if I open the Package.swift file with Xcode and build like usual, there are no .dylib files produced in the DerivedData folder. This causes all my tests which rely on dynamic linking to fail because the dylib is not in the products directory.
Is there something I can do to convince Xcode to build the dylibs, or is it necessary to build from the command line?

How to use CoreML Model in a Swift Package Manager macOS Command Line App?

I'm trying to create a command line app that runs on macOS and uses CoreML. I am using Swift Package Manager. Here are some steps to reproduce the problem:
Run
swift package init --type executable
Move a CoreML model into the Sources folder, for example, CNNEmotions.mlmodel
In main.swift, write
print(CNNEmotions()) // CNNEmotions is the name of the generated model type
I know that CoreML only runs on macOS and iOS., so in Package.swift, I added a platform parameter:
let package = Package.init(
name: "MyProject",
platforms: [
.macOS(.v10_13), // this is the minimum macOS version that supports CoreML
],
...
Run
swift build
And there will be an error saying that CNNEmotions is an unresolved identifier.
If I do swift package generate-xcodeproj and open up the project in Xcode, I can see that the .mlmodel file is not added to the project at all!
This person on Apple Forums seems to also be in the same situation as me, but there are no answers to their question...
How can I make SPM work with mlmodels?
Just when I thought it's the end of the world, I found that if I add the .mlmodel file into the project in Xcode, the program can compile and run successfully. But the problem with building it in Xcode is that it's quite inconvenient. It doesn't produce an executable in a convenient location (I have to go all the way to the DerivedData folder to find it). To be honest, I would just like a convenient command to build & run it, like swift build. This is my ultimate goal.

Convert XCodeProj to Package.swift

I have recently inherited a swift project and would prefer to do my development on a Linux VM, rather then the under powered Mac I have. I have found lots of tutorials on how to got from a Package.swift to a xcodeproj. But I haven't found anything to go the other direction (xcodeproj to Package.swift). It seems that I need the Package.swift to be able to use the swift cli (swift build).
Is there a way to build without the Package.swift file?
Is there a way to do this that I haven't found?
Is there a technical reason that we can't go from a xcodeproj to a Package.swift?
1./2.
A Package.swift file is internally translated to a set of swiftc commands.
If you run swift build -v (verbose) on a fully working Swift package, you can see the commands that are being run. Using these commands, you may be able to figure out how to compile any collection of Swift sources without a Package.swift.
For a framework, one command could look something like this:
swiftc -module-name TestPackage -emit-dependencies -emit-module -c Path/to/Sources/*.swift -Onone -g -enable-testing -j8 -DSWIFT_PACKAGE -DDEBUG -Xfrontend -color-diagnostics
When compiling an executable, there may be additional commands to link the standard library, etc.
3.
The feature set of Xcode far exceeds the capabilities of Swift packages (e.g. .app bundles, Storyboards, Metal source files, ObjC, C, C++, etc.)
However, you can convert your command line project to a Swift package by running swift package init --type library|executable to create a Package.swift file. You can then specify a path parameter for the target in the Package.swift file:
.target(name: "YourTarget", path: "Path/To/Your/Swift/Files")

`swift package generate-xcodeproj` fails with "Swift does not support the SDK"

I'm having trouble running swift package generate-xcodeproj. I created my package like this:
$ /Applications/Xcode9.4.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift package init --type executable
(as I have many Xcode versions installed I explicitly targeted a swift binary when running the command so that I don't need to xcode-select all the time)
This created a Package.swift with the version header // swift-tools-version:4.0.
Now, when I run swift package generate-xcodeproj I get a fatal error:
$ /Applications/Xcode9.4.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift package generate-xcodeproj
/Users/max.chuquimia/Desktop/xcode/MyPackage: error: manifest parse error(s):
<unknown>:0: error: Swift does not support the SDK 'MacOSX10.12.sdk'
No .xcodeproj is generated. Why is this occurring?
It seems the problem is the $DEVELOPER_DIR environment variable is wrong - it should also be made to point to the Xcode version that the swift binary resides in.
$ DEVELOPER_DIR=/Applications/Xcode9.4.1.app/Contents/Developer /Applications/Xcode9.4.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift package generate-xcodeproj

Module compiled with swift 3.0 cannot be imported in Swift 3.0.1

I upgraded Xcode to 8.1 GM and am now getting the below error for SwiftyJSON. Other imported frameworks seem to work. Is there a way to force this to work in Swift 3 until SwiftyJSON upgrades their framework? I used Carthage to import/update frameworks. I also tried changing Use Legacy Swift language version On and Off to no avail.
Module compiled with Swift 3.0 cannot be imported in Swift 3.0.1:
Modules/SwiftyJSON.swiftmodule/arm64.swiftmodule
SwiftyJson is being downloaded precompiled by carthage. The precompiled download is with Swift Version 3.0. That makes the compiler complain that the version is not correct. Using the following command:
carthage update --platform iOS --no-use-binaries
SwiftyJson (and all other frameworks within Carthage) will be compiled locally using the local version of Swift (3.0.1) and the compiler will not complain anymore.
Remove the app chache from DerivedData, and rebuild. the error may be fixed.
The DerivedData path like this:
~/Library/Developer/Xcode/DerivedData/
Make sure you've placed the new XCode 8.1 GM package in your Applications folder. We ran into this issue when one of us was running Carthage to update our dependencies, but had not replaced the XCode old 8.0 application in the applications folder (8.1 GM was running off the Desktop).
You want to make sure that when you run the following in terminal: xcrun swift -version that it returns Apple Swift version 3.0.1.
Updating default Xcode to new one on terminal worked for me.
Step 1 : Use following command to update Xcode version to latest on Terminal. Ref
sudo xcode-select -switch <path/to/>Xcode.app
Step 2 : Now try carthage update command
carthage update --platform iOS
Just to give the latest updates:
Carthage has released version 0.20 on Feb 27, 2017.
Carthage now only uses the pre-build binary if available pre-build binary is compatible.
That is being said, you no longer have to use: --no-use-binaries to avoid incompatible pre-build framework.
So make sure that you have carthage version greater than 0.20 and simply do:
carthage update --platform iOS
Just like #zirinisp said:
You can Using the following command:carthage update --platform iOS --no-use-binaries
Using the following command:xcrun swift -version to see the Swift version
Do this: Xcode->preferences->locations to clear the derived data and archives data, the most important to change the command line tools to "Xcode 8.1"
Using the following command:xcrun swift -version,you can see the swift version is 3.0.1
Set Use Legacy Swift Language Version = NO
I hope it will help you
Move the beta/GM version if the Xcode to /Applications folder and name it Xcode-beta
Check the output of:
xcrun swift --version
by running this command in terminal, its output should match with the swift version you want the app to compile, because Carthage uses output of this command, to determine the local Swift version.
Update Xcode version to latest on Terminal by running following command:
sudo xcode-select -s /Applications/Xcode-beta.app/
Build the libraries for iOS and prevents Carthage from downloading existing (yet incompatible) precompiled binaries, by running following command:
carthage update --platform iOS --no-use-binaries
Clean & Build
I had exactly the same issue with the library XCTest_Gherkin, what it worked for me was:
Product -> Scheme -> XCTest-Gherkin
Product -> Build
Hope it helps. I am using Cocoapods.
In Xcode Build Settings make sure your Framework Search Paths contain the appropriate Carthage Build folder:
$(inherited)
$(PROJECT_DIR)/Carthage/Build/iOS