Many From One, Again
Several months ago I wrote about some tricks I was using to build many targets from one code base. The rubber is meeting the road on that project as we get closer to being ready to submit to Apple, and what I thought then was the solution is turning out not to be so.
In the original post, I basically suggested that this simple command lined would do the trick:
[code lang=”shell” gutter=”false”]
% xcodebuild -alltargets -configuration Distribution
[/code]
And in fact, it does, to the extent that all the targets are built. The problem? This is a build, not an archive operation. So lots of bianries are created, but nowhere useful, and certainly not in the Organizer. (Anyone know any tricks to go from this point to an archive in the Organizer?)
It turns out that xcodebuild has an archive build action, but that only works if you also specify a scheme, for example:
[code lang=”shell” gutter=”false”]
% xcodebuild -scheme MyApp archive # No dash on ‘archive’, the build action
[/code]
This has the nice result that the Archive action is taken for the specified scheme, and the resulting package can be found in the Organizer. But there are 2 problems with this (at least in my setup):
- My Archive configuration is set to Ad Hoc, not Distribution, and
- I am building each target manually.
In that old post, someone commented that I might be able to have Xcode do all the work (never using the command line) if I created a “Build All” scheme, and added all my targets to it. I thought that would do the trick of building and archiving each target. But it doesn’t work that way; it builds all the targets into a single package, archives that single package, and puts that into the Organizer. Not useful at all, at least not for then being able to submit to the App Store.
In another post, I wrote about something I called The Distro Scheme, a scheme whose Archive action’s configuration was Distribution. For a project where you have one target, duplicating that target as “Distro: MyApp” (or whatever) and setting it up as described works nicely. But for many targets? I am not so sure…
Be that as it may, I may have to create a “Distro: xxx” scheme for each target in my project, and then write a shell script that uses the output from “xcodebuild -list” to pluck out the Distro schemes, and build those schemes with the “archive” build action. It could work!
The drudgery of duplicating and editing schemes awaits… I’ll post the script somewhere when it’s done.
If you have any thoughts on this topic, please chime in!
Thanks for the post. For all these extra schemes, is the only different is the signing and provisioning? If so, maybe it’s possible to just feed in a little xcconfig file with these settings in it, that would override anything provided in the actual project file and schemes (I think, I’ve not used this particular mechanism before). You can also specify the config file using the XCODE_XCCONFIG_FILE environment variable.
xcodebuild -scheme “MyApp” -xcconfig Distribution.xcconfig archive
I wouldn’t shy away from the command line though… if it doesn’t run from the command line, it’s not running on my continuous integration server, and it a lot less useful to me.
That might be a great solution! Creating one or more .xcconfig files (I’m thinking 1 per target, because each requires its own provisioning profile), and then creating in Xcode an “aggregate target” that runs a shell command to utilize the appropriate .xcconfig file for each target (or something like that) might just do the trick. I’ll have to look into it! I did some work over a year ago with .xcconfig files for a CI project. I had forgotten about all that stuff, so thanks for the reminder.
We use xconfig files in our build process, specifically to switch out profiles and signing. So I can confirm that it works. 🙂 also, remember that you can re-sign the binary when you upload in Xcode, so you don’t necessarily need a separate release target anymore.
I’d be happy to chat on Tuesday as well, if you’re still struggling with it. I’ve lost a LOT of sleep over Xcode and building, so I know how it goes. I’m @bdebow on twitter.
Thanks for this. Glad to know it can be done this way. I am going to try tackling this over the weekend, I think. But I may be in touch just the same. 🙂
I had read you can re-sign a binary. But can you then archive it as well? Or is the resigning actually resigning the archive? I’ll have to look into that too!
The re-signing is part of the share or submit process. So first you archive and then, when you go to submit or share, it offers you a selection of signing profiles. So we typically archive every build with the signing for ad hoc. Then we re-sign that archived bundle and submit to apple from within the Xcode organizer – no need to rebuild
Nice. I wondered if it was that easy. I thought there were 2 separate signing points: When you actually build/archive, and when you submit. But it sounds like the whole point of Xcode asking which profile to use when “sharing” the build is to be able to re-sign if you need to. Makes sense.