Question

I downloaded and built GNUstep libobjc2 1.6.1,

svn co http://svn.gna.org/svn/gnustep/libs/libobjc2/1.6.1/ rep
cd rep
make

and got this error when I tried to compile a Objective-C code.

hoon@ubuntu:~/work/objc2$ clang -fobjc-nonfragile-abi -fobjc-arc -fblocks *.m *.a -l pthread; ./a.out
Objective-C ABI Error: Loading modules from incompatible ABIs while loading 
a.out: loader.c:38: __objc_exec_class: Assertion `objc_check_abi_version(module)' failed.
Aborted (core dumped)

It seems I need to build libobjc.a with some different configurations. What is the problem and what should I do to fix this error?

Env: Ubuntu 12.04 LTS

Was it helpful?

Solution

This is a good question because LLVM and CLang and GNUstep don't claim to be hard or complicated to use. They do ask their users to read (and reread) their documentation though. I've just discovered this combination for Ubuntu myself and it is very intriguing. And there are a lot of moving parts at the moment.

If the OP got an answer on one of the gnustep mailing lists, then it would be nice to hear here how it was resolved.

Without suggesting the normal route of starting over and only installing the latest from LLVM and GNUstep directly, here's my take.

The OP is trying to use ARC and blocks with the runtime provided by the gunstep/libobjc2 project.

libobjc2 should probably be built with clang version 3.2 - or maybe the top of tree. clang -v will tell you what version you have on your machine. I've found even Ubuntu 12.10 doesn't provide clang-3.2. So I download it from the LLVM website. They have prebuilt binaries for Ubuntu 12.04 LTS. To get make to use clang for this build step, I've seen instructions to set and export CC=clang and CXX=clang++.

Once libobjc2 is built, care must be taken where it gets installed. If the system already has an older libobjc.so.x.y library (this provides the runtime environment for Obj-C), clang or the linker may be picking up the wrong one when you start compiling your own source. I found libobjc.so.4.6.0 built from the libobjc2 source was installed to /usr/local/lib both on Ubuntu 12.04 and 12.10 when I ran the make install step. This path was not setup by the libobjc2 install step.

To get this library picked up, I had to add /usr/local/lib to the env variable LD_LIBRARY_PATH. It wouldn't hurt to try 'locate libojbc.so' to see if there are other versions on the system.

Finally, the libobjc2 readme, https://github.com/gnustep/gnustep-libobjc2#readme, says this new version of the gnustep library supports two ABIs, and each ABI supports ARC and blocks. The advice I've seen about compiling with libobjc2 is to also provide the runtime version expected to be compiling and linking with: -fobjc-runtime=gnustep. Clang on Ubuntu still defaults to the older ABI. -fobjc-nonfragile-abi may accomplish the same thing but I've seen it mentioned that flag was or will be deprecated.

The OP error may actually come from the step where a.out is being run, rather than where clang was compiled. Perhaps the dynamic loader is picking up the legacy libobj.so. Again, I would use locate to see if the system even has more than one.

OTHER TIPS

This is just a guess, but I'm gonna go out on a limb and guess that GNUstep is going to build with GCC by default. A good first step might be to reconfigure the GNUstep build to use Clang. I can't say what variety of issues that will expose, but...

Alternately, you could try building your application with GCC instead of Clang.

This is a fairly late answer, but I have found a way to get everything working (on Elementary OS specifically so I imagine it should be fine on Ubuntu and similar distros).

As mentioned, it is better/easier to build everything from source because you get to pick the prefix, build options, etc. The general method:

  1. Install cmake (if it's not already installed) --> sudo apt-get install cmake
  2. Download, build and install llvm and clang as per the instructions here (or see attached build script). For speed, use the --enable-optimized flag. Tests are "optional" ;-)
  3. The default build scripts for compiler-rt do not include the Blocks runtime. You could modify the build scripts, or rejoice that someone else has already done it (particularly if, like me, your cmake isn't great). Download, build and install libBlocksRuntime from this git repo (it is essentially a clone of the latest compiler-rt Blocks runtime code with custom build scripts). FOLLOW THEIR COMPILATION AND TESTING METHOD.
  4. Download, build and install libobjc2 from GNUStep. The instructions for correct building are actually inside the now-deprecated makefile.
  5. Run ldconfig (if required - though there's no harm in running it even if it isn't).

As @WeakPointer you may still need to edit the LD_LIBRARY_PATH environment variable to pick up your new libraries. Another option is to make some quick and dirty symlinks so clang can find your new libraries.

Final note: I haven't done any comparisons between GNUStep's libobjc2 and GCC's libobjc, the latter of which DOES contain some Objective-C 2.0 features... Be careful with your library selection if you keep both on your system at the same time!


The following script should do it all (untested!):

#!/bin/bash
# Temporary base directories
basedir="./clangllvm_temp"
basedir2="./libBlocksRuntime_temp"
basedir3="./libObjc2_temp"

# Clang, llvm, compiler-rt
mkdir $basedir
cd $basedir
svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm
cd llvm/tools
svn co http://llvm.org/svn/llvm-project/cfe/trunk clang
cd ../..
cd llvm/tools/clang/tools
svn co http://llvm.org/svn/llvm-project/clang-tools-extra/trunk extra
cd ../../../..
cd llvm/projects
svn co http://llvm.org/svn/llvm-project/compiler-rt/trunk compiler-rt
cd ../..

mkdir build
cd build
../llvm/configure --prefix=$PREFIX --enable-optimized
make
sudo make install
cd ../..

# libBlocksRuntime
git clone https://github.com/mackyle/blocksruntime.git $basedir2
cd $basedir2
sudo ./buildlib
sudo ./checktests
sudo ./installlib
# Test!
clang -o sample -fblocks sample.c -lBlocksRuntime && ./sample
cd ..

# libobjc2
https://github.com/gnustep/gnustep-libobjc2.git $basedir3
cd $basedir3
mkdir Build
cd Build
cmake .. -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++
sudo make && sudo -E make install
cd ../..    

# Cleanup
rm -rf $basedir
rm -rf $basedir2
rm -rf $basedir3

# ldconfig
sudo ldconfig

# Additional symlink/LD_LIBRARY_PATH stuff here if required.

# EOF

Key difference was using Clang for build. Take care not to use GCC which is system default compiler. I removed gobjc and g++ packages from system to avoid this issue.

export CC=clang
export CXX=clang++

svn co http://svn.gna.org/svn/gnustep/libs/libobjc2/1.6.1/
cd 1.6.1
make

This answer was hinted from this mailing list thread: http://lists.gnu.org/archive/html/discuss-gnustep/2012-12/msg00036.html

Described script is posted here: http://wiki.gnustep.org/index.php/GNUstep_under_Ubuntu_Linux

Now it compiles simple ARC code.


It seems GCC and Clang generated codes are incompatible.

Update

I wrote scripts to setup libobjc2 on FreeBSD and CentOS.

The scripts are mostly copied from a blog.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top