Skip to content

Commit

Permalink
Repeat recipe for latest version of Xcode
Browse files Browse the repository at this point in the history
  • Loading branch information
fulldecent committed Dec 30, 2021
1 parent ea41648 commit 9dbb723
Show file tree
Hide file tree
Showing 13 changed files with 304 additions and 234 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# Swift 5 Module Template
Use this template as a starting point for any Swift 5 module that you want other people to include in their projects.

**STATUS: This template is ready and works in production code, compatible with Xcode 12.4 (12D4e)**
**STATUS: This template is ready and works in production code, compatible with Xcode 13.1 (13A1030d)**

![Swift 5 Module directory layout](https://user-images.githubusercontent.com/382183/66881876-63cca680-ef96-11e9-9dde-ae9d5c35350c.png)

Expand All @@ -14,7 +14,7 @@ Your new Swift 5 module will immediately have working, compilable code, and all
- Clean folder structure
- MIT license
- Testing as a standard
- Turnkey access to Travis CI
- Turnkey access to GitHub Actions testing
- Semantic versioning and a CHANGELOG
- Included example/demo app using SwiftUI

Expand Down
Binary file removed Recipe.assets/bad.png
Binary file not shown.
Binary file removed Recipe.assets/good.png
Binary file not shown.
86 changes: 34 additions & 52 deletions Recipe.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ This recipe may also be useful for other scenarios, for example maybe you want t

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

Some variables have spaces in them. That is intentional because it causes Xcode to use double quotes around them in its project configuration files.
Some variables have spaces in them. That is intentional because Xcode only uses robust quoting in its project configuration files (which we want) if the variables have spaces in them.

- `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-.]+$/).
- 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__`
Expand All @@ -35,13 +35,13 @@ Some variables have spaces in them. That is intentional because it causes Xcode

Complete all these instructions on the same calendar day.

Use Xcode Version 12.4 (12D4e). *This is the latest publicly released or Gold Master version.*
Use Xcode Version 13.1 (13A1030d). *This is the latest publicly released or Gold Master version.*

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 > Swift Package…
1. In Xcode, choose File > New > Package…
1. Navigate to your Desktop folder
2. Type the name `xxPROJECTxNAMExx`
3. Ensure "Create Git repository on my Mac" is unchecked
Expand All @@ -68,11 +68,10 @@ This recipe is also demonstrated in a YouTube flyover at https://youtu.be/ksYXtN

2. *Set the project options*
1. Set Product Name to "iOS Example"
2. Set Team to "NONE"
2. Set Team to "None"
3. Set Organization Identifier to `com.AN.ORGANIZATION.IDENTIFIER`
4. Set User Interface to "SwiftUI"
5. Set Life Cycle to "SwiftUI App"
6. Set Language to "Swift"
5. Set Language to "Swift"
7. Ensure “Use Core Data” and "Include Tests" are not selected
8. Click “Next"
3. *Create the project*
Expand All @@ -85,18 +84,16 @@ This recipe is also demonstrated in a YouTube flyover at https://youtu.be/ksYXtN

1. *Move iOS Example source code to a folder named "Sources"*
1. Open the file iOS Example.xcodeproj in Xcode
2. Enable the Project navigator on the left (folder icon)
3. Use the Project navigator to select the "iOS Example" folder (yellow icon)
2. Show the Project navigator on the left (folder icon)
3. Use the Project navigator to select the "iOS Example" folder (gray icon)
4. From the Project navigator, rename this folder as "Sources"
* :information_source: The Alamofire project uses [the folder name "Source"](https://github.com/Alamofire/Alamofire/tree/master/Example/Source) but we choose "Sources" here to be consistent with [the default of Swift Package Manager](https://github.com/apple/swift-package-manager/blob/b1a6f45aa9daed0c8a609d34af8f71cf4282ddd4/Sources/Workspace/InitPackage.swift#L256)
* :information_source: The Alamofire project uses [the folder name "Source"](https://github.com/Alamofire/Alamofire/tree/master/Example/Source) but we choose "Sources" here to be consistent with [the default of Swift Package Manager](https://github.com/apple/swift-package-manager/blob/4fd4df4275627ebc91a0f288c38658738cd9fa0f/Sources/Workspace/InitPackage.swift#L275)
2. *Fix the Info.plist file configuration and preview content folder (Xcode makes renaming folders a pain)*
1. Click "iOS Example" on the left (the blue icon)
2. Click the target "iOS Example" in the middle (white app icon)
3. Click "Build Settings" on the top of the middle
4. Enter "/Info" in the search box
5. Edit the "Info.plist File" from "iOS Example/Info.plist" to be "Sources/Info.plist”
6. Enter "Development Assets" in the search box
7. Edit the value from “iOS Example/Preview Content” to "Sources/Preview Content"
7. In the "Deployment" section, edit the value from “iOS Example/Preview Content” to "Sources/Preview Content"

### V. Add some functionality to your iOS Example application

Expand All @@ -110,28 +107,20 @@ This recipe is also demonstrated in a YouTube flyover at https://youtu.be/ksYXtN
### VI. Make your iOS Example application depend on your module

1. Open iOS Example.xcodeproj in Xcode
2. In Xcode, choose File > Add Packages...
1. Click "Add Local..."
2. Select the `xxPROJECTxNAMExx` folder on your desktop
3. Click "Add Package"

3. Drag the `xxPROJECTxNAMExx` folder on your desktop into the Xcode Project navigator at the bottom, be sure it is subordinated under iOS Example
:x:: ![bad](Recipe.assets/bad.png)

:white_check_mark:: ![good](Recipe.assets/good.png)

1. At the dialog "Do you want to save this project in a new workspace?" click "Save"
2. Navigate inside the iOS Example folder, in the `xxPROJECTxNAMExx` folder on your desktop
3. Set the name as "iOS Example"
4. Click Save
- ⚠️ Xcode will also show the iOS Example folder inside the `xxPROJECTxNAMExx` module. Swift packages are unable to specify excluded files. You can safely ignore that folder.
- :warning: Xcode has an error where this added dependency will show as ".." instead of the correct name. This discrepency can be safely ignored and it will show correctly the next time you open "iOS Example.xcworkspace".

4. *Add a build dependency*

1. Click "iOS Example" on the left (the blue icon) at the top-level (not subordinated to the `xxPROJECTxNAMExx` module)
2. Click the target "iOS Example" in the middle (white app icon)
3. Click "Build Phases" on the top
4. Open the section Link Binary With Libraries
5. Click the plus (+) button
6. Select `xxPROJECTxNAMExx` (the building icon)
7. Click "Add"
3. *Add a build dependency*
1. :information_source: You may or may not need to quit and reopen Xcode to proceed and see the required library, this is a known Xcode issue
1. Click "iOS Example" on the left (the blue icon)
1. Click the target "iOS Example" in the middle (white app icon)
1. Click "Build Phases" on the top
1. Open the section Link Binary With Libraries
1. Click the plus (+) button
1. Select `xxPROJECTxNAMExx` (the building icon)
1. Click "Add"

### VII. Add additional project management files to the module

Expand All @@ -141,14 +130,15 @@ This recipe is also demonstrated in a YouTube flyover at https://youtu.be/ksYXtN

```sh
cd ~/Desktop/xxPROJECTxNAMExx/
curl 'https://raw.githubusercontent.com/github/gitignore/master/Swift.gitignore' -o .gitignore
curl 'https://raw.githubusercontent.com/fulldecent/swift5-module-template/master/xxPROJECTxNAMExx/.travis.yml' -o .travis.yml
curl 'https://raw.githubusercontent.com/fulldecent/swift5-module-template/master/xxPROJECTxNAMExx/LICENSE' -o LICENSE
curl 'https://raw.githubusercontent.com/fulldecent/swift5-module-template/master/xxPROJECTxNAMExx/README.md' -o README.md
curl 'https://raw.githubusercontent.com/fulldecent/swift5-module-template/master/xxPROJECTxNAMExx/CHANGELOG.md' -o CHANGELOG.md
curl 'https://raw.githubusercontent.com/fulldecent/swift5-module-template/master/xxPROJECTxNAMExx/CONTRIBUTING.md' -o CONTRIBUTING.md
echo 'xxPROJECTxNAMExx.framework.zip' >> .gitignore
curl 'https://raw.githubusercontent.com/fulldecent/swift5-module-template/master/xxPROJECTxNAMExx/Tests/CheckCocoaPodsQualityIndexes.rb' -o Tests/CheckCocoaPodsQualityIndexes.rb
curl 'https://raw.githubusercontent.com/github/gitignore/master/Swift.gitignore' -o .gitignore
mkdir -p .github/workflows
curl 'https://raw.githubusercontent.com/fulldecent/swift5-module-template/master/xxPROJECTxNAMExx/.github/workflows/ci.yml' -o .github/workflows/ci.yml
curl 'https://raw.githubusercontent.com/fulldecent/swift5-module-template/master/xxPROJECTxNAMExx/LICENSE' -o LICENSE
curl 'https://raw.githubusercontent.com/fulldecent/swift5-module-template/master/xxPROJECTxNAMExx/README.md' -o README.md
curl 'https://raw.githubusercontent.com/fulldecent/swift5-module-template/master/xxPROJECTxNAMExx/CHANGELOG.md' -o CHANGELOG.md
curl 'https://raw.githubusercontent.com/fulldecent/swift5-module-template/master/xxPROJECTxNAMExx/CONTRIBUTING.md' -o CONTRIBUTING.md
echo 'xxPROJECTxNAMExx.framework.zip' >> .gitignore
curl 'https://raw.githubusercontent.com/fulldecent/swift5-module-template/master/xxPROJECTxNAMExx/Tests/CheckCocoaPodsQualityIndexes.rb' -o Tests/CheckCocoaPodsQualityIndexes.rb
```
### VIII. Remove identifying parts of your project

Expand All @@ -164,14 +154,6 @@ This recipe is also demonstrated in a YouTube flyover at https://youtu.be/ksYXtN
'{}' \;
```

2. Use Terminal.app to remove all references to development team IDs

```sh
find ~/Desktop/xxPROJECTxNAMExx -name project.pbxproj \
-exec sed -i '' -E -e '/DevelopmentTeam = /d
s/(DEVELOPMENT_TEAM = )[^;]+/\1""/' '{}' \;
```

## Taste testing

1. Open iOS Example.xcworkspace in Xcode
Expand All @@ -180,7 +162,7 @@ This recipe is also demonstrated in a YouTube flyover at https://youtu.be/ksYXtN

3. Choose Product > Run

* :white_check_mark: You should see a big white king (♔). That means it worked!
* :white_check_mark: You should see a big white king (♔) after a few moments. That means it worked!

4. *Compare with the distributed Swift 5 Module Template repository*

Expand All @@ -199,6 +181,6 @@ This recipe is also demonstrated in a YouTube flyover at https://youtu.be/ksYXtN
git diff
```

* :white_check_mark: You should see an empty screen (press <kbd>q</kbd> to close)
* :white_check_mark: You should see an empty screen indicating no differences (press <kbd>q</kbd> to close)
* :mega: If you see differences, please raise an issue in the project repository

172 changes: 172 additions & 0 deletions xxPROJECTxNAMExx/.github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
name: "xxPROJECTxNAMExx CI"

on:
push:
branches:
- main
paths:
- 'Source/**'
- 'Tests/**'
- '.github/workflows/**'
- 'Package.swift'
pull_request:
paths:
- 'Source/**'
- 'Tests/**'
- '.github/workflows/**'
- 'Package.swift'

concurrency:
group: ci
cancel-in-progress: true
# Keep this up to date with https://github.com/xxPROJECTxNAMExx/xxPROJECTxNAMExx/blob/master/.github/workflows/ci.yml
jobs:
macOS_5_3:
name: Test macOS 10.15 (5.3)
runs-on: macOS-10.15
env:
DEVELOPER_DIR: /Applications/Xcode_12.4.app/Contents/Developer
timeout-minutes: 10
steps:
- uses: actions/checkout@v2
- name: macOS 10.15 (5.3)
run: set -o pipefail && env NSUnbufferedIO=YES xcodebuild -project "xxPROJECTxNAMExx.xcodeproj" -scheme "xxPROJECTxNAMExx macOS" -destination "platform=macOS" clean test | xcpretty
macOS_5_4:
name: Test macOS 11 (5.4)
runs-on: macOS-11
env:
DEVELOPER_DIR: /Applications/Xcode_12.5.1.app/Contents/Developer
timeout-minutes: 10
steps:
- uses: actions/checkout@v2
- name: macOS 11 (5.4)
run: set -o pipefail && env NSUnbufferedIO=YES xcodebuild -project "xxPROJECTxNAMExx.xcodeproj" -scheme "xxPROJECTxNAMExx macOS" -destination "platform=macOS" clean test | xcpretty
macOS_5_5:
name: Test macOS 11 (5.5)
env:
DEVELOPER_DIR: /Applications/Xcode_13.1.app/Contents/Developer
timeout-minutes: 10
steps:
- uses: actions/checkout@v2
- name: macOS 11 (5.5)
run: set -o pipefail && arch -arch arm64e env NSUnbufferedIO=YES xcodebuild -project "xxPROJECTxNAMExx.xcodeproj" -scheme "xxPROJECTxNAMExx macOS" -destination "platform=macOS" clean test | xcpretty
Catalyst:
name: Test Catalyst
runs-on: macOS-11
env:
DEVELOPER_DIR: /Applications/Xcode_13.1.app/Contents/Developer
timeout-minutes: 10
steps:
- uses: actions/checkout@v2
- name: Catalyst
run: set -o pipefail && env NSUnbufferedIO=YES xcodebuild -project "xxPROJECTxNAMExx.xcodeproj" -scheme "xxPROJECTxNAMExx iOS" -destination "platform=macOS" clean test | xcpretty
iOS:
name: Test iOS 15
env:
DEVELOPER_DIR: /Applications/Xcode_13.1.app/Contents/Developer
timeout-minutes: 10
strategy:
matrix:
destination: ["OS=15.0,name=iPhone 13 Pro"]
steps:
- uses: actions/checkout@v2
- name: iOS - ${{ matrix.destination }}
run: set -o pipefail && arch -arch arm64e env NSUnbufferedIO=YES xcodebuild -project "xxPROJECTxNAMExx.xcodeproj" -scheme "xxPROJECTxNAMExx iOS" -destination "${{ matrix.destination }}" clean test | xcpretty
iOS_Concurrency:
name: Test Swift Concurrency
runs-on: macOS-11
env:
DEVELOPER_DIR: /Applications/Xcode_13.2.app/Contents/Developer
timeout-minutes: 10
strategy:
matrix:
destination: ["OS=15.2,name=iPhone 13 Pro"]
steps:
- uses: actions/checkout@v2
- name: iOS - ${{ matrix.destination }}
run: set -o pipefail && env NSUnbufferedIO=YES xcodebuild -project "xxPROJECTxNAMExx.xcodeproj" -scheme "xxPROJECTxNAMExx iOS" -destination "${{ matrix.destination }}" -enableThreadSanitizer NO clean test | xcpretty
tvOS:
name: Test tvOS
env:
DEVELOPER_DIR: /Applications/Xcode_13.1.app/Contents/Developer
timeout-minutes: 10
strategy:
matrix:
destination: ["OS=15.0,name=Apple TV"]
steps:
- uses: actions/checkout@v2
- name: tvOS - ${{ matrix.destination }}
run: set -o pipefail && arch -arch arm64e env NSUnbufferedIO=YES xcodebuild -project "xxPROJECTxNAMExx.xcodeproj" -scheme "xxPROJECTxNAMExx tvOS" -destination "${{ matrix.destination }}" clean test | xcpretty
watchOS:
name: Test watchOS
env:
DEVELOPER_DIR: /Applications/Xcode_13.1.app/Contents/Developer
timeout-minutes: 10
strategy:
matrix:
destination: ["OS=8.0,name=Apple Watch Series 7 - 45mm"]
steps:
- uses: actions/checkout@v2
- name: watchOS - ${{ matrix.destination }}
run: set -o pipefail && arch -arch arm64e env NSUnbufferedIO=YES xcodebuild -project "xxPROJECTxNAMExx.xcodeproj" -scheme "xxPROJECTxNAMExx watchOS" -destination "${{ matrix.destination }}" clean test | xcpretty
SPM:
name: Test with SPM
env:
DEVELOPER_DIR: /Applications/Xcode_13.1.app/Contents/Developer
timeout-minutes: 10
steps:
- uses: actions/checkout@v2
- name: SPM Test
run: arch -arch arm64e swift test -c debug
Linux:
name: Linux
runs-on: ubuntu-20.04
container:
image: swift:5.5.1-focal
timeout-minutes: 10
steps:
- uses: actions/checkout@v2
- name: SPM Linux build
run: swift build --build-tests -c debug
Linux_Nightly:
name: Linux Nightly
runs-on: ubuntu-20.04
container:
image: swiftlang/swift:nightly-focal
timeout-minutes: 10
steps:
- uses: actions/checkout@v2
- name: SPM Linux build
run: swift build --build-tests -c debug
Windows:
name: Windows
runs-on: windows-2019
timeout-minutes: 10
steps:
- name: "Clone Project"
uses: actions/checkout@v2
- uses: seanmiddleditch/gha-setup-vsdevenv@master
- name: Install Swift
run: |
Install-Binary -Url "https://swift.org/builds/swift-5.5.1-release/windows10/swift-5.5.1-RELEASE/swift-5.5.1-RELEASE-windows10.exe" -Name "installer.exe" -ArgumentList ("-q")
- name: Set Environment Variables
run: |
echo "SDKROOT=C:\Library\Developer\Platforms\Windows.platform\Developer\SDKs\Windows.sdk" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
echo "DEVELOPER_DIR=C:\Library\Developer" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
- name: Adjust Paths
run: |
echo "C:\Library\Swift-development\bin;C:\Library\icu-67\usr\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
echo "C:\Library\Developer\Toolchains\unknown-Asserts-development.xctoolchain\usr\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
- name: Install Supporting Files
run: |
Copy-Item "$env:SDKROOT\usr\share\ucrt.modulemap" -destination "$env:UniversalCRTSdkDir\Include\$env:UCRTVersion\ucrt\module.modulemap"
Copy-Item "$env:SDKROOT\usr\share\visualc.modulemap" -destination "$env:VCToolsInstallDir\include\module.modulemap"
Copy-Item "$env:SDKROOT\usr\share\visualc.apinotes" -destination "$env:VCToolsInstallDir\include\visualc.apinotes"
Copy-Item "$env:SDKROOT\usr\share\winsdk.modulemap" -destination "$env:UniversalCRTSdkDir\Include\$env:UCRTVersion\um\module.modulemap"
- name: SPM Windows build
shell: cmd
run: |
cd ${{ github.workspace}}
set SDKROOT=%SystemDrive%\Library\Developer\Platforms\Windows.platform\Developer\SDKs\Windows.sdk
%SystemDrive%\Library\Developer\Toolchains\unknown-Asserts-development.xctoolchain\usr\bin\swift-build.exe --build-tests -c debug -Xlinker /INCREMENTAL:NO -v
if not exist .build\x86_64-unknown-windows-msvc\debug\xxPROJECTxNAMExx.swiftmodule exit 1
19 changes: 0 additions & 19 deletions xxPROJECTxNAMExx/.travis.yml

This file was deleted.

7 changes: 0 additions & 7 deletions xxPROJECTxNAMExx/Tests/LinuxMain.swift

This file was deleted.

This file was deleted.

Loading

0 comments on commit 9dbb723

Please sign in to comment.