On Oct 16, 2015, at 8:15 AM, Sak Wathanasin < email@hidden> wrote:
I'm not too clear on whether you have multiple versions inside your F/W or just 1, but not called 'A'. If the latter, the easiest thing is to let XCode do the signing. I modified the "framework versions" of one of our F/Ws to be 'B', told Xcode to sign it (release builds only), which it did. Then I built the appl, which, amomg other things, embeds all components including the signed F/Ws, then signs the appl and it's happy.
From the CLI (we use a python script on our CI system), I can codesign either the top-level F/W dir or xxxx.framework/Versions/Current and it's happy. This is with Xcode 6 (XC 4, 5 & 7 work fine as far as I know). Our build script follows what XC does, which is to sign the appl "inside out".
If you have multiple versions, I don't know how you would sign versions other "Current" without explicitly specifying them. Are the older versions not already signed from the previous builds? My (not extensive) experiments suggests that's what happens, unless you "clean" first.
There are many ways to build and codesign frameworks and applications in Xcode, and you've covered several of the bases.
Starting with your last point: In previous releases of my application product, I built shared frameworks to be installed in /Library/Frameworks/ using an installer package, which of course also installed the application itself in /Applications. The shared framework as installed included several versions of the executable (L, J and K, for example), to allow users of older and newer client applications to use the framework versions they were built for. As Apple's codesigning documentation specifies, each separate version subfolder in the shared framework is separately codesigned. I generally built each version in Xcode in turn over a period of years. I did the codesigning of each version apart from Xcode, using codesign commands in Terminal. Because each version folder is separately signed, you can manually add and remove them from the overall framework bundle without running afoul of GateKeeper, as the Apple documentation points out. So I just saved each built, codesigned version, and then assembled the ones I wanted when it came time to issue a new release of the multi-versioned, shared framework. That technique still works perfectly well, but for reasons that aren't explained in any convincing detail by Apple, Apple now recommends embedded frameworks (with one exception, which I mentioned in a previous post).
So I am now building my frameworks to embed them in each separate application. (I actually have always built a version for embedding, because all of my customers except myself have always preferred to use embedded frameworks -- presumably because it's easier unless you have already figured out how to do it the other way, as I had.) Obviously, since any particular version of the application is going to use only one version of the framework, I only need to include a single version of the embedded framework in the application. As you suggest, one way to do this is to build the framework in its own project or workspace and codesign it, and then incorporate the built framework product in a separate application project and codesign the application alone in the next stage. That works fine when you have a finished and tested version of the framework. And that's what I'm doing with most of my application products.
However, when a framwork isn't finished or isn't fully tested, it makes sense to place the framework project and the application project in a single workspace so you can edit, debug and build both of them together. It is very helpful to be able to single-step from application code into framework code and back out again. That's what I'm doing now. However, when I set both the framework target and, separately, the application target within the single workspace to build with my Developer ID for codesigning, I consistently get an error (as does one of my customers) when Xcode tries to codesign the framework, because it tries to codesign version "A" when the actual framework project contains only version "M" (or whatever). It feels like the codesign instructions must be hardwired into Xcode as "A" on the assumption that everybody will use "A" as their version in this scenario (as John Daniel suggested). But that would really surprise me, because I am also still distributing my multi-versioned framework to customers in case they want to use the shared framework approach -- and it would be terribly confusing to them and to me to lable a version as "M" in the multi-version, shared framework bundle and lable the very same version as "A" in the embedded version. As noted above, people can and do pull labeled versions out of and shove them into other framework bundles without running afoul of GateKeeper, and this would quickly lead to mistakes.
So, my original question still stands. I won't bother to look it up so as to word it identically again, but it's basically this: Is there any way in Xcode for me to specify that I want to codesign version "M" of the framework if I codesign it at build time in the target's General tab?
There is a workaround, and it's actually easier. In my two-project workspace, I can "Archive" the product and specify to Export it as a Developer-ID codesigned product. One of the dialogs that comes up specifies the application product and the "M" framework product, and when I click OK (or whatever the button says) it builds without difficulty and generates a properly codesigned application with embedded framework "M" that is also properly codesigned, and the whole application package passes all Terminal tests including one using -deep. It's only when I use the codesigning radio buttons in the General tab of each target that I run into the wrong-version error. |