-
Notifications
You must be signed in to change notification settings - Fork 823
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
Add caching #412
Add caching #412
Conversation
files.append(contentsOf: target.configFilePaths) | ||
for source in target.sources { | ||
let sourcePath = basePath + source.path | ||
let sourceChildren = (try? sourcePath.recursiveChildren()) ?? [] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess I could filter out directories?
project.lock
Outdated
@@ -0,0 +1,348 @@ | |||
# XCODEGEN VERSION | |||
1.11.2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an example of a lockfile
I get this error when trying to use this:
|
I added the specific error to the log and got this:
|
We can test this once this is working fine, but in our experience using the json project spec instead of the yaml one was significantly faster, that might make sense to do for the lockfile too, especially since the format of it shouldn't matter for consumers |
Ok with this change (we'd have to solve the 10.13 issue some other way): diff --git i/Sources/XcodeGen/main.swift w/Sources/XcodeGen/main.swift
index 132c48b..dcf7caf 100644
--- i/Sources/XcodeGen/main.swift
+++ w/Sources/XcodeGen/main.swift
@@ -44,7 +44,7 @@ func fatalError(_ message: String) -> Never {
// Lock file
var lockFileContent: String = ""
let lockFilePath = lockfile.isEmpty ? nil : Path(lockfile)
- if let lockFilePath = lockFilePath {
+ if let lockFilePath = lockFilePath, #available(macOS 10.13, *) {
let files = Array(Set(project.allFiles))
.map { $0.byRemovingBase(path: project.basePath).string }
@@ -53,8 +53,9 @@ if let lockFilePath = lockFilePath {
let spec: String
do {
- let node = try Node(projectDictionary)
- spec = try Yams.serialize(node: node)
+ let data = try JSONSerialization.data(withJSONObject: projectDictionary,
+ options: [.sortedKeys,.prettyPrinted])
+ spec = String(data: data, encoding: .utf8)!
} catch {
fatalError("Couldn't serialize spec for lockfile")
} I was able to use this successfully. Here are our timings:
We're currently on 1.11.1 and our gen time on my machine is ~13 seconds. So we're seeing a pretty serious hit here. I think the no-op time is likely a little higher than we'd want. Maybe that's different because of my change though. Happy to help profile more if you'd like. |
Is there any reason why it's opt-in, instead of defaulting to somewhere like
I don't think we should know about how to run other third party commands. Especially cocoapods does a lot of complicated stuff, so I would leave it alone, not adding |
I tried it for now. It works fine with a project with 3000 source files. awesome! $ time ./XcodeGen --spec project.yml --lockfile project.lock --quiet
7.52 real 6.82 user 0.44 sys
$ time ./XcodeGen --spec project.yml --lockfile project.lock --quiet
1.59 real 0.78 user 0.09 sys
$ time ./XcodeGen --spec project.yml --lockfile project.lock --quiet
0.61 real 0.51 user 0.07 sys
$ time ./XcodeGen --spec project.yml --quiet
6.87 real 6.23 user 0.39 sys
$ time ./XcodeGen --spec project.yml --quiet
10.82 real 8.00 user 0.49 sys
$ rm project.lock
$ time ./XcodeGen --spec project.yml --lockfile project.lock --quiet
12.68 real 9.10 user 0.49 sys
$ rm project.lock
$ time ./XcodeGen --spec project.yml --lockfile project.lock --quiet
12.24 real 8.90 user 0.62 sys
$ rm project.lock
$ time ./XcodeGen --spec project.yml --lockfile project.lock --quiet
6.00 real 5.58 user 0.35 sys
$ rm project.lock
$ time ./XcodeGen --spec project.yml --lockfile project.lock --quiet
6.34 real 5.83 user 0.39 sys |
@keith yeah json will be better 👍 @toshi0383 it's opt in for now as it's just a test, but will be opt out if it runs performantly and without issues. I like your idea of writing the cache file to a special directory. That way people don't have to bother adding it to their Any ideas for another name for this functionality? Maybe |
Why don't we just do |
@toshi0383 because you wouldn't want to run an unnecessary and lengthy pod install if the project hasn't changed. |
Or we can add option like It gets a little complex when you want to execute multiple commands. ref: https://github.com/sharkdp/fd#parallel-command-execution |
If possible I think XcodeGen should avoid tying itself to CocoaPods or any other tool that isn't required for using XcodeGen itself |
I'm 👌 to this option. Maybe with optional exit code from user. |
f513dd8
to
b5d3fb5
Compare
I've updated and renamed to |
Also added a |
Still not sure on the naming of this feature. Does anyone have any thoughts on it? |
EDIT: Renamed feature to caching
This is a start at resolving #409, and solving the problem of generating projects when they don't need to be. This makes using xcodegen in a git-checkout hook much better
How it currently works is you have to pass a
--lockfile
argument to xcodegen specifying a file it should read and write to for determining if the project has changed. egxcodegen --lockfile project.lock
. This file would be added to.gitignore
.If this file exists it is read before generation. Only if any of the following has changed will it continue with generation:
includes
)I'm not sold on the idea of the name lockfile. Not sure if the filename should be configurable either or just be a default filename, or configurable via the spec itself?
Another possible enhancement would be handling only running
pod install
if no generation occurs.This could happen via:
--pod-install
flag that automatically runs pod installTasks: