0

I'm trying to understand how Objective-C works, and the simplest example I found so far is from https://codeseekah.com/2012/09/12/compiling-objective-c-without-a-gui/ ; unfortunately, I cannot quite get it to compile (actually, link).

First of all, I use Ubuntu 14.04 (64-bit), and here I've installed:

sudo apt-get install clang-3.5 libobjc-4.8-dev

Then, I have the (slightly modified) files from the referenced page in this gist, so you can just do:

cd /tmp
git clone https://gist.github.com/dc0b573ae8ef2424aaeb043a6014b7fd.git testobjc
cd testobjc
make

The Makefile there is modified to use the currently installed clang-3.5.

The first problem I had, was:

main.m:45:26: error: class method '+new' not found (return type defaults to 'id') [-Werror,-Wobjc-method-access]
  Person *brad = [Person new];

I found Unable to compile Objective-C code on Ubuntu :

+(id)new is a function of the NSObject class. However, you are subclassing a runtime Object. To use most of the Apple methods you're used to using in OS X, you'll need to subclass NSObject instead.
You can still use the Foundation framework while using the GNU runtime. It should be available. There is a reference you can use here: blog.lyxite.com/2008/01/…

That last is a dead link, but copy on http://www.cnblogs.com/jack204/archive/2012/03/21/2410095.html :

To Compile Objective-C Programs on Linux, GNUstep needs to be installed

Then I found How to instantiate a class in Objective-C that don't inherit from NSObject :

You absolutely can do so. Your class simply needs to implement +alloc itself, the way that NSObject does. At base, this just means using malloc() to grab a chunk of memory big enough to fit the structure defining an instance of your class.

So this is what I don't get:

  • If GNUstep provides Foundation Objective-C framework on GNU/Linux, then what is the role of libobjc?!

Since none of these zoneAlloc functions (needed for init/alloc) etc are available with the install of the above two packages, I did grep -r " id" //usr/lib/gcc/x86_64-linux-gnu/4.8/include/objc, and found there is a function class_createInstance that returns an id, and so by defining a new method that uses it, the compiler does not generate error messages in the compilation step anymore.

But then, it fails in the linking step - the full build log is also in the gist (as make.log) - with:

/usr/bin/ld: cannot find -lobjc
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [all] Error 1

Well, first of all, libobjc.so is in the directory /usr/lib/x86_64-linux-gnu:

$ ls -la /usr/lib/x86_64-linux-gnu/libobjc*
lrwxrwxrwx 1 root root     19 May  7  2016 /usr/lib/x86_64-linux-gnu/libobjc_gc.so.4 -> libobjc_gc.so.4.0.0
-rw-r--r-- 1 root root 267552 May  7  2016 /usr/lib/x86_64-linux-gnu/libobjc_gc.so.4.0.0
lrwxrwxrwx 1 root root     16 May  7  2016 /usr/lib/x86_64-linux-gnu/libobjc.so.4 -> libobjc.so.4.0.0
-rw-r--r-- 1 root root 112536 May  7  2016 /usr/lib/x86_64-linux-gnu/libobjc.so.4.0.0

... and in the Makefile, I've tried running the clang command by setting both LD_LIBRARY_PATH and LIBRARY_PATH to /usr/lib/x86_64-linux-gnu - and I've also specified it with the "additional library paths" switch -L (in LDFLAGS). All of this seems to be ignored by the time the linker command "/usr/bin/ld" runs, but that doesn't matter, because the linker command itself has this in its arguments:

... -L/usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu ...

... and this path does indeed expand to /usr/lib/x86_64-linux-gnu (checked it with readlink -f), which is where libobjc.so.* are. But still the linker command fails ?!

So my second question is:

  • Why doesn't ld find libobjc.so.*, even if /usr/lib/x86_64-linux-gnu where it is located is specified on its command line arguments via -L -- and what do I need to do, to get this program to link?
sdaau
  • 36,975
  • 46
  • 198
  • 278
  • I could expect a closevote for this question for many reasons, but definitely not for "off-topic"? Can someone explain how come this is off topic, and where can I post it instead (if there is such a site on Stack Exchange?) Thanks! – sdaau Oct 09 '17 at 14:11

1 Answers1

0

Oh, well, turns out the linking stage can be solved with a symlink; I first tried to test with ld, and at first I was getting:

$ ld -L/usr/lib/x86_64-linux-gnu  -lobjc
ld: cannot find -lobjc

... however, with an explicit path, then ld does not complain about "cannot find" anymore:

$ ld -v /usr/lib/x86_64-linux-gnu/libobjc.so.4
GNU ld (GNU Binutils for Ubuntu) 2.24
ld: warning: cannot find entry symbol _start; not setting start address

So, when I looked at the directory more closely:

$ (cd /usr/lib/x86_64-linux-gnu; ls libobjc*)
libobjc_gc.so.4  libobjc_gc.so.4.0.0  libobjc.so.4  libobjc.so.4.0.0

... it turns out, there are no files called simply libobjc.so - they all have names like libobjc.so.*... So I thought, maybe I should maybe a symlink with a name of libobjc.so:

cd /usr/lib/x86_64-linux-gnu/
sudo ln -s libobjc.so.4.0.0 libobjc.so

... and now when I run make - it actually succeeds! I get an executable file called main, and it runs fine:

$ ./main 
Hello, my name is Brad Cox!
Hello, my name is Tom Love!

Well, nice to have that sorted...

sdaau
  • 36,975
  • 46
  • 198
  • 278