It took me almost an entire day to figure out that the following issue is caused by some indeterministic behavior of Xcode. As a developer, you expect to see the same results if you use the same parameters (i.e. “deterministic”), but this is a situation that sometimes succeeds, sometimes doesn’t.
In DTFoundation I have two targets that produce a DTFoundation.framework, for iOS and OS X respectively. Now the problems seems to be that since I set both to define a module “DTFoundation”, Xcode randomly gets confused during building an iOS app and sometimes might try to build the OS X framework for iOS.
This was filed as rdar://22008701 and on Open Radar. From the looks of things Rob Rix has filed bug report rdar://20490378 that appears to be describing the same issue. If you disable implicit dependency finding in the scheme, the problem also goes away.
Xcode randomly builds dependent framework for wrong platform
Summary
Building a project randomly fails if it refers to a module which exists for both iOS and OS X with the same name. Sometimes it would correctly build the iOS version and succeed. Sometimes it would incorrectly try to build the OS X version which fails because the OS X cannot be compiled with iOS headers.
I have tried different variants of “enabling modules”, “defines module” and enabling framework auto-linking. As far as I can tell, the problem goes away if I disable “defines module” for the OS X framework, but that cannot be the solution.
As a developer I would expect for xcodebuild to always build the same dependent targets and not make non-deterministic/incorrect choices.
Steps to Reproduce
- Clone the DTRichTextEditor project from github
git clone --recursive https://github.com/Cocoanetics/DTRichTextEditor.git
- Change into the cloned folder
cd DTRichTextEditor
- Build the demo app:
xcodebuild -project DTRichTextEditor.xcodeproj -scheme "Demo App" build -sdk iphonesimulator -arch x86_64 | grep "^=|^*"
- Repeat step 3 a couple of times
Expected Results
- The build should always show ** BUILD SUCCEEDED **
- It should do that every time
- The output of step 3 should be:
=== BUILD TARGET Resource Bundle OF PROJECT DTLoupe WITH CONFIGURATION Debug ===
=== BUILD TARGET Static Library OF PROJECT DTLoupe WITH CONFIGURATION Debug ===
=== BUILD TARGET DTFoundation (iOS) OF PROJECT DTFoundation WITH CONFIGURATION Debug ===
=== BUILD TARGET Static Library OF PROJECT DTWebArchive WITH CONFIGURATION Debug ===
=== BUILD TARGET DTCoreText (iOS) OF PROJECT DTCoreText WITH CONFIGURATION Debug ===
=== BUILD TARGET DTRichTextEditor (iOS) OF PROJECT DTRichTextEditor WITH CONFIGURATION Debug ===
=== BUILD TARGET Demo App OF PROJECT DTRichTextEditor WITH CONFIGURATION Debug ===
** BUILD SUCCEEDED **
Actual Results
- Some builds succeed, some builds fail
- when the build fails you can see in the output that “DTFoundation (OS X)” is included there
- when a build fails the output of step 3 is:
=== BUILD TARGET Resource Bundle OF PROJECT DTLoupe WITH CONFIGURATION Debug ===
=== BUILD TARGET Static Library OF PROJECT DTLoupe WITH CONFIGURATION Debug ===
=== <span style="color: #ff0000;">BUILD TARGET DTFoundation (OSX) OF PROJECT DTFoundation</span> WITH CONFIGURATION Debug ===
=== BUILD TARGET DTFoundation (iOS) OF PROJECT DTFoundation WITH CONFIGURATION Debug ===
=== BUILD TARGET Static Library OF PROJECT DTWebArchive WITH CONFIGURATION Debug ===
=== BUILD TARGET DTCoreText (iOS) OF PROJECT DTCoreText WITH CONFIGURATION Debug ===
** BUILD FAILED **
Notes
Here’s a Travis-CI build that worked, with an easier to read xctool log: https://travis-ci.org/Cocoanetics/DTRichTextEditor/builds/72820037
And here’s a Travis-CI that didn’t just before. See line 683 where it fails to build a category on NSDocument which of course couldn’t be built for iOS:
https://travis-ci.org/Cocoanetics/DTRichTextEditor/builds/72819401
I found – after filing this – that I didn’t have one dependency implicit. Use the following line before step 3 to get to a state of the repository where the dependency is still implicit:
git checkout e7a8ed5e9524df1ce732fe7568cd490486505369
After I added the explicit dependency building also seems to be generally work. So the workaround is to disable implicit dependencies (and fixing all build errors that result from that). Once you have all dependencies explicit you can re-enable implicit dependencies as those don’t seem to be doing anything, at least for frameworks.
Categories: Bug Reports