unraveling libcxxabi/libcxx

Hi,
   I'm currently looking into porting libcxx to an ancient system (powerpc-darwin8), and I noticed that libcxx depends on libcxxabi. However, libcxxabi's sources include headers like <exception> which are expected to be in some C++ library. Does it (mutually) depend on libcxx? Maybe this was obvious, but I take it libcxxabi needs a c++11 compiler to build, correct? (This would be fine, as I have stage-1 clang built from gcc-4.0/libstdc++.) Does one {libcxx,libcxxabi} need to be installed before the other, or should they be built cross-referencing each others include dirs? In terms of shared-library dependencies, libcxx should link to libcxxabi, right?

Is there better documentation somewhere that I don't know about?
All I see are html pages at http://libcxxabi.llvm.org and http://libcxx.llvm.org/.

Fang

Contributions to better documentation (and your experiences in doing this) are welcome. :slight_smile:

Yes, libcxxabi is the lower-level library. libcxx should link to libcxxabi.

Yes, currently libcxxabi is using -std=c++0x and probably needs it, though I can't think offhand of a specific need. If you need to, try changing that to -std=c++03. If there's any breakage it will almost certainly be compile-time breakage. So that is a safe experiment.

libcxxabi is designed to be ABI compatible with a gcc-4.2 era libstdc++. And therefore could almost certainly use a libstdc++-4.2 set of headers if need be to build against (another untested theory).

As libcxxabi is the lower-level library, I would go with installing that first. But understand you're traversing territory where few have gone before.

Keep us posted, and blogs of your experience which might help future porters are welcome.

Howard

Hi,

I'm currently looking into porting libcxx to an ancient system
(powerpc-darwin8), and I noticed that libcxx depends on libcxxabi. However, libcxxabi's sources include headers like <exception> which are expected to be in some C++ library. Does it (mutually) depend on libcxx? Maybe this was obvious, but I take it libcxxabi needs a c++11 compiler to build, correct? (This would be fine, as I have stage-1 clang built from gcc-4.0/libstdc++.) Does one {libcxx,libcxxabi} need to be installed before the other, or should they be built cross-referencing each others include dirs? In terms of shared-library dependencies, libcxx should link to libcxxabi, right?

Is there better documentation somewhere that I don't know about? All I see are html pages at http://libcxxabi.llvm.org and http://libcxx.llvm.org/.

Contributions to better documentation (and your experiences in doing this) are welcome. :slight_smile:

Sure, once I have a better understanding (and success). (And maybe along with it some Makefile/autotool files...)

Yes, libcxxabi is the lower-level library. libcxx should link to libcxxabi.

Yes, currently libcxxabi is using -std=c++0x and probably needs it, though I can't think offhand of a specific need. If you need to, try changing that to -std=c++03. If there's any breakage it will almost certainly be compile-time breakage. So that is a safe experiment.

One symbol that is referenced is std::get_unexpected(), which is both new and deprecated in c++11. Another c++11 symbol needed is std::get_terminate(). I discovered this when I tried to use g++-4.0's libstdc++ headers and got compilation errors.

libcxxabi is designed to be ABI compatible with a gcc-4.2 era libstdc++. And therefore could almost certainly use a libstdc++-4.2 set of headers if need be to build against (another untested theory).

I also encountered:
../src/cxa_exception.hpp:66:9: error: unknown type name '_Unwind_Exception'

and a search led me to various versions of "unwind.h".
The one in clang does some include_next magic.
I did however find one buried in /usr/lib/gcc/powerpc-apple-darwin8/4.0.1/include/unwind.h
with the needed typedef.
I'm trying that now, but stop me if I'm going down a wrong path!

As libcxxabi is the lower-level library, I would go with installing that first. But understand you're traversing territory where few have gone before.

I'll try this, pointing to libcxx's headers just for the prototypes that are needed from <exception>. As you said, there should be no symbol dependence to libcxx.

Keep us posted, and blogs of your experience which might help future porters are welcome.

Howard

Fang

Hi,

I'm currently looking into porting libcxx to an ancient system
(powerpc-darwin8), and I noticed that libcxx depends on libcxxabi. However, libcxxabi's sources include headers like <exception> which are expected to be in some C++ library. Does it (mutually) depend on libcxx? Maybe this was obvious, but I take it libcxxabi needs a c++11 compiler to build, correct? (This would be fine, as I have stage-1 clang built from gcc-4.0/libstdc++.) Does one {libcxx,libcxxabi} need to be installed before the other, or should they be built cross-referencing each others include dirs? In terms of shared-library dependencies, libcxx should link to libcxxabi, right?

Is there better documentation somewhere that I don't know about? All I see are html pages at http://libcxxabi.llvm.org and http://libcxx.llvm.org/.

Contributions to better documentation (and your experiences in doing this) are welcome. :slight_smile:

Sure, once I have a better understanding (and success). (And maybe along with it some Makefile/autotool files...)

Yes, libcxxabi is the lower-level library. libcxx should link to libcxxabi.

Yes, currently libcxxabi is using -std=c++0x and probably needs it, though I can't think offhand of a specific need. If you need to, try changing that to -std=c++03. If there's any breakage it will almost certainly be compile-time breakage. So that is a safe experiment.

One symbol that is referenced is std::get_unexpected(), which is both new and deprecated in c++11.

Yeah, my motto is: If you're going to standardize, do it with sense of humor. :slight_smile:

Another c++11 symbol needed is std::get_terminate(). I discovered this when I tried to use g++-4.0's libstdc++ headers and got compilation errors.

libcxxabi is designed to be ABI compatible with a gcc-4.2 era libstdc++. And therefore could almost certainly use a libstdc++-4.2 set of headers if need be to build against (another untested theory).

I also encountered:
../src/cxa_exception.hpp:66:9: error: unknown type name '_Unwind_Exception'

and a search led me to various versions of "unwind.h".
The one in clang does some include_next magic.
I did however find one buried in /usr/lib/gcc/powerpc-apple-darwin8/4.0.1/include/unwind.h
with the needed typedef.
I'm trying that now, but stop me if I'm going down a wrong path!

This is a serious problem. The unwind library is a part of the Itanium ABI, a public specification of the API: http://mentorembedded.github.com/cxx-abi/

But at this point in time, Apple does not open source this part of the API (to the best of my knowledge anyway). There may or may not be other open source implementations of this part of the API, I honestly do not know (maybe others here do?).

As libcxxabi is the lower-level library, I would go with installing that first. But understand you're traversing territory where few have gone before.

I'll try this, pointing to libcxx's headers just for the prototypes that are needed from <exception>. As you said, there should be no symbol dependence to libcxx.

<nod>

Howard

Hi Howard, David,

Hi,

I'm currently looking into porting libcxx to an ancient system
(powerpc-darwin8), and I noticed that libcxx depends on libcxxabi. However, libcxxabi's sources include headers like <exception> which are expected to be in some C++ library. Does it (mutually) depend on libcxx? Maybe this was obvious, but I take it libcxxabi needs a c++11 compiler to build, correct? (This would be fine, as I have stage-1 clang built from gcc-4.0/libstdc++.) Does one {libcxx,libcxxabi} need to be installed before the other, or should they be built cross-referencing each others include dirs? In terms of shared-library dependencies, libcxx should link to libcxxabi, right?

Is there better documentation somewhere that I don't know about? All I see are html pages at http://libcxxabi.llvm.org and http://libcxx.llvm.org/.

Contributions to better documentation (and your experiences in doing this) are welcome. :slight_smile:

Sure, once I have a better understanding (and success). (And maybe along with it some Makefile/autotool files...)

Yes, libcxxabi is the lower-level library. libcxx should link to libcxxabi.

Yes, currently libcxxabi is using -std=c++0x and probably needs it, though I can't think offhand of a specific need. If you need to, try changing that to -std=c++03. If there's any breakage it will almost certainly be compile-time breakage. So that is a safe experiment.

One symbol that is referenced is std::get_unexpected(), which is both new and deprecated in c++11.

Yeah, my motto is: If you're going to standardize, do it with sense of humor. :slight_smile:

Another c++11 symbol needed is std::get_terminate(). I discovered this when I tried to use g++-4.0's libstdc++ headers and got compilation errors.

libcxxabi is designed to be ABI compatible with a gcc-4.2 era libstdc++. And therefore could almost certainly use a libstdc++-4.2 set of headers if need be to build against (another untested theory).

I also encountered:
../src/cxa_exception.hpp:66:9: error: unknown type name '_Unwind_Exception'

and a search led me to various versions of "unwind.h".
The one in clang does some include_next magic.
I did however find one buried in /usr/lib/gcc/powerpc-apple-darwin8/4.0.1/include/unwind.h
with the needed typedef.
I'm trying that now, but stop me if I'm going down a wrong path!

This is a serious problem. The unwind library is a part of the Itanium ABI, a public specification of the API: http://mentorembedded.github.com/cxx-abi/

But at this point in time, Apple does not open source this part of the API (to the best of my knowledge anyway). There may or may not be other open source implementations of this part of the API, I honestly do not know (maybe others here do?).

If you're looking for a pristine clang environment with no GPL, then libunwind can do this for you (http://www.nongnu.org/libunwind/). If you don't mind some GPL code, then libgcc also contains the level 1 unwinder.

As libcxxabi is the lower-level library, I would go with installing that first. But understand you're traversing territory where few have gone before.

I'll try this, pointing to libcxx's headers just for the prototypes that are needed from <exception>. As you said, there should be no symbol dependence to libcxx.

<nod>

Howard

Michael

Hi Michael,

If you're looking for a pristine clang environment with no GPL, then libunwind can do this for you (http://www.nongnu.org/libunwind/). If you don't mind some GPL code, then libgcc also contains the level 1 unwinder.

I found that as well. For now, I just want to get off the ground as quickly as possibly, GPL or not. I can just link to
/usr/lib/libgcc_s.10.4.dylib on powerpc-darwin8 for libunwind. Maybe later, when I run out of road-block issues, I'll checkout nongnu.org/libunwind (and hope they support powerpc-darwin8).

Fang

Some success here compiling and linking libc++abi.

I whipped up a Makefile (attached) and tweaked some flags, a bunch of variables defined to my environment.
My compile looks like:

ccache /Volumes/Isolde/builds/LLVM/gcc40-cmake-build/bin/clang++ -gdwarf2 -O0 -std=c++0x -stdlib=libc++ -fstrict-aliasing -Wstrict-aliasing=2 -Wsign-conversion -Wshadow -Wconversion -Wunused-variable -Wmissing-field-initializers -Wchar-subscripts -Wmismatched-tags -Wmissing-braces -Wshorten-64-to-32 -Wsign-compare -Wstrict-aliasing=2 -Wstrict-overflow=4 -Wunused-parameter -Wnewline-eof -fPIC -fno-common -no-integrated-as -I../include -I/Users/fang/local/src/LLVM-svn/libcxx.git/include -I/usr/lib/gcc/powerpc-apple-darwin8/4.0.1/include -c ../src/typeinfo.cpp -o typeinfo.o

ccache /Volumes/Isolde/builds/LLVM/gcc40-cmake-build/bin/clang++ -dynamiclib -nodefaultlibs -current_version 1 -compatibility_version 1 -install_name /usr/local/experimental/llvm/lib/libc++abi.1.dylib -lSystem -lgcc_s.10.4 abort_message.o cxa_aux_runtime.o cxa_default_handlers.o cxa_demangle.o cxa_exception.o cxa_exception_storage.o cxa_guard.o cxa_handlers.o cxa_new_delete.o cxa_personality.o cxa_unexpected.o cxa_vector.o cxa_virtual.o exception.o private_typeinfo.o stdexcept.o typeinfo.o -o libc++abi.1.dylib

I used -O0 because -O1 is buggy (bug 14579).
-gdwarf2 because that's what old /usr/bin/ld can understand.
-fno-common for targeting dylibs.
-no-integrated-as because integrated-as was giving me a few relocation entries in non-writable sections (__TEXT,__eh_frame).

After installation:
% otool -L /usr/local/experimental/llvm/lib/libc++abi.dylib
/usr/local/experimental/llvm/lib/libc++abi.dylib:
   /usr/local/experimental/llvm/lib/libc++abi.1.dylib (compatibility version 1.0.0, current version 1.0.0)
   /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 88.1.12)
   /usr/lib/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0)

Next, I'll need to run tests, after I understand what 'testit' is doing, and after some sleep. :slight_smile:

Fang

Makefile.darwin (2.53 KB)

Hi Howard and all,

I was able to build libcxxabi and libcxx on powerpc-darwin8.
I've documented my experiences here. http://www.csl.cornell.edu/~fang/sw/llvm/#libcxx

I might need some explanation for how the test suite is expected to be run. The 'testit' script in libcxxabi doesn't even refer to the libc++abi.dylib that was built, so there must be some implicit assumptions in this script?

I'm hoping there's a way to test the dylib before having to install it.
Likewise with libc++.

Fang

On OS X, you can:

export DYLD_LIBRARY_PATH=<path-to-libcxx>/lib
clang++ -std=c++11 -stdlib=libc++ -nostdinc++ -I<path-to-libcxx>/include -L<path-to-libcxx>/lib test.cpp

(sub in libc++abi where appropriate). The DYLD_LIBRARY_PATH symbol can contain multiple paths, using ':' as a separator.

Howard

I also figured out how to run your testit script:

% env TRIPLE=powerpc-apple-darwin8 CC=/Users/fang/local/src/LLVM-svn/gcc40-cmake-build/bin/clang++ HEADER_INCLUDE="-I/usr/local/experimental/llvm/lib/libcxxabi/include -I/usr/local/experimental/llvm/lib/libcxx/include/c++/v1" SOURCE_LIB="-L/usr/local/experimental/llvm/lib/libcxx/lib -L/usr/local/experimental/llvm/lib/libcxxabi -lc++abi" ./testit
/Users/fang/local/src/LLVM-svn/gcc40-cmake-build/bin/clang++ -std=c++0x -stdlib=libc++ -I/usr/local/experimental/llvm/lib/libcxxabi/include -I/usr/local/experimental/llvm/lib/libcxx/include/c++/v1 -L/usr/local/experimental/llvm/lib/libcxx/lib -L/usr/local/experimental/llvm/lib/libcxxabi -lc++abi catch_array_01.cpp -o ./a.out
/usr/bin/ld: Undefined symbols:
___eprintf
clang-3.1: error: linker command failed with exit code 1 (use -v to see invocation)
catch_array_01.cpp failed to compile

I should also be able to change the variables to point to built directories instead of installed directories.

As for the link error, I found the ___eprintf symbol defined in /usr/lib/libstdc++.6.0.4.dylib, even though this symbol comes from <assert.h>. Apparently this symbol was provided in darwin8.

references:
http://www.opensource.apple.com/source/libstdcxx/libstdcxx-5.1/patches/eprintf.patch
http://gcc.gnu.org/ml/libstdc++/2005-11/msg00183.html
https://github.com/bdunogier/spotyxbmc2/blob/master/xbmc/osx/eprintf.cpp

For compatibility, I'll need to amend libc++ with the trivial implementation of ___eprintf for compatibility, as libstdc++ did.

Fang

Hi Howard,

I whipped up another Makefile to compile tests to different executables, where the resulting commands look like:

/Users/fang/local/src/LLVM-svn/gcc40-cmake-build/bin/clang++ -std=c++0x -stdlib=libc++ -O0 -no-integrated-as -I../include -cxx-isystem /usr/local/experimental/llvm/lib/libcxx/include/c++/v1 -I/usr/lib/gcc/powerpc-apple-darwin8/4.0.1/include unwind_01.cpp ../lib/libc++abi.1.dylib -L/usr/local/experimental/llvm/lib/libcxx/lib -o unwind_01

Unfortunately, I get a ton of test failures. Just to pick one arbitrarily:

% env DYLD_LIBRARY_PATH=../lib gdb ./unwind_01
GNU gdb 6.3.50-20050815 (Apple version gdb-696) (Sat Oct 20 18:20:28 GMT 2007)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "powerpc-apple-darwin"...
warning: --arch option not supported in this gdb.
Reading symbols for shared libraries ..... done

(gdb) run
Starting program: /Volumes/Isolde/sources/LLVM-svn/libcxxabi.git/test/unwind_01
tcsh: Word too long.
Reading symbols for shared libraries .++ done
libc++abi.dylib: terminating with uncaught exception of type int

Program received signal SIGABRT, Aborted.
0x90047dac in kill ()
(gdb) where
#0 0x90047dac in kill ()
#1 0x9012d7b4 in abort ()
#2 0x00205a18 in abort_message ()
#3 0x00205ce0 in _ZL25default_terminate_handlerv ()
#4 0x00214738 in std::__terminate ()
#5 0x00215888 in __cxxabiv1::call_terminate ()
#6 0x0021580c in __cxxabiv1::scan_eh_tab ()
#7 0x00214d38 in __gxx_personality_v0 ()
#8 0x9143cbc0 in _Unwind_RaiseException ()
#9 0x00212cd4 in __cxa_throw ()
#10 0x000020c8 in f2 ()
#11 0x0000212c in f1 ()
#12 0x000021cc in main ()

I see how unwind_01.cpp is supposed to work. Any idea why
"throw 55;" isn't getting caught by catch(int)?

The libunwind I'm using happens to be the one shipped with libgcc_s.10.4.
Not sure what Apple version number that would correspond to.

How can I go about debugging this?

Fang

I'm not sure what's wrong. But my first guess is that the type_info for int isn't getting laid down by the compiler, or perhaps more than one is.

It surprised the heck out of me when I first discovered where and how this happens. In:

libxxabi/src/private_typeinfo.cpp, line 79:

// __fundamental_type_info

// This miraculously (compiler magic) emits the type_info's for:
// 1. all of the fundamental types
// 2. pointers to all of the fundamental types
// 3. pointers to all of the const fundamental types
__fundamental_type_info::~__fundamental_type_info()
{
}

So possibilities include:

* Maybe clang isn't actually laying down the type_info's for the fundamental types here.
* Maybe the type_info's are getting laid down, but they aren't getting exported.
* Maybe the type_info's are getting laid down, but not just here, but elsewhere too, and you're getting multiple type_info's for int. For catch(int) to work, there must be only one type_info for int in the entire application.

Hope this helps. I'm basically rambling without knowing what's going on, in the hopes that my random walk will accidentally hit a solution.

Howard