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

Allow setting deployment target devices #541

Merged
merged 26 commits into from Oct 16, 2019

Conversation

mollyIV
Copy link
Collaborator

@mollyIV mollyIV commented Oct 9, 2019

Resolves #526

Short description πŸ“

This PR is introducing a possibility to declare deployment target in project manifest.

Solution πŸ“¦

Added deploymentTarget parameter to project manifest.

Implementation πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

  • Create DeploymentTarget descriptor
  • Add DeploymentTarget to TuistGenerator.Target
  • Update TARGETED_DEVICE_FAMILY and *_DEPLOYMENT_TARGET in Build Settings
  • Update Changelog

@tuistbot
Copy link
Contributor

tuistbot commented Oct 9, 2019

1 Warning
⚠️ Have you introduced any user-facing changes? If so, please take some time to update the documentation. Keeping the documentation up to date makes it easier for users to learn how to use Tuist.

Generated by 🚫 Danger

@mollyIV
Copy link
Collaborator Author

mollyIV commented Oct 9, 2019

Hey @pepibumur πŸ‘‹

Just started a draft PR. I added a DeploymentTarget to a Target description.

Now I am trying to apply these changes into a target generation (pbxproj under the hood). According to the documentation:

TuistGenerator: It contains all the business logic to read the project definition and generate Xcode projects

so I believe this is a folder I should take a look at. Still figuring out the core concepts of xcodeproj generation. I believe the next step should be adding deploymentTarget to TuistGenerator.Models.Target, right? πŸ€” Is there any Target's property that I can have a look at the reference and do it in a similar manner?

I believe we should do the changes in DefaultSettingsProvider. We use BuildSettingsProvider.targetDefault to get target values. How we could update the one we are interested in, i.e. TARGETED_DEVICE_FAMILY?

Could you please confirm I am heading a good direction? πŸ™ Thanks!

@codecov
Copy link

codecov bot commented Oct 9, 2019

Codecov Report

Merging #541 into master will decrease coverage by 0.33%.
The diff coverage is 98.79%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #541      +/-   ##
==========================================
- Coverage    91.6%   91.27%   -0.34%     
==========================================
  Files         370      369       -1     
  Lines       20165    19681     -484     
==========================================
- Hits        18472    17963     -509     
- Misses       1693     1718      +25
Impacted Files Coverage Ξ”
Sources/ProjectDescription/Target.swift 100% <100%> (ΓΈ) ⬆️
Sources/TuistGenerator/Linter/SettingsLinter.swift 100% <100%> (ΓΈ) ⬆️
Sources/TuistGenerator/Linter/TargetLinter.swift 97.05% <100%> (+0.47%) ⬆️
Tests/ProjectDescriptionTests/TargetTests.swift 100% <100%> (ΓΈ) ⬆️
...TuistGeneratorTests/Linter/TargetLinterTests.swift 100% <100%> (ΓΈ) ⬆️
...neratorTests/Models/TestData/Target+TestData.swift 100% <100%> (ΓΈ) ⬆️
Sources/ProjectDescription/DeploymentTarget.swift 100% <100%> (ΓΈ) ⬆️
Sources/ProjectDescription/DeploymentDevice.swift 100% <100%> (ΓΈ) ⬆️
...rojectDescriptionTests/DeploymentTargetTests.swift 100% <100%> (ΓΈ) ⬆️
...urces/TuistGenerator/Models/DeploymentDevice.swift 100% <100%> (ΓΈ) ⬆️
... and 129 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Ξ” = absolute <relative> (impact), ΓΈ = not affected, ? = missing data
Powered by Codecov. Last update 166272b...86d1980. Read the comment docs.

@pepicrft
Copy link
Contributor

so I believe this is a folder I should take a look at. Still figuring out the core concepts of xcodeproj generation. I believe the next step should be adding deploymentTarget to TuistGenerator.Models.Target, right? πŸ€” Is there any Target's property that I can have a look at the reference and do it in a similar manner?

You are right. On one side we have the models in the ProjectDescription framework that are the ones that the users use in their Project.swift files, and on the other side we have the models in the TuistGenerator that are akin to the ones in ProjectDescription but in some cases extended. For example, some paths in the ProjectDescription framework are provided as globs, and in the TuistGenerator are expanded to an array of paths. This class contains some extensions that are responsible for the mapping between the models in the two domains.

I believe we should do the changes in DefaultSettingsProvider. We use BuildSettingsProvider.targetDefault to get target values. How we could update the one we are interested in, i.e. TARGETED_DEVICE_FAMILY?

The DefaultSettingsProvider is a utility class that returns project and target build that are default to the target's product and platform. Since this is information provided by the user, I don't think that utility class is a good place to define those.

If you look at the ConfigGenerator utility class, there are some methods to generate the build settings for the project and the target. Notice that the settings are the result of extend the settings in the following order of priority:

  • Default settings
  • Base settings
  • Variant settings

In your case, I'd add another type of settings:

  • Default settings
  • Manifest settings
  • Base settings
  • Variant settings

That way we make the manifest settings overridable through base & variant settings. Does it make sense?

public enum DeploymentTarget: Codable {
case iOS(String, [DeploymentDevice])
case macOS(String)
// TODO: πŸ™ˆ Add `watchOS` and `tvOS` support
Copy link
Contributor

Choose a reason for hiding this comment

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

Soon :)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Actually, what platforms should we support in this PR? πŸ€”

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Should I leave this TODO or is it possible to support watchOS and tvOS right now?

@pepicrft
Copy link
Contributor

The PR is looking good so far @mollyIV

@mollyIV
Copy link
Collaborator Author

mollyIV commented Oct 10, 2019

That way we make the manifest settings overridable through base & variant settings. Does it make sense?

Yes, it does @pepibumur thank you! πŸ™‡
I added the new changes to the PR. Would you mind to have a look? πŸ™

As the next step, we need to update Build Settings to set a *_DEPLOYMENT_TARGET option, i.e.:

image

IPHONEOS_DEPLOYMENT_TARGET
MACOSX_DEPLOYMENT_TARGET
TVOS_DEPLOYMENT_TARGET
WATCHOS_DEPLOYMENT_TARGET

Any tip where to look for it in the codebase? πŸ™‡

@kwridan
Copy link
Collaborator

kwridan commented Oct 10, 2019

Nice work @mollyIV! πŸ‘

Any tip where to look for it in the codebase? πŸ™‡

I don't believe they are currently set anywhere, perhaps set them in
ConfigGenerator.updateTargetDerived(buildSettings:...)? That currently does something similar where it sets build settings based on the various Target properties

CHANGELOG.md Outdated Show resolved Hide resolved
@mollyIV
Copy link
Collaborator Author

mollyIV commented Oct 11, 2019

πŸ‘‹ I think this PR is ready for a round of manual testing 🎊

Could you please briefly describe the best way to test my changes manually? I can imagine the following testing steps:

  1. Create a new project via
tuist init --name demoProject --platform ios 
  1. Update Project.swift
let project = Project(name: "App",
                      targets: [
                        Target(name: "App",
                                    platform: .iOS,
                                    deploymentTarget: .iOS("13.0", [.iphone])
  1. Generate Xcode project via
tuist generate
  1. Check if the deployment target was set correctly in Xcode project.

Unfortunately I am not sure how to execute tuist commands that include the changes from this PR.

Thoughts? πŸ™‡

@mollyIV mollyIV marked this pull request as ready for review October 12, 2019 09:31
@pepicrft
Copy link
Contributor

I left some minor comments. Besides them, I'd also:

  • Update any of the existing acceptance tests to use the new API. Acceptance tests are very handy to test Tuist's features end to end and detect if changes are breaking. You can read more about testing here.
  • I'd also add documentation for the new attribute in this file, otherwise the users won't know that this feature is available and how to use it.

After addressing this things I think we are in a good state to merge the PR. So happy to seeing this feature making it into Tuist and also your first contribution to the project πŸŽ‰

@pepicrft
Copy link
Contributor

I forgot to add one thing. What about extending the init command to include that attribute in the generated manifest?

@mollyIV
Copy link
Collaborator Author

mollyIV commented Oct 14, 2019

I forgot to add one thing. What about extending the init command to include that attribute in the generated manifest?

I had a look at InitCommand and I am wondering how we would like to get a deployment target from a user:

$ tuist init --name Demo --platform ios --deployment-target-version ios --deployment-target-devices iphone ipad

Thoughts? πŸ€”

@mollyIV
Copy link
Collaborator Author

mollyIV commented Oct 14, 2019

I noticed all of the deploy/* jobs started failing, do you know why? πŸ€”

@pepicrft
Copy link
Contributor

I had a look at InitCommand and I am wondering how we would like to get a deployment target from a user:

I'd not add more parameters. Instead, I'd default the platform most common's destination device and latest OS device.

I noticed all of the deploy/* jobs started failing, do you know why? πŸ€”

You can ignore those. I have to fix it 😬

@mollyIV
Copy link
Collaborator Author

mollyIV commented Oct 15, 2019

I forgot to add one thing. What about extending the init command to include that attribute in the generated manifest?

I'd not add more parameters. Instead, I'd default the platform most common's destination device and latest OS device.

This PR contains quite a few changes already. Maybe we could create a separate task for this one and tackle it when this PR is merged?

@pepicrft
Copy link
Contributor

This PR contains quite a few changes already. Maybe we could create a separate task for this one and tackle it when this PR is merged?

You can make the call here :). My only concern is that task might end up forgotten in the backlog.

@@ -191,5 +191,24 @@ final class ConfigGenerator: ConfigGenerating {
}
}
}

if let deploymentTarget = target.deploymentTarget {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Any help how we could test it? Shall we add checking the settings build to an existing method in ConfigGeneratorTest or maybe create a new one?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Sure, here's an example of one of the test cases that could be written in ConfigGeneratorTests

func test_generateTargetWithDeploymentTarget() throws {
        // Given
        let target = Target.test(deploymentTarget: .iOS("12.0", [.iphone, .ipad]))
        
        // When
        try subject.generateTargetConfig(target,
                                     pbxTarget: pbxTarget,
                                     pbxproj: pbxproj,
                                     projectSettings: .default,
                                     fileElements: ProjectFileElements(),
                                     graph: Graph.test(),
                                     sourceRootPath: AbsolutePath("/project"))
        
        // Then
        let configurationList = pbxTarget.buildConfigurationList
        let debugConfig = configurationList?.configuration(name: "Debug")
        let releaseConfig = configurationList?.configuration(name: "Release")
        
        let expectedSettings = [
            "TARGETED_DEVICE_FAMILY": "1,2",
            "IPHONEOS_DEPLOYMENT_TARGET": "12.0"
        ]
        
        assert(config: debugConfig, contains: expectedSettings)
        assert(config: releaseConfig, contains: expectedSettings)
    }

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I added deployment target tests to ConfigGenerator, thanks for your help πŸ™‡

@mollyIV
Copy link
Collaborator Author

mollyIV commented Oct 15, 2019

Hello @pepibumur and @kwridan πŸ‘‹

Thank you so much for your feedback and help with this PR, I really appreciate it πŸ™‡
I did the requested changes. I'd like to kindly ask you for another round of code review πŸ™ Could you also have a look at unresolved conversations and add your comments there?

I did a bit of manual testing (mostly base positive scenarios) and looks it is working as expected πŸ’―I will be testing it more tomorrow.

Cheers πŸ™‡

settings["TARGETED_DEVICE_FAMILY"] = .string(deviceFamilyValues.map { "\($0)" }.joined(separator: ","))
settings["IPHONEOS_DEPLOYMENT_TARGET"] = .string(version)

if devices.contains(.ipad), devices.contains(.mac) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

ah didn't realise this ... is the iPad checkbox a pre-requisite to the Mac checkbox ? i.e. is [.iphone, .mac] an invalid option?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

is the iPad checkbox a pre-requisite to the Mac checkbox ?

Exactly πŸ‘

image

☝️ If the iPad is un-checked, we cannot select a Mac.

Screen Shot 2019-10-15 at 21 22 51

☝️ If the iPad is checked, we can select a Mac.

is [.iphone, .mac] an invalid option?

Yes, that is why we need the condition I added.

@pepicrft
Copy link
Contributor

One more conflict to solve and I think we are good to merge this PR πŸŽ‰

@pepicrft pepicrft merged commit 2e04f8c into tuist:master Oct 16, 2019
@pepicrft
Copy link
Contributor

Congrats @mollyIV on your first contribution πŸŽ‰ πŸŽ‰

@mollyIV mollyIV deleted the allow-setting-deployment-target-devices branch October 16, 2019 10:27
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.

feature request: Allow setting deployment target devices
4 participants