Adventures in compiling for Mac OSX

I’ve come to the conclusion that the module auto-downloader concept I’d been working on was not useful to implement - there’s no ability for it to scale. With potentially dozens or more of modules for the engine being possible, there’s no sane way of building an auto-downloader that can be easily maintained and kept up-to-date. It is much simpler just to provide simple instructions for how to install a module and let the users get them from wherever they want to get them. Thus I’ve turned my attention to getting the codebase compiling and working on OSX.

Apple Xcode Logo

What. A. Nightmare. First of all I’m no big fan of MSVC, and I’m blogging from a Mac right now - and wishing my Linux box was operational: long story about bad memory chips… That said, I’d assumed when I initially stubbed support for Mac and Linux into my CMake configuration that I could use G++ - the C++ side to GCC - for both environments. I was wrong. Our codebase is written for C++11, only introduced to GCC around version 4.4 or 4.7. Apple has apparently left their shipped-with-XCode version of GCC languishing at version 4.2. Their reason? They are going full-bore forward with clang.

Clang is a rather neat front end for the LLVM compiler - in fact I’ve become rather fond of how detailed it is at analyzing the faults in our codebase; I’m ever interested in writing better code. However, it’s not the default compiler - that’s still G++. So I worked around that in CMake. Then came another shocker - while clang supports C++11, its default standard library does not. So off I went to learn about the –stdlib flag and libc++. It was about here that I realized one of clang’s biggest faults - no dedicated documentation. While my searches dug up some mention that the best documentation for clang is “man gcc”, trying to do that kind of interpretation, with all the testing and fact verifying involved, is not my idea of fun! I’d much rather be forming a beautiful logic tree, or fitting a structure around the data, etc. That IS my kind of fun.

Once I got all that worked out, then I tripped across a problem - one apparently quite common in this area: my libraries - specifically Boost - needed to be compiled with the same flags. After applying the digital equivalent of a wrench and elbow grease to my custom GetBoost.cmake I got that in place too. Now I’m only 3 linker errors away from a full compile.

These errors seem to be an interference between AngelScript, clang/LLVM, and libc++. More to come when I came get my dev environment operable again - my older Mac Mini (running Snow Leopard) decided that crazy was better than stable.


– Update 2012-07-26 –

Ok, got my systems sane again. Here’s the linker error I’m currently arguing with:

Undefined symbols for architecture x86_64:
"std::__1::basic_string, std::__1::allocator >::operator+=(std::__1::basic_string, std::__1::allocator > const& )", referenced from:
    RegisterStdString_Native(asIScriptEngine*) in libAngelScript.a(scriptstdstring.o)
"std::__1::basic_string, std::__1::allocator >::empty() const", referenced from:
    RegisterStdString_Native(asIScriptEngine*) in libAngelScript.a(scriptstdstring.o)

So it looks like, for some reason, that basic_string’s operator+= and empty() methods are not found by the linker. Commenting out the corresponding lines in the scriptstdstring add-on for AngelScript hides the problem and allows for compilation - thus we can know that all the rest of the methods were detected. It feels like there’s something not quite normal about libc++ - again, documentation would be helpful. Instead I’m going to have to digging through the source.

This is one of those few times an IDE is very helpful: right-click, Jump to Definition. Makes life much easier. Here’s the declaration and definition of these items:

/*line 1247*/ _LIBCPP_INLINE_VISIBILITY bool empty() const _NOEXCEPT {return size() == 0;}
/*line 1255*/ _LIBCPP_INLINE_VISIBILITY basic_string&  operator+=(const basic_string&  __str) {return append(__str);}

Ok, hypothesis time: the compiler might be inlining the definitions and removing the declarations. This would definitely cause the linker to not find them.

Out of time for this morning - more is coming.


– Update 2012-07-29 –

Ah, Sundays - time to really dig into the code. After some thought, and running under the assumption that my hypothesis is correct, I patched the scriptstdstring add-on to use local static functions, following the format existing in those files. This has allowed me to succeed in compiling. Now to get the OS-specific code in place so that the executable can actually run!

I’ve posted my discovery and patch over in the GameDev.net AngelCode forum for Andreas et al to comment on.