在Ubuntu上使用clang构建简单的Objective-C示例(链接失败)?

时间:2017-10-09 14:03:06

标签: objective-c linux linker clang

我试图了解Objective-C的工作原理,到目前为止我发现的最简单的例子来自https://codeseekah.com/2012/09/12/compiling-objective-c-without-a-gui/;不幸的是,我无法完全编译(实际上是链接)。

首先,我使用的是Ubuntu 14.04(64位),这里我安装了:

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

然后,我在this gist中的引用页面中有(略微修改过的)文件,所以你可以这样做:

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

Makefile已修改为使用当前安装的clang-3.5

我遇到的第一个问题是:

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

我找到Unable to compile Objective-C code on Ubuntu

  

+(id)new是NSObject类的一个函数。但是,您是运行时对象的子类。要使用您在OS X中习惯使用的大多数Apple方法,您需要替代NSObject的子类。
  在使用GNU运行时,您仍然可以使用Foundation框架。它应该可用。你可以在这里找到一个参考资料:blog.lyxite.com/2008/01/...

最后一个是死链接,但复制在http://www.cnblogs.com/jack204/archive/2012/03/21/2410095.html

  

要在Linux上编译Objective-C程序,需要安装GNUstep

然后我找到How to instantiate a class in Objective-C that don't inherit from NSObject

  

你绝对可以这样做。你的类只需要实现+ alloc本身,就像NSObject那样。在base,这只是意味着使用malloc()来获取足够大的内存块以适合定义类实例的结构。

所以这就是我不能得到的:

  • 如果GNUstep在GNU / Linux上提供Foundation Objective-C框架,那么libobjc的作用是什么?!

由于上述两个软件包的安装都没有这些zoneAlloc函数(init / alloc所需)等,我做了grep -r " id" //usr/lib/gcc/x86_64-linux-gnu/4.8/include/objc,并找到了有一个函数class_createInstance返回id,因此通过定义使用它的new方法,编译器不再在编译步骤中生成错误消息。

但是,它在链接步骤中失败了 - 完整的构建日志也在gist中(如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

首先,libobjc.so位于/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

...在Makefile中,我尝试通过将clangLD_LIBRARY_PATH设置为LIBRARY_PATH - 来运行/usr/lib/x86_64-linux-gnu命令, 我还使用"其他库路径"来指定它。切换-L(在LDFLAGS中)。 所有似乎在链接器命令"/usr/bin/ld"运行时被忽略,但这并不重要,因为链接器命令本身在其参数中有这个:

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

...此路径确实扩展为/usr/lib/x86_64-linux-gnu(使用readlink -f检查),这是libobjc.so.*的位置。但链接器命令仍然失败了吗?!

所以我的第二个问题是:

  • 为什么ld libobjc.so.*找不到/usr/lib/x86_64-linux-gnu,即使它所在的-L通过DatePickerDialog dialog = new DatePickerDialog(getActivity(),AlertDialog.THEME_HOLO_LIGHT, this, year, month, day); 在其命令行参数中指定 - 以及我需要这样做才能让这个程序链接起来?

1 个答案:

答案 0 :(得分:0)

哦,好吧,事实证明链接阶段可以通过符号链接来解决;我首先尝试使用ld进行测试,起初我得到了:

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

...但是,如果有明确的路径,那么ld就不会抱怨“找不到”了:

$ 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

所以,当我更仔细地查看目录时:

$ (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

...事实证明,没有简单地称为libobjc.so的文件 - 它们都有libobjc.so.*这样的名字......所以我想,也许我应该是一个名字为{的符号链接{1}}:

libobjc.so

...现在当我运行cd /usr/lib/x86_64-linux-gnu/ sudo ln -s libobjc.so.4.0.0 libobjc.so 时 - 它实际上成功了!我得到一个名为make的可执行文件,运行正常:

main

嗯,很高兴有这个排序......