Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiplatform Phase 3 - Expose support in ProjectDescription #5381

Closed
wants to merge 65 commits into from

Conversation

waltflanagan
Copy link
Member

Very first exposure of multiplatform work in ProjectDescription. All feedback on API design welcome.

Short description πŸ“

tbd

How to test the changes locally 🧐

tbd

Contributor checklist βœ…

  • The code has been linted using run ./fourier lint tuist --fix
  • The change is tested via unit testing or acceptance testing, or both
  • The title of the PR is formulated in a way that is usable as a changelog entry
  • In case the PR introduces changes that affect users, the documentation has been updated

Reviewer checklist βœ…

  • The code architecture and patterns are consistent with the rest of the codebase
  • Reviewer has checked that, if needed, the PR includes the label changelog:added, changelog:fixed, or changelog:changed, and the title is usable as a changelog entry

Copy link
Collaborator

@kwridan kwridan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @waltflanagan

@@ -0,0 +1,112 @@
import Foundation

extension Multiplatform {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The approach you've taken here is much cleaner though so I see the value in that, main concern is maintaining two duplicate Targets

Would it be possible to make this the main Target structure but map the the legacy properties to the appropriate underlying new properties?

e.g.

init(
// ...
  platform: Platform,
  deploymentTarget: DeploymentTarget,
// ...
) {
  self.init(
   // ...
     destinations: [Destination.from(platform)],
     deploymentTargets: DeploymentTargets.from(deploymentTarget)
   // ...
  )
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes we can and should. this approach was taken to continue to support source compatibility for current Tuist users. given that platform is a public property of Target, I didn't feel safe changing how things like that are exposed at this point in time.

If we're open to breaking changes, we can very much adjust the main Target type for our new needs as well as provide a convenience initializer that makes migration simpler for folks that dont need multiplatform support.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense to maintain source compatibility.

My thinking is we may be able to map / derive the old properties to prevent breaking changes, however if that proves to be too much hassle the approach you have taken is much cleaner.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm on the fence here. While supporting source compatibility is important, the cost of maintaining two similar structures in the codebase creates room for inconsistencies. I'm not a big fan of breaking changes, but multi-platform support is an important change for Tuist and might warrant going with a major release, in which we can batch other deprecated APIs. If I'm not wrong here, the changes developers would have to make are not that significant, so even if it's a breaking change, which is always undesirable, the process "should" be straightforward.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My main thought for this was that it would be "short" lived. We could publish the source compatible version for a while, allow users to migrate at their own pace and incrementally if they have many targets to migrate. After enough time we can make the source breaking change to remove the old deprecated target implementation and promote the multiplatform one to the only one.


extension Target {
/// Platform for use with services when a platform is not specified
var servicePlatform: Platform {
Copy link
Contributor

@pepicrft pepicrft Sep 4, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about naming this one platformIfOneOrThrow? It reads more verbose, but someone reading the code will immediately get the logic by reading the getter name.

kwridan added a commit that referenced this pull request Sep 22, 2023
…ations

- When specifying multiple destination, the `SUPPORTED_PLATFORMS` build setting needs to be set to include the various sdks for both simulator and device

Notes:

- This was cherry-picked from a draft PR for multi-platform support #5381

Test Plan:

- Multiple destinations is not yet exposed via public as such can only be validated with unit tests at this time
kwridan added a commit that referenced this pull request Sep 22, 2023
…ations

- When specifying multiple destination, the `SUPPORTED_PLATFORMS` build setting needs to be set to include the various sdks for both simulator and device

Notes:

- This was cherry-picked from a draft PR for multi-platform support #5381

Test Plan:

- Multiple destinations is not yet exposed via public as such can only be validated with unit tests at this time
kwridan added a commit that referenced this pull request Sep 22, 2023
…ations

- When specifying multiple destination, the `SUPPORTED_PLATFORMS` build setting needs to be set to include the various sdks for both simulator and device

Notes:

- This was cherry-picked from a draft PR for multi-platform support #5381

Test Plan:

- Multiple destinations is not yet exposed via public as such can only be validated with unit tests at this time
kwridan added a commit that referenced this pull request Sep 25, 2023
…ations

- When specifying multiple destination, the `SUPPORTED_PLATFORMS` build setting needs to be set to include the various sdks for both simulator and device

Notes:

- This was cherry-picked from a draft PR for multi-platform support #5381

Test Plan:

- Multiple destinations is not yet exposed via public as such can only be validated with unit tests at this time
kwridan added a commit that referenced this pull request Sep 25, 2023
- Updated the `GraphLinter` to account for multi-destination (multi-platform) targets
- Lint issues are now flagged only if there are no valid source and destination platform combination based on the existing rules rather than only using the `legacyPlatform` (single platform) to base the rules on

Test Plan:

- Existing unit tests should continue to pass
- New cases for valid and invalid combinations were addeed

Notes:

- This is a pre-requiste for #5381 which adds the public API for multi-desintations
kwridan added a commit to bloomberg/tuist that referenced this pull request Sep 25, 2023
…ations

- When specifying multiple destination, the `SUPPORTED_PLATFORMS` build setting needs to be set to include the various sdks for both simulator and device

Notes:

- This was cherry-picked from a draft PR for multi-platform support tuist#5381

Test Plan:

- Multiple destinations is not yet exposed via public as such can only be validated with unit tests at this time
pepicrft pushed a commit that referenced this pull request Sep 26, 2023
…ations (#5438)

- When specifying multiple destination, the `SUPPORTED_PLATFORMS` build setting needs to be set to include the various sdks for both simulator and device

Notes:

- This was cherry-picked from a draft PR for multi-platform support #5381

Test Plan:

- Multiple destinations is not yet exposed via public as such can only be validated with unit tests at this time
pepicrft pushed a commit that referenced this pull request Sep 28, 2023
- Updated the `GraphLinter` to account for multi-destination (multi-platform) targets
- Lint issues are now flagged only if there are no valid source and destination platform combination based on the existing rules rather than only using the `legacyPlatform` (single platform) to base the rules on

Test Plan:

- Existing unit tests should continue to pass
- New cases for valid and invalid combinations were addeed

Notes:

- This is a pre-requiste for #5381 which adds the public API for multi-desintations
pepicrft pushed a commit that referenced this pull request Sep 29, 2023
- Updated the `GraphLinter` to account for multi-destination (multi-platform) targets
- Lint issues are now flagged only if there are no valid source and destination platform combination based on the existing rules rather than only using the `legacyPlatform` (single platform) to base the rules on

Test Plan:

- Existing unit tests should continue to pass
- New cases for valid and invalid combinations were addeed

Notes:

- This is a pre-requiste for #5381 which adds the public API for multi-desintations
Copy link
Collaborator

@kwridan kwridan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @waltflanagan πŸ™

I'll experiment locally to see how much of a lift would the refactor of the graph types to account for platforms be if we think that is a valid path.

I think we can split this (I appreciate it further delays getting a working version πŸ™ˆ)

Option A - Exposing API first to allow limited usage + further testing

  • (1) Expose destinations in ProjectDescription and map using existing logic
  • (2) Add platformFilters support to dependencies etc...

Option B - Internally refactor to support platformFilters on dependencies ahead of exposing API

  • (1) Propagating platformFilters internally within Graph / Models
  • (2) Exposing API in ProjectDescription

Sources/TuistCore/Graph/GraphLoader.swift Outdated Show resolved Hide resolved
)
case let .target(name, path):
guard let target = target(path: path, name: name) else { return nil }
return .product(
target: target.target.name,
productName: target.target.productNameWithExtension,
platformFilters: target.target.dependencyPlatformFilters
platformFilters: target.target.dependencyPlatformFilters // What to do here now that we have smart things?
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we have a few options:

  • We can either omit platformFilters from product dependencies (i.e. .target / .project) dependencies and automatically derive this as we do today on main
  • if we expose platformFilters we'd have to do some form of intersection between the user specified filters (which may contain errors - possibly lint warn / error ahead of time) + valid filters we determine

@danieleformichelli danieleformichelli linked an issue Oct 24, 2023 that may be closed by this pull request
@waltflanagan waltflanagan force-pushed the multi-platform/Phase3 branch 6 times, most recently from 8288fe1 to 44b9a81 Compare November 10, 2023 20:13
@waltflanagan waltflanagan changed the base branch from main to multi-platform/GraphEdges November 10, 2023 20:14
@@ -15,3 +15,19 @@ public enum Platform: String, Codable, Equatable, CaseIterable {
/// The visionOS platform
case visionOS = "visionos"
}

/// A supported platform representation.
public enum PackagePlatform: String, Codable, Equatable, CaseIterable {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was introduced because SPM includes catalyst as a platform while many other parts of our system map catalyst to iOS. This was a necessary distinction when inferring destinations from a SPM package.

@waltflanagan waltflanagan force-pushed the multi-platform/GraphEdges branch 2 times, most recently from 15c5268 to 842c4a6 Compare November 27, 2023 22:21
Base automatically changed from multi-platform/GraphEdges to main November 28, 2023 15:23
@waltflanagan waltflanagan deleted the multi-platform/Phase3 branch November 28, 2023 17:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support multiplatform Targets
3 participants