├── .gitignore ├── README.md ├── SwiftLint ├── LICENSE └── swiftlint ├── SwiftlintBuildPhase.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── xcshareddata │ └── xcschemes │ │ └── SwiftlintBuildPhase.xcscheme └── xcuserdata │ └── istvanbalogh.xcuserdatad │ └── xcschemes │ └── xcschememanagement.plist ├── SwiftlintBuildPhase ├── AppDelegate.swift ├── Assets.xcassets │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── Info.plist ├── SceneDelegate.swift └── ViewController.swift ├── SwiftlintBuildPhaseTests └── SwiftlintBuildPhaseTests.swift ├── SwiftlintBuildPhaseUITests ├── SwiftlintBuildPhaseUITests.swift └── SwiftlintBuildPhaseUITestsLaunchTests.swift └── generate_swifttlint_filelist.sh /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SwiftLint Build Phases with Xcode Input Output Files 2 | 3 | This repository contains an example project demonstrating how to set up SwiftLint build phases using Xcode's input-output files feature by defining a pre-build action to generate the input file list for SwiftLint. This setup solves the new warning introduced in Xcode 14: 4 | 5 | `warning build: Run script build phase 'SwiftLint' will be run during every build because it does not specify any outputs. To address this warning, either add output dependencies to the script phase, or configure it to run in every build by unchecking "Based on dependency analysis" in the script phase.` 6 | 7 | Other than solving the warning, this will also improve the speed of incremental builds in Xcode. 8 | 9 | Table of contents 10 | ----------------- 11 | 12 | * [What is SwiftLint?](#what-is-swiftlint) 13 | * [Why use Xcode input-output files?](#why-use-xcode-input-output-files) 14 | * [Project setup](#project-setup) 15 | * [How it works](#how-it-works) 16 | * [How to set this up in your project](#how-to-set-this-up-in-your-project) 17 | * [Known issues](#known-issues) 18 | 19 | ## What is SwiftLint? 20 | 21 | SwiftLint is a static analysis tool for Swift code that helps developers enforce style and conventions in their projects. It can be run as a build phase in Xcode to automatically check for linting issues as part of the build process. 22 | 23 | ## Why use Xcode input-output files? 24 | 25 | Xcode's input-output files feature allows you to specify which files should be used as input to a build phase and which files should be generated as output. This can be useful when running tools like SwiftLint, as it allows you to only run the build phase when certain input files have changed, rather than running it every time the project is built. This can significantly improve build times, especially for build phases that take a long time to complete. 26 | 27 | ## Project setup 28 | 29 | Important: The project only compiles when managed by git since the scripts use git commands. This means you should clone the repository instead of downloading it as a ZIP; otherwise, the pre-build script will fail. 30 | 31 | I set up SwiftLint build phases with Xcode input-output files and custom pre-build script by following these steps: 32 | 33 | - Have SwiftLint set up as a "Build Phase" as explained in the [SwiftLint documentation.](https://github.com/realm/SwiftLint#usage) 34 | - Add a new pre-action build script under Edit Scheme -> Build -> Pre-actions called "Generate build phase file lists." 35 | - Select your Scheme for the "Provide build settings from" drop-down menu 36 | Screenshot 2022-12-27 at 16 30 17 37 | - Add the following code for the pre-build script: 38 | 39 | ```bash 40 | cd $SOURCE_ROOT 41 | ${SOURCE_ROOT}/generate_swifttlint_filelist.sh 42 | ``` 43 | 44 | - Add the `generate_swifttlint_filelist.sh` [script file](generate_swifttlint_filelist.sh) to the project 45 | - For all three targets (SwiftlintBuildPhase, SwiftlintBuildPhaseTests, SwiftlintBuildPhaseUITests), enable the "Based on dependency analysis" checkbox under the SwiftLint build phase 46 | - Set up the input file lists and output for every target under the build phases using the matching generated file: 47 | Screenshot 2022-12-27 at 16 43 23 48 | 49 | - Hit Cmd+U in the project twice and check the build time under the Report Navigator. Hit Control+Option+Cmd+Enter to show the Recent build timeline and check Xcode didn't run SwiftLint when no file has changed: 50 | Screenshot 2022-12-27 at 16 51 59 51 | 52 | - Add a new .swift file / change a swift file. Hit Cmd+U again, and check Xcode run SwiftLint only for the target a change occurred: 53 | Screenshot 2022-12-27 at 17 01 50 54 | 55 | ## How it works 56 | 57 | Xcode needs the input file list for the SwiftLint build phase to determine when to run SwiftLint. We want to run SwiftLint whenever we change a swift file in the current target or add a new file to the project. Unfortunately, we can't define a folder as an input file list therefore, we have to define a file list with the paths to all swift source files. Since the list of source files changes when we add, delete or rename files, we need to generate the input file list dynamically before every build. This is precisely what the [generate_swifttlint_filelist.sh](generate_swifttlint_filelist.sh) is doing that runs as a pre-action build script. 58 | 59 | I've added comments to the script file, but here is an overview of what it is doing: 60 | - The script compares the current git diff to the git diff from the previous build and determines if there was any change to the swift files list e.g.: added, deleted, or renamed 61 | - If there was a change since the last build, it generates the new input file list for all targets 62 | - If there is no change, it does nothing. 63 | - The script generates an input file list (.xcfilelist) and output file list for every target defined in the `swiftlint_dirs` variable 64 | - The script generates these files into the `/build/build_phases` folder, which git ignores. 65 | 66 | ## How to set this up in your project 67 | 68 | Follow the setup defined in the [Project setup](#project-setup). All you need to change is the `swiftlint_dirs` variable to match your source folders and set up the correct input-output file list in your target's SwiftLint build phase. You can also change the location of the generated files. 69 | 70 | ## Known issues 71 | 72 | Xcode has a bug handling the shared xcschemes where the pre-action script is defined. When we switch branches between two branches where one has the pre-action script defined and the other doesn't, it doesn't update the changes from the new branch but keeps the old one. This can cause an error in the build logs or a build failure. Restarting Xcode and discarding the changes in the .xcodeproj file solves this issue. 73 | 74 | This issue will go away as soon as all branch has the newly defined pre-action build definition. 75 | -------------------------------------------------------------------------------- /SwiftLint/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2020 Realm Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /SwiftLint/swiftlint: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/steven851007/SwiftLint_build_phase_example/d5abf81ccbefd78f49be02b7ee132cf9bd285b5b/SwiftLint/swiftlint -------------------------------------------------------------------------------- /SwiftlintBuildPhase.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 56; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 87A931DE295AD9FA005ECD90 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87A931DD295AD9FA005ECD90 /* AppDelegate.swift */; }; 11 | 87A931E0295AD9FA005ECD90 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87A931DF295AD9FA005ECD90 /* SceneDelegate.swift */; }; 12 | 87A931E2295AD9FA005ECD90 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87A931E1295AD9FA005ECD90 /* ViewController.swift */; }; 13 | 87A931E5295AD9FA005ECD90 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 87A931E3295AD9FA005ECD90 /* Main.storyboard */; }; 14 | 87A931E7295AD9FB005ECD90 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 87A931E6295AD9FB005ECD90 /* Assets.xcassets */; }; 15 | 87A931EA295AD9FB005ECD90 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 87A931E8295AD9FB005ECD90 /* LaunchScreen.storyboard */; }; 16 | 87A931F5295AD9FB005ECD90 /* SwiftlintBuildPhaseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87A931F4295AD9FB005ECD90 /* SwiftlintBuildPhaseTests.swift */; }; 17 | 87A931FF295AD9FB005ECD90 /* SwiftlintBuildPhaseUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87A931FE295AD9FB005ECD90 /* SwiftlintBuildPhaseUITests.swift */; }; 18 | 87A93201295AD9FB005ECD90 /* SwiftlintBuildPhaseUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87A93200295AD9FB005ECD90 /* SwiftlintBuildPhaseUITestsLaunchTests.swift */; }; 19 | /* End PBXBuildFile section */ 20 | 21 | /* Begin PBXContainerItemProxy section */ 22 | 87A931F1295AD9FB005ECD90 /* PBXContainerItemProxy */ = { 23 | isa = PBXContainerItemProxy; 24 | containerPortal = 87A931D2295AD9FA005ECD90 /* Project object */; 25 | proxyType = 1; 26 | remoteGlobalIDString = 87A931D9295AD9FA005ECD90; 27 | remoteInfo = SwiftlintBuildPhase; 28 | }; 29 | 87A931FB295AD9FB005ECD90 /* PBXContainerItemProxy */ = { 30 | isa = PBXContainerItemProxy; 31 | containerPortal = 87A931D2295AD9FA005ECD90 /* Project object */; 32 | proxyType = 1; 33 | remoteGlobalIDString = 87A931D9295AD9FA005ECD90; 34 | remoteInfo = SwiftlintBuildPhase; 35 | }; 36 | /* End PBXContainerItemProxy section */ 37 | 38 | /* Begin PBXFileReference section */ 39 | 87A931DA295AD9FA005ECD90 /* SwiftlintBuildPhase.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SwiftlintBuildPhase.app; sourceTree = BUILT_PRODUCTS_DIR; }; 40 | 87A931DD295AD9FA005ECD90 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 41 | 87A931DF295AD9FA005ECD90 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; 42 | 87A931E1295AD9FA005ECD90 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 43 | 87A931E4295AD9FA005ECD90 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 44 | 87A931E6295AD9FB005ECD90 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 45 | 87A931E9295AD9FB005ECD90 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 46 | 87A931EB295AD9FB005ECD90 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 47 | 87A931F0295AD9FB005ECD90 /* SwiftlintBuildPhaseTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SwiftlintBuildPhaseTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 48 | 87A931F4295AD9FB005ECD90 /* SwiftlintBuildPhaseTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftlintBuildPhaseTests.swift; sourceTree = ""; }; 49 | 87A931FA295AD9FB005ECD90 /* SwiftlintBuildPhaseUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SwiftlintBuildPhaseUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 50 | 87A931FE295AD9FB005ECD90 /* SwiftlintBuildPhaseUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftlintBuildPhaseUITests.swift; sourceTree = ""; }; 51 | 87A93200295AD9FB005ECD90 /* SwiftlintBuildPhaseUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftlintBuildPhaseUITestsLaunchTests.swift; sourceTree = ""; }; 52 | /* End PBXFileReference section */ 53 | 54 | /* Begin PBXFrameworksBuildPhase section */ 55 | 87A931D7295AD9FA005ECD90 /* Frameworks */ = { 56 | isa = PBXFrameworksBuildPhase; 57 | buildActionMask = 2147483647; 58 | files = ( 59 | ); 60 | runOnlyForDeploymentPostprocessing = 0; 61 | }; 62 | 87A931ED295AD9FB005ECD90 /* Frameworks */ = { 63 | isa = PBXFrameworksBuildPhase; 64 | buildActionMask = 2147483647; 65 | files = ( 66 | ); 67 | runOnlyForDeploymentPostprocessing = 0; 68 | }; 69 | 87A931F7295AD9FB005ECD90 /* Frameworks */ = { 70 | isa = PBXFrameworksBuildPhase; 71 | buildActionMask = 2147483647; 72 | files = ( 73 | ); 74 | runOnlyForDeploymentPostprocessing = 0; 75 | }; 76 | /* End PBXFrameworksBuildPhase section */ 77 | 78 | /* Begin PBXGroup section */ 79 | 87A931D1295AD9FA005ECD90 = { 80 | isa = PBXGroup; 81 | children = ( 82 | 87A931DC295AD9FA005ECD90 /* SwiftlintBuildPhase */, 83 | 87A931F3295AD9FB005ECD90 /* SwiftlintBuildPhaseTests */, 84 | 87A931FD295AD9FB005ECD90 /* SwiftlintBuildPhaseUITests */, 85 | 87A931DB295AD9FA005ECD90 /* Products */, 86 | ); 87 | sourceTree = ""; 88 | }; 89 | 87A931DB295AD9FA005ECD90 /* Products */ = { 90 | isa = PBXGroup; 91 | children = ( 92 | 87A931DA295AD9FA005ECD90 /* SwiftlintBuildPhase.app */, 93 | 87A931F0295AD9FB005ECD90 /* SwiftlintBuildPhaseTests.xctest */, 94 | 87A931FA295AD9FB005ECD90 /* SwiftlintBuildPhaseUITests.xctest */, 95 | ); 96 | name = Products; 97 | sourceTree = ""; 98 | }; 99 | 87A931DC295AD9FA005ECD90 /* SwiftlintBuildPhase */ = { 100 | isa = PBXGroup; 101 | children = ( 102 | 87A931DD295AD9FA005ECD90 /* AppDelegate.swift */, 103 | 87A931DF295AD9FA005ECD90 /* SceneDelegate.swift */, 104 | 87A931E1295AD9FA005ECD90 /* ViewController.swift */, 105 | 87A931E3295AD9FA005ECD90 /* Main.storyboard */, 106 | 87A931E6295AD9FB005ECD90 /* Assets.xcassets */, 107 | 87A931E8295AD9FB005ECD90 /* LaunchScreen.storyboard */, 108 | 87A931EB295AD9FB005ECD90 /* Info.plist */, 109 | ); 110 | path = SwiftlintBuildPhase; 111 | sourceTree = ""; 112 | }; 113 | 87A931F3295AD9FB005ECD90 /* SwiftlintBuildPhaseTests */ = { 114 | isa = PBXGroup; 115 | children = ( 116 | 87A931F4295AD9FB005ECD90 /* SwiftlintBuildPhaseTests.swift */, 117 | ); 118 | path = SwiftlintBuildPhaseTests; 119 | sourceTree = ""; 120 | }; 121 | 87A931FD295AD9FB005ECD90 /* SwiftlintBuildPhaseUITests */ = { 122 | isa = PBXGroup; 123 | children = ( 124 | 87A931FE295AD9FB005ECD90 /* SwiftlintBuildPhaseUITests.swift */, 125 | 87A93200295AD9FB005ECD90 /* SwiftlintBuildPhaseUITestsLaunchTests.swift */, 126 | ); 127 | path = SwiftlintBuildPhaseUITests; 128 | sourceTree = ""; 129 | }; 130 | /* End PBXGroup section */ 131 | 132 | /* Begin PBXNativeTarget section */ 133 | 87A931D9295AD9FA005ECD90 /* SwiftlintBuildPhase */ = { 134 | isa = PBXNativeTarget; 135 | buildConfigurationList = 87A93204295AD9FB005ECD90 /* Build configuration list for PBXNativeTarget "SwiftlintBuildPhase" */; 136 | buildPhases = ( 137 | 87A9320D295ADAA1005ECD90 /* Swiftlint */, 138 | 87A931D6295AD9FA005ECD90 /* Sources */, 139 | 87A931D7295AD9FA005ECD90 /* Frameworks */, 140 | 87A931D8295AD9FA005ECD90 /* Resources */, 141 | ); 142 | buildRules = ( 143 | ); 144 | dependencies = ( 145 | ); 146 | name = SwiftlintBuildPhase; 147 | productName = SwiftlintBuildPhase; 148 | productReference = 87A931DA295AD9FA005ECD90 /* SwiftlintBuildPhase.app */; 149 | productType = "com.apple.product-type.application"; 150 | }; 151 | 87A931EF295AD9FB005ECD90 /* SwiftlintBuildPhaseTests */ = { 152 | isa = PBXNativeTarget; 153 | buildConfigurationList = 87A93207295AD9FB005ECD90 /* Build configuration list for PBXNativeTarget "SwiftlintBuildPhaseTests" */; 154 | buildPhases = ( 155 | 87A9320E295ADC57005ECD90 /* Swiftlint */, 156 | 87A931EC295AD9FB005ECD90 /* Sources */, 157 | 87A931ED295AD9FB005ECD90 /* Frameworks */, 158 | 87A931EE295AD9FB005ECD90 /* Resources */, 159 | ); 160 | buildRules = ( 161 | ); 162 | dependencies = ( 163 | 87A931F2295AD9FB005ECD90 /* PBXTargetDependency */, 164 | ); 165 | name = SwiftlintBuildPhaseTests; 166 | productName = SwiftlintBuildPhaseTests; 167 | productReference = 87A931F0295AD9FB005ECD90 /* SwiftlintBuildPhaseTests.xctest */; 168 | productType = "com.apple.product-type.bundle.unit-test"; 169 | }; 170 | 87A931F9295AD9FB005ECD90 /* SwiftlintBuildPhaseUITests */ = { 171 | isa = PBXNativeTarget; 172 | buildConfigurationList = 87A9320A295AD9FB005ECD90 /* Build configuration list for PBXNativeTarget "SwiftlintBuildPhaseUITests" */; 173 | buildPhases = ( 174 | 87A9320F295ADC62005ECD90 /* Swiftlint */, 175 | 87A931F6295AD9FB005ECD90 /* Sources */, 176 | 87A931F7295AD9FB005ECD90 /* Frameworks */, 177 | 87A931F8295AD9FB005ECD90 /* Resources */, 178 | ); 179 | buildRules = ( 180 | ); 181 | dependencies = ( 182 | 87A931FC295AD9FB005ECD90 /* PBXTargetDependency */, 183 | ); 184 | name = SwiftlintBuildPhaseUITests; 185 | productName = SwiftlintBuildPhaseUITests; 186 | productReference = 87A931FA295AD9FB005ECD90 /* SwiftlintBuildPhaseUITests.xctest */; 187 | productType = "com.apple.product-type.bundle.ui-testing"; 188 | }; 189 | /* End PBXNativeTarget section */ 190 | 191 | /* Begin PBXProject section */ 192 | 87A931D2295AD9FA005ECD90 /* Project object */ = { 193 | isa = PBXProject; 194 | attributes = { 195 | BuildIndependentTargetsInParallel = 1; 196 | LastSwiftUpdateCheck = 1420; 197 | LastUpgradeCheck = 1420; 198 | TargetAttributes = { 199 | 87A931D9295AD9FA005ECD90 = { 200 | CreatedOnToolsVersion = 14.2; 201 | }; 202 | 87A931EF295AD9FB005ECD90 = { 203 | CreatedOnToolsVersion = 14.2; 204 | TestTargetID = 87A931D9295AD9FA005ECD90; 205 | }; 206 | 87A931F9295AD9FB005ECD90 = { 207 | CreatedOnToolsVersion = 14.2; 208 | TestTargetID = 87A931D9295AD9FA005ECD90; 209 | }; 210 | }; 211 | }; 212 | buildConfigurationList = 87A931D5295AD9FA005ECD90 /* Build configuration list for PBXProject "SwiftlintBuildPhase" */; 213 | compatibilityVersion = "Xcode 14.0"; 214 | developmentRegion = en; 215 | hasScannedForEncodings = 0; 216 | knownRegions = ( 217 | en, 218 | Base, 219 | ); 220 | mainGroup = 87A931D1295AD9FA005ECD90; 221 | productRefGroup = 87A931DB295AD9FA005ECD90 /* Products */; 222 | projectDirPath = ""; 223 | projectRoot = ""; 224 | targets = ( 225 | 87A931D9295AD9FA005ECD90 /* SwiftlintBuildPhase */, 226 | 87A931EF295AD9FB005ECD90 /* SwiftlintBuildPhaseTests */, 227 | 87A931F9295AD9FB005ECD90 /* SwiftlintBuildPhaseUITests */, 228 | ); 229 | }; 230 | /* End PBXProject section */ 231 | 232 | /* Begin PBXResourcesBuildPhase section */ 233 | 87A931D8295AD9FA005ECD90 /* Resources */ = { 234 | isa = PBXResourcesBuildPhase; 235 | buildActionMask = 2147483647; 236 | files = ( 237 | 87A931EA295AD9FB005ECD90 /* LaunchScreen.storyboard in Resources */, 238 | 87A931E7295AD9FB005ECD90 /* Assets.xcassets in Resources */, 239 | 87A931E5295AD9FA005ECD90 /* Main.storyboard in Resources */, 240 | ); 241 | runOnlyForDeploymentPostprocessing = 0; 242 | }; 243 | 87A931EE295AD9FB005ECD90 /* Resources */ = { 244 | isa = PBXResourcesBuildPhase; 245 | buildActionMask = 2147483647; 246 | files = ( 247 | ); 248 | runOnlyForDeploymentPostprocessing = 0; 249 | }; 250 | 87A931F8295AD9FB005ECD90 /* Resources */ = { 251 | isa = PBXResourcesBuildPhase; 252 | buildActionMask = 2147483647; 253 | files = ( 254 | ); 255 | runOnlyForDeploymentPostprocessing = 0; 256 | }; 257 | /* End PBXResourcesBuildPhase section */ 258 | 259 | /* Begin PBXShellScriptBuildPhase section */ 260 | 87A9320D295ADAA1005ECD90 /* Swiftlint */ = { 261 | isa = PBXShellScriptBuildPhase; 262 | buildActionMask = 2147483647; 263 | files = ( 264 | ); 265 | inputFileListPaths = ( 266 | "$(SRCROOT)/build/build_phases/SwiftlintBuildPhase_swiftlint.xcfilelist", 267 | ); 268 | inputPaths = ( 269 | ); 270 | name = Swiftlint; 271 | outputFileListPaths = ( 272 | ); 273 | outputPaths = ( 274 | "$(SRCROOT)/build/build_phases/SwiftlintBuildPhase_swiftlint_static_output", 275 | ); 276 | runOnlyForDeploymentPostprocessing = 0; 277 | shellPath = /bin/sh; 278 | shellScript = "./SwiftLint/swiftlint\n"; 279 | }; 280 | 87A9320E295ADC57005ECD90 /* Swiftlint */ = { 281 | isa = PBXShellScriptBuildPhase; 282 | buildActionMask = 2147483647; 283 | files = ( 284 | ); 285 | inputFileListPaths = ( 286 | "$(SRCROOT)/build/build_phases/SwiftlintBuildPhaseTests_swiftlint.xcfilelist", 287 | ); 288 | inputPaths = ( 289 | ); 290 | name = Swiftlint; 291 | outputFileListPaths = ( 292 | ); 293 | outputPaths = ( 294 | "$(SRCROOT)/build/build_phases/SwiftlintBuildPhaseTests_swiftlint_static_output", 295 | ); 296 | runOnlyForDeploymentPostprocessing = 0; 297 | shellPath = /bin/sh; 298 | shellScript = "./SwiftLint/swiftlint\n"; 299 | }; 300 | 87A9320F295ADC62005ECD90 /* Swiftlint */ = { 301 | isa = PBXShellScriptBuildPhase; 302 | buildActionMask = 2147483647; 303 | files = ( 304 | ); 305 | inputFileListPaths = ( 306 | "$(SRCROOT)/build/build_phases/SwiftlintBuildPhaseUITests_swiftlint.xcfilelist", 307 | ); 308 | inputPaths = ( 309 | ); 310 | name = Swiftlint; 311 | outputFileListPaths = ( 312 | ); 313 | outputPaths = ( 314 | "$(SRCROOT)/build/build_phases/SwiftlintBuildPhaseUITests_swiftlint_static_output", 315 | ); 316 | runOnlyForDeploymentPostprocessing = 0; 317 | shellPath = /bin/sh; 318 | shellScript = "./SwiftLint/swiftlint\n"; 319 | }; 320 | /* End PBXShellScriptBuildPhase section */ 321 | 322 | /* Begin PBXSourcesBuildPhase section */ 323 | 87A931D6295AD9FA005ECD90 /* Sources */ = { 324 | isa = PBXSourcesBuildPhase; 325 | buildActionMask = 2147483647; 326 | files = ( 327 | 87A931E2295AD9FA005ECD90 /* ViewController.swift in Sources */, 328 | 87A931DE295AD9FA005ECD90 /* AppDelegate.swift in Sources */, 329 | 87A931E0295AD9FA005ECD90 /* SceneDelegate.swift in Sources */, 330 | ); 331 | runOnlyForDeploymentPostprocessing = 0; 332 | }; 333 | 87A931EC295AD9FB005ECD90 /* Sources */ = { 334 | isa = PBXSourcesBuildPhase; 335 | buildActionMask = 2147483647; 336 | files = ( 337 | 87A931F5295AD9FB005ECD90 /* SwiftlintBuildPhaseTests.swift in Sources */, 338 | ); 339 | runOnlyForDeploymentPostprocessing = 0; 340 | }; 341 | 87A931F6295AD9FB005ECD90 /* Sources */ = { 342 | isa = PBXSourcesBuildPhase; 343 | buildActionMask = 2147483647; 344 | files = ( 345 | 87A93201295AD9FB005ECD90 /* SwiftlintBuildPhaseUITestsLaunchTests.swift in Sources */, 346 | 87A931FF295AD9FB005ECD90 /* SwiftlintBuildPhaseUITests.swift in Sources */, 347 | ); 348 | runOnlyForDeploymentPostprocessing = 0; 349 | }; 350 | /* End PBXSourcesBuildPhase section */ 351 | 352 | /* Begin PBXTargetDependency section */ 353 | 87A931F2295AD9FB005ECD90 /* PBXTargetDependency */ = { 354 | isa = PBXTargetDependency; 355 | target = 87A931D9295AD9FA005ECD90 /* SwiftlintBuildPhase */; 356 | targetProxy = 87A931F1295AD9FB005ECD90 /* PBXContainerItemProxy */; 357 | }; 358 | 87A931FC295AD9FB005ECD90 /* PBXTargetDependency */ = { 359 | isa = PBXTargetDependency; 360 | target = 87A931D9295AD9FA005ECD90 /* SwiftlintBuildPhase */; 361 | targetProxy = 87A931FB295AD9FB005ECD90 /* PBXContainerItemProxy */; 362 | }; 363 | /* End PBXTargetDependency section */ 364 | 365 | /* Begin PBXVariantGroup section */ 366 | 87A931E3295AD9FA005ECD90 /* Main.storyboard */ = { 367 | isa = PBXVariantGroup; 368 | children = ( 369 | 87A931E4295AD9FA005ECD90 /* Base */, 370 | ); 371 | name = Main.storyboard; 372 | sourceTree = ""; 373 | }; 374 | 87A931E8295AD9FB005ECD90 /* LaunchScreen.storyboard */ = { 375 | isa = PBXVariantGroup; 376 | children = ( 377 | 87A931E9295AD9FB005ECD90 /* Base */, 378 | ); 379 | name = LaunchScreen.storyboard; 380 | sourceTree = ""; 381 | }; 382 | /* End PBXVariantGroup section */ 383 | 384 | /* Begin XCBuildConfiguration section */ 385 | 87A93202295AD9FB005ECD90 /* Debug */ = { 386 | isa = XCBuildConfiguration; 387 | buildSettings = { 388 | ALWAYS_SEARCH_USER_PATHS = NO; 389 | CLANG_ANALYZER_NONNULL = YES; 390 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 391 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 392 | CLANG_ENABLE_MODULES = YES; 393 | CLANG_ENABLE_OBJC_ARC = YES; 394 | CLANG_ENABLE_OBJC_WEAK = YES; 395 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 396 | CLANG_WARN_BOOL_CONVERSION = YES; 397 | CLANG_WARN_COMMA = YES; 398 | CLANG_WARN_CONSTANT_CONVERSION = YES; 399 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 400 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 401 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 402 | CLANG_WARN_EMPTY_BODY = YES; 403 | CLANG_WARN_ENUM_CONVERSION = YES; 404 | CLANG_WARN_INFINITE_RECURSION = YES; 405 | CLANG_WARN_INT_CONVERSION = YES; 406 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 407 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 408 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 409 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 410 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 411 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 412 | CLANG_WARN_STRICT_PROTOTYPES = YES; 413 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 414 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 415 | CLANG_WARN_UNREACHABLE_CODE = YES; 416 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 417 | COPY_PHASE_STRIP = NO; 418 | DEBUG_INFORMATION_FORMAT = dwarf; 419 | ENABLE_STRICT_OBJC_MSGSEND = YES; 420 | ENABLE_TESTABILITY = YES; 421 | GCC_C_LANGUAGE_STANDARD = gnu11; 422 | GCC_DYNAMIC_NO_PIC = NO; 423 | GCC_NO_COMMON_BLOCKS = YES; 424 | GCC_OPTIMIZATION_LEVEL = 0; 425 | GCC_PREPROCESSOR_DEFINITIONS = ( 426 | "DEBUG=1", 427 | "$(inherited)", 428 | ); 429 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 430 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 431 | GCC_WARN_UNDECLARED_SELECTOR = YES; 432 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 433 | GCC_WARN_UNUSED_FUNCTION = YES; 434 | GCC_WARN_UNUSED_VARIABLE = YES; 435 | IPHONEOS_DEPLOYMENT_TARGET = 16.2; 436 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 437 | MTL_FAST_MATH = YES; 438 | ONLY_ACTIVE_ARCH = YES; 439 | SDKROOT = iphoneos; 440 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 441 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 442 | }; 443 | name = Debug; 444 | }; 445 | 87A93203295AD9FB005ECD90 /* Release */ = { 446 | isa = XCBuildConfiguration; 447 | buildSettings = { 448 | ALWAYS_SEARCH_USER_PATHS = NO; 449 | CLANG_ANALYZER_NONNULL = YES; 450 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 451 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 452 | CLANG_ENABLE_MODULES = YES; 453 | CLANG_ENABLE_OBJC_ARC = YES; 454 | CLANG_ENABLE_OBJC_WEAK = YES; 455 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 456 | CLANG_WARN_BOOL_CONVERSION = YES; 457 | CLANG_WARN_COMMA = YES; 458 | CLANG_WARN_CONSTANT_CONVERSION = YES; 459 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 460 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 461 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 462 | CLANG_WARN_EMPTY_BODY = YES; 463 | CLANG_WARN_ENUM_CONVERSION = YES; 464 | CLANG_WARN_INFINITE_RECURSION = YES; 465 | CLANG_WARN_INT_CONVERSION = YES; 466 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 467 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 468 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 469 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 470 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 471 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 472 | CLANG_WARN_STRICT_PROTOTYPES = YES; 473 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 474 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 475 | CLANG_WARN_UNREACHABLE_CODE = YES; 476 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 477 | COPY_PHASE_STRIP = NO; 478 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 479 | ENABLE_NS_ASSERTIONS = NO; 480 | ENABLE_STRICT_OBJC_MSGSEND = YES; 481 | GCC_C_LANGUAGE_STANDARD = gnu11; 482 | GCC_NO_COMMON_BLOCKS = YES; 483 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 484 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 485 | GCC_WARN_UNDECLARED_SELECTOR = YES; 486 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 487 | GCC_WARN_UNUSED_FUNCTION = YES; 488 | GCC_WARN_UNUSED_VARIABLE = YES; 489 | IPHONEOS_DEPLOYMENT_TARGET = 16.2; 490 | MTL_ENABLE_DEBUG_INFO = NO; 491 | MTL_FAST_MATH = YES; 492 | SDKROOT = iphoneos; 493 | SWIFT_COMPILATION_MODE = wholemodule; 494 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 495 | VALIDATE_PRODUCT = YES; 496 | }; 497 | name = Release; 498 | }; 499 | 87A93205295AD9FB005ECD90 /* Debug */ = { 500 | isa = XCBuildConfiguration; 501 | buildSettings = { 502 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 503 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 504 | CODE_SIGN_STYLE = Automatic; 505 | CURRENT_PROJECT_VERSION = 1; 506 | GENERATE_INFOPLIST_FILE = YES; 507 | INFOPLIST_FILE = SwiftlintBuildPhase/Info.plist; 508 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 509 | INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; 510 | INFOPLIST_KEY_UIMainStoryboardFile = Main; 511 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 512 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 513 | LD_RUNPATH_SEARCH_PATHS = ( 514 | "$(inherited)", 515 | "@executable_path/Frameworks", 516 | ); 517 | MARKETING_VERSION = 1.0; 518 | PRODUCT_BUNDLE_IDENTIFIER = none.SwiftlintBuildPhase; 519 | PRODUCT_NAME = "$(TARGET_NAME)"; 520 | SWIFT_EMIT_LOC_STRINGS = YES; 521 | SWIFT_VERSION = 5.0; 522 | TARGETED_DEVICE_FAMILY = "1,2"; 523 | }; 524 | name = Debug; 525 | }; 526 | 87A93206295AD9FB005ECD90 /* Release */ = { 527 | isa = XCBuildConfiguration; 528 | buildSettings = { 529 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 530 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 531 | CODE_SIGN_STYLE = Automatic; 532 | CURRENT_PROJECT_VERSION = 1; 533 | GENERATE_INFOPLIST_FILE = YES; 534 | INFOPLIST_FILE = SwiftlintBuildPhase/Info.plist; 535 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 536 | INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; 537 | INFOPLIST_KEY_UIMainStoryboardFile = Main; 538 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 539 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 540 | LD_RUNPATH_SEARCH_PATHS = ( 541 | "$(inherited)", 542 | "@executable_path/Frameworks", 543 | ); 544 | MARKETING_VERSION = 1.0; 545 | PRODUCT_BUNDLE_IDENTIFIER = none.SwiftlintBuildPhase; 546 | PRODUCT_NAME = "$(TARGET_NAME)"; 547 | SWIFT_EMIT_LOC_STRINGS = YES; 548 | SWIFT_VERSION = 5.0; 549 | TARGETED_DEVICE_FAMILY = "1,2"; 550 | }; 551 | name = Release; 552 | }; 553 | 87A93208295AD9FB005ECD90 /* Debug */ = { 554 | isa = XCBuildConfiguration; 555 | buildSettings = { 556 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 557 | BUNDLE_LOADER = "$(TEST_HOST)"; 558 | CODE_SIGN_STYLE = Automatic; 559 | CURRENT_PROJECT_VERSION = 1; 560 | GENERATE_INFOPLIST_FILE = YES; 561 | IPHONEOS_DEPLOYMENT_TARGET = 16.2; 562 | MARKETING_VERSION = 1.0; 563 | PRODUCT_BUNDLE_IDENTIFIER = none.SwiftlintBuildPhaseTests; 564 | PRODUCT_NAME = "$(TARGET_NAME)"; 565 | SWIFT_EMIT_LOC_STRINGS = NO; 566 | SWIFT_VERSION = 5.0; 567 | TARGETED_DEVICE_FAMILY = "1,2"; 568 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SwiftlintBuildPhase.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/SwiftlintBuildPhase"; 569 | }; 570 | name = Debug; 571 | }; 572 | 87A93209295AD9FB005ECD90 /* Release */ = { 573 | isa = XCBuildConfiguration; 574 | buildSettings = { 575 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 576 | BUNDLE_LOADER = "$(TEST_HOST)"; 577 | CODE_SIGN_STYLE = Automatic; 578 | CURRENT_PROJECT_VERSION = 1; 579 | GENERATE_INFOPLIST_FILE = YES; 580 | IPHONEOS_DEPLOYMENT_TARGET = 16.2; 581 | MARKETING_VERSION = 1.0; 582 | PRODUCT_BUNDLE_IDENTIFIER = none.SwiftlintBuildPhaseTests; 583 | PRODUCT_NAME = "$(TARGET_NAME)"; 584 | SWIFT_EMIT_LOC_STRINGS = NO; 585 | SWIFT_VERSION = 5.0; 586 | TARGETED_DEVICE_FAMILY = "1,2"; 587 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SwiftlintBuildPhase.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/SwiftlintBuildPhase"; 588 | }; 589 | name = Release; 590 | }; 591 | 87A9320B295AD9FB005ECD90 /* Debug */ = { 592 | isa = XCBuildConfiguration; 593 | buildSettings = { 594 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 595 | CODE_SIGN_STYLE = Automatic; 596 | CURRENT_PROJECT_VERSION = 1; 597 | GENERATE_INFOPLIST_FILE = YES; 598 | MARKETING_VERSION = 1.0; 599 | PRODUCT_BUNDLE_IDENTIFIER = none.SwiftlintBuildPhaseUITests; 600 | PRODUCT_NAME = "$(TARGET_NAME)"; 601 | SWIFT_EMIT_LOC_STRINGS = NO; 602 | SWIFT_VERSION = 5.0; 603 | TARGETED_DEVICE_FAMILY = "1,2"; 604 | TEST_TARGET_NAME = SwiftlintBuildPhase; 605 | }; 606 | name = Debug; 607 | }; 608 | 87A9320C295AD9FB005ECD90 /* Release */ = { 609 | isa = XCBuildConfiguration; 610 | buildSettings = { 611 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 612 | CODE_SIGN_STYLE = Automatic; 613 | CURRENT_PROJECT_VERSION = 1; 614 | GENERATE_INFOPLIST_FILE = YES; 615 | MARKETING_VERSION = 1.0; 616 | PRODUCT_BUNDLE_IDENTIFIER = none.SwiftlintBuildPhaseUITests; 617 | PRODUCT_NAME = "$(TARGET_NAME)"; 618 | SWIFT_EMIT_LOC_STRINGS = NO; 619 | SWIFT_VERSION = 5.0; 620 | TARGETED_DEVICE_FAMILY = "1,2"; 621 | TEST_TARGET_NAME = SwiftlintBuildPhase; 622 | }; 623 | name = Release; 624 | }; 625 | /* End XCBuildConfiguration section */ 626 | 627 | /* Begin XCConfigurationList section */ 628 | 87A931D5295AD9FA005ECD90 /* Build configuration list for PBXProject "SwiftlintBuildPhase" */ = { 629 | isa = XCConfigurationList; 630 | buildConfigurations = ( 631 | 87A93202295AD9FB005ECD90 /* Debug */, 632 | 87A93203295AD9FB005ECD90 /* Release */, 633 | ); 634 | defaultConfigurationIsVisible = 0; 635 | defaultConfigurationName = Release; 636 | }; 637 | 87A93204295AD9FB005ECD90 /* Build configuration list for PBXNativeTarget "SwiftlintBuildPhase" */ = { 638 | isa = XCConfigurationList; 639 | buildConfigurations = ( 640 | 87A93205295AD9FB005ECD90 /* Debug */, 641 | 87A93206295AD9FB005ECD90 /* Release */, 642 | ); 643 | defaultConfigurationIsVisible = 0; 644 | defaultConfigurationName = Release; 645 | }; 646 | 87A93207295AD9FB005ECD90 /* Build configuration list for PBXNativeTarget "SwiftlintBuildPhaseTests" */ = { 647 | isa = XCConfigurationList; 648 | buildConfigurations = ( 649 | 87A93208295AD9FB005ECD90 /* Debug */, 650 | 87A93209295AD9FB005ECD90 /* Release */, 651 | ); 652 | defaultConfigurationIsVisible = 0; 653 | defaultConfigurationName = Release; 654 | }; 655 | 87A9320A295AD9FB005ECD90 /* Build configuration list for PBXNativeTarget "SwiftlintBuildPhaseUITests" */ = { 656 | isa = XCConfigurationList; 657 | buildConfigurations = ( 658 | 87A9320B295AD9FB005ECD90 /* Debug */, 659 | 87A9320C295AD9FB005ECD90 /* Release */, 660 | ); 661 | defaultConfigurationIsVisible = 0; 662 | defaultConfigurationName = Release; 663 | }; 664 | /* End XCConfigurationList section */ 665 | }; 666 | rootObject = 87A931D2295AD9FA005ECD90 /* Project object */; 667 | } 668 | -------------------------------------------------------------------------------- /SwiftlintBuildPhase.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SwiftlintBuildPhase.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /SwiftlintBuildPhase.xcodeproj/xcshareddata/xcschemes/SwiftlintBuildPhase.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 11 | 14 | 15 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 33 | 39 | 40 | 41 | 42 | 43 | 48 | 49 | 52 | 58 | 59 | 60 | 63 | 69 | 70 | 71 | 72 | 73 | 83 | 85 | 91 | 92 | 93 | 94 | 100 | 102 | 108 | 109 | 110 | 111 | 113 | 114 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /SwiftlintBuildPhase.xcodeproj/xcuserdata/istvanbalogh.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | SwiftlintBuildPhase.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 87A931D9295AD9FA005ECD90 16 | 17 | primary 18 | 19 | 20 | 87A931EF295AD9FB005ECD90 21 | 22 | primary 23 | 24 | 25 | 87A931F9295AD9FB005ECD90 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /SwiftlintBuildPhase/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // SwiftlintBuildPhase 4 | // 5 | // Created by Istvan Balogh on 27.12.22. 6 | // 7 | 8 | import UIKit 9 | 10 | @main 11 | class AppDelegate: UIResponder, UIApplicationDelegate { 12 | 13 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // swiftlint:disable:this line_length 14 | // Override point for customization after application launch. 15 | return true 16 | } 17 | 18 | // MARK: UISceneSession Lifecycle 19 | 20 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { // swiftlint:disable:this line_length 21 | // Called when a new scene session is being created. 22 | // Use this method to select a configuration to create the new scene with. 23 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) 24 | } 25 | 26 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /SwiftlintBuildPhase/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /SwiftlintBuildPhase/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | } 8 | ], 9 | "info" : { 10 | "author" : "xcode", 11 | "version" : 1 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /SwiftlintBuildPhase/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SwiftlintBuildPhase/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /SwiftlintBuildPhase/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /SwiftlintBuildPhase/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | UIApplicationSceneManifest 6 | 7 | UIApplicationSupportsMultipleScenes 8 | 9 | UISceneConfigurations 10 | 11 | UIWindowSceneSessionRoleApplication 12 | 13 | 14 | UISceneConfigurationName 15 | Default Configuration 16 | UISceneDelegateClassName 17 | $(PRODUCT_MODULE_NAME).SceneDelegate 18 | UISceneStoryboardFile 19 | Main 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /SwiftlintBuildPhase/SceneDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.swift 3 | // SwiftlintBuildPhase 4 | // 5 | // Created by Istvan Balogh on 27.12.22. 6 | // 7 | 8 | import UIKit 9 | 10 | class SceneDelegate: UIResponder, UIWindowSceneDelegate { 11 | 12 | var window: UIWindow? 13 | 14 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { // swiftlint:disable:this line_length 15 | } 16 | 17 | func sceneDidDisconnect(_ scene: UIScene) { 18 | // Called as the scene is being released by the system. 19 | // This occurs shortly after the scene enters the background, or when its session is discarded. 20 | // Release any resources associated with this scene that can be re-created the next time the scene connects. 21 | } 22 | 23 | func sceneDidBecomeActive(_ scene: UIScene) { 24 | // Called when the scene has moved from an inactive state to an active state. 25 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. 26 | } 27 | 28 | func sceneWillResignActive(_ scene: UIScene) { 29 | // Called when the scene will move from an active state to an inactive state. 30 | // This may occur due to temporary interruptions (ex. an incoming phone call). 31 | } 32 | 33 | func sceneWillEnterForeground(_ scene: UIScene) { 34 | // Called as the scene transitions from the background to the foreground. 35 | // Use this method to undo the changes made on entering the background. 36 | } 37 | 38 | func sceneDidEnterBackground(_ scene: UIScene) { 39 | // Called as the scene transitions from the foreground to the background. 40 | // Use this method to save data, release shared resources, and store enough scene-specific state information 41 | // to restore the scene back to its current state. 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /SwiftlintBuildPhase/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // SwiftlintBuildPhase 4 | // 5 | // Created by Istvan Balogh on 27.12.22. 6 | // 7 | 8 | import UIKit 9 | 10 | class ViewController: UIViewController { 11 | 12 | override func viewDidLoad() { 13 | super.viewDidLoad() 14 | // Do any additional setup after loading the view. 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /SwiftlintBuildPhaseTests/SwiftlintBuildPhaseTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftlintBuildPhaseTests.swift 3 | // SwiftlintBuildPhaseTests 4 | // 5 | // Created by Istvan Balogh on 27.12.22. 6 | // 7 | 8 | import XCTest 9 | @testable import SwiftlintBuildPhase 10 | 11 | final class SwiftlintBuildPhaseTests: XCTestCase { 12 | 13 | override func setUpWithError() throws { 14 | // Put setup code here. This method is called before the invocation of each test method in the class. 15 | } 16 | 17 | override func tearDownWithError() throws { 18 | // Put teardown code here. This method is called after the invocation of each test method in the class. 19 | } 20 | 21 | func testExample() throws { 22 | // This is an example of a functional test case. 23 | // Use XCTAssert and related functions to verify your tests produce the correct results. 24 | // Any test you write for XCTest can be annotated as throws and async. 25 | // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error. 26 | } 27 | 28 | func testPerformanceExample() throws { 29 | // This is an example of a performance test case. 30 | self.measure { 31 | // Put the code you want to measure the time of here. 32 | } 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /SwiftlintBuildPhaseUITests/SwiftlintBuildPhaseUITests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftlintBuildPhaseUITests.swift 3 | // SwiftlintBuildPhaseUITests 4 | // 5 | // Created by Istvan Balogh on 27.12.22. 6 | // 7 | 8 | import XCTest 9 | 10 | final class SwiftlintBuildPhaseUITests: XCTestCase { 11 | 12 | override func setUpWithError() throws { 13 | // Put setup code here. This method is called before the invocation of each test method in the class. 14 | 15 | // In UI tests it is usually best to stop immediately when a failure occurs. 16 | continueAfterFailure = false 17 | 18 | } 19 | 20 | override func tearDownWithError() throws { 21 | // Put teardown code here. This method is called after the invocation of each test method in the class. 22 | } 23 | 24 | func testExample() throws { 25 | // UI tests must launch the application that they test. 26 | let app = XCUIApplication() 27 | app.launch() 28 | 29 | // Use XCTAssert and related functions to verify your tests produce the correct results. 30 | } 31 | 32 | func testLaunchPerformance() throws { 33 | if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) { 34 | // This measures how long it takes to launch your application. 35 | measure(metrics: [XCTApplicationLaunchMetric()]) { 36 | XCUIApplication().launch() 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /SwiftlintBuildPhaseUITests/SwiftlintBuildPhaseUITestsLaunchTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftlintBuildPhaseUITestsLaunchTests.swift 3 | // SwiftlintBuildPhaseUITests 4 | // 5 | // Created by Istvan Balogh on 27.12.22. 6 | // 7 | 8 | import XCTest 9 | 10 | final class SwiftlintBuildPhaseUITestsLaunchTests: XCTestCase { 11 | 12 | override class var runsForEachTargetApplicationUIConfiguration: Bool { 13 | true 14 | } 15 | 16 | override func setUpWithError() throws { 17 | continueAfterFailure = false 18 | } 19 | 20 | func testLaunch() throws { 21 | let app = XCUIApplication() 22 | app.launch() 23 | 24 | // Insert steps here to perform after app launch but before taking a screenshot, 25 | // such as logging into a test account or navigating somewhere in the app 26 | 27 | let attachment = XCTAttachment(screenshot: app.screenshot()) 28 | attachment.name = "Launch Screen" 29 | attachment.lifetime = .keepAlways 30 | add(attachment) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /generate_swifttlint_filelist.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # This script generates the input and output files for SwiftLint build phases for the targets we have in the project 4 | # to improve the speed of incrementail builds: https://developer.apple.com/documentation/xcode/improving-the-speed-of-incremental-builds 5 | 6 | # Get the git root path 7 | SRC_ROOT=$(git rev-parse --show-toplevel) 8 | 9 | # Create a directory where we store the input/output files. This should be a folder that is ignored by git. 10 | mkdir -p "$SRC_ROOT/build/build_phases" 11 | 12 | # Path to this new folder where we generate the input & output files 13 | BUILD_FOLDER="$SRC_ROOT/build/build_phases" 14 | 15 | # The path of the result file where we save the current git diff 16 | RESULT_FILE=$BUILD_FOLDER/git_diff_result 17 | 18 | # Create the result file if it doesn't exist yet 19 | if [ ! -f $RESULT_FILE ] 20 | then 21 | echo "creating result file" 22 | # Add a dummy text to the file, so we generate the input files when the file didn't exist before and git has no changes. 23 | echo -n "dummy" > "$RESULT_FILE" 24 | fi 25 | 26 | # Check if there is any .swift file added / deleted / renamed in the current git changes 27 | NEW_FILES=`git diff HEAD --name-only --diff-filter=ADR -- '***.swift'` 28 | 29 | # Load the git diff result from the last compilation 30 | PREV_GIT_RESULT=$(<"$RESULT_FILE") 31 | 32 | # If there were no new .swift files added since the last compilation, we don't need to regenerate the input files 33 | if [[ "$PREV_GIT_RESULT" == "$NEW_FILES" ]]; then 34 | echo "No changes since last git diff, do nothing" 35 | exit 0 36 | fi 37 | 38 | # Store the current git diff for the next run 39 | echo -n "$NEW_FILES" > "$RESULT_FILE" 40 | echo "Generating new source file list" 41 | 42 | # List of folders in which we generate filelist for Swiftlint (e.g. only .swift) 43 | swiftlint_dirs=( 44 | 'SwiftlintBuildPhase' 45 | 'SwiftlintBuildPhaseTests' 46 | 'SwiftlintBuildPhaseUITests' 47 | ) 48 | 49 | for dir in "${swiftlint_dirs[@]}" 50 | do 51 | # Find all .swift files in the folder to create the xcfilelist file for the SwiftLint build script 52 | find "${dir}" -type f -name "*.swift" | sed -e 's/^/$(SRCROOT)\//;' > "$BUILD_FOLDER/${dir}_swiftlint.xcfilelist" 53 | # Create a static empty output file. We need to create these empty output files as stated in the documentation linked above: 54 | # "You must still specify an input and output file to prevent Xcode from running the script every time, even if your script doesn’t actually require those files. 55 | # For a script that requires no input, provide a file that never changes as the input file. For a script with no outputs, create a static output file from your script so Xcode has something to check." 56 | touch "${BUILD_FOLDER}/${dir}_swiftlint_static_output" 57 | done --------------------------------------------------------------------------------