Alamofire: Build error with Swift Package Manager

Created on 15 Sep 2016  路  16Comments  路  Source: Alamofire/Alamofire

I'm using Xcode 8 and the official SPM. I try to use Alamofire through SPM:

import PackageDescription

let package = Package(
    name: "swift-playground",
    dependencies: [
        .Package(url: "https://github.com/Alamofire/Alamofire.git", majorVersion: 4)
    ]
)

However, swift build gives me a lot of errors:

Cloning https://github.com/Alamofire/Alamofire.git
HEAD is now at 5fe5b20 Added release notes to the CHANGELOG and bumped the version to 4.0.0.
Resolved version: 4.0.0
Compile Swift Module 'Alamofire' (17 sources)
/Users/skyline/Projects/Github/swift-playground/Packages/Alamofire-4.0.0/Source/DispatchQueue+Alamofire.swift:33:25: error: use of undeclared type 'TimeInterval'
    func after(_ delay: TimeInterval, execute closure: @escaping () -> Void) {
                        ^~~~~~~~~~~~
/Users/skyline/Projects/Github/swift-playground/Packages/Alamofire-4.0.0/Source/SessionDelegate.swift:111:50: error: 'URLSessionStreamTask' is only available on OS X 10.11 or newer
    open var streamTaskReadClosed: ((URLSession, URLSessionStreamTask) -> Void)?
                                                 ^
/Users/skyline/Projects/Github/swift-playground/Packages/Alamofire-4.0.0/Source/SessionDelegate.swift:111:50: note: add @available attribute to enclosing class
    open var streamTaskReadClosed: ((URLSession, URLSessionStreamTask) -> Void)?
                                                 ^
/Users/skyline/Projects/Github/swift-playground/Packages/Alamofire-4.0.0/Source/SessionDelegate.swift:114:51: error: 'URLSessionStreamTask' is only available on OS X 10.11 or newer
support

Most helpful comment

So I've spent some time on swift-users trying to get to the bottom of how this all is supposed to work and I think I have it pretty much figured out. Although there are still some serious shortcomings, you can at least get things to work. If you follow these steps, you can get things working.

Using SPM with Alamofire

1) Clone Alamofire locally and tag the master branch as 4.0.2

This is necessary to pick up a change I made in the Package.swift file that hasn't been released yet

2) Create an example project
3) Create a Package.swift file for your project similar to the following:

import PackageDescription

let package = Package(
    name: "SPMTester", 
    dependencies: [
        .Package(url: "/Users/cnoon/Desktop/Alamofire", "4.0.2")
    ]
)

4) Create your main.swift file in Sources

import Alamofire
import Foundation

Alamofire.request("https://httpbin.org/get").responseJSON { response in
    debugPrint(response)
    exit(0)
}

RunLoop.current.run()

5) Create a Configuration.xcconfig file to override the deployment target

SDKROOT = macosx
MACOSX_DEPLOYMENT_TARGET = 10.11

6) Generate the Xcode project for your new example

$ swift package generate-xcodeproj --verbose --xcconfig-overrides ./Configuration.xcconfig --output ./SPMTester.xcodeproj

7) Open the Xcode project, navigate to the project (not target) settings and delete the MACOSX_DEPLOYMENT_TARGET setting so the xcconfig value can be picked up by the project
8) Build and run

Here's an example of a small SPMTester project that I put together.


Summary

Now this is certainly still WAY more painful than it should be, but at least it's actually up and running. Once the community adds more features this process should get easier and easier.

All 16 comments

From those errors it appears you aren't using Xcode 8. Alamofire 4 requires Xcode 8. If you need to keep using Xcode 7, please use Alamofire 3.5.0.

I'm indeed using Xcode 8 and Swift 3. I think there may be some kind of bug in SPM.

I used Xcode8 too, got the same errors
(https://cloud.githubusercontent.com/assets/8327777/18612992/2221341e-7da0-11e6-9f58-73a57e8451d0.png)

Package Manager integration is broken? Similar issue as reported + and Swift seems confused by the tag if I also include AlamofireNetworkActivityIndicator. It will choose "4.0.0-beta.2" over "4.0.0". Perhaps the patch number should be increased?

@jshier Please consider reopening this. I think maybe #1549 is also related to this.

Also now #1582!

Hi everyone,

I agree this issue was closed pre-maturely without a proper response. With that said, please cut @jshier some slack. He's been plowing through 50+ issues every day since we've released. We all make mistakes from time to time.

As for this particular issue, the problem is that the SPM automatically uses a deployment target of 10.10 which doesn't work with AF 4 since AF 4 requires 10.11+. That's why you see all the URLSessionStreamTask errors when trying to compile.

I've reached out to swift-users to see if there's any way to customize this, but from what I can tell, there isn't. I'll file a feature request under the Swift bug reporter if this ends up being the case. If you can actually override it, I'll post back here with instructions.

Cheers. 馃嵒

So I've spent some time on swift-users trying to get to the bottom of how this all is supposed to work and I think I have it pretty much figured out. Although there are still some serious shortcomings, you can at least get things to work. If you follow these steps, you can get things working.

Using SPM with Alamofire

1) Clone Alamofire locally and tag the master branch as 4.0.2

This is necessary to pick up a change I made in the Package.swift file that hasn't been released yet

2) Create an example project
3) Create a Package.swift file for your project similar to the following:

import PackageDescription

let package = Package(
    name: "SPMTester", 
    dependencies: [
        .Package(url: "/Users/cnoon/Desktop/Alamofire", "4.0.2")
    ]
)

4) Create your main.swift file in Sources

import Alamofire
import Foundation

Alamofire.request("https://httpbin.org/get").responseJSON { response in
    debugPrint(response)
    exit(0)
}

RunLoop.current.run()

5) Create a Configuration.xcconfig file to override the deployment target

SDKROOT = macosx
MACOSX_DEPLOYMENT_TARGET = 10.11

6) Generate the Xcode project for your new example

$ swift package generate-xcodeproj --verbose --xcconfig-overrides ./Configuration.xcconfig --output ./SPMTester.xcodeproj

7) Open the Xcode project, navigate to the project (not target) settings and delete the MACOSX_DEPLOYMENT_TARGET setting so the xcconfig value can be picked up by the project
8) Build and run

Here's an example of a small SPMTester project that I put together.


Summary

Now this is certainly still WAY more painful than it should be, but at least it's actually up and running. Once the community adds more features this process should get easier and easier.

@jshier @cnoon Thanks for the feedback. Really appreciate it.

@cnoon When I tried generating the xcodeproj following those steps I got a Swift compiler error: "Illegal Instruction: 4".

Hm nvm, doesn't happen anymore. It's still not working 100%, though - while I can work on the project in Xcode, running "swift build" from the command line gives the same error as before.

@cnoon how does this work if I'm trying to get Alamofire building for iOS with swift package manager?

I'm working on https://github.com/Moya/Moya/pull/643, and I'm having trouble getting the project to swift build - the same issues that @skyline75489 was having in https://github.com/Alamofire/Alamofire/issues/1544#issue-177155724. Moya doesn't have a main.swift, so I'm not sure if the instructions you gave in https://github.com/Alamofire/Alamofire/issues/1544#issuecomment-250995345 apply here.

@cnoon so there is no known solution that supports swift build from the command line without using Xcode?

@cnoon thx for the temporary solution. +1 for this issue.

Dont work without RunLoop.current.run()
EXC_BAD_ACCESS on:

import Foundation
import Alamofire

Alamofire.request("https://httpbin.org/get").responseJSON { response in
  print("Request: \(String(describing: response.request))") // original url request
  print("Response: \(String(describing: response.response))") // http url response
  print("Result: \(response.result)") // response serialization result

  if let json = response.result.value {
    print("JSON: \(json)") // serialized json response
  }

  if let data = response.data, let utf8Text = String(data: data, encoding: .utf8) {
    print("Data: \(utf8Text)") // original server data as UTF8 string
  }
}

but fine with:

import Alamofire
import Foundation

Alamofire.request("https://httpbin.org/get").responseJSON { response in
  print("Request: \(String(describing: response.request))") // original url request
  print("Response: \(String(describing: response.response))") // http url response
  print("Result: \(response.result)") // response serialization result

  if let json = response.result.value {
    print("JSON: \(json)") // serialized json response
  }

  if let data = response.data, let utf8Text = String(data: data, encoding: .utf8) {
    print("Data: \(utf8Text)") // original server data as UTF8 string
  }

  exit(0)
}

RunLoop.current.run()

Why?

That's a requirement of using asynchronous code inside a Swift command line tool: you must have something spin the run loop. I prefer to use dispatchMain() to startup the main queue.

In the future, this type of question is best suited for a forum like StackOverflow.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

matthijsotterloo picture matthijsotterloo  路  3Comments

tobiasoleary picture tobiasoleary  路  3Comments

dpstart picture dpstart  路  3Comments

filippovdev picture filippovdev  路  3Comments

borek2 picture borek2  路  3Comments