In the previous article (https://qiita.com/doi_daihei/items/594c15282e70c7d9235b), I talked about a project that introduced XcodeGen. The project introduced in that article used CocoaPods and Carthage to manage the library. I think it's time to move to Swift Package Manager (hereinafter SwiftPM) introduced in Xcode 9, and I will talk about the knowledge when I tried to change the library management to Swift PM without changing XcodeGen.
For the explanation of XcodeGen, please refer to Previous article and omit it in this article.
It is a tool to manage packages configured with Swift like CocoaPods and Carthage. The other strengths are as follows.
-** Made by Apple ** --There is IDE support for Xcode
Since it is made by Apple, it has a high affinity around tools including Xcode, so I think it is better to use Swift PM in the future.
Before Xcode11, it was managed by the source code Package.swift and could only handle tool apps and server-side source code, but with the introduction of IDE support from Xcode11, it can now be completed with Xcode.
Libraries that support SwiftPM can basically be used for projects that have Package.swift in the project root.
XcodeGen+SwiftPM
Before I started, I thought I would need Package.swift.
However, when I finished, I was able to complete it with only the XcodeGen project configuration file project.yml.
project.yml
name: test
packages: #First define the Package handled by SwiftPM
  Reusable:
    url: https://github.com/AliSoftware/Reusable
    exactVersion: 4.1.1 #Version specification version is OK
  RxSwift:
    url: https://github.com/ReactiveX/RxSwift
    minorVersion: 5.1.1 #Specified minor version ex: 5.Any 1 system is OK
  Action:
    url: https://github.com/RxSwiftCommunity/Action
    branch: master #Branch specification
  RxSwiftExt:
    url: https://github.com/RxSwiftCommunity/RxSwiftExt
    minVersion: 5.1.0 #Specified version or higher
    maxVersion: 5.2.0 #Less than the specified version
  APIKit:
    url: https://github.com/ishkawa/APIKit
    revision: b95a941 #Commit specification
  Rswift:
    url: https://github.com/mac-cain13/R.swift.Library
    majorVersion: 5.2.0 #Specified major version from is OK ex:Any 5 series is OK
  SwiftyUserDefaults:
    url: https://github.com/sunshinejr/SwiftyUserDefaults
    from: 5.0.0 #Synonymous with majorVersion
#The rest is the same writing style and detailed settings, so I will omit it
targets:
  test:
    type: application
    platform: iOS
    scheme: {}
    deploymentTarget: "13.0"
    sources:
      - test
      - path: "test/Resources/R.generated.swift"
        optional: true
        type: file
    dependencies:
      - target: TestFramework # Embedded Framework
      - package: Action
      - package: Reusable
      - package: Rswift
      - package: RxSwift 
        product: RxCocoa #Specify RxCocoa inside RxSwift
      - package: RxSwift
        product: RxRelay #Specify RxRelay inside RxSwift
      - package: RxSwift
      - package: RxSwiftExt
    #The rest is around the setting, so I will omit it in this article
  TestFramework:
    type: framework
    platform: iOS
    scheme: {}
    deploymentTarget: "13.0"
    sources:
      - TestFramework
    dependencies:
      - package: APIKit
      - package: SwiftyUserDefaults
    #The rest is around the setting, so I will omit it in this article
If you want to check the overall settings, see here.
After that, hit xcodegen at the project root and a project with the SwiftPM library dependency resolved will be generated.
When you open the generated project with Xcode, each fetch starts, and after a while, you can check it on Project Navigator as follows.

Next, I will explain the detailed definition.
First, define each package to be handled in the entire project by referring to XcodeGen Document.
You can specify the remote destination with url, and then specify the version etc. in detail with the parameters after that.
This time, there was nothing to handle locally, but it can be introduced as described in the above document.
project.yml
name: test
packages: #First define the Package handled by SwiftPM
  Reusable:
    url: https://github.com/AliSoftware/Reusable
    exactVersion: 4.1.1 #Version specification version is OK
  RxSwift:
    url: https://github.com/ReactiveX/RxSwift
    minorVersion: 5.1.1 #Specified minor version ex: 5.Any 1 system is OK
  Action:
    url: https://github.com/RxSwiftCommunity/Action
    branch: master #Branch specification
  RxSwiftExt:
    url: https://github.com/RxSwiftCommunity/RxSwiftExt
    minVersion: 5.1.0 #Specified version or higher
    maxVersion: 5.2.0 #Less than the specified version
  APIKit:
    url: https://github.com/ishkawa/APIKit
    revision: b95a941 #Commit specification
  Rswift:
    url: https://github.com/mac-cain13/R.swift.Library
    majorVersion: 5.2.0 #Specified major version from is OK ex:Any 5 series is OK
  SwiftyUserDefaults:
    url: https://github.com/sunshinejr/SwiftyUserDefaults
    from: 5.0.0 #Synonymous with majorVersion
  #The rest is the same writing style and detailed settings, so I will omit it
| Notation | Specified content | 
|---|---|
majorVersion: n.m.i or from: n.m.i | 
Any specified major version n series is OK | 
minorVersion: n.m.i | 
Specified minor version Any n.m system is OK | 
exactVersion: n.m.i or version: n.m.i | 
Version specification version is OK | 
branch: main | 
Specified branch | 
revision: xxxxxx | 
Commit specification | 
Next, in each Target, describe the dependency by referring to the XcodeGen document.
As a point, if the library is in a project like RxSwift, you need to specify it further.
project.yml
targets:
  test:
    type: application
    platform: iOS
    scheme: {}
    deploymentTarget: "13.0"
    sources:
      - test
      - path: "test/Resources/R.generated.swift"
        optional: true
        type: file
    dependencies:
      - target: TestFramework # Embedded Framework
      - package: Action
      - package: Reusable
      - package: Rswift
      - package: RxSwift 
        product: RxCocoa #Specify RxCocoa inside RxSwift
      - package: RxSwift
        product: RxRelay #Specify RxRelay inside RxSwift
      - package: RxSwift
      - package: RxSwiftExt
    #The rest is around the setting, so I will omit it in this article
  TestFramework:
    type: framework
    platform: iOS
    scheme: {}
    deploymentTarget: "13.0"
    sources:
      - TestFramework
    dependencies:
      - package: APIKit
      - package: SwiftyUserDefaults
    #The rest is around the setting, so I will omit it in this article
It is also described in here, but if you go from [File]-> [Swift Packages]-> [Add Package Dependency ...] from Xcode, ProjectName.xcodeproj/project.xcworkspace/xcshareddata/Generated in swiftpm/Package.resolved.
If you install a new library from Xcode, you need to drop the above file to be updated into project.yml, which is annoying.
Package.resolved defines the actual version information. It's like Podfile.lock in CocoaPods.The installation itself can be easily done by looking at the XcodeGen documentation. Since it can be managed on the IDE from Xcode 11, it can be expected to improve efficiency and reduce management costs.
However, as mentioned in the notes, the work of dropping it in project.yml is more troublesome than others.
After all, I think that there are few compatible ones compared to CocoaPods and Carthage.
So, I think it's a good idea to introduce a small project that requires less library dependency.
Recommended Posts