Have you ever submitted a version for your app to iTunes Connect, to receive a mail after about 10-20 minutes containing the following error?

Invalid Bundle - Do not submit apps with GCC-style coverage instrumentation enabled. Specifically, the following Xcode build settings should be disabled: Instrument Program Flow Generate Test Coverage Files

After using some Google-foo, one would find that the build settings this error refers to are one or both off the following:


But these were already disabled, in all of my targets! And yet, iTunes Connect kept refusing my build(s)😔

So… What happened?

I was in the process of changing from CocoaPods to Carthage, so it had to be something related to that, but I had no clue what. And as if that wasn’t enough, our newly released Xcode 9 had changed something too:

Schemes with Code Coverage enabled (in the Test action) will now always build with Code Coverage, including for the Run and Launch actions. This reduces the need to build multiple versions of the application. Users who require code coverage to be off for their non-test actions can explicitly use a separate scheme with coverage disabled. (31848014)

I found a thread in which the effects of this change are described, and I’d summarise1 them as follows:

If you avoid Xcode building your dependency directly, e.g. if you’re using Carthage, and your dependencies are built with those symbols included, then those symbols won’t be filtered out at compile time.

These end up in your app, and iTunes Connect will respond:

Problem sir!

Who would’ve thought of that after reading those release notes, right?

Fast forward

3 months, and a lot of tension later, I resumed my search for a way to submit a version to the App Store. It turned out that Apple has published a Q&A, and there’s a way to locate and fix this.

Based on that I created the following:

Throw this in an executable shell file, pass it the directory of your IPA in the following way sh verify_no_gcc_or_llvm_symbols.sh /somedir/somewhere/your.ipa. If you don’t, it’ll recursively look in the current directory.

This script will verify that there are no GCC nor LLVM symbols at all in your IPA file. If there is, it’ll end with an exit code 1.

What I learned

In retrospect I can say that if it weren’t for switching to Carthage, I’d probably never have noticed this change. And although I had a hard time figuring this one out, there’s a lot I learned from this.

Due to the change in Xcode’s default behaviour, my transition to Carthage and moving our in-house Pod over to a Dynamic Framework, I learned a great deal about some of the things that CocoaPods does behind the scenes, without us ever knowing it.

So my advice:

Try coupling those frameworks manually, instead of just grabbing one of these dependency managers. Once you know how it works and what you need to do, only then move on to something like CocoaPods. It’ll pay off, trust me.

Some other insights I got:

  • IPA file structure
  • Knowing the existence and use off the lipo, nm and otool commands
  • Why Carthage has to strip those simulator architectures from our (fat) libraries
    • What happens if we don’t (hint: rejection)
  • How to set up a Dynamic Framework
    • With dependencies

The story

Initially I opened a Digital Support Request for this and conversed with an Apple DTS Engineer for about 10 mails back and forth. After that 10th reply nothing ever came back. I might have scared him away 😕 He might well be in hiding. Who knows ¯\_(ツ)_/¯

His timing was very inconvenient though. We had a big release coming up, there was a lot of work to be done, and with this I wasn’t sure I would be able to release nor submit alpha/beta builds at all! At least I was able to deploy directly on-device, so I could keep developping and testing those features out.

Despite that I focussed on my work, pushed on and hoped that there’d be some record of how to fix this me by the time I’d have to publish our new app (3 months later), and there was 🎉

Take away: Don’t expect too much from DTS Engineers, they scare easily!