- The `defaultSettingsProvider` passed to the `Generator` wasn't being passed along to the `ProjectGenerator`
- This led to having 2 different implementations running side by side
- Sadly this got missed in a previous fix https://github.com/tuist/tuist/pull/389
Test Plan:
- Verify unit tests pass via `swift tests`
- Verify acceptance tests pass via `bundle exec rake features`
Resolves https://github.com/tuist/tuist/issues/390
### Short description
The `DefaultSettingsProvider` `targetSettings` combines the build settings for the specified build variant with the build settings for variants. If there is a common build setting with `$(inherited)` in its value, the value is appended twice.
### Solution
In the `SettingsHelper` before combining build settings by appending the new value to the existing one check if the value are equal
### Implementation
- Change `SettingsHelper` to check if setting values are equal before appending
- Add unit test to cover this case
### Test Plan
- Verify unit tests pass via swift tests
- The `defaultSettingsProvider` passed to the `WorkspaceGenerator` wasn't being passed along to the `TargetGenerator`
- This led to having 2 different implementations running side by side
- The target generator is now created and injected to the project generator
Test Plan:
- Verify unit tests pass via `swift tests`
- Verify acceptance tests pass via `bundle exec rake features`
Resolves https://github.com/tuist/tuist/issues/350
- Added a new protocol `DefaultSettingsProviding` that allows to control default settings at project and target level with a default implementation. `.recommended` set of settings is exactly the same as what Tuist currently generates so this it's not a breaking change.
- Moved some of the settings helpers to a separated class `SettingsHelper`.
- Extended `Settings` manifest so the users can control the default set of settings.
- Including a resource bundle as one of the elements in the "Copy Bundle Resources" build phase doesn't get it built!
- When within the same project, the solution is to add the resource bundle target as an explicit target dependency
- This is not possible when the dependency is between two different projects
- To workaround this issue, a similar technique currently employed by static products can be used
- The resource bundle is now included in a copy files phase - which get Xcode to build it!
- The logic used for static products has been generalized slightly to allow accommodating the resource bundle targets
Test Plan:
- Run the unit tests via `swift test`
Note: this is not yet exposed via the project description manifests
* Define Info.plist in the ProjectDescription target
* Update infoPlist attribute type
* Update models to use the new type, InfoPlist
* Update changelog
Resolves https://github.com/tuist/tuist/issues/349
- Update `func embeddableFrameworks(path: AbsolutePath, name: String, system: Systeming)` of `Graph` to return ordered references
- Update method generating products file references so it can generate sorted list of products of the project targets and the dependencies
- Add integration test to make sure the project does not change after regeneration
Test Plan:
- Run unit tests via `swift test`
- Run acceptance tests via `bundle exec rake features`
- Manually generate `fixtures/ios_app_with_frameworks` via `tuist generate` at least two times without making any changes to the project
- Verify the generated workspace and projects are stable (do not change after regeneration)
### Short description
Custom debug settings were populated with release default settings (provided by XcodeProj). The issue was introduced while implementing custom configurations (https://github.com/tuist/tuist/pull/320). It does not affect Tuist users as we still support only `.debug` and `.release` configurations.
### Solution
- Fixed incorrect code converting build configuration into XcodeProj variant in `ConfigGenerator`
- Added unit and integration tests
Resolves https://github.com/tuist/tuist/issues/337
- The graph linter didn't account for which targets could link static products
- This led to raising an incorrect lint warning
- A `canLinkStaticProducts` method has been added to share rules between the linter and graph during link generation
- `GraphLinter` has been updated to no longer keep state internally
Test Plan:
- Run unit tests via `swift lint`
- Run acceptance tests via `bundle exec rake features`
- Manually generate `fixtures/ios_app_with_static_frameworks` via `tuist generate`
- Verify no lint warnings are displayed
Resolves https://github.com/tuist/tuist/issues/361
### Short description
Localized resources can up getting duplicated within the resources build phase and the project files elements.
The reason this was occurring:
- Give a path to a resource e.g. `/resources/en.lproj/foo.png`
- `/resources/en.lproj/` is used detected
- All files within `/resources/en.lproj/` are enumerated and added
- When another path to a resource is encountered e.g. `/resources/en.lproj/bar.png`
- The same process is repeated, resulting in duplicate file elements!
### Solution
- Update project files element logic to better accommodate multiple localized files
- Add a cache to keep track of which build files were added the resources build phase to prevent adding duplicates.
- Improved file element missing file warnings for directories
e.g. `resources: ["Resources/en.lproj"]` would yield the following warnings:
```
Warning: 'Resources/en.lproj' is a directory, try using: 'Resources/en.lproj/**' to list its files
```
### Test Plan
- Verify unit tests pass via `swift tests`
- Verify acceptance tests pass via `bundle rake exec features`
- Manually generate `fixtures/ios_app_with_framework_and_resources` via `tuist generate`
- Verify the generated project includes the localized string files without any duplicates
Resolves https://github.com/tuist/tuist/issues/352
- Specifying a permissive glob pattern (e.g. `Headers/**`) for headers would incorrectly include all files and folders as headers
- Limiting the paths to header files resolves this issue
- Adding Objective-C classes to test out headers within the fixtures
Test Plan:
- Verify unit tests pass via `swift build`
- Verify acceptance tests pass via `bundle exec rake features`
- Manually generate `fixtures/ios_app_with_frameworks` via `tuist generate`
- Verify `Framework2` has the appropriate public, private & project headers set
Part of: https://github.com/tuist/tuist/issues/290
- Previously only bundle target dependencies within the same projects worked
- This was due to leveraging `targetDependencies` method on `Graph` which only returns the target dependencies with the same project
- Updating `Graph` to include a new method to return all bundle resource dependencies
Test Plan:
- Run unit tests via `swift test` and verify they pass
Note: bundle resources are not yet exposed to the manifests
Resolves https://github.com/tuist/tuist/issues/345
- Using the `**/*` style patterns are "eager" they will list out files recursively including ones within `.xcassets`
- The order in which the `ProjectFileElements` elements are processes isn't guaranteed
- If a file within the `.xcassets` is encountered first, e.g. `App/Resources/Assets.xcassets/assetCatalogLogo.imageset/tuist.png` before `App/Resources/Assets.xcassets`, `App/Resources/Assets.xcassets` is mistaken for a group and isn't added as a file element
- To mitigate this, the logic that determines if a group or file is added checks for `.xcassets` files
Test Plan:
- Verify unit tests pass
- Verify acceptance tests pass
- Run `tuist generate` within `fixtures/ios_app_with_framework_and_resources`
- Verify the generation passes
- Verify the asset catalog is included in the generated `MainApp` within the workspace
Resolves https://github.com/tuist/tuist/issues/334
- The path to resources is now commented out and left as an example to aid users get started defining the manifest
- The warnings were caused due to the `Resources` directory not existing
Test Plan:
- Create a new empty directory
- Run `tuist init`
- Run `tuist focus`
- Verify no warnings are displayed
Resolves https://github.com/tuist/tuist/issues/329
### Short description 📝
To keep an eye on how long the generation process takes as users add more dependencies to their projects and as Tuist developers add more features to Tuist itself, it would be useful to print out the total generation time.
### Solution
Print out the total time taken to generate a project within the generate command.
### Implementation
- Introduce `Clock` and `ClockTimers` to allow obtaining current date and time differences
- Time the generate process within the generate command
### Test Plan
- Verify unit tests and acceptance tests pass
- Run `tuist generate` within any of the fixtures in `fixtures`
- Verify the generation time is displayed in the console output
Resolves https://github.com/tuist/tuist/issues/330 and https://github.com/tuist/tuist/issues/322
### Short description:
- This issue can occur when files like `README` without extensions exist within the project
- Additionally another issue can be encountered in the event folders contain a `.` in their name
- To solve this we now only create groups if the file element component being added is a leaf (i.e. `/path/to/a` when `path` and `to` are added, they will be added as groups, and `a` will be added as a file element)
## Test Plan:
- Verify unit tests pass `swift test`
- Verify acceptance tests pass `bundle rake features`
- Manually generate `fixtures/ios_app_with_framework_and_resources` via `tuist generate`
- Verify `resource_without_extension` and `resource.txt` are included as resources within the project
- Manually generate `fixtures/ios_app_with_custom_workspace` via `tuist generate`
- Verify the `CHANGELOG` file appears as a file and not a group
* Headers build phase should be put on top of Compile build phase
* Add test
* Add changelog
* Set Code Sign On Copy to true for Embbed Frameworks
* Add changelog
* Update CHANGELOG
Resolves https://github.com/tuist/tuist/issues/324
- Using `replaceItemAt` has a caveat where it requires the item and its replacement to be on the same volume (see https://developer.apple.com/documentation/foundation/filemanager/2293212-replaceitemat)
- To mitigate this, the documentation suggests creating a temporary file within that volume
- The item can be moved there first
- Then a `replaceItemAt` can be performed
Test Plan:
- Manually create a RAM disk e.g. `diskutil erasevolume HFS+ “RAMDisk” `hdiutil attach -nomount ram://524288`` (this creates a 250MB RAM disk)
- Create a new folder within that disk
- run `tuist --init`
- run `tuist generate`
- Verify the generation succeeds
Part of https://github.com/tuist/tuist/issues/160
### Short description
As mentioned in https://github.com/tuist/tuist/issues/160, currently, Tuist only supports debug and release build configurations. This can be seen as a limitation for some projects. We'd like to avoid this limitation and allow users to control the configurations themselves and base them on xcconfig files if needed.
### Solution
Added `Settings` property to `Project` and `Target` generator models. `Settings` contains `base` property for settings that are common for all the configurations. `configurations` property stores dictionary mapping `BuildConfiguration` (i.e. Release, Debug, Beta etc.) to `Configuration`. The structure won't preserve the order of the configurations but can help avoid situation when the same configuration is set twice (which would require additional linting). Maintaining the original order would be particularly difficult in cases when the defined configurations orders are different in project and target settings. To keep the ordering stable, the generator sorts the configurations alphabetically.
To make the implementation backward compatible, `GeneratorModelLoader` always passes `release` and `debug` configurations with the settings defined in the manifest.
```swift
return TuistGenerator.Settings(base: base, configurations: [.debug: debug, .release: release]
```
Part of: https://github.com/tuist/tuist/issues/290
### Short description
Static frameworks & libraries currently can't host resources, one common technique to work around this is by introducing resource bundle targets to host the resources instead.
### Solution
To aid solving this wholistically, an incremental step is to introduce the bundle product type to `TuistGenerator` (generator library).
### Implementation
- Add bundle product type
- Add lint rules
### Notes
- The `.bundle` product type is not yet exposed in the manifests - this may be done separately once more foundations are in place to support resources holistically (See #290)
- Updating SwiftPM dependency
- `asString` has been renamed to `pathString`
- `Utility` module has been renamed to `SPMUtility`
Test Plan:
- Verify unit tests pass `swift test`
- Verify acceptance tests pass `bundle exec rake features`
Resolves https://github.com/tuist/tuist/issues/254
- When creating new Xcode projects manually from the UI, the product names do not include the extension
- Renaming existing `productName` references to `productNameWithExtension`
Test Plan:
- Ensure unit tests pass via `swift test`
- Ensure acceptance tests pass via `bundle exec rake features`
* Support Swift 5
* Fix test
* Don't check if the versions match when both local and remote versions are greater or equal than 5
* Updating fixtures for Swift 5 support
- Included a build script to allow re-creating the pre-built `Framework2` framework
- Updated build script for pre-built static library to require less manual steps
* Updates for Swift 5
- `swift package tools-version --set-current`
* Relaxed error output checks in acceptance tests
* Adding trace for acceptance test (to aid troubleshooting)
* skipping build during error message acceptance test
- Adding a step to build tuist separately ahead of calling run
- When running tuist via `swift run` we now skip the build
* Disable Swiftformat
- `GraphNode` subclasses like `TargetNode` that share a common path could mistakenly be identified as equal
- This is due to the static `==` method being called on `GraphNode` rather than the subclass
- To ensure the appropriate method is called, we can create an `isEqual` method to call, and override it in all subclasses
- Additionally we need to perform the equality check twice reversing the sides and ensuring they match - this ensures we call the appropriate subclass implementation
Test Plan:
- Verify unit tests pass
Reference: https://forums.swift.org/t/implement-equatable-protocol-in-a-class-hierarchy/13844/6
Resolves https://github.com/tuist/tuist/issues/202
### Short description
Resources to include in an application can be in the form of files as well as folder references.
### Solution
Add support for folder references within target resources. For consistency, we can use `FileElement` which has already been used in `Project` and `Workspace` to define additional files.
e.g.
```swift
import ProjectDescription
let project = Project(
name: "MainApp",
targets: [
Target(
name: "App",
platform: .iOS,
product: .app,
bundleId: "io.tuist.App",
infoPlist: "Config/App-Info.plist",
sources: "Sources/**",
resources: [
"Resources/*.png",
.folderReference(path: "Examples")
])
]
)
```
### Test Plan
- Verify unit tests pass via `swift test`
- Verify acceptance tests pass via `bundle exec rake features`
- Run `tuist generate` within `fixtures/ios_app_with_framework_and_resources`
- Inspect the generated workspace
- Verify `MainApp` has a folder reference to `Examples` which is also included in the **Copy Bundle Resources** phase
Part of https://github.com/tuist/tuist/issues/202
### Short description
Often projects may include additional files or folder references that don't need to be part of any build phase (e.g. design references, documentation etc...)
### Solution
`Workspace.swift` manifest now supports `additionalFiles`, the same concept can be added to the `Project.swift` manifest with the same rules.
- `.glob(pattern: "Documentation/**")`: glob pattern to one or more files
- `.folderReference(path: "Designs")`: single path to a directory that is added as a folder reference
Example:
```swift
let project = Project(name: "App",
targets: [
// ...
],
additionalFiles: [
"Dangerfile.swift"
"Documentation/**",
.folderReference(path: "Designs")
])
```
### Implementation
- [x] Update `Project` manifest to include `additionalFiles`
- [x] Update models to translate globs to paths
- [x] Update `ProjectFileElements` to include `additionalFiles`
- [x] Include fixture
- [x] Update documentation
- [x] Update changelog
### Test Plan
- Run `tuist generate` within `fixtures/ios_app_with_custom_workspace/App`
- Open the generated workspace
- Verify `Dangerfile.swift` is included in the project but isn't part of the resource phase
- Verify `Documentation` files are included (with the appropriate group structure that reflects the file system) and that the files aren't copied to resources
- Verify `Server` folder reference is included
### Short description
Tuist is a command line tool that offers several useful features related to managing Xcode projects at scale. The generation features are worthy of bundling in a library to enable external tools to leverage it and build on top of it.
### Solution
The `TuistGenerator` library has been previously created and several changes have been incrementally made to allow seamlessly migrating all the generation related code to it.
### Test Plan
- Ensure unit tests continue to pass
`swift test`
- Ensure acceptance tests continue to pass
`bundle exec rake features`
- Manually generate any of the projects within `fixtures`
`tuist generate`
### Notes
`TuistGenerator` is not yet stable - breaking changes will most likely be made.
- A few additional build settings are needed when linking against pre-built static libraries
- `LIBRARY_SEARCH_PATHS` needs to point to the directory containing the `.a` file
- `SWIFT_INCLUDE_PATHS` need to point to the directory containing the `.swiftmodule` file
Test Plan:
- Generate `fixtures/ios_app_with_static_libraries`
- Verify the application builds
- Verify the `LIBRARY_SEARCH_PATHS` and `SWIFT_INCLUDE_PATHS` settings are set on target `A`
Resolves https://github.com/tuist/tuist/issues/258
### Short description
Workspace manifests allow users to customize which project are included in their workspace however doesn't yet offer the ability to add arbitrary files and folder references (to support included things like Documentation and README files).
### Solution
Extend the workspace manifest to allow specifying `additionalFiles`
e.g.
```swift
import ProjectDescription
let workspace = Workspace(name: "Workspace",
projects: [
"App",
"Frameworks/FrameworkA",
"Frameworks/FrameworkB",
],
additionalFiles: [
"Documentation/**",
.folderReference(path: "Website")
])
```
As an added bonus of these changes, we can add the ability to specify glob patterns for `projects` to make it easier to include new projects without needing to constantly update the workspace manifest.
e.g.
```swift
import ProjectDescription
let workspace = Workspace(name: "Workspace",
projects: [
"App",
"Frameworks/**",
],
additionalFiles: [
"Documentation/**",
.folderReference(path: "Website")
])
```
### Implementation
- [x] Update workspace manifests
- [x] Parse workspace manifests > models
- [x] Add workspace structure generator
- [x] Integrate workspace structure
- [x] Include fixture
- [x] Update documentation
### Test Plan
- Run `tuist generate` on the following fixtures:
- `fixture/ios_app_with_custom_workspace`
<img width="254" alt="custom-workspace" src="https://user-images.githubusercontent.com/11914919/54780257-36db2f80-4c11-11e9-8fda-5f59554533c0.png">
- `fixture/ios_app_with_custom_workspace/App`
<img width="161" alt="custom-workspace-app" src="https://user-images.githubusercontent.com/11914919/54780299-4a869600-4c11-11e9-9637-cdfaa20bb8c8.png">
- `fixture/ios_app_with_setup`
<img width="175" alt="setup" src="https://user-images.githubusercontent.com/11914919/54780315-540ffe00-4c11-11e9-99fd-e9175ee4de27.png">
- `fixture/ios_app_with_frameworks`
<img width="184" alt="frameworks" src="https://user-images.githubusercontent.com/11914919/54780335-5d00cf80-4c11-11e9-906c-b53f26c36007.png">
Verify the generated workspace structure
### Notes
All this work is based on group effort and iteration from #262 - thanks @ollieatkinson, @pepibumur! 👍
- While unifying manifest target generation (#271) one crucial step was missed, removing the "Manifest" project group from the pre-defined list of groups
- The manifest loader is also no longer used in the target generator - this was also missed in #271
Test Plan:
- Generate any of the fixtures
- Inspect the generated project
- Verify there are no duplicate manifest groups
* Update UIKit `didFinishLaunchingWithOptions` method to remove warning
* Update UIKit `didFinishLaunchingWithOptions` method in fixtures
* Exclude fixtures from SwiftFormat
* Fix line too long lint error
* Update CHANGELOG.md
* Fix build settings not being generated properly
* update changelog
* Adding unit test for debug/release target settings
* Fix tests
* Solve some issues after rebasing
* Manifest targets are now static frameworks to prevent link errors
- The manifest target can be built to ensure there are no syntax errors in the project manifests
- This target doesn't need to be linked, a compilation step is sufficient to serve its purpose
- By converting the manifest target to a static framework, the link step is skipped and the errors that were obtained during that step can be avoided all together
Test Plan:
- Run `tuist generate` on any fixture within `fixtures`
- Open the generated workspace (you can use `tuist focus` as a shortcut to those steps)
- Build the `<Project>-Manifest` scheme in Xcode
- Verify no link errors appear
* Updated changelog
- The manifest target can be generated using the exiting generator code without needing any additional logic
- Manifest targets models are now created at the point of loading project models
Test Plan:
- Verify unit tests pass via `swift test`
- Verify acceptance tests pass via `bundle exec rake features`
- Generate any fixture and validate the `Manifest` target is still generated
- Verify autocomplete still work within the `Project.swift` file
- The idea is to enable declaring the root folder in which target sources are hosted
- This will allow us to unify the creation of the manifest target (just like any other target with some custom settings) without needing any additional logic
- For example, at the model loader level, we can create a target and re-use the existing target generation logic to generate the manifest target
- To ensure the manifest can get its dedicated top level folder, we could add a target level option (at the generator level) to specify the root group - `filesGroup`
- The manifest target can declare its `filesGroup: .group(name: "Manifest")` while all other targets use the default `filesGroup: .group(name: "Project")`
- Note: this is a very simplistic solution for the specific use case of supporting the manifest target, a more flexible solution could be explored as a follow up
Test Plan:
- Ensure unit and acceptance tests pass
- run `tuist generate` within any of the `fixtures` and the structure is as it was before (sources appear within `Project` group)
* Fix#253 - Include linked library and embed in any top level executable bundle
* Fix fixture test, removed explicit link inside of main app and compiled Framework2 as a fat binary
* swiftformat .
* Update CHANGELOG.md
* Add acceptance tests
* Delete copying the working directory
* Store DerivedData in the working directory
Part of: #205
- To ease the migration of classes to the generator library, the generator is added to `TuistKit` temporarily
- This component will later move to `TuistGenerator`
- This allows decoupling commands from the workspace generator / graph related classes
- `GraphLoader` no longer depends on the `GraphManifestLoader`
- Focus command no longer has a `--config` option as it's no longer used
Test Plan:
- Ensure unit tests pass `swift test`
- Ensure acceptance tests pass `bundle exec rake features`
- Navigate to any of the fixtures and test out `tuist focus`
- `Workspace` and `Scheme` are now decoupled from manifests json
- `ProjectLinter` no longer requires the `UpLinter`
- Adding scheme conversion from `ProjectDescriotion` to `TuistKit` models
Test Plan:
- Verify unit tests continue to pass
- Introducing a `GeneratorModelLoader` component responsible for obtaining the model objects required by the `TuistGenerator` library
- To support this, the models are being decoupled from the manifest definitions (and the JSON representation)
- The conversion between the manifest and model types takes place within the model loader
Test Plan:
- Ensure unit tests continue to pass `swift test`
- Ensure acceptance tests pass `bundle exec rake features`
- Verify projects within the `fixtures` directory are still correctly generated when performing `tuist generate`