Problems when compiling Objective C with Clang (Ubuntu) - objective-c

I'm learning Objective-C language. Since I don't have a Mac, I'm compiling and running my code within Ubuntu 11.04 platform.
Until now, I was using gcc to compile. I've installed GNUStep and all was working. But then I started to try some Objective-C 2.0 features, like #property and #synthesize, that gcc does not allow.
So I tried to compile the code with Clang, but it seems that it is not correctly linking my code with the GNUStep libraries, not even with a simple Hello world program.
For example, if I compile the following code:
#import <Foundation/Foundation.h>
int main(void) {
NSLog(#"Hello world!");
return 0;
}
The output of the compiler is:
/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)
The command I'm using to compile is
clang -I /usr/include/GNUstep/ test.m -o test
with the -I directive to include the GNUStep libraries (otherwise, Clang is not able to find Foundation.h).
I've googled my problem, and visited both GNUStep and Clang web pages, but I haven't found a solution to it. So any help will be appreciated.
Thanks!

The problem was that the library gnustep-base was not being used by the linker. So the solution to this was using the option -Xlinker, that sends arguments to the linker used by clang:
clang -I /usr/include/GNUstep/ -Xlinker -lgnustep-base test.m -o test
The statement "-X linker -lgnustep-base" made the magic. However, I had problems with this command related to the class that represents a string in Objective-C:
./test: Uncaught exception NSInvalidArgumentException, reason: GSFFIInvocation:
Class 'NXConstantString'(instance) does not respond to forwardInvocation: for
'hasSuffix:'
I could solve it adding the argument "-fconstant-string-class=NSConstantString":
clang -I /usr/include/GNUstep/ -fconstant-string-class=NSConstantString \
-Xlinker -lgnustep-base test.m -o test
In addition, I've tried with some Objective-C 2.0 pieces of code and it seems to work.
Thank you for the help!

You can try gcc compiler:
First of all install GNU Objective-C Runtime: sudo apt-get install gobjc
then compile: gcc -o hello hello.m -Wall -lobjc

You are not able to use ObjC 2.0 features because you're missing a ObjC-runtime supporting those. GCC's runtime is old and outdated, it doesn't support ObjC 2.0. Clang/LLVM doesn't have a acompanied runtime, you need to install the ObjC2-runtime from GNUstep (which can be found here: https://github.com/gnustep/libobjc2 ) and reinstall GNUstep using this runtime.
Here are some bash scripts for different Ubuntu versions, that do everything for you:
http://wiki.gnustep.org/index.php/GNUstep_under_Ubuntu_Linux
And please don't try to reinvent GNUstep make, instead, use it:
http://www.gnustep.org/resources/documentation/Developer/Make/Manual/gnustep-make_1.html
If you really don't think so, here is some excerpt from there:
1.2 Structure of a Makefile
Here is an example makefile (named GNUmakefile to emphasis the fact that it relies on special features of the GNU make program).
#
# 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
This is all that is necessary to define the project.
In your case replace all occurrences of simple with test and you're done
1.3 Running Make
Normally to compile a package which uses the Makefile Package it is purely a matter of typing make from the top-level directory of the package, and the package is compiled without any additional interaction.

Related

Objective C program Compilation and Execution

I am a newbie to Objective C programs. I'm learning to code from tutorialspoint.com
As mentioned therein I downloaded GNUstep (Windows).
First, installed the MSYS/MinGW System package and then core package.
After that followed the steps mentioned there. I created a simple program with name hello.m and Stored that in C drive (Snapshot 1)
I don't know the meaning of this command below but entered it:
$ gcc gnustep-config --objc-flags -L /GNUstep/System/Library/Libraries hello.m -o hello -lgnustep-base -lobjc
The error it shows is - sh: gcc: command not found
Please help with the same, to compile and run my first Objective C program
gcc is the compiler, the other parameters are for compiling objective-c code.
Apparently you have misconfiguration in MSYS/MinGW setup.
Check out following post which has alternative and easier solution for running gcc under Windows.

Lapack undefined reference

I am new to g++ and lapack, and attempting to use them. I encountered a problem when I tried to compile the following naive code
#include <lapackpp.h>
int main()
{
LaGenMatDouble A;
return 0;
}
If I run the command
$g++ -L/usr/local/lib -llapackpp test2.cpp
where test2.cpp is the name of the cpp file, the terminal would give an error:
test2.cpp:1:22: fatal error: lapackpp.h: No such file or directory
But if I run the command:
$g++ -I/usr/local/include/lapackpp -L/usr/local/lib -llapackpp test2.cpp
the terminal would give an error:
/tmp/ccUi11DG.o: In function `main':
test2.cpp:(.text+0x12): undefined reference to `LaGenMatDouble::LaGenMatDouble()'
test2.cpp:(.text+0x23): undefined reference to `LaGenMatDouble::~LaGenMatDouble()'
collect2: ld returned 1 exit status
BTW, if I run the command
$pkg-config lapackpp --libs
the result is
-L/usr/local/lib -llapackpp
Could you please help me solve this? Thanks in advance!
Lapack requires fortran libraries, so that's where the -lgfortran comes from. Moreover, it appears the exact way to provide that library for the compiler depends on the Linux distriburion. From the documentation:
Requirements
This package requires the packages "blas", "lapack" (without the "++"), and a Fortran compiler. On most Linuxes these are available as pre-compiled binaries under the name "blas" and "lapack". For SuSE 10.x, the Fortran compiler is available as package "gfortran". For SuSE 9.x, the Fortran compiler is available as package "gcc-g77".
Not sure why pkg-config lapackpp --libs does not list -lgfortran
The -I/usr/local/include/lapackpp specifes the lapackpp-related header files. Without it the compiler cannot find lapackpp.h when you try to include it (#include <lapackpp.h>) -- see the compiler error in your question
I finally solved the problem but would still wonder why it has to be so.
The only command that can link cpp file to lapackpp library is:
g++ foo.cpp -o foo -lgfortran -llapackpp -I/usr/local/include/lapackpp
It would not work without -lgfortran, or with -I/usr/local/include/lapackpp replaced by -L/usr/local/lib.
Does anyone have an answer?

How to compile objc code on Linux?

Assuming you have your .h and .m ready on a Linux server, which command would you issue to GCC to have it compiled?
The relevant parts:
gcc -c -Wno-import List.m
gcc -o prog -Wno-import List.o main.o -lobjc
. . . make sure that the Objective-C library and header files (objc/Object.h) were installed when gcc was built.
Note that when linking Objective-C with gcc, you need to specify the Objective-C library by using the -lobjc switch.
See this link for more information.
Additional link with possible solution to the missing compiler issue:
Try installing either gobjc++ or gobjc
sudo apt-get install gobjc++
gcc -x objective-c file.m -o out
Google is your friend

Can not compile simple C# application with mkbundle

I have written some console "Hello world"-like app. and have followed c# cywgwin mono mkbundle windows 7 - cannot compile file answer. But I have got:
$ mkbundle -o Fur Furries.exe --deps -z
OS is: Windows
Sources: 1 Auto-dependencies: True
embedding: C:\Monotest\Furries.exe
compression ratio: 40.43%
embedding: C:\Soft\Mono\lib\mono\4.0\mscorlib.dll
compression ratio: 34.68%
Compiling:
as -o temp.o temp.s
gcc -mno-cygwin -g -o Fur -Wall temp.c `pkg-config --cflags --libs mono-2|dos2un
ix` -lz temp.o
temp.c: In function `main':
temp.c:173: warning: implicit declaration of function `g_utf16_to_utf8'
temp.c:173: warning: assignment makes pointer from integer without a cast
temp.c:188: warning: assignment makes pointer from integer without a cast
/tmp/ccQwnxrF.o: In function `main':
/cygdrive/c/Monotest/temp.c:173: undefined reference to `_g_utf16_to_utf8'
/cygdrive/c/Monotest/temp.c:188: undefined reference to `_g_utf16_to_utf8'
collect2: ld returned 1 exit status
[Fail]
It's in Windows XP.
First of all, prepare development environment:
Install Mono. For example, you have installed it into "C:\Soft\Mono".
Install Cygwin. When selecting which packages to install select following: gcc-mingw, mingw-zlib, pkg-config, nano.
Start Cygwin Bash shell (either using a link or "bash --login -i" command).
Open "$HOME/.bashrc" with "nano" ("nano ~/.bashrc"). Don't use editors which don't preserve end-of-line-s ("CR", "LF", "CR/LF" or other), or it will corrupt the file!
Add following lines to the end of the file:
export PKG_CONFIG_PATH=/cygdrive/c/Soft/Mono/lib/pkgconfig
export PATH=$PATH:/cygdrive/c/Soft/Mono/bin
Restart Cygwin Bash shell.
After that you can compile your assemblies with "mkbundle":
Perform the following command: "mkbundle -c -o host.c -oo bundle.o --deps YourAssembly.exe <additional arguments>". You also may optionally pass "-z" to compress resultant bundle. You should get "host.c" and "bundle.o" files.
In "host.c" you should remove "_WIN32" "branch" (except "#include <windows.h>" one). It doesn't work. You may do it just by adding "#undef _WIN32" right after following lines in it:
#ifdef _WIN32
#include <windows.h>
#endif
So you'll get:
#ifdef _WIN32
#include <windows.h>
#endif
#undef _WIN32
Perform the following command: "gcc -mno-cygwin -o ResultantBundle.exe -Wall host.c `pkg-config --cflags --libs mono-2|dos2unix` bundle.o <additional arguments>". If you added a -z additional argument in step 2, you must add a -lz additional argument in this step.
You will get "ResultantBundle.exe". This is your Mono application packed as standalone executable.
It still requires "mono-2.0.dll" and some additional DLL-s and resources you depended on during development (for example, it may require GTK# native DLL-s) but it doesn't require full Mono runtime to run.
Just wanted to add that if you pass -z to mkbundle then you'll need to pass -lz to gcc. I had some issues getting an application with winforms and net access to work properly, and I had to copy machine.config from C:\Mono\etc\mono\4.0\machine.config to where my application was. I then passed --machine-config machine.config to mkbundle.
All of these steps are pretty confusing and frustrating, why is not as simple as just typing mkbundle --deps app.exe? I tried making a change to the template used by mkbundle and compiling it myself, but it wont run. I've gone as far now as to download the mono source and attempt to build the whole thing, but I doubt it will work. If anyone can explain what the hell is going on with mkbundle to make this so annoying, I'd be interested in contributing.
after you have the temp.o and temp.c, you can add them to visual c++ to make a windows application with other sources.

Help with GCC and ObjectiveC code and Cygwin

Is it possible to build objective c code correctly with GCC under cygwin.
I have the following application that should work on a Mac environment, but can't get the most basic stuff to work with gcc. Are there more libraries I need to have.
#import "HelloWorldApp.h"
int main(int argc, char *argv[]) {
return 0;
} // End of the //
#interface Car
{
int test;
}
//The registration is a read-only field, set by copy
#property int (readonly, copy) test;
//the driver is a weak reference (no retain), and can be modified
//#property Person* (assign) driver;
#end
CC=gcc
CXX=gcc-g++
LD=$(CC)
CFLAGS=
LDFLAGS=-lobjc
all: HelloWorld
HelloWorld: HelloWorld.o
$(LD) $(LDFLAGS) -o $# $^
%.o: %.m
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $#
clean:
rm -rvf *.o HelloWorld HelloWorld.exe
Error:
gcc -c HelloWorld.m -o HelloWorld.o
In file included from HelloWorld.m:6:
HelloWorldApp.h:19: error: stray '#' in program
HelloWorldApp.h:19: error: parse error before "int"
make: *** [HelloWorld.o] Error 1
I think it's because you're using Objective-C 2.0, which is a private extension that Apple developed and that they did not contribute back to the "standard", FSF GCC. Thus, your mingw compiler (which is not based on Apple's, but on the FSF's) does not understand new syntax like properties.
# Malaxeur - you hit the nail right on the head. I've just been bashing about with ObjC on a PC and had that exact problem - my path was pointing to a v3.x gcc compiler. I switched to the 4.x version and voila!
It's also worth noting that the "stray '#'" error also pops up if you spell 'implementation' wrong, which is a little misleading.
Anyway, thanks for the help.
Have you tried running the gcc commands directly from command line rather than via makefile?
Found this reference:
Taken directly from http://www.cs.indiana.edu/classes/c304/ObjCompile.html
Compiling Objective-C
Objective-C code can be compiled using the GNU C compiler gcc. Objective-C interface files usually marked by the extension .h as in List.h. Implementation files are usually marked by the extension .m as in List.m. The implementation file should #import its corresponding interface file. Your main program should also #import the interface files of all of the classes it uses.
Usually, you will want to compile the files which implement your classes separately. For instance, to compile List.m, use the following command:
gcc -c -Wno-import List.m
The -c switch tells the compiler to produce an object file, List.o, which can then later be linked into your program. Do this for each of your implementation files, and your main program.
The -Wno-import switch tells the compiler not to give a warning if you have a #import statement in your code. For some reason, Richard Stallman (the GNU Project founder) doesn't like the #import construction.
When you are ready to compile your program, you can link all of the implementations of your classes using gcc again. For example, to compile the files List.o, and main.o you could use the following command:
gcc -o prog -Wno-import List.o main.o -lobjc
The -o prog tells gcc to create an executable program with the name prog (if you do not specify this, it will default to a.out.
Note that when linking Objective-C with gcc, you need to specify the Objective-C library by using the -lobjc switch. If gcc reports an error, contact your system administrator to make sure that the Objective-C library and header files (objc/Object.h) were installed when gcc was built.