Based off of PR: #1361
Currently generating the plist file for a watchOS resource bundle target includes the key CFBundleExecutable, having it included causes a validation error when uploading application to the App Store
```
Error 1: ITMS-90535 - Unexpected CFBundleExecutable Key
```
Solution:
Omit that key incase the target is a watchOS bundle.
* bump up Xcodeproj to 8.9.0
* add shellPath property at ExecuteAction
* update changelog
* run lint
* update pull request link
* match changelog with PR title
* remove changes in changelog (it will be auto-generated)
* update shellPath comment
* update fixture to use shellPath in ExecutionAction
* bump up XcodeProj to 8.10.0
Resolves: https://github.com/tuist/tuist/issues/5152
- Archiving projects with static XCFramework dependencies can yield the following error
```
Multiple commands products: ....
```
- This issue was accidentally introduced while attempting to add better static XCFramework support in https://github.com/tuist/tuist/pull/5107
- It is caused due to the technique employed to get Xcode to process the XCFramework (and thereby have its symbols visible to the target) without explicitly linking it to avoid duplicate symbol issues that can arise when having static targets depend on static products.
- The XCFramework as added to a custom Copy Files build phase that would copy it to the products directory
- The same technique is currently employed by regular static targets, where Xcode simply ignores the copy if the product already exists
- This didn't seem to work with XCFrameworks
- The custom copy phase is marked with "Copy only when installing" which is why the issue surfaced when archiving only
- There are a few options to resolve this (see https://github.com/tuist/tuist/issues/5152)
- A solution that is closer to the current implementation involves specifying unique destinations per target in the custom copy phase for XCFrameworks to avoid the conflict
- This is somewhat redundant / wasteful as those copies won't be used and only serve as way for Xcode to process the XCFramework without explicitly linking it nor produce the build error due to multiple targets having the same build identical build action
- A new copy files build phase is added for this
- The fixture has now been extended to include more targets and the acceptance test to perform an archive to verify the new soltuon
Test Plan:
- Build this version of tuist
```
swift build
```
- Generate the fixture `ios_app_with_xcframeworks`
```
swift run tuist generate --path projects/tuist/fixtures/ios_app_with_xcframeworks
```
- Inspect the generated project
- Verify the new copy files build phases (named "Static XCFramework Dependencies") are added to `StaticFrameworkA` and `StaticFrameworkB`
- Veirfy the following targets build successfully in isolation (perform a clean + select the appropriate scheme)
- `App
- `StaticFrameworkA`
- `StaticFrameworkB`
- Verify archivig `App` succeeds (note: may need to temporarily select a development team to get this working)
Short description:
- WatchOS extension targets can now include WidgetKit extension targets (as of Xcode 14)
- WidgetKit extension targets are regular app extension targets
- Tuist already supports embedding app extensions, the only change needed to support it for watchOS extension was to update the linter logic to allow this dependency combination
- A new fixture was added to demo a watchOS WidgetKit extension
Notes:
- WidgetKit extension targets require the following info plist keys
```
<dict>
<key>NSExtension</key>
<dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.widgetkit-extension</string>
</dict>
</dict>
```
How to test the changes locally:
- Generate the watch application fixture
```
swift build
swift run tuist generate --path projects/tuist/fixtures/ios_app_with_watchapp2_xcode14
```
- Verify the project generates successfully without any lint errors
- Inspect the generated project and verify the WidgetKit extension for the watch extension is created correctly
- Static precompiled targets were currently being "linked" directly by the target that declared a dependency on them
- note: linking only really took place if the target was one that supports linking (e.g. app, unit tests, etc..), for any static targets the symbols of the precomplied binary symbols would be included
- This worked in simple cases where only one target would depend on the precompiled static target
- In scenarios where multiple static targets needed to depend on the same precompiled static target, build failures would occur due to duplicate symbols
- To solve this, the precompiled static product is now only linked in targets that support linking and instead they are marked as dependencies of the static targets to ensure they can compile
- For `XCFramework`s those are added to the "Dependencies" copy products build phase
- For precompiled `Framework`s they are added to the framework search paths _(no change from before the changes)_
- For precompiled libraries (`.a`)
- They are added to the library and swift include search paths of the static targets that depend on them _(no change from before the changes)_
- Additionally, they are also added to the library search paths of the final linking target
Fixture Update:
- Moved frameworks to "xcframeworks" directory to avoid confusion with any native targets
- Added a modules directory to host native target projects to help replicate additional xcframework integration examples
- Updated code samples of precompiled xcframeworks to ensure they are imported and their code is exercised to validate the integration works
XCFramework Test Plan:
- Build this version of tuist
```sh
swift build
```
- Generate the fixture `ios_app_with_xcframeworks`
```sh
swift run tuist generate --path projects/tuist/fixtures/ios_app_with_xcframeworks
```
- Build the project and verify it succeeds
- Verify the precompiled `MyStaticLibrary.xcframework` is only linked in the `App` target
- Verify the precompiled `MyStaticLibrary.xcframework` is declared a dependency (but not in the link phase) of target `StaticFrameworkA`
- Verify `StaticFrameworkA` build successfully in isolation
- Verify `App` builds and runs successfully without any duplicate symbol errors
Framework Test Plan:
- Generate the fixture `ios_app_with_static_frameworks`
```sh
swift run tuist generate --path projects/tuist/fixtures/ios_app_with_static_frameworks
```
- Build the project and verify it succeeds
- Verify the precompiled static framework is only linked in the `App` target
- Verify the precompiled static framework is not in the link phase of target `A`
- Verify building the target `A` in isolation still works
Co-authored-by: Daniele Formichelli <df@bendingspoons.com>