Merge pull request #692 from tuist/document-helpers
Document project description helpers
This commit is contained in:
commit
371a7f0d6f
|
@ -73,7 +73,7 @@ bash <(curl -Ls https://install.tuist.io)
|
|||
## Bootstrap your first project 🌀
|
||||
|
||||
```bash
|
||||
tuist init --platform ios --product application
|
||||
tuist init --platform ios
|
||||
tuist generate # Generates Xcode project & workspace
|
||||
```
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ export default {
|
|||
menu: [
|
||||
'Getting started',
|
||||
'Project & Workspace',
|
||||
'Project description helpers',
|
||||
'Configuration',
|
||||
'Dependencies',
|
||||
'Setup',
|
||||
|
|
|
@ -33,7 +33,7 @@ cd MyApp
|
|||
And then run:
|
||||
|
||||
```bash
|
||||
tuist init --platform ios --product application
|
||||
tuist init --platform ios
|
||||
```
|
||||
|
||||
The `init` command will bootstrap an iOS application, which includes the `Info.plist` files, an `AppDelegate.swift,` a tests file, and a **`Project.swift` that contains the definition of the project.**
|
|
@ -0,0 +1,163 @@
|
|||
---
|
||||
name: Project description helpers
|
||||
---
|
||||
|
||||
import Message from '../components/message'
|
||||
import { List } from 'semantic-ui-react'
|
||||
|
||||
# Project description helpers
|
||||
|
||||
## Motivation
|
||||
|
||||
One of the inconveniences of Xcode when we use it with large projects is that it doesn't allow reusing elements of the projects other than the build settings through `.xcconfig` files. Being able to reuse project definitions is useful for the following reasons:
|
||||
|
||||
- It eases the **maintenance** because changes can be applied in one place and all the projects get the changes automatically.
|
||||
- It makes it possible to define **conventions** that new projects can conform to.
|
||||
- Projects are more **consistent** and therefore the likelihood of broken builds due inconsistencies is significantly less.
|
||||
- Adding a new projects becomes an easy task because we can reuse the existing logic.
|
||||
|
||||
Reusing code across manifest files is possible in Tuist thanks to the concept of **project description helpers**.
|
||||
|
||||
## Definition
|
||||
|
||||
Project description helpers are Swift files that get compiled into a framework, `ProjectDescriptionHelpers`, that manifest files can import.
|
||||
|
||||
<Message
|
||||
info
|
||||
title="Structure"
|
||||
description="Tuist is not opinionated about the files structure and the content in them so it's up to you to give them a structure that makes sense for your project."
|
||||
/>
|
||||
|
||||
You can import them into your manifest file by adding an import statement at the top of the file:
|
||||
|
||||
```swift
|
||||
// Project.swift
|
||||
import ProjectDescription
|
||||
import ProjectDescriptionHelpers
|
||||
```
|
||||
|
||||
## Location
|
||||
|
||||
Tuist traverses up the directories hierarchy until it finds a `Tuist` directory. Then it builds the helpers module including all the files under the `ProjectDescriptionHelpers` directory in the `Tuist` directory. Below you find an example of a project with helpers:
|
||||
|
||||
<List>
|
||||
<List.Item>
|
||||
<List.Icon name='folder' />
|
||||
<List.Content>
|
||||
<List.Header>Tuist</List.Header>
|
||||
<List.Description>A global Tuist's directory</List.Description>
|
||||
<List.List>
|
||||
<List.Item>
|
||||
<List.Icon name='folder' />
|
||||
<List.Content>
|
||||
<List.Header>ProjectDescriptionHelpers</List.Header>
|
||||
<List.Description>A directory that contains all the helpers</List.Description>
|
||||
<List.List>
|
||||
<List.Item>
|
||||
<List.Icon name='file'/>
|
||||
<List.Content>
|
||||
<List.Header>Project+Templates.swift</List.Header>
|
||||
<List.Description>A helper that extends the Project with some templated initializers.</List.Description>
|
||||
</List.Content>
|
||||
</List.Item>
|
||||
</List.List>
|
||||
</List.Content>
|
||||
</List.Item>
|
||||
</List.List>
|
||||
</List.Content>
|
||||
</List.Item>
|
||||
<List.Item>
|
||||
<List.Icon name='folder' />
|
||||
<List.Content>
|
||||
<List.Header>Projects</List.Header>
|
||||
<List.Description>A directory that contains all the projects</List.Description>
|
||||
<List.List>
|
||||
<List.Item>
|
||||
<List.Icon name='folder' />
|
||||
<List.Content>
|
||||
<List.Header>App</List.Header>
|
||||
<List.Description>A contains the app project</List.Description>
|
||||
<List.List>
|
||||
<List.Item>
|
||||
<List.Icon name='file' />
|
||||
<List.Content>
|
||||
<List.Header>Project.swift</List.Header>
|
||||
<List.Description>The app's Project.swift. It can import helpers.</List.Description>
|
||||
</List.Content>
|
||||
</List.Item>
|
||||
</List.List>
|
||||
</List.Content>
|
||||
</List.Item>
|
||||
<List.Item>
|
||||
<List.Icon name='folder' />
|
||||
<List.Content>
|
||||
<List.Header>Settings</List.Header>
|
||||
<List.Description>A contains the settings project</List.Description>
|
||||
<List.List>
|
||||
<List.Item>
|
||||
<List.Icon name='file' />
|
||||
<List.Content>
|
||||
<List.Header>Project.swift</List.Header>
|
||||
<List.Description>The settings' Project.swift. It can import helpers.</List.Description>
|
||||
</List.Content>
|
||||
</List.Item>
|
||||
</List.List>
|
||||
</List.Content>
|
||||
</List.Item>
|
||||
</List.List>
|
||||
</List.Content>
|
||||
</List.Item>
|
||||
</List>
|
||||
|
||||
|
||||
|
||||
## Example
|
||||
|
||||
The snippets below contain an example of how we extend the `Project` model to add static constructors and how we use them from a `Project.swift` file:
|
||||
|
||||
**Project+Templates.swift**
|
||||
|
||||
```swift
|
||||
import ProjectDescription
|
||||
|
||||
extension Project {
|
||||
public static func featureFramework(name: String, dependencies: [TargetDependency] = []) -> Project {
|
||||
return Project(name: name,
|
||||
targets: [
|
||||
Target(name: name,
|
||||
platform: .iOS,
|
||||
product: .framework,
|
||||
bundleId: "io.tuist.\(name)",
|
||||
infoPlist: "\(name).plist",
|
||||
sources: ["Sources/\(name)/**"],
|
||||
resources: ["Resources/\(name)/**",],
|
||||
dependencies: dependencies),
|
||||
Target(name: "\(name)Tests",
|
||||
platform: .iOS,
|
||||
product: .unitTests,
|
||||
bundleId: "io.tuist.\(name)Tests",
|
||||
infoPlist: "\(name)Tests.plist",
|
||||
sources: ["Sources/\(name)Tests/**"],
|
||||
resources: ["Resources/\(name)Tests/**",],
|
||||
dependencies: [.target(name)])
|
||||
])
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Project.swift**
|
||||
|
||||
|
||||
```swift
|
||||
import ProjectDescription
|
||||
import ProjectDescriptionHelpers
|
||||
|
||||
let project = Project.featureFramework(name: "MyFeature")
|
||||
```
|
||||
|
||||
|
||||
<Message
|
||||
info
|
||||
title="Conventions"
|
||||
description="Note how through the function we are defining conventions about the name of the targets, the bundle identifier, and the folders structure."
|
||||
/>
|
Loading…
Reference in New Issue