Проблемы при компиляции Objective C с Clang (Ubuntu)

Я изучаю язык Objective-C. Поскольку у меня нет Mac, я компилирую и запускаю свой код на платформе Ubuntu 11.04.

До сих пор я использовал gcc для компиляции. Я установил GNUStep, и все работает. Но потом я начал использовать некоторые функции Objective-C 2.0, такие как @property и @synthesize, которые gcc не разрешает.

Итак, я попытался скомпилировать код с Clang, но кажется, что он неправильно связывает мой код с библиотеками GNUStep, даже с простой программой Hello world.

Например, если я скомпилирую следующий код:

#import <Foundation/Foundation.h>

int main(void) {
  NSLog(@"Hello world!");
  return 0;
}

Вывод компилятора:

/tmp/cc-dHZIp1.o: In function `main':
test.m:(.text+0x1f): undefined reference to `NSLog'
/tmp/cc-dHZIp1.o: In function `.objc_load_function':
test.m:(.text+0x3c): undefined reference to `__objc_exec_class'
collect2: ld returned 1 exit status
clang: error: linker (via gcc) command failed with exit code 1 (use -v to see invocation)

Команда, которую я использую для компиляции,

clang -I /usr/include/GNUstep/ test.m -o test

с директивой -I включить библиотеки GNUStep (иначе Clang не сможет найти Foundation.h).

Я искал свою проблему и посещал как веб-страницы GNUStep, так и Clang, но я не нашел для нее решения. Поэтому любая помощь будет оценена.

Спасибо!

Ответ 1

Проблема заключалась в том, что библиотека gnustep-base не использовалась компоновщиком. Таким образом, для решения этой проблемы использовался параметр -Xlinker, который отправляет аргументы компоновщику, используемому clang:

clang -I /usr/include/GNUstep/ -Xlinker -lgnustep-base test.m -o test

Заявление "-X линкер -lgnustep-base" сделало магию. Однако у меня были проблемы с этой командой, связанной с классом, который представляет строку в Objective-C:

./test: Uncaught exception NSInvalidArgumentException, reason: GSFFIInvocation:
Class 'NXConstantString'(instance) does not respond to forwardInvocation: for
'hasSuffix:'

Я мог бы решить это, добавив аргумент "-fconstant-string-class= NSConstantString":

clang -I /usr/include/GNUstep/ -fconstant-string-class=NSConstantString \
-Xlinker -lgnustep-base test.m -o test

Кроме того, я пробовал с некоторыми Objective-C 2.0 фрагментами кода и, похоже, работает.

Спасибо за помощь!

Ответ 2

Вы можете попробовать gcc-компилятор:
Прежде всего установите GNU Objective-C Время выполнения: sudo apt-get install gobjc
затем скомпилируйте: gcc -o hello hello.m -Wall -lobjc

Ответ 3

Вы не можете использовать функции ObjC 2.0, потому что вам не хватает ObjC-среды выполнения, поддерживающей их. Среда выполнения GCC старая и устаревшая, она не поддерживает ObjC 2.0. Clang/LLVM не имеет сопутствующей среды выполнения, вам нужно установить ObjC2-среду выполнения из GNUstep (которую можно найти здесь: https://github.com/gnustep/libobjc2) и переустановить GNUstep с помощью этой среды выполнения.

Вот несколько скриптов bash для разных версий Ubuntu, которые делают все за вас:

http://wiki.gnustep.org/index.php/GNUstep_under_Ubuntu_Linux

И, пожалуйста, не пытайтесь заново изобретать GNUstep make, вместо этого используйте его:

http://www.gnustep.org/resources/documentation/Developer/Make/Manual/gnustep-make_1.html

Если вы действительно так не думаете, вот отрывок:

1.2 Структура Makefile

Вот пример make файла (названный GNUmakefile, чтобы подчеркнуть тот факт, что он опирается на специальные функции программы GNU make).

#
# An example GNUmakefile
#

# Include the common variables defined by the Makefile Package
include $(GNUSTEP_MAKEFILES)/common.make

# Build a simple Objective-C program
TOOL_NAME = simple

# The Objective-C files to compile
simple_OBJC_FILES = simple.m

-include GNUmakefile.preamble

# Include in the rules for making GNUstep command-line programs
include $(GNUSTEP_MAKEFILES)/tool.make

-include GNUmakefile.postamble

Это все, что необходимо для определения проекта.

В вашем случае замените все вхождения simple с test и все готово

1.3 Запуск Make

Обычно для компиляции пакета, который использует пакет Makefile, достаточно просто набрать make из каталога верхнего уровня пакета, и пакет компилируется без какого-либо дополнительного взаимодействия.