学而实习之 不亦乐乎

在 Linux 上编译运行 Objective-C 程序

2024-01-03 20:40:37

gcc 可以编译 Objective-C,但是不用 GNUstep 是没有什么意义。 会出现如下问题: 

Foundation/Foundation.h: No such file or directory 

一、安装编译环境

安装软件和编译环境

# apt-get install gnustep
# apt-get install gnustep-devel

二、编译运行

1、编写程序

hello.m 

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[])
{
        NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
        NSLog (@"hello world");
        [pool drain];
        return 0;
}

2、添加环境变量

当代码编写完成后,尝试用 gcc 去编译是会出错的,如下:

# gcc -o hello hello.m  
fatal error: Foundation/Foundation.h: No such file or directory 

因为使用了 foundation 库,gcc 并不知道其位置。 

我们现在要用 GNUstep 的方式即 makefile 的方式来编译,GNUstep 已经给我们做好了编译脚本在:

/usr/share/GNUstep/Makefiles/GNUstep.sh 

我们现在就要用到它,可以用 source 命令(.)引入 GNUstep.sh 到环境变量,如下:

. /usr/share/GNUstep/Makefiles/GNUstep.sh

但这种方式,每次打开一个新终端时都需要执行一次。当然,也可以直接将其加入到环境变量中去,新增一个 GNUSTEP_MAKEFILES (名字随便)环境变量,并打开 .bashrc 添加环境变量,如下:

# cd  
# vim .bashrc 

在最下面添加 

#set GNUstep 
GNUSTEP_MAKEFILES=/usr/share/GNUstep.sh 
export GNUSTEP_MAKEFILES 
source /usr/share/GNUstep/Makefiles/GNUstep.sh 

3、编译并运行

【1】使用 gcc

# gcc `gnustep-config --objc-flags` -Wl,--no-as-need -lgnustep-base -fconstant-string-class=NSConstantString  -lobjc  hello.m -o hello

最初使用下面的命令

# gcc `gnustep-config --objc-flags` -Wl,--no-as-need -lgnustep-base hello.m -o hello

出现如下错误:

/usr/bin/ld: /tmp/ccxA8Bfm.o: in function `main':
/data/proj/hello.m:4: undefined reference to `objc_get_class'
/usr/bin/ld: /data/proj/hello.m:4: undefined reference to `objc_msg_lookup'
/usr/bin/ld: /data/proj/hello.m:4: undefined reference to `objc_msg_lookup'
/usr/bin/ld: /data/proj/hello.m:5: undefined reference to `NSLog'
/usr/bin/ld: /data/proj/hello.m:6: undefined reference to `objc_msg_lookup'
/usr/bin/ld: /tmp/ccxA8Bfm.o: in function `__objc_gnu_init':
/data/proj/hello.m:8: undefined reference to `__objc_exec_class'
/usr/bin/ld: /tmp/ccxA8Bfm.o:(.data.rel+0x0): undefined reference to `__objc_class_name_NSConstantString'
/usr/bin/ld: /tmp/ccxA8Bfm.o:(.data.rel+0x8): undefined reference to __objc_class_name_NSAutoreleasePool'
collect2: error: ld returned 1 exit status

经过查资料调整后,可以正常编译,并可以生成 hello 可执行文件。

undefined reference to `objc_get_class'  需要在编译的时候加上选项 -Wl,--no-as-need

undefined reference to symbol 'objc_msg_lookup' 需要在编译的时候加上选项 -lobjc

error: cannot find interface declaration for ‘NXConstantString’ 则需要在编译的命令行加上“-fconstant-string-class=NSConstantString”

/bin/ld: cannot find -lgnustep-base  找到 gnustep-base 的库路径,然后在编译的时候带上即可。-L/usr/GNUstep/System/Library/Libraries

【2】使用 make

在项目目录中创建文件 GNUmakefile (必须命名为 GNUmakefile) 并编辑:

include $(GNUSTEP_MAKEFILES)/common.make 
TOOL_NAME = hello 
hello_OBJC_FILES = hello.m 
include $(GNUSTEP_MAKEFILES)/tool.make 

然后,直接运行:

# make