Project file serialized as XML #52

Closed
exalted opened this Issue Feb 18, 2013 · 24 comments

Projects

None yet

5 participants

@exalted
exalted commented Feb 18, 2013

Xcodeproj will serialize *.pbxproj file as XML instead of Xcode default's property list (OpenStep plist) format. This is pretty annoying. Frankly I didn’t expect this, is there anyway keeping original file format and apply only related changes?

P.S.: do you think could you somehow trigger Xcode from CLI and make it re–serialize its own way after Xcodeproj did its job? Like a fake change, undo it and save (which is what would you do manually after all)…

Reference: thoughtbot/liftoff#27

@alloy
Member
alloy commented Feb 18, 2013

Frankly I didn’t expect this, is there anyway keeping original file format and apply only related changes?

Hmm, I was going to say ‘no’, but I re-read the documentation on it and I may have been confused when I initially read this.

It is definitely deprecated in NSPropertyListSerialization, but we use the lower level CFPropertyList API and there it’s only ‘discouraged’, so maybe it actually does work.

I will take a look at this tonight!

@alloy
Member
alloy commented Feb 18, 2013

Note though, that Xcode adds inline comments and probably has some custom sorting which we won’t have anyways, so there will still be diffs.

@alloy alloy was assigned Feb 18, 2013
@exalted
exalted commented Feb 18, 2013

@alloy I understand that Xcode may be doing more under the hood, but still I hope it’s worth giving a shot! Thanks… I am personally looking forward on this.

@alloy
Member
alloy commented Feb 18, 2013

Alas, unfortunately it definitely is a no-go:

Property list format kCFPropertyListOpenStepFormat not supported for writing

The only solution I can see is to implement a generator in pure Ruby, but I’m not yet sold on the idea. Mainly because people –and I assume you as well– want this for diff/merge reasons, which we won’t prevent this way either because of the aforementioned comments that Xcode adds.

@irrationalfab Do you have any thoughts on the matter?

@exalted
exalted commented Feb 18, 2013

@alloy although it stinks, how about an Xcode CLI hackery or maybe an automator script which will trigger Xcode to re–serialize?

@alloy
Member
alloy commented Feb 19, 2013

@exalted Do you know of a way to do this reliably from the CLI without automator/applescript etc?

@fabiopelosin
Member

Although it would be nice, I think that we should not spend too much time on this because I expect Apple to drop the old plist format from Xcode sooner or later.

Unfortunately I don't know about an automatic way use Xcode for restoring the old format. To trigger the save in Xcode it is necessary to edit the project (like chaining the order of a file reference), however to my knowledge there is no way to this from the command line.

@exalted
exalted commented Feb 19, 2013

@alloy nope, not that I know if… I wouldn’t be too sceptical on a quick AppleScript hack though: play/play uses it and it’s 🤘 !

@alloy
Member
alloy commented Feb 20, 2013

AppleScript does its job of interfacing with UI applications well, which is why it’s ideal for apps like Play, but this is a lib that’s usually used from the CLI and as such I don’t think that that’s a good match, sorry.

@alloy alloy closed this Feb 20, 2013
@shortstuffsushi

I know this issue is a year old, but as Xcode still hasn't stopped using it, is there any chance you might consider offering a way to generate the old style output? Perhaps not as the default, but as an option?

The use case I have is using it with Cordova, which uses node-xcode to manage it's Xcode project. Unfortunately, node-xcode is only compatible with the old style. It has a number of other problems as well, but Cordova is built on top of it, and so we can't really get around using it.

I looked at using the xcproj tool you mentioned as well, but this would require people to also have Homebrew installed, or build it themselves. Even then, they're installing an entire tool to literally run the touch command, which hardly seems worth it for our case (an install/upgrade script).

So, maybe?

@shortstuffsushi

I also noticed #61 references including (?) the xcproj tool, and that was closed, but I'm not seeing that within this; is it supposed to be a part of the xcodeproj gem?

@fabiopelosin
Member

@shortstuffsushi you need to install the https://github.com/0xced/xcproj tool manually. If available xcodeproj will pick it up automatically.

@shortstuffsushi

Thanks @irrationalfab, but what I was saying above is that it would be nice if people didn't have to do this. We're building a sort of framework projects for other teams at our company, and we're trying to minimize dependencies (obviously). At this point, Homebrew isn't required, and we were hoping to avoid it (installing Homebrew to install xcproj to run touch is a bit unfortunate).

Would you consider adding an option to write in the old style? I recognize that you're trying to be forward compatible, but since everything else is using the old style, it would be really helpful.

@fabiopelosin
Member

The old style is deprecated and can't be serialised to in Foundation, it can only be read. Moreover Xcode adds a multitude of inline comments which are not easy to replicate. The xcproj tool internally loads the private frameworks of Xcodeproj and thus is the best approach.

So the only reasonable way to have that behaviour with the dependency is to ship a binary with this gem. I'm not opposed to it, but @alloy might. Moreover, it requires some logic to easily opt out from it and to disable it on linux. This is not high in my priority list, though.

@shortstuffsushi

What is Foundation in this context? I'm familiar with the Foundation library in Objective C, but are you talking in terms of Ruby maybe?

Shipping with the binary is something I hadn't thought of, but would ultimately solve the problem as well. It would be a problem on other systems, but is Cocoapods really meant to be used with other systems? You can't build iOS applications on them, and Xcode is entirely specific to OSX, right?

@fabiopelosin
Member

CoreFoundation... the Objective-C one: see https://github.com/CocoaPods/Xcodeproj/blob/master/ext/xcodeproj/xcodeproj_ext.c#L13-L15.

Shipping with the binary is something I hadn't thought of, but would ultimately solve the problem as well. It would be a problem on other systems, but is Cocoapods really meant to be used with other systems? You can't build iOS applications on them, and Xcode is entirely specific to OSX, right?

Please disregard what I said. Xcodeproj is already bound to OS X by Foundation.

@shortstuffsushi

Aha! I was trying to find how you guys were doing serialization -- missed that file altogether. And yes, that way, with those classes specifically, is probably not going to be able to write in the old fashion.

Is there any reason you aren't able to use the same libs/functions xcproj uses though? It's using Objective C, but that shouldn't be an issue -- it's all compiled by the same tools, and your users will certainly have them. You wouldn't even have to change any existing code, since it's just a superset of C -- you could just add the new functionality.

@fabiopelosin
Member

Depending on loading the private frameworks of Xcode is very fragile (it breaks every time you update xcode requiring a re-compilation specific to that version of Xcode – and now that I remember this is the reason why we don't bundle it).

@shortstuffsushi

I'm not sure I follow. If you just reused your existing code, but made it a .m instead of .c, and compiled with xcrun, like you currently are for the.c file, it should continue to "just work." From there, you could change/add into that file the ability to write into the old style, like xcproj is. Does that make sense? Do you think that would work, or do you see other potential for problems?

@alloy
Member
alloy commented Apr 30, 2014

@shortstuffsushi Alas, we cannot do this. The amount of edge-cases that this opens-up is too much to even list (so please excuse me for not even trying), but the simplest one is probably:

We are using the most documented form of the Xcode document, namely that it’s a serialised ‘plist’. We do not make any assumptions about the implementation thereof, so we are safe from Apple switching the plist format they use in any upcoming Xcode update (assuming they still use a serialised ‘plist’), node-xcode clearly is not safe of this. Thus, adding something (xcproj) that potentially breaks the CocoaPods workflow of users while CocoaPods itself works fine with their documents is not an improvement in my book.

From reading the discussion, I think you guys should include the prebuilt xcproj prebuilt binary in your Cordova bundle and deal with those edge-cases instead.

@fabiopelosin
Member

@shortstuffsushi to be clear xcproj needs to be recompiled every time xcode is updated and shipping it would open a can worm of related to support issues for CocoaPods.

@shortstuffsushi

Well there's a copout haha 😉 I still think you might be missing the point that I'm trying to make, though. You wouldn't have to break backwards compatibility -- you can keep the default behavior and code the same. I'm proposing an additional code path when some flag or option is provided that instead invokes the other writing behavior.

Maybe it'd be best if I tried to actually do this myself and then submitted a PR for further discussion. Actually having the example in front of everyone might make more sense then talking about the hypothetical solution.

@irrationalfab, do you know why xcproj needs to be recompiled with Xcode updates? I'm having a hard time finding a reason this would be the case. A compiled binary shouldn't stop working when your IDE/SDK changes. I could see it no longer compiling with the updates, which seems to happen with every iOS update, but compiled items don't stop working.

@kylef
Contributor
kylef commented Apr 30, 2014

@shortstuffsushi Check the limitations on xcproj.

It might not be worth wasting time on this right now so close to WWDC. Apple may 😉 release a new Xcode soon, updating Xcode to use the newer plist format.

@shortstuffsushi

Ah perfect, thanks @kylef. That makes much more sense in terms of the changing between versions. I didn't realize it was linking to a framework via a local path, I can see how that would be unstable. I'm still curious about trying it, but perhaps waiting to see what they mention at WWDC would be a good call. Thanks for taking the time to discuss it guys.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment