I tried putting XcodeGen + SwiftPM

Introduction

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.

What is Swift PM

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.

The completed part related to Swift PM is excerpted. Click to open.

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.

xcode.png

Next, I will explain the detailed definition.

1. Define the Package to be handled in the entire project

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

Version notation

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

2. Describe the dependency in Target

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

important point

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.

Summary

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

I tried putting XcodeGen + SwiftPM
I tried putting Domino11 in CentOS7
I tried Spring.
I tried tomcat
I tried youtubeDataApi.
Microservices 101-I tried putting Docker on Ubuntu-
I tried refactoring ①
I tried FizzBuzz.
I tried JHipster 5.1
I tried putting Java on my Mac easily
[I tried] Spring tutorial
I tried running Autoware
I tried using Gson
I tried QUARKUS immediately
I tried using TestNG
I tried Spring Batch
I tried using Galasa
I tried node-jt400 (Programs)
I tried node-jt400 (execute)
I tried node-jt400 (Transactions)
I tried DI with Ruby
I tried node-jt400 (IFS write)
I tried node-jt400 (SQL Update)
I tried using azure cloud-init
I tried Spring State machine
I tried Drools (Java, InputStream)
I tried the Docker tutorial!
I tried node-jt400 (SQL query)
I tried using Java REPL
I tried source code analysis
I tried the FizzBuzz problem
I tried node-jt400 (SQL stream)
I tried node-jt400 (IFS read)
I tried Rails beginner [Chapter 2]
I tried UPSERT with PostgreSQL.
I tried BIND with Docker
I tried to verify yum-cron
I tried Jets (ruby serverless)
I tried metaprogramming in Java
I tried using anakia + Jing now
I tried Angular tutorial + SpringBoot + PostgreSQL
I tried to chew C # (indexer)
I tried something called recursive search
I tried using Spring + Mybatis + DbUnit
I tried using JOOQ with Gradle
[K8s] I tried communication between pods!
I tried morphological analysis with MeCab
I tried a little digdag docker.run_options
I tried to summarize iOS 14 support
I tried UDP communication with Java
I tried to explain the method
I tried the Java framework "Quarkus"
[Rails] I tried deleting the application
I tried using Java8 Stream API
I tried using JWT in Java
I tried GraphQL with Spring Boot
I tried to summarize Java learning (1)
I tried to understand nil guard
[Android] I tried using Coordinator Layout.
I tried installing CentOS 8 on ESXi 6.7
I tried Flyway with Spring Boot