-
Notifications
You must be signed in to change notification settings - Fork 810
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 support for Copy Files build phase #345
Conversation
case .none: return nil | ||
} | ||
} | ||
} | ||
|
||
public struct CopyFiles: Equatable, Hashable { |
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.
Thinking about this, maybe this should be called CopyFilesBuildPhaseSettings
. I know it's longer, but I think it makes it clear what it's for.
Docs/ProjectSpec.md
Outdated
- `none` - Will not be added to any build phases | ||
- [ ] **copyFiles**: **[Copy Files](#copy-files)** - Options for the Copy Files build phase. If specified the `buildPhase` needs to be `copyFiles` or unspecified (in which case it will default to `copyFiles`). |
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.
Instead of this I could make it so when you specify copyFiles
for buildPhase
you have to do it as an object:
- buildPhase:
type: copyFiles
destination: productsDirectory
subpath: include/$(PRODUCT_NAME)
This might complicate it too much though, which is why I went the route I did.
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.
Also, I believe the way people will specify this is just by using the copyFiles
object and not specifying a buildPhase
manually.
@@ -74,6 +74,10 @@ extension Project { | |||
if !source.optional && !sourcePath.exists { | |||
errors.append(.invalidTargetSource(target: target.name, source: sourcePath.string)) | |||
} | |||
|
|||
if let buildPhase = source.buildPhase, buildPhase != .copyFiles, source.copyFiles != nil { |
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 need this to also pick up the case when build phase is copyFiles
but a copyFiles
section doesn't exist.
@@ -12,6 +12,7 @@ public struct TargetSource: Equatable { | |||
public var type: SourceType? | |||
public var optional: Bool | |||
public var buildPhase: BuildPhase? | |||
public var copyFiles: CopyFiles? |
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.
Instead of adding another field, I’m going to make BuildPhase
have an associated value. It makes my follow up PR easier as well as cleaning up the paths that don’t care about copyFiles.
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.
Great!
I'll update |
@yonaskolb Not sure on the protocol here. Is this fine for me to merge? |
There were just a couple of comments I wanted to make. Just on the road at the moment, but will get to them all tomorrow 😀👍 |
dstSubfolderSpec: copyFiles.destination.destination, | ||
files: buildPhaseFiles | ||
) | ||
let copyFilesBuildPhase = createObject(id: target.name, buildPhase) |
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.
Can the id include string copy files
similar to the other PBXCopyFilesBuildPhases
. That makes the resulting UUID handle clashes for when there is more than one PBXCopyFilesBuildPhase
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.
Yes, I’ll adjust 🙂.
case none | ||
// Not currently exposed as selectable options, but here to translate to PBXCopyFilesBuildPhase completely | ||
case frameworks |
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.
Do we need these in here?
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.
Yes, since this type is now used where xcproj ones were before, to allow defaulting to work correctly (see the modulemap
PR for an example).
|
||
public var buildPhase: xcproj.BuildPhase? { | ||
switch self { | ||
case .sources: return .sources | ||
case .headers: return .headers | ||
case .resources: return .resources | ||
case .copyFiles(_): return .copyFiles |
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.
nitpick: we don't need the (_)
. This would probably get removed by make format_code
anyway, so not really an issue
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 did it without and got an error. I’ll try again.
guard case let .copyFiles(copyFilesSettings)? = sourceFile.buildPhase else { continue } | ||
var sourceFilesForCopyFiles = sourceFilesByCopyFiles[copyFilesSettings] ?? [] | ||
sourceFilesForCopyFiles.append(sourceFile) | ||
sourceFilesByCopyFiles[copyFilesSettings] = sourceFilesForCopyFiles |
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.
You can use Swift 4's new dictionary accessors:
sourceFilesByCopyFiles[copyFilesSettings, default: []].append(sourceFile)
if let string = string { | ||
chosenString = string | ||
} else if copyFilesSettings != nil { | ||
chosenString = "copyFiles" |
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.
The downside of this is that if they have a TargetSource
with mixed files, there's no way to just specify the settings for the ones that will be in copyFiles
by default, because if you do that everything will be moved to the copyFiles
build phase.
I would be ok with keeping the copyFiles
struct out of the enum like you had it before. The validation error could then be thrown in the generator when searching through the files and finding any copyFiles build phase SourceFiles
(like modulemap) and it not having a copyFiles
settings.
Are there other sorts of files you would want to add to copyFiles
, or is it just modulemap
?
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.
Header files in the case of static libraries.
Let me think about your downside comment. When I had it different before it would default the whole sources to the copy files build phase, and the way I see you recommending it is that if it were determined to need to be copied it should use these settings. Right now I’m treating it exactly like all the other build phases and if specified they override any default logic. This phase just happens to require additional configuration options.
Docs/ProjectSpec.md
Outdated
@@ -279,10 +281,31 @@ targets: | |||
- "-Wextra" | |||
- path: MyOtherTargetSource3 | |||
compilerFlags: "-Werror -Wextra" | |||
- path: ModuleMaps | |||
copyFiles: |
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.
indentation
68b1cb4
to
0bb4dd5
Compare
@yonaskolb I adressed all your feedback, expect for |
Cool, I'll take a look later 😄👍 |
Will do! I'll add commits next time (I rebased a couple other PRs, sorry, I won't in the future). |
Also I should clarify. It's ok to rebase off the target branch to get new changes, but I meant not amending or squashing new commits 👍 |
@yonaskolb Rebased and ready to go. |
Docs/ProjectSpec.md
Outdated
- `sharedSupport` | ||
- `plugins` | ||
- [x] **subpath**: **String** - The path inside of the destination to copy the files. | ||
- [x] **subpath**: **String** - The path inside of the destination to copy the files. |
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.
duplicate line
case none | ||
// Not currently exposed as selectable options, but used internally | ||
case frameworks |
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.
indenting
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.
@yonaskolb I’m not sure what you are referring to here. Do you want a newline before the comment, the comment to be indented differently, or something else?
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.
Hmm, it's not showing up now. I swear case frameworks
looked indented differently before
let copyFilesBuildPhase = createObject( | ||
id: "copy files" + copyFiles.destination.rawValue + copyFiles.subpath + target.name, | ||
PBXCopyFilesBuildPhase( | ||
dstPath: copyFiles.subpath, |
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 you've tested if a the default subpath
of ""
is valid, as opposed to nil? As the value is optional in PBXCopyFilesBuildPhase
. Just trying to minimise diffs when projects are opened in Xcode
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’ll reaffirm.
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.
The default is ""
. If you don't specify it, it won't exist, which is still valid, but to match what Xcode does naturally it's ""
specified. Xcode won't change when opening either way.
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.
👍
Sometimes Xcode won't change the project on open, but if something else changes (like reordering some files is an easy way to test), then it will rewrite things in it's preferred way
|
||
public init(jsonDictionary: JSONDictionary) throws { | ||
destination = try jsonDictionary.json(atKeyPath: "destination") | ||
subpath = jsonDictionary.json(atKeyPath: "subpath") ?? "" |
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.
Would the default be nil?
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'll adjust the docs to say it's optional. We should still default it to ""
though to match Xcode behavior (there isn't a way to make it not ""
by using just Xcode).
@@ -5,6 +5,7 @@ public enum SpecParsingError: Error, CustomStringConvertible { | |||
case unknownTargetPlatform(String) | |||
case invalidDependency([String: Any]) | |||
case unknownSourceBuildPhase(String) | |||
case invalidSourceCopyFilesPhase |
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 might get unwieldy if we add more build phase enum options. Can we just used the existing unknownSourceBuildPhase
but renamed to invalidSourceBuildPhase
along with the error. Then the string can be copyFiles must be a dictionary
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.
Yep. I’ll adjust.
Consolidate `.unknownSourceBuildPhase` and `.invalidSourceCopyFilesPhase` into one.
@yonaskolb All feedback addressed besides for the indentation one (I left a question). This is G2G 😄. |
Docs/ProjectSpec.md
Outdated
@@ -260,21 +260,33 @@ A source can be provided via a string (the path) or an object of the form: | |||
- `sources` - Compile Sources phase | |||
- `resources` - Copy Bundle Resources phase | |||
- `headers` - Headers Phase | |||
- `none` - Will not be added to any build phases |
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.
Has none been removed?
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.
No. I’m not sure how that happened. I’ll fix it.
case "headers": self = .headers | ||
case "resources": self = .resources | ||
case "copyFiles": | ||
throw SpecParsingError.invalidSourceBuildPhase("copyFiles must specify directory") |
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.
Should this be copyFiles must specify a \"destination\" and optional \"subpath\"
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.
Yes, that's more descriptive.
throw SpecParsingError.invalidSourceBuildPhase("copyFiles must specify directory") | ||
case "none": self = .none | ||
default: | ||
throw SpecParsingError.invalidSourceBuildPhase("Unknown build phase \(string.quoted)") |
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 this can just be the string
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.
👍
Feel free to merge |
Nice work @brentleyjones! 🎉 |
Related to #344, this allows manually setting up Copy Files build phases.