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

标签 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 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/…

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

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

然后我发现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.

所以这就是我不明白的:

  • 如果 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 方法,编译器将不再在编译步骤中生成错误消息。

但是,它在链接步骤中失败了 - 完整的构建日志也在要点中(如 make.log) - 带有:

/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

... 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). 所有这些似乎在链接器命令“/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在其命令行参数上指定的——我需要做什么才能链接这个程序?

最佳答案

哦,好吧,事实证明链接阶段可以通过符号链接(symbolic link)来解决;我首先尝试使用 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.* 这样的名称...所以我想,也许我应该使用名称为 libobjc.so 的符号链接(symbolic link):

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

...现在当我运行 make 时 - 它实际上成功了!我得到一个名为 main 的可执行文件,它运行良好:

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

嗯,很高兴能解决这个问题......

关于objective-c - 在 Ubuntu 上使用 clang 构建简单的 Objective-C 示例(链接失败)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46648363/

相关文章:

ios - 'MyController' 的@interface 不可见声明选择器

c - VS2012项目+openssl(LNK2001)

c++ - 链接器实际上如何处理多重定义的 `inline` 函数?

c - 如何向 GCC 默认链接描述文件添加新的内存部分?

c - 如何将 cstring 转换为 NSString 并将 NSString 转换为 cstring?

iphone - 从文件取消归档时 NSOrderedSet addObject 出现问题

java - 为 .NET 开发人员推荐 Linux + Java 书籍和资源

java - NFS 共享文件访问问题

linux - 在 GNU/Linux 或 FreeBSD 中读取设备

ios - 无法在 AppDelegate 中初始化委托(delegate),但在类方法中它可以工作