Compiling .m objective-C file from command-line - objective-c

In the old days I could have compiled objective-c .m files with
$ gcc -fobjc-gc-only -framework Foundation sample.m
$ ./a.out
But now it doesn't work because there is a high chance the program has
#autoreleasepool { ... }
clause. How do I compile an objective-C on command-line now?

So I just tried out clang and it worked out beautifully.
$ clang -fobjc-gc-only -framework Foundation sample.m
$ ./a.out
2013-09-22 20:17:57.150 a.out[19858:903] Hello world.
Case closed! :)

xcodebuild is what the XCode IDE uses under the hood to build you app, and what you use in things like CI servers to kick off a build from the command line. It uses your .xcproj or .xcworkspace files to work out what to build, so that may still be too high level for you.
In which case, under xcodebuild is clang and llvm. Clang replaced gcc, and is somewhat backwardly compatible, so that would be where you would want to start I would think.

Related

J2ObjC undefined symbols for architecture arm64

I'm trying to convert a java library to objective-c using j2objc and include the generated objc files into my XCode project. I managed to generate the objc files, but XCode gives me the following error: https://i.stack.imgur.com/QX3zF.png
I used lipo -info on a .o file and I get this "architecture: x86_64". Does it mean those objc files are not meant to run on arm64 architectures and if so, how can I solve this ? Are there any flags I could use to generate the files for arm64 ?
A previous error I had was "ARC forbids explicit message" and I solved this by adding a compiler flag -fno-objc-arc to all the compile sources related to this error. Is this solution safe ?
To compile for arm64, the -arch arm64 and -isysroot IPHONE_SDK_DIRECTORY flags are needed. To find the IPHONE_SDK_DIRECTORY on your system, run xcrun -sdk iphoneos --show-sdk-path.
There's nothing J2ObjC-specific about this, they are normal iOS flags you'll find in you look at the log of a successful compile of an Objective C file in Xcode and click its right button to expand and show all the flags used.
J2ObjC by default does not generate ARC code, so the -fno-objc-arc flag is okay. If you would prefer ARC, run j2objc with its -use-arc flag. Don't compile those generated files with -fno-objc-arc, however, as objects won't be released when your app is finished with them.

How do I compile objective-C in code blocks?

I downloaded Codeblocks bundled with GCC from here
The C part is running fine
I read this wiki tutorial which says having GCC will allow me to compile objective C by just adding -lobjc to the compiler options
However, I have followed the steps mentioned in this tutorial and added the -lobjc option, but it doesn't compile
This is the build error message I get in codeblocks:
-------------- Build: Debug in test_prog_proj (compiler: GNU GCC Obj-C Compiler)---------------
mingw32-gcc.exe -Wall -g -c D:\backup\cb_files\objc_files\test_prog_proj\test_prog.m -o obj\Debug\test_prog.o
mingw32-gcc.exe: error: CreateProcess: No such file or directory
Process terminated with status 1 (0 minute(s), 2 second(s))
1 error(s), 0 warning(s) (0 minute(s), 2 second(s))
As shown above, it does not show the -lobjc option
I have also tried manually compiling the above program in Windows cmd by going into the folder containing the .m file. I gave the following command:
mingw32-gcc.exe -Wall -g -c D:\backup\cb_files\objc_files\test_prog_proj\test_prog.m -o obj\Debug\test_prog.o -lobjc
But I get the same error in cmd
mingw32-gcc.exe: error: CreateProcess: No such file or directory
I also tried
gcc -g -fgnu-runtime -O -c some_class.m
that I got from here, but it gives me the same CreateProcess error. How do I start compiling Objective C code in Windows (preferably using GCC and Codeblocks) ?
--- EDIT 1 ---
I did as suggested in Mike Kinghan's answer below, and uninstalled my older Codeblocks instgallation, then reinstalled MinGW and codeblocks separately. The Codeblocks uninstall removed the Codeblocks folder in Program Files, but when I reinstalled Codeblocks again (version without MinGW bundled together), the "GNU GCC Obj-C" settings I made with the previous installation was still there, along with the -lobjc flag in the "linker settings" tab.
However, the problem is that it's still not working. I get the following error if I try to build from Codeblocks
Goto "Settings->Compiler...->Global compiler settings->GNU GCC Obj-C Compiler->Toolchain executables" and fix the compiler's setup.
Tried to run compiler executable 'C:\Program Files\CodeBlocks\MinGW/bin/mingw32-gcc.exe', but failed!
Skipping... Nothing to be done (all items are up-to-date).
This is what Toolchains executable looks like:
If I try to compile it from cmd by going in to the folder with the .m file and issuing the command
mingw32-gcc.exe -Wall -g -c D:\backup\cb_files\objc_files\test_prog_proj\test_prog.m -o obj\Debug\test_prog.o -lobjc
it gives the error
mingw32-gcc.exe: error: CreateProcess: No such file or directory
What is the problem here?
--- EDIT 2 ---
Following the suggestion in Mike Kinghan's answer I deleted the old instance of "GNU GCC Obj-C Compiler" in the list of compiliers, and recreated with the current version of "GNU GCC Compiler"
However, the program still does not work. This is the message I get in the build log:
-------------- Build: Debug in test_prog_proj (compiler: GNU GCC Obj-C Compiler)---------------
Linking stage skipped (build target has no object files to link)
Nothing to be done (all items are up-to-date).
Cleaning the project and then building it again gives the same message. Trying to run the project anyway gives me a dialog box saying the project is not built, and clicking on Yes to build the project just pops the same "project not built yet" dialog box up again. The file icons in the Workspace tree of the Projects tab also seem to be grayed out:
This is what Toolchain Executable looks like:
I have added -lobjc in Linker Settings as mentioned here as well.
I right clicked the project icon in the Project tree, went to Build Options and added -lobjc in the Linker Settings as well:
What is the problem with this project at the moment?
--- EDIT 3 ---
I ended up completely uninstalling Codeblocks (uninstall from windows start menu, delete codeblocks folder in %APPDATA%), uninstalling MinGW (deleting the c:\MinGW folder) and reinstalling everything from scratch. I followed all the instructions in the Wiki (except the Troubleshooting section, but I think that part is irrelevant) and it still doesn't work (same problem as described in Edit 2 in this post).
How do I get Codeblocks to detect and compile obj-C code? Also, it is not showing me the compiler command line arguments when I try to build it from the Codeblocks interface. Why is this and how can I get it to show me whatever the full command line it is using?
The GCC program we loosely call the "the compiler" - [mingw32-](gcc|g++) -
is actually a compiler/linker frontend that invokes a real language
compiler and/or linker depending on what the input files and commandline options
indicate you want it to do.
Input files with an .m extension indicate they are Objective C source files
that are to be compiled with the GNU Objective C compiler, cc1obj. But you
haven't got it. Hence the failure you see.
A GCC installation will include the C compiler cc1 and, optionally, compilers
for other languages - C++, Fortran, Objective (C|C++), Go ... You say you got your MinGW GCC installation as
bundled with Code::Blocks. That bundled MinGW omits the Objective C compiler, cc1obj , because the maintainers
reckon it a niche language.
Best remove your CB installation and bundled MinGW and then install MinGW GCC independently from
one of the rival projects:-
https://sourceforge.net/projects/mingw-w64/
https://sourceforge.net/projects/mingw/
Run the installer and ensure that you get Objective C as well as any other compilers you
want.
After that, replace your CB installation it with the codeblocks-17.12-setup.exe installer (not codeblocks-17.12mingw-setup.exe),
from https://sourceforge.net/projects/codeblocks/files/Binaries/17.12/Windows/. This installer includes no compilers and
will auto-detect your MinGW installation.
Then proceed as you already did to create a GNU GCC Obj-C compiler setup in the CB IDE.
Later ... still not working
Your GNU GCC Obj-C compiler-setup has persisted from your previous
CB install and has been rendered out-of-date by the fact that your
new MinGW installation is no longer part of Code::Blocks. As you see,
it still looks for the toolchain executables in C:\Program Files\Codeblocks\MinGW,
whereas your new MinGW is somewhere else.
When you reinstalled Code::Blocks you should have seen its attempt to auto-detect compilers,
and that it detected your MinGW toolchain in (say) C:\MinGW. It will have configured
a compiler setup for GNU GCC Compiler on that basis, with the correct path to
the toolchain executables. But it will not have modified any persisting compiler setups that
you created yourself, such as GNU GCC Obj-C.
First check that the auto-detected setup GNU GCC Compiler is good just
by creating a "Hello world" C console project and seeing that you can build it.
I assume you'll be able to, but if not, then go into the GNU GCC Compiler setup
yourself and manually set the Compiler's installation directory correctly.
Then, set the same Compiler's installation directory for your GNU GCC Obj-C
compiler setup.

Using Mono mkbundle To Target SGEN Garbage Collector

Is it possible to bundle a Mono executable using mkbundle that uses the sgen GC?
I assume that because the produced bundle requires the libmono-2.0.so.1 instead of the libmonosgen-2.0.so that it is using the standard boehm GC. I have tried using $MONO_OPTIONS=--gc=sgen but the resulting bundle still requires the non-sgen lib.
Am I misunderstanding the use of the libmono and libmonsgen libs?
Thank you for any assistance or guidance
This is a bit tricky, because Mono actually has two separate executables and two separate libraries, one for each garbage collector. For example, if you run mono --gc=sgen ... then mono will actually do an execvp() of mono-sgen ... to switch to a different executable.
Similarly, mkbundle will use pkg-config to select the library and link one or the other (i.e. whichever is the system default). To get the other library, there are two options:
One is to rebuild Mono with sgen being the default. Obviously, that may not be a viable solution.
The alternative is to use pkg-config to override the selection. You'd create a copy of mono-2.pc, replace -lmono-2.0 with -lmonosgen-2.0, update prefix and exec_prefix and use the PKG_CONFIG_PATH environment variable to pick that version.
Note that I've never actually tried the latter, but there is no reason why it shouldn't work, since pkg-config is where mkbundle gets the library path from.
Thanks for this question as it helps me to determine why one of my applications is running too slowly after bundling with the mkbundle. It was because of the Boehm GC engine being used.
To include SGen you just need to invoke mkbundle with --keeptemp flag and then rewrite compiler command (which is printed by mkbundle) to include monosgen-2 instead of mono-2.
Example: (for Mac, but could be easily rewritten for Linux)
export PATH=/Library/Frameworks/Mono.framework/Commands/:$PATH
export AS="as -arch i386"
export CC="cc -arch i386 -framework CoreFoundation -lobjc -liconv"
mkbundle TestApp.exe --deps --static -o TestAppBundleName --keeptemp
cc -arch i386 -framework CoreFoundation -lobjc -liconv -o TestAppBundleName -Wall `pkg-config --cflags monosgen-2` temp.c `pkg-config --libs-only-L monosgen-2` `pkg-config --variable=libdir monosgen-2`/libmonosgen-2.0.a `pkg-config --libs-only-l monosgen-2 | sed -e "s/\-lmonosgen-2.0 //"` temp.o

To -lobjc or not to -lobjc?

GCC manual says:
file.m
Objective-C source code. Note that you must link with thelibobjc
library yo make an Objective-C program work.
And:
-lobjc
You need this special case of the-loption in order to link an
Objective-C or Objective-C++ program.
However, I can succesfully compile a program with simply:
$ cc prg.m -framework Foundation
Is it a linker default, when you include a framework? If so, where is it
documented? The program gets linked anyway:
$ otool -L a.out
a.out:
/System/Library/Frameworks/Foundation.framework/.../Foundation (...)
/usr/lib/libSystem.B.dylib (...)
--> /usr/lib/libobjc.A.dylib (...)
/System/Library/Frameworks/CoreFoundation.f...k/.../CoreFoundation (...)
This is because the Foundation framework is already linked with libobjc.
So on OSX, you'll need -lobjc option only if you doesn't link with the Foundation framework (which is very rare).

Objective-C compiler flags

When compiling Objective-C from the command line (gcc), what are some good flags to use? Many of the standard C flags (-Wall, -ansi, etc) don't play well with Objective-C.
I currently just use -lobjc and -frameworkwith various frameworks.
Many of the standard C flags (-Wall, -ansi, etc) don't play well with Objective-C
-Wall works perfectly fine with Objective-C.
The thing to do is build an Objective-C file with Xcode and have a look at the build transcript. I've just done that and here are some highlights:
-x objective-c I guess that means "compile as Objective-C", probably important
-arch x86_64 build for a particular CPU architecture
-std=gnu99 build for C99 + GNU extensions (actually surprised me, I thought Xcode used -std=c99).
-isysroot .... specifies the location of the SDK.
-mmacosx-version-min=10.6 I am compiling for 10.6 and up
-fobjc-gc-only this file was intended to be used with garbage collection and won't work without it, so I compile for GC only.
-Wall the obvious.
If you are compiling from the command line, it's probably a good idea to set the option to treat warnings as errors. I don't from within Xcode because the build results window remembers the uncleared warnings from previous builds.