Resolving App Rejections for GCC and LLVM Instrumentation
Q: My app was rejected for containing GCC or LLVM instrumentation. How do I resolve this?
A: What is instrumentation?
In this context, instrumentation is additional code compiled in to your app that allows Xcode to analyze your code and produce reports about how much of your code is run by your test cases. This coverage information is only useful when developing an app; it negatively impacts the app's speed and increases the app's size, so apps submitted to the App Store can not contain any instrumentation code.
Apps, app extensions, or frameworks containing GCC instrumentation code are rejected by the App Store with the following message:
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
To solve this rejection, configure the following build settings to
No for every target in your app:
Instrument Program Flow (
Generate Test Coverage Files (
See Configure build settings for instructions on finding and configuring build settings.
If you are unable to identify which binary in your app bundle is creating this error based on the build settings, follow the instructions in Inspect The App Package to identify the specific binary with the issue. Once you've done so, ensure the build settings for the Xcode target producing that binary are set correctly.
Apps, app extensions, or frameworks containing LLVM instrumentation code are rejected by the App Store with the following message:
Invalid Bundle - Disallowed LLVM instrumentation. Do not submit apps with LLVM profiling instrumentation or coverage collection enabled. Turn off LLVM profiling or code coverage, rebuild your app and resubmit the app.
To solve this rejection, there are multiple things to look for:
Set the Instrument Program Flow (
GCC_INSTRUMENT_PROGRAM_FLOW_ARCS) build setting to
Noand remove the flags
fcoverage-mappingfrom the Other C Flags (
OTHER_CFLAGS) build setting. See Configure build settings for instructions on finding and configuring build settings.
Disable coverage data on the scheme
Ensure all pre-compiled frameworks are built using the archive build action
Starting with Xcode 9, if the Gather coverage data option is enabled on the scheme, regular builds for the Run action will also build with code coverage instrumentation, but archive builds will not. If your app's build uses scripts to generate or move build products into place, you need to ensure these scripts only use archived build products when receiving the archive build action; otherwise, build products created with the build action will contain instrumentation and result in a rejection from the App Store.
If you are unable to identify which binary in your app bundle is creating this error based on the build settings, follow the instructions in Inspect The App Package to identify the specific binary with the issue. Once you've done so, ensure the build settings for the target producing that binary are set correctly.
Inspect The App Package
If you are unable to identify which binaries are causing the instrumentation rejection, you can manually inspect the contents of the app to discover the source of the problem.
In the Xcode Organizer, right click on the archive producing the error and select "Show In Finder."
Right click on the
.xcarchiveand select "Show Package Contents."
Navigate to the
Products/Applicationsdirectory. Right click on the app and select "Show Package Contents."
Find your app's binary, usually named the same as the app's target in Xcode.
Open Terminal, and run the command in Listing 1 to look for GCC instrumentation. Listing 2 shows an example binary with GCC instrumentation that must be removed for the App Store. Listing 3 shows the command for finding LLVM instrumentation, with Listing 4 showing an example binary with LLVM instrumentation that must be removed for the App Store. You can drag and drop the binary from Finder to the Terminal to fill in the path.
Repeat these steps for all app extensions and all frameworks in your app. If your app contains a watchOS app, also run the same procedure on the watch extension and all frameworks in the watchOS app. Make sure to give the
otoolcommand the path to the binary, and not the outer
Listing 1 Terminal command to look for GCC Instrumentation
$ nm -m -arch all <PathToArchive>/Products/Applications/<AppName>.app/<AppBinary> | grep gcov
Listing 2 Example app containing GCC Instrumentation
$ nm -m -arch all /Users/username/Desktop/Example.app/Example | grep gcov
0000000100009d34 (__TEXT,__text) external ___gcov_flush
000000010000cf20 (__DATA,__bss) non-external ___llvm_gcov_ctr
000000010000cf60 (__DATA,__bss) non-external ___llvm_gcov_ctr
000000010000d1a0 (__DATA,__bss) non-external ___llvm_gcov_ctr
000000010000d1b0 (__DATA,__bss) non-external ___llvm_gcov_ctr.1
000000010000cf70 (__DATA,__bss) non-external ___llvm_gcov_ctr.148
Listing 3 Terminal command to look for LLVM Instrumentation
$ otool -l -arch all <PathToArchive>/Products/Applications/<AppName>.app/<AppBinary> | grep __llvm_prf
Listing 4 Example app containing LLVM Instrumentation
$ otool -l -arch all /Users/username/Desktop/Example.app/Example | grep __llvm_prf
Document Revision History
New document that describes how to resolve an App Store rejection for an app containing instrumentation