Testflight status
Posted: 22 Nov 2015, 16:25
Lions, Tigers and Bears, oh my
Getting MrMC into Testflight has certainly been a test of our coding-fu. For those that do not realize, MrMC is big, really big. We have about 25+ dependent libs that are built. Some are static, some are dynamic. Then there's the main core codebase and on top of that, sprinkle binary addons for pvr. Like I said, big, very big and very complex.
Our first pass at submitting to Testflight uncovered some minor things that were easy to fix. bundle versions and such. A tweak here and there and presto, up it goes past the Xcode nanny.
This got us past Xcode nagging and let us actually upload to Testflight which promptly sends us an email about 'invalid binary', oh snap...
Lucky, the email from Testflight contained useful but cryptic information.
Non-public API usage:
The app references non-public symbols in MrMC: __tlv_bootstrap, _yp_get_default_domain.
Humm, cryptic indeed. Time to start grep'ing and figure out which bit is the offender. I suspected one of the libs so straight to them I go. I find the symbol "__tlv_bootstrap" in libssh but then it gets strange. Nothing in the code actually refs it, WTF? More digging and bingo, it's really a side effect of libssh enabling thread local storage via __thread and THAT is a private API under iOS/tvOS. Simple fix, pass -DHAVE_GCC_THREAD_LOCAL_STORAGE=0 and tell libssh to stop using it. Poof, no more '__tlv_bootstrap'. Time to find/fix, five hours.
The next one '_yp_get_default_domain' was samba, Ugg, I hate going into samba, she's twichy but hey, I'm a pro port-master... Simple fix again, force 'ac_cv_func_yp_get_default_domain=no' and '__tlv_bootstrap' bits the dust. Time to find/fix, less than one hour then a few more for regression testing. Yep, I'm good.
Next, some dynamic libs were being build with -fembed-bitcode but missing -Wl,-bitcode_bundle for linking. Luckily, we get good feedback from the email and it points us to the offenders, a bit of diddling with linker flags and double checks to make sure we have no regressions as a result. Time to find/fix/verify, one day. Keep in mind that part of these checks rebuilding ALL of our lib depends from scratch, runtime testing then upload to Testflight and wait for the results. Like watching paint dry. Each cycle is several hours.
The last one was a bit of a mystery and stumped us for more than a few days.
"Invalid Swift Support - The SwiftSupport folder is missing. Rebuild your app using the current public (GM) version of Xcode and resubmit it."
WTF ? We have zero swift code and we ARE using the GM version of Xcode. Finally, after trying all the 'similar' fixes that others did, I take out the axe and start chopping parts out. The resulting app would never run but at least it would point to the chunk that was removed. Bingo, find it on 1st pass. Something with the dylibs we put into Frameworks. We poke and poke and oh. Turns out that what Apple means when they say dynamic libs are supported in iOS8+ is dynamic FRAMEWORKS are supported, not raw dylibs. But wait, raw dylibs are ok for the swift libs that Xcode copies over. Really ? Come on Apple, eat your own dog food now. Grrr. ok, I can deal with that.
The cleanest quick solution was add a post packing run-script that runs after we pack dylibs into Frameworks. It converts the dylibs into a valid framework bundles and off to the races we go. No more "Invalid Swift Support". But wait, step two of this is fixing how the libs are loaded in code since now the name/path does not match the codebase name/path. Grr, three days on this while we come up with a reasonable solution that actually works too
Now, we can upload (yea) , get 'binary valid' (yea) but then we barf at "There was an error importing this build. We are working to resolve the issue." (boo). Every. Single. Time. Grr. More cryptic feedback. This is where we stand today and the next step is to call them up and start pestering them...
2015.11.24 update:
Well, it's about time. That last one was a doozy. Called Dev support, after a few round with level 1, elevated to a 'senior Advisor'. While I was waiting for more paint to dry, I had a thought (which could be dangerous sometimes). I remembered that doing an achive/export/developer with bitcode gen error'ed out when I tried it a few weeks ago. The problem then was the silly error window continued way past the bottom of my display and with no scollbar, I could not see the problem. So I ignored it and moved on to better things.
My thought was, use preview to grab a screenshot and I might see the error. Well, the 1st thing I see is a 'show logs' button. OMFG, been looking for that very thing. A quick display rez change and now I can see the buttons. When you gen bitcode, it's the same thing itunes connect it doing so I figure, same problem.
9_7tznjx6gl2n54ykdf19zhh0000gn/T/MrMCMYxCe5/MrMC.arm64.out"
-= Output =-
duplicate symbol ___hidden#42769_ in:
1223.o
3295.o
duplicate symbol ___hidden#42766_ in:
1223.o
3295.o
duplicate symbol ___hidden#42770_ in:
1223.o
3295.o
ld: 3 duplicate symbols for architecture arm64
Exited with 1
WTF, the normal Linker never barfs at this ? I catch 1223.o and 3295.o on the fly (which is not as easy as it sounds) as Xcode deletes them at the end. A quick nm shows no real info. Where do these come from in a sea of MBs of compiled code. Good old nm shows nothing, grep comes up empty as does strings. Humm, a few hours of picking the scab of depends goes nowhere. I know it has to do with linking and on a hunch I remove a linker flag that is on the todo list to remove, legacy stuff that we really should not require and presto, achive/export/developer with bitcode gen completes. A quick flick into itunes connect and more watching paint dry, then after an hour and 15 mins, ding. Out pops the goodies. Oh happy day
2015.11.25 update:
“iTunes Connect: Your app MrMC has been approved for beta testing”
Time to release the kraken
Getting MrMC into Testflight has certainly been a test of our coding-fu. For those that do not realize, MrMC is big, really big. We have about 25+ dependent libs that are built. Some are static, some are dynamic. Then there's the main core codebase and on top of that, sprinkle binary addons for pvr. Like I said, big, very big and very complex.
Our first pass at submitting to Testflight uncovered some minor things that were easy to fix. bundle versions and such. A tweak here and there and presto, up it goes past the Xcode nanny.
This got us past Xcode nagging and let us actually upload to Testflight which promptly sends us an email about 'invalid binary', oh snap...
Lucky, the email from Testflight contained useful but cryptic information.
Non-public API usage:
The app references non-public symbols in MrMC: __tlv_bootstrap, _yp_get_default_domain.
Humm, cryptic indeed. Time to start grep'ing and figure out which bit is the offender. I suspected one of the libs so straight to them I go. I find the symbol "__tlv_bootstrap" in libssh but then it gets strange. Nothing in the code actually refs it, WTF? More digging and bingo, it's really a side effect of libssh enabling thread local storage via __thread and THAT is a private API under iOS/tvOS. Simple fix, pass -DHAVE_GCC_THREAD_LOCAL_STORAGE=0 and tell libssh to stop using it. Poof, no more '__tlv_bootstrap'. Time to find/fix, five hours.
The next one '_yp_get_default_domain' was samba, Ugg, I hate going into samba, she's twichy but hey, I'm a pro port-master... Simple fix again, force 'ac_cv_func_yp_get_default_domain=no' and '__tlv_bootstrap' bits the dust. Time to find/fix, less than one hour then a few more for regression testing. Yep, I'm good.
Next, some dynamic libs were being build with -fembed-bitcode but missing -Wl,-bitcode_bundle for linking. Luckily, we get good feedback from the email and it points us to the offenders, a bit of diddling with linker flags and double checks to make sure we have no regressions as a result. Time to find/fix/verify, one day. Keep in mind that part of these checks rebuilding ALL of our lib depends from scratch, runtime testing then upload to Testflight and wait for the results. Like watching paint dry. Each cycle is several hours.
The last one was a bit of a mystery and stumped us for more than a few days.
"Invalid Swift Support - The SwiftSupport folder is missing. Rebuild your app using the current public (GM) version of Xcode and resubmit it."
WTF ? We have zero swift code and we ARE using the GM version of Xcode. Finally, after trying all the 'similar' fixes that others did, I take out the axe and start chopping parts out. The resulting app would never run but at least it would point to the chunk that was removed. Bingo, find it on 1st pass. Something with the dylibs we put into Frameworks. We poke and poke and oh. Turns out that what Apple means when they say dynamic libs are supported in iOS8+ is dynamic FRAMEWORKS are supported, not raw dylibs. But wait, raw dylibs are ok for the swift libs that Xcode copies over. Really ? Come on Apple, eat your own dog food now. Grrr. ok, I can deal with that.
The cleanest quick solution was add a post packing run-script that runs after we pack dylibs into Frameworks. It converts the dylibs into a valid framework bundles and off to the races we go. No more "Invalid Swift Support". But wait, step two of this is fixing how the libs are loaded in code since now the name/path does not match the codebase name/path. Grr, three days on this while we come up with a reasonable solution that actually works too
Now, we can upload (yea) , get 'binary valid' (yea) but then we barf at "There was an error importing this build. We are working to resolve the issue." (boo). Every. Single. Time. Grr. More cryptic feedback. This is where we stand today and the next step is to call them up and start pestering them...
2015.11.24 update:
Well, it's about time. That last one was a doozy. Called Dev support, after a few round with level 1, elevated to a 'senior Advisor'. While I was waiting for more paint to dry, I had a thought (which could be dangerous sometimes). I remembered that doing an achive/export/developer with bitcode gen error'ed out when I tried it a few weeks ago. The problem then was the silly error window continued way past the bottom of my display and with no scollbar, I could not see the problem. So I ignored it and moved on to better things.
My thought was, use preview to grab a screenshot and I might see the error. Well, the 1st thing I see is a 'show logs' button. OMFG, been looking for that very thing. A quick display rez change and now I can see the buttons. When you gen bitcode, it's the same thing itunes connect it doing so I figure, same problem.
9_7tznjx6gl2n54ykdf19zhh0000gn/T/MrMCMYxCe5/MrMC.arm64.out"
-= Output =-
duplicate symbol ___hidden#42769_ in:
1223.o
3295.o
duplicate symbol ___hidden#42766_ in:
1223.o
3295.o
duplicate symbol ___hidden#42770_ in:
1223.o
3295.o
ld: 3 duplicate symbols for architecture arm64
Exited with 1
WTF, the normal Linker never barfs at this ? I catch 1223.o and 3295.o on the fly (which is not as easy as it sounds) as Xcode deletes them at the end. A quick nm shows no real info. Where do these come from in a sea of MBs of compiled code. Good old nm shows nothing, grep comes up empty as does strings. Humm, a few hours of picking the scab of depends goes nowhere. I know it has to do with linking and on a hunch I remove a linker flag that is on the todo list to remove, legacy stuff that we really should not require and presto, achive/export/developer with bitcode gen completes. A quick flick into itunes connect and more watching paint dry, then after an hour and 15 mins, ding. Out pops the goodies. Oh happy day
2015.11.25 update:
“iTunes Connect: Your app MrMC has been approved for beta testing”
Time to release the kraken