Skip to content

Latest commit

 

History

History
181 lines (125 loc) · 8.85 KB

File metadata and controls

181 lines (125 loc) · 8.85 KB

Recipe

This recipe cites all best practices we follow and documents exactly how we created the Swift 6 Module Template which is the xxPROJECTxNAMExx folder in this repo.

Please follow along and you should create a template that is identical to the one we provided. If this recipe is not perfect (or your result is different from our template in any way) then please submit an issue or pull request.

This recipe may also be useful for other scenarios, for example maybe you want to make a project that has the Example app using storyboards instead of SwiftUI.

Ingredients

During the steps of this recipe we enter specific values where needed. These are chosen carefully so that the ./configure.swift script can later find and replace these values in the template to create your project.

  • xxPROJECTxNAMExx

    • This must be a valid C99 extended identifier (otherwise the Xcode check dependencies step fails). It cannot contain spaces.
    • This must also be a Uniform Target Identifier (/^[a-zA-Z0-9-.]+$/).
    • If this contains the characters - or . then they will be transliterated to _ for file names.
  • __ORGANIZATION_NAME__

    • This intentionally has a space which causes Xcode to use double quotes in its project configuration files.
  • com.AN.ORGANIZATION.IDENTIFIER

  • __AUTHOR_NAME__

    • This intentionally has a space which causes Xcode to use double quotes in its project configuration files.
  • __TODAYS_DATE__

  • __TODAYS_YEAR__

  • __GITHUB_USERNAME__

Steps

Complete all these instructions on the same calendar day.

Use Xcode version 26.0.1 (17A400). This is the latest publicly released or Gold Master version.

A previous version of this recipe is also demonstrated in a YouTube flyover at https://youtu.be/ksYXtNn8lhE (15 minutes).

I. Create a package for your module

  1. In Xcode, choose File > New > Package…
    1. Choose Multiplatform > Library > Library, and click "Next"
    2. For testing system, select Swift Testing, and click "Next"
    3. Navigate to your Desktop folder
    4. Type the name xxPROJECTxNAMExx
    5. Ensure "Create Git repository on my Mac" is unchecked
    6. Click “Create"

II. Add some functionality to the module

  1. Use Terminal.app to insert some files into the project

    cd ~/Desktop/xxPROJECTxNAMExx/Sources/xxPROJECTxNAMExx/
    curl 'https://raw.githubusercontent.com/fulldecent/swift6-module-template/main/xxPROJECTxNAMExx/Sources/xxPROJECTxNAMExx/xxPROJECTxNAMExx.swift' -o xxPROJECTxNAMExx.swift
    curl 'https://raw.githubusercontent.com/fulldecent/swift6-module-template/main/xxPROJECTxNAMExx/Sources/xxPROJECTxNAMExx/White%20King.swift' -o White\ King.swift
    curl 'https://raw.githubusercontent.com/fulldecent/swift6-module-template/refs/heads/main/xxPROJECTxNAMExx/Tests/xxPROJECTxNAMExxTests/xxPROJECTxNAMExxTests.swift' -o ../../Tests/xxPROJECTxNAMExxTests/xxPROJECTxNAMExxTests.swift
  2. Quit Xcode :information_source: This is a workaround for a bug introduced in Xcode 16.4 (16F6) where opening a Swift package then also opening a project containing that package at the same time produces the error:

    Compiled module was created by a different version of the compiler '6.1.0.110.21'

    ℹ️ This is also a separate workaround for a separate bug introduced in Xcode 16.4 (16F6) which reproducibly crashes the program at this step if you attempt to build the Example project and then close that window.

III. Create a Swift project for your Example application

  1. In Xcode, choose File > New > Project…
    1. Choose a template
      1. Click iOS > Application > App, and click "Next"
    2. Set the project options
      1. Set Product Name to "Example"
      2. Set Team to "None"
      3. Set Organization Identifier to com.AN.ORGANIZATION.IDENTIFIER
      4. Set User Interface to "SwiftUI"
      5. Set Language to "Swift"
      6. Set Testing System to "Swift Testing with XCTest UI Tests"
      7. Set Storage to "None"
      8. Ensure "Host in CloudKit" is not selected
      9. Click “Next"
    3. Create the project
      1. Ensure “Create Git Repository on my Mac" is not selected
      2. Ensure "Add to" is “Don’t add to any project or workspace"
      3. Select the folder xxPROJECTxNAMExx on the desktop (don't double click it)
      4. Click “Create"

IV. Use the directory layout structure like Alamofire

  1. Move Example source code to a folder named "Sources" ℹ️ The Alamofire project uses the folder name "Source" but we choose "Sources" here to be consistent with the default of Swift Package Manager.
    1. Open the file Example.xcodeproj in Xcode (it's on your desktop, in the xxPROJECTxNAMExx > Example folder)

    2. Show the Project navigator on the left (folder icon)

    3. Use the Project navigator to select the "Example" folder (blue icon)

    4. From the Project navigator, rename this folder as "Sources"

V. Add some functionality to your Example application

  1. Use Terminal.app to insert some files into the project

    cd ~/Desktop/xxPROJECTxNAMExx/Example/Sources
    curl 'https://raw.githubusercontent.com/fulldecent/swift6-module-template/main/xxPROJECTxNAMExx/Example/Sources/ContentView.swift' -o ContentView.swift

    ℹ️ You will see "Module compiled with Swift 6.1.2 cannot be imported by the Swift 6.2 compiler", but we will resolve this in the step "make your example application depend on your module" below.

VI. Make your example application depend on your module

  1. Open Example.xcodeproj in Xcode
  2. In Xcode, choose File > Add Package Dependencies...
    1. Click "Add Local..."
    2. Select the folder xxPROJECTxNAMExx on the desktop (don't double click it)
    3. Click "Add Package"
    4. In the choose package products, set the "add to target" to "Example", and click "Add Package"

VII. Add additional project management files to the module

These files represent best practices which every open source Swift module author should adopt for published code.

  1. Use Terminal.app to add additional files to the project

    cd ~/Desktop/xxPROJECTxNAMExx/
    curl 'https://raw.githubusercontent.com/github/gitignore/main/Swift.gitignore' -o .gitignore
    mkdir -p .github/workflows
    curl 'https://raw.githubusercontent.com/fulldecent/swift6-module-template/main/xxPROJECTxNAMExx/.github/workflows/ci.yml' -o .github/workflows/ci.yml
    curl 'https://raw.githubusercontent.com/fulldecent/swift6-module-template/main/xxPROJECTxNAMExx/LICENSE' -o LICENSE
    curl 'https://raw.githubusercontent.com/fulldecent/swift6-module-template/main/xxPROJECTxNAMExx/README.md' -o README.md
    curl 'https://raw.githubusercontent.com/fulldecent/swift6-module-template/main/xxPROJECTxNAMExx/CHANGELOG.md' -o CHANGELOG.md
    curl 'https://raw.githubusercontent.com/fulldecent/swift6-module-template/main/xxPROJECTxNAMExx/CONTRIBUTING.md' -o CONTRIBUTING.md

VIII. Remove identifying parts of your project

This step allows everybody to achieve byte-for-byte consistency with the published Swift 6 Module Template but otherwise provides no value to you.

  1. Use Terminal.app to find and replace all occurrences of hard-coded strings with template variables

    find -E ~/Desktop/xxPROJECTxNAMExx \
            -type f -name '*.swift' -exec sed -i '' -E -e '
              s-(// +Created by ).*( on ).*\.-\1__AUTHOR_NAME__\2__TODAYS_DATE__.-
              s-(// +Copyright © ).*-\1__TODAYS_YEAR__ __ORGANIZATION_NAME__. All rights reserved.-' \
              '{}' \;

Taste testing

  1. Open Example.xcodeproj in Xcode

  2. Use the scheme navigator to select Example and the latest iPhone version simulator

  3. Choose Product > Run :white_check_mark: You should see a big white king (♔) after a few moments. That means it worked!

    ℹ️ You may see a nag screen in your app about Apple Intelligence. This advertisement is installed by Apple and Apple prevents you from removing it.

  4. Compare with the distributed Swift 6 Module Template repository

    1. Use Terminal.app to clone the repository to your Developer folder

      git clone https://github.com/fulldecent/swift6-module-template.git ~/Developer/swift6-module-template
    2. Compare the distributed version with your version

      cd ~/Developer/swift6-module-template
      rm -rf xxPROJECTxNAMExx
      cp -r ~/Desktop/xxPROJECTxNAMExx .
      git diff
      • ✅ You should see an empty screen indicating no differences (press q to close)
      • 📣 If you see differences, please raise an issue in the project repository