tuist / tuist Goto Github PK
View Code? Open in Web Editor NEWTuist's CLI
Home Page: https://tuist.io
License: MIT License
Tuist's CLI
Home Page: https://tuist.io
License: MIT License
If you try to run any Tuist command on a project that depends on a Carthage framework that doesn't exist, it fails.
Instead of failing, print a warning telling developers to update the Carthage dependencies.
If it is possible, it would be nice to have it and be able to process any project/workspace definition and generate appropriate file(s) :)
Describe the bug
Build setting passed as user-defined value in generated projects
To Reproduce
Target(
name: "______",
platform: .iOS,
product: .app,
bundleId: "com.xcodepm._____",
infoPlist: "____/Info.plist",
sources: "____/**",
entitlements: "____/____dev.entitlements",
dependencies: [
.carthage("Alamofire"),
],
settings: Settings(
base: ["SWIFT_OBJC_BRIDGING_HEADER": "${PROJECT_DIR}/___/BridgingHeader.h"],
debug: nil,
release: nil
)
)
Expected behavior
Set bridging header build setting to desired value.
Desktop (please complete the following information):
Since the API hides the concept of a scheme, which is considered aanXcode implementation detail, we need to generate a basic list of schemes that allows developers:
The target ProjectDescription
contains the public interface that developers have access to when they import the framework from their Project.swift
files. Although some of the code there is documented, not all of it is.
Make sure everything is documented.
Link on website to docs does not work. Same for github etc.
Is your feature request related to a problem? Please describe.
It would be nice to have the ability to convert an existing project to XPM, this would generally be a one-shot thing and would be done to easier on-board projects.
Describe the solution you'd like
An additional command for xpm to migrate an existing xcodeproj
xpm migrate
This would also have to resolve any dependencies, and would be great if it can traverse for other nested projects and automatically convert them too.
e.g.
.
โโโ Modules
โย ย โโโ Core
โย ย โย ย โโโ Core.xcodeproj
โย ย โโโ FeatureA
โย ย โย ย โโโ FeatureA.xcodeproj
โย ย โโโ Result
โย ย โโโ Result.xcodeproj
โโโ MyApp.xcodeproj
โโโ MyApp.xcworkspace
migrates to
.
โโโ Modules
โย ย โโโ Core
โย ย โย ย โโโ Core.xcodeproj
โย ย โย ย โโโ Project.swift
โย ย โโโ FeatureA
โย ย โย ย โโโ FeatureA.xcodeproj
โย ย โย ย โโโ Project.swift
โย ย โโโ Result
โย ย โโโ Project.swift
โย ย โโโ Result.xcodeproj
โโโ MyApp.xcodeproj
โโโ MyApp.xcworkspace
โโโ Project.swift
โโโ Workspace.swift
Describe alternatives you've considered
The alternative is not integrating this directly into xpm but having an alternative tool which can be used to perform the migration.
Products of type extension are copied into the app that they are extending through a build phase. The current generation logic doesn't take that into account and thus, defining extensions in xpm is not fully supported.
Ensure that all kinds of extensions are supported. That includes, watch, iMessage, stickers and tv extension.
I want to be able to include all transitive dependencies inside an executable bundle.
When building an app and breaking it up by features, I want to organise them by creating static libraries. If I link one of those static libraries in my App
then I also need to link every single transitive dependency.
In the example above, when building App
I have to ensure FeatureA
, FeatureB
and FeatureC
are all included in the "Link Binary With Libraries" build phase. Otherwise App
will fail to compile due to unresolved symbols.
App
Linked Libraries:
- FeatureA
- FeatureB
- FeatureC
It can get a little more complicated too, if we start to include resource bundles.
In this example, App
must also include the the resource bundles which are dependencies for FeatureB
and FeatureC
. These will be included in an Copy Files Phase
.
App
Linked Libraries:
- FeatureA
- FeatureB
- FeatureC
Copy Files Phase:
- FeatureBResources
- FeatureCResources
We should have the ability to automate this, otherwise the overhead in maintenance of keeping these up-to date will be costly.
Consider a more contrived example when we introduce a test bundle for FeatureA
Here we now have to include all the transitive dependencies for FeatureA
into the FeatureATest
executable bundle.
FeatureATest
Linked Libraries:
- FeatureA
- FeatureC
Copy Files Phase:
- FeatureCResources
Now scale this with more projects and more features and you then have quite a difficult task to manage them all.
Describe alternatives you've considered
This could be written externally from the project inside a different tool.
This could not be done at all, and transitive dependencies would have to manually be managed.
Additional context
Static Libraries do cause a bit of an issue when managing these transitive dependencies and trying to build them in the correct order. We need some way to force this, I experimented a few ways and have found the below method to be the least-intrusive method.
If the current target, which is non-shared (e.g., static lib), depends on other focused targets which include Swift code, we must ensure those are treated as dependencies so that Xcode builds the targets in the correct order. Unfortunately, those deps can be part of other projects which would require cross-project references.
Thankfully, there's an easy workaround because we can just create a phony copy phase which depends on the outputs of the deps (i.e., the static libs). The copy phase will effectively say "Copy libX.a from Products Dir into Products Dir" which is a nop. To be on the safe side, we're explicitly marking the copy phase as only running for deployment postprocessing (i.e., "Copy only when installing") and disabling deployment postprocessing (it's enabled by default for release builds).
By investigating into the above, these are the changes which get made to a modules xcodeproj when creating a copy files phase and adding a dependency to another module build product.
-- File Reference --
FE49F8B22101BD0200DF2D9E /* libFeatureA.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libFeatureA.a; sourceTree = BUILT_PRODUCTS_DIR; };
-- Build File --
FE49F8B32101BD0700DF2D9E /* libFeatureA.a in [MyProject] Dependencies */ = {isa = PBXBuildFile; fileRef = FE49F8B22101BD0200DF2D9E /* libFeatureA.a */; };
-- Group --
FE49F8B22101BD0200DF2D9E /* libFeatureA.a */,
-- Copy Phase --
FE49F8B02101BCE300DF2D9E /* [MyProject] Dependencies */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 8;
dstPath = "";
dstSubfolderSpec = 16;
files = (
FE49F8B32101BD0700DF2D9E /* libFeatureA.a in [MyProject] Dependencies */,
);
name = "[MyProject] Dependencies";
runOnlyForDeploymentPostprocessing = 1;
};
SPM alike, Tuist can provide a command to test the project in the current directory. The command would wrap xcodebuild
, simplifying the interface and inferring things whenever it's possible. For instance, we know the path to the project and workspace.
Here's the other issue to something similar for building the target.
Being in a folder where a project is defined, a developer could execute:
tuist test # main/default target
tuist test target
test
command which is a gateway to xcodebuild
.xcodebuild
. For example, if a -destination
command is passed, we should pass it to xcodebuild
.xcodebuild
without any formatting. We might add some improvements here in the future, but for now, let's keep the raw output.Add a Rake task to generate xcbuddyKit
documentation and include it as part of the release process.
When tuistenv
installs a new version, it pulls the source code, compiles it, and copies the files to the right folder in the system. That takes time which could be avoided if it pulled an already-compiled version of Tuist.
With every release, include a tuist.zip
file that contains the release artifacts (binary, frameworks and swiftmodules). When tuistenv
tries to install a new version, it pulls it if the bundle exist, otherwise, it falls back to the current process that compiles the source code.
tuistenv
to use the bundled release if it exists.The install command does not work.
Also it seems from resolved issues that theres Homebrew support, but it is not documented or linked anywhere.
the command 'xcbuddy version' is not working
ProjectDescription
is the framework that contains models to define projects. Since this is one of the public interfaces of Tuist, it's important that it's well documented.
Make sure all the models that are part of the framework are well documented. Moreover, make sure that the Jazzy configuration generates the right documentation for those models.
Note: Since we plan to add support for other manifest formats such as
.json
or.yaml
, it's important that attributes specify the key that should be used for those formats.
The following dependencies can be replaced by frameworks from the SPM project:
The goal of this task is to replace those with the ones from the SPM and get rid of the Swifter
dependency that is not being used. By depending on SPM packages we make sure those are actively maintained and the project is very aligned with Apple's standards.
Is your feature request related to a problem? Please describe.
Generate a scheme that includes all the targets that are part of the project. We can call that scheme: XXXProject
where XXX
is the name of the project.
Describe the solution you'd like
Update the generator to generate that scheme.
Describe the bug
If you try to update the app running xpm update
it fails after downloading the new version.
To Reproduce
Steps to reproduce the behavior:
Expected behavior
The app should get updated.
Notes
Since xpm is a command line tool, we can maybe get rid of the Sparkle complexity and build something ourselves. It'd need to pull the zip from the releases page, unzip the app, and replace the current one.
Is your feature request related to a problem? Please describe.
It can happen that the developer defines more than one headers or sources build phase in their targets. Although the manifest format supports it, Xcode projects don't.
Describe the solution you'd like
We should detect this and fail.
Describe the bug
If the glob pattern includes folders, we try to add them as if they were files. They are not so we should filter them out.
To Reproduce
Sources
.Sources/
swift generate
.Expected behavior
The Xcode project generated.
The current version of the init command only supports initializing an app or a framework for iOS, macOS and tvOS.
The goal of this task is to support initializing an app for React Native:
tuist init --platform ios --product application --react-native
Describe the bug
~ swift package generate-xcodeproj
Fetching https://github.com/apple/swift-package-manager
Fetching [email protected]:xcode-project-manager/xcodeproj.git
Fetching https://github.com/tadija/AEXML.git
Fetching [email protected]:Bouke/Glob.git
error: failed to clone; Cloning into bare repository '/Users/freak4pc/Work/Libs/xpm/.build/repositories/xcodeproj.git-7308023860412066479'...
[email protected]: Permission denied (publickey).
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
'xpm' /Users/freak4pc/Work/Libs/xpm: error: product dependency 'Utility' not found
'xpm' /Users/freak4pc/Work/Libs/xpm: error: product dependency 'Utility' not found
'xpm' /Users/freak4pc/Work/Libs/xpm: error: product dependency 'Utility' not found
'xpm' /Users/freak4pc/Work/Libs/xpm: error: product dependency 'xcodeproj' not found
'xpm' /Users/freak4pc/Work/Libs/xpm: error: product dependency 'Utility' not found`
Not sure if I'm doing anything wrong.
Describe the bug
Generating a project with Carthage dependency ends up with error.
โ Error: /bin/bash: file /Users/__/projects/___/____/Carthage/Build/iOS/Alamofire.framework/Alamofire: No such file or directory
To Reproduce
Steps to reproduce the behavior:
Add carthage dependency to target with .framework(path: "Carthage/Build/iOS/Alamofire.framework"),
Expected behavior
Generates projects with linked binary to Alamofire.framework
Desktop (please complete the following information):
Cartfile
github "Alamofire/Alamofire"
Project.swift:
import ProjectDescription
let project = Project(name: "tuistTest",
targets: [
Target(name: "tuistTest",
platform: .iOS,
product: .app,
bundleId: "com.xcodepm.tuistTest",
infoPlist: "Info.plist",
sources: "Sources/**",
dependencies: [
.framework(path: "Carthage/Build/iOS/Alamofire.framework")
]),
Target(name: "tuistTestTests",
platform: .iOS,
product: .unitTests,
bundleId: "com.xcodepm.tuistTestTests",
infoPlist: "Info.plist",
sources: "Tests/**",
dependencies: [
.target(name: "tuistTest")
])
])
command tuist generate
Since Tuist supports defining dependencies between targets and projects, and we have that information when we parse the manifests, we could offer a command that exports the dependency graph. Xcode doesn't provide such feature and I think it's very useful for modular projects where it can be hard to know what depends on what.
We can use the cocoapods-dependencies library as a reference, which does the same for CocoaPods dependencies.
Add a command that looks like:
tuist dependencies
And export the dependencies using the given format. The first implementation can export it as a JSON and we can add more formats in the future:
{
"TargetA": {
"project_path": "/xxx/xxx.xcodeproj",
"product_type": "application",
"dependencies": [
"TargetB"
]
},
"TargetB": {
"project_path": "/xx/xx.xcodeproj",
"product_type": "framework",
"dependencies": []
}
}
Is your feature request related to a problem? Please describe.
Xcode Playgrounds are very useful for:
Describe the solution you'd like
It'd be great if a project could specify a list of playgrounds that would get added to the project.
Option 1
Pass a path to a folder where all the playgrounds are contained:
let project = Project(playgrounds: ["./Playgrounds"])
Option 2
Don't pass anything and read the playgrounds from the Playgrounds
directory in the folder where the project is defined.
Describe alternatives you've considered
Not having support for Playgrounds at all.
Is your feature request related to a problem? Please describe.
The current version of Tuist outputs the Swift manifests as a JSON and then reads them. We could easily add support for other formats such as .json
and .yaml
.
Describe the solution you'd like
Project.swift
or Workspace.swift
files and remove the extension.Describe alternatives you've considered
The alternative would be keeping the Swift format as the only supported one. This format has clear advantages over the other formats, like reusability and editability using Xcode, but we should allow developers choose the format suits their needs best.
Additional context
Foundation
.When you are developing an app, the most common action that developers perform is running the app on the system or on a simulator. Unfortunately, this action is not supported by xcodebuild
which only allows building or testing a scheme.
Provide a run
action from tuist:
tuist run Target
When we execute the action:
We could remember the last simulator that the developer used and suggest using that one the next time.
Some tests are integration tests which run the commands without injecting any mock. As a consequence, there are some logs that are printed while running the tests, polluting the output of the test runner.
Ensure that we don't print any log when running the tests.
Update those tests to use the MockPrinter
, which doesn't print but collects the requests for printing for testing purposes.
This issue contains all the work that needs to be done for the first tool release.
Init
command to generate a Workspace.swift
, Project.swift
and Config.swift
.ProjectDescription
target that contains the .swift
manifests.Would be a good point add a verbose argument (--verbose || -v)
xcbuddy relies in some precompiled frameworks that are bundled in the application bundle. If the user updates its version of Xcode, which might include a new version of Swift, xcbuddy will stop working. This will change once Swift has the ABI stability.
Detect this and throws instead of crashing the app.
Targets can depend on precompiled frameworks. Tuist checks that those frameworks exit in the project before running anything. If those frameworks are generated by Carthage, the developer might forget to run Carthage before using Tuist, resulting oinan error from Tuist that cannot continue unless those files exist.
Since we can infer from the path whether a framework is generated or not by Carthage, we could run the Carthage update command ourselves. If we detect Carthage needs to be run, we compare the Cartfile
with the Cartfile.lock
file and if it changed, we pull the Carthage dependencies before continuing executing anything.
First of all, thanks for open sourcing this amazing project. ๐ฉ off
Issue
I recently faced the same issue described by #73 when installing Tuist in a new machine in which I did not have my SSH certificates configured yet.
Since Github started recommending HTTPs over SSH to clone repos, I think this issue might be faced for more people in the future.
I think defining the dependencies via HTTPs might avoid those issues.
Additional context
Definition of dependencies via SSH
https://github.com/tuist/tuist/blob/master/Package.swift#L15
The documentation to install Tuist via Homebrew also relies on SSH:
https://github.com/tuist/tuist/blame/master/README.md#L24
Github recommends HTTPs over SSH here
https://help.github.com/articles/which-remote-url-should-i-use/#cloning-with-https-urls-recommended
The tuistenv
binary is currently included in the repository. As a consequence, working on the git repository might be a bit slow since the binary needs to be pulled.
There's no need to have the binary in the repository. We can tie its versioning with tuist's and include the binary as an artifact of the release.
Besides being able to inject dependencies through one instance, there isn't outstanding benefit to justify its usage.
Deprecate the context-related protocols and classes to avoid developers from using it in the future and warn them to refactor the code whenever it's possible to stop using it.
The current error handling strategy processes and reports all the errors that blow up to the command. In order for the strategy to work, it's crucial that errors are not captured elsewhere. That can happen if you use the Swift do { } catch { }
clause without specifying the type of error that should be caught.
Since we don't want errors to go unnoticed, we should enforce that any error handling clause includes the error. To do that, we can implement a danger check that does pattern matching on the content of the modified files. If an issue is found, Danger should fail.
Well, in general, but mostly for Configurations that we are using extensively with Schemes.
Is your feature request related to a problem? Please describe.
Currently there's a custom implementation for JSON - is there a reason that we don't use the Codable API?
Describe the solution you'd like
Remove https://github.com/xcode-project-manager/xpm/blob/master/Sources/ProjectDescription/JSON.swift and make the models implement Codable API. (https://developer.apple.com/documentation/swift/codable)
Describe alternatives you've considered
The alternative is to avoid doing the work and keep the current system
This issue contains a backlog of ideas with high potential to become part of xpm in the future.
Describe the bug
The root groups in the generated projects don't refer the systems folder properly. If you do right click, and then "Show in Finder" it misleads to another folder.
To Reproduce
Expected behavior
Open the right folder on Finder.
Is your feature request related to a problem? Please describe.
We used to use Sentry but we removed it because it didn't add much value. Since we are using GitHub to track issues we could implement a utility within the project that creates issues when bugs are raised. It should first search if there's already another issue with the same error. If there is, we should point the developer to that one. If not, we should create one and let the developer know.
Describe alternatives you've considered
SPM alike, Tuist can provide a command to build the project in the current directory. The command would wrap xcodebuild
, simplifying the interface and inferring things whenever it's possible. For instance, we know the path to the project and workspace.
Being in a folder where a project is defined, a developer could execute:
tuist build # main/default target
tuist build target
build
command which is a gateway to xcodebuild
.xcodebuild
. For example, if a -destination
command is passed, we should pass it to xcodebuild
.xcodebuild
without any formatting. We might add some improvements here in the future, but for now, let's keep the raw output.Add the necessary logic to detect when there's a circular dependency between targets.
Like CocoaPods does to document the syntax of the Podfile
and the .podspec
files, we should have a reference on the website as well. The reference is useful for developers to know which attributes are available in the API and their keys when defining the manifests as a yaml or json.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.