So I want to publicly expose a Box2D (C++) pointer to other Objective-C++ classes in my cocos2d + box2d project. I declare a method "getWorld" in my interface which references C++ class b2World and imports Box2D.h. All the files in my project are .mm extension, and I get the following compile error:
In file included from DebugDrawLayer.mm:2:
In file included from World.h:10:
In file included from external/Box2d/Box2D/Box2D.h:34:
external/Box2d/Box2D/Common/b2Settings.h:22:10: fatal error: 'cassert' file not found
#include <cassert>
I guess Box2D.h is somehow compiled as C instead of C++, but I fail to understand how this happens. According to the log the include chain clearly starts from a .mm file.
Update:
The log says for World.mm (compiled earlier) that it clearly compiles as objective-c++
CompileC Objects-normal/i386/World.o World.mm normal i386 objective-c++ com.apple.compilers.llvm.clang.1_0.compiler
but for DebugDrawLayer.mm it says objective-c
CompileC Objects-normal/i386/DebugDrawLayer.o DebugDrawLayer.mm normal i386 objective-c com.apple.compilers.llvm.clang.1_0.compiler
Both files are set as default - Objective-C++ source. What gives..?
Removing DebugDrawLayer from the project and then re-adding it again solved the issue. Maybe there were some strange compiler settings on the file in the build phases settings, never checked those.
Actually correct solution it's take your code into:
I had problems with this in my Cocos2D/Box2D project, it wasn't solved until I renamed ALL my
.m
files in my project (excluding the ones in Cocos2D of course) to.mm
to compile them as Objective-C++.I guess @Adam's solution works too, but I prefer to leave compilation settings as "According to File Type", feels cleaner.
This appears to be a MAJOR bug in Xcode4, nothing to do with compiler settings - just Xcode internals.
UPDATE:
I eventually found the root cause. Yes, it's a bug in Xcode/LLVM. It compiles files in the wrong order, and then overrides its own settings, and breaks itself. Apple's tech support was too incompetent to even understand the problem, so I doubt they'll be fixing the bug anytime soon.
(NB: Skip this section, and see below, for my original answer, that gives a BRUTE FORCE but VERY QUICK TO DO solution)
What happens is ... if the compiler "sees" a C++ header while processing a C class ... it then marks that header (internally) as "C" (even when this is literally impossible).
Later on, when it comes back to that header, trying to compile it with C++, it finds it has already told-itself that the header is "C" (because it's incredibly stupid) ... and promptly crashes.
The correct solution (which requires lots of time and effort) is to go through EVERY C FILE in your project, and check (manually, because Xcode sucks) EVERY reference to EVERY header file -- and, for each one, EVERY header file it imports ... etc.
(this can take hours)
...until you find the chain of imports that leads to a C file "seeing" a C++ header.
All of this should be automated (but isn't). And the root problem shouldn't happen (if Xcode were correctly written).
I tried everything listed elsewhere on the web, most of the solutions are "keep removing/adding the file, and eventually Xcode will fix itself if you're lucky".
I wasn't lucky. The only thing that worked was:
The actual name/value is: "GCC_INPUT_FILETYPE = sourcecode.cpp.objcpp" - so my guess is that this sidesteps Xcode's (broken!) internal logic.
I had this problem when having the
#import "Box2D.h"
inPrefix.pch
. I changed the#import "Box2D.h"
to be in each file that uses it instead.I had same error and I just renamed one of my class(from which I call my box2d classes) from className.m to className.mm and now it works.