Nat! bio photo

Nat!

Senior Mull.

Twitter RSS

Github

Moan: Xcode hates me and wants me to fail

The strange case of the doubly #imported file:

CompileC /Volumes/Source/srcC/hdt_release/Daemons/build/Intermediates/ArchiveIntermediates/Daemons/IntermediateBuildFilesPath/HDTFramework.build/Release/HDTFramework.build/Objects-normal/x86_64/HDTSystembenutzer+Brain.o AllgemeinBrains.subproj/HDTSystembenutzer+Brain.m normal x86_64 objective-c com.apple.compilers.llvm.clang.1_0.compiler
    cd /Volumes/Source/srcC/hdt_release/Frameworks/HDTFramework
    export LANG=en_US.US-ASCII
    /Applications/Xcode-6.3.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -x objective-c -arch x86_64 -fmessage-length=193 -fdiagnostics-show-note-include-stack -fmacro-backtrace-limit=0 -fcolor-diagnostics -Wno-trigraphs -O3 -Wno-missing-field-initializers -Wno-missing-prototypes -Wno-return-type -Wno-implicit-atomic-properties -Wno-receiver-is-weak -Wno-arc-repeated-use-of-weak -Wno-missing-braces -Wno-parentheses -Wswitch -Wno-unused-function -Wno-unused-label -Wno-unused-parameter -Wno-unused-variable -Wunused-value -Wno-empty-body -Wno-uninitialized -Wno-unknown-pragmas -Wno-shadow -Wno-four-char-constants -Wno-conversion -Wno-constant-conversion -Wno-int-conversion -Wno-bool-conversion -Wno-enum-conversion -Wshorten-64-to-32 -Wpointer-sign -Wno-newline-eof -Wno-selector -Wno-strict-selector-match -Wno-undeclared-selector -Wno-deprecated-implementations -DNS_BLOCK_ASSERTIONS -DNDEBUG -isysroot /Applications/Xcode-6.3.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk -funroll-loops -fstrict-aliasing -Wprotocol -Wno-deprecated-declarations -mmacosx-version-min=10.6 -g -Wno-sign-conversion -iquote /Volumes/Source/srcC/hdt_release/Daemons/build/Intermediates/ArchiveIntermediates/Daemons/IntermediateBuildFilesPath/HDTFramework.build/Release/HDTFramework.build/HDTFramework-generated-files.hmap -I/Volumes/Source/srcC/hdt_release/Daemons/build/Intermediates/ArchiveIntermediates/Daemons/IntermediateBuildFilesPath/HDTFramework.build/Release/HDTFramework.build/HDTFramework-own-target-headers.hmap -I/Volumes/Source/srcC/hdt_release/Daemons/build/Intermediates/ArchiveIntermediates/Daemons/IntermediateBuildFilesPath/HDTFramework.build/Release/HDTFramework.build/HDTFramework-all-target-headers.hmap -iquote /Volumes/Source/srcC/hdt_release/Daemons/build/Intermediates/ArchiveIntermediates/Daemons/IntermediateBuildFilesPath/HDTFramework.build/Release/HDTFramework.build/HDTFramework-project-headers.hmap -I/Volumes/Source/srcC/hdt_release/Daemons/build/Intermediates/ArchiveIntermediates/Daemons/BuildProductsPath/Release/include -I/Applications/Xcode-6.3.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include -I/usr/local/include -I/Volumes/Source/srcC/hdt_release/Daemons/build/Intermediates/ArchiveIntermediates/Daemons/IntermediateBuildFilesPath/HDTFramework.build/Release/HDTFramework.build/DerivedSources/x86_64 -I/Volumes/Source/srcC/hdt_release/Daemons/build/Intermediates/ArchiveIntermediates/Daemons/IntermediateBuildFilesPath/HDTFramework.build/Release/HDTFramework.build/DerivedSources -Wno-deprecated-objc-pointer-introspection -fdiagnostics-show-option -F/Volumes/Source/srcC/hdt_release/Daemons/build/Intermediates/ArchiveIntermediates/Daemons/BuildProductsPath/Release -F/Library/Frameworks -DHDT_MAJOR=1 -DHDT_MINOR=100 -DMACOSX -MMD -MT dependencies -MF /Volumes/Source/srcC/hdt_release/Daemons/build/Intermediates/ArchiveIntermediates/Daemons/IntermediateBuildFilesPath/HDTFramework.build/Release/HDTFramework.build/Objects-normal/x86_64/HDTSystembenutzer+Brain.d --serialize-diagnostics /Volumes/Source/srcC/hdt_release/Daemons/build/Intermediates/ArchiveIntermediates/Daemons/IntermediateBuildFilesPath/HDTFramework.build/Release/HDTFramework.build/Objects-normal/x86_64/HDTSystembenutzer+Brain.dia -c /Volumes/Source/srcC/hdt_release/Frameworks/HDTFramework/AllgemeinBrains.subproj/HDTSystembenutzer+Brain.m -o /Volumes/Source/srcC/hdt_release/Daemons/build/Intermediates/ArchiveIntermediates/Daemons/IntermediateBuildFilesPath/HDTFramework.build/Release/HDTFramework.build/Objects-normal/x86_64/HDTSystembenutzer+Brain.o

In file included from /Volumes/Source/srcC/hdt_release/Frameworks/HDTFramework/AllgemeinBrains.subproj/HDTSystembenutzer+Brain.m:151:
In file included from /Volumes/Source/srcC/hdt_master/Frameworks/HDTFramework/AdresseBrains.subproj/HDTPerson+Brain.h:298:
In file included from /Volumes/Source/srcC/hdt_master/Frameworks/HDTFramework/AllgemeinBrains.subproj/HDTBase+Brain.h:191:
/Volumes/Source/srcC/hdt_master/Frameworks/HDTFramework/AllgemeinBrains.subproj/_HDTBase+FetchBrain.h:42:26: warning: duplicate definition of category 'FetchBrain' on interface 'HDTBaseBase'
@interface HDTBaseBase ( FetchBrain)
                        ^
In file included from /Volumes/Source/srcC/hdt_release/Frameworks/HDTFramework/AllgemeinBrains.subproj/HDTSystembenutzer+Brain.m:150:
In file included from /Volumes/Source/srcC/hdt_release/Frameworks/HDTFramework/AllgemeinBrains.subproj/HDTBase+Brain.h:191:
/Volumes/Source/srcC/hdt_release/Frameworks/HDTFramework/AllgemeinBrains.subproj/_HDTBase+FetchBrain.h:42:12: note: previous definition is here
@interface HDTBaseBase ( FetchBrain)
          ^

So I accidentally typed #include instead of #import, right ? No:

nat@kempe:hdt_release(^release) $ grep _HDTBase+FetchBrain.h ./Frameworks/HDTFramework/AllgemeinBrains.subproj/HDTBase+Brain.h
#import "_HDTBase+FetchBrain.h"

It took me a while to finally see, that one of the headers is fetched from my developer directory hdt_master and one from my release directory hdt_release where I am building. The funny thing is, that when I grep through the clang invocation, there is no mention of hdt_master and all the files are included with #import "file.ext".How that can happen within the compilation of one source file, where the include paths should be fixed ?

You see if you make a mistake somewhere, Xcode notices this, but tries very hard to come up with a seemingly unrelated error. Xcode silently builds some header maps from the project files and places them at strategic yet obscure places in the filesystem:

nat@kempe:hdt_master(^master) $ grep hdt_master  /Volumes/Source/srcC/hdt_release/Daemons/build/Intermediates/ArchiveIntermediates/Daemons/IntermediateBuildFilesPath/HDTFramework.build/Release/HDTFramework.build/HDTFramework-project-headers.hmap
Binary file /Volumes/Source/srcC/hdt_release/Daemons/build/Intermediates/ArchiveIntermediates/Daemons/IntermediateBuildFilesPath/HDTFramework.build/Release/HDTFramework.build/HDTFramework-project-headers.hmap matches

My best guess is that HDTPerson+Brain.h is in a different directory than HDTSystembenutzer+Brain.m and because of that the header map file is consulted. This is setup with wrong absolute paths from the project and everything fails.

So it has to do with subprojects and absolute paths. When I had a large number of dependent subprojects and added it to a top project, Xcode set them all to "absolute path" references (possibly fixed in 6.3). This behaviour sucks, as the subprojects are actually parts of my repository.

So first I needed to find the problematic frameworks using ack

ack '<absolute>' | egrep -v '/Library/Frameworks'  | grep project.pbxproj

Setting these subproject references to "Group relative" is what I want.

Tips:
1. If you are nesting subprojects deeply, try to get the leaf projects 100% right first and then build up.
2. Check your target dependencies and linked frameworks after changing path types. They will be silently deleted by Xcode.
3. Quit Xcode often and gratuitously, because it gets easily confused.
4. If you are aggregating subprojects make very sure, that shared subprojects are all referenced identically.
5. Double and triple check everthing, because Xcode hates you and wants you to fail.


Post a comment

All comments are held for moderation; basic HTML formatting accepted.

Name:
E-mail: (not published)
Website: