2552/01/19

iPhone Building and Installing Applications

Finally, the last thing you'll need is a copy of your iPhone's filesystem; specifically, the libraries and frameworks. For dramatic effect, and because our lawyers make us, we'll display this general disclaimer:
Having installed SSH onto the iPhone in Chapter 1, use the following commands to download the files you need into a folder called /usr/local/share/iphone-filesystem.

# mkdir -p /usr/local/share/iphone-filesystem
# cd /usr/local/share/iphone-filesystem
# mkdir -p ./System/Library ./usr
# scp -r root@iphone:/System/Library/Frameworks/ .
# mv Frameworks ./System/Library
# scp -r root@iphone:/usr/lib .
# mv lib ./usr

The source code for the tool chain is split into two repositories: one for the LLVM compiler framework and one for the rest of the tool chain. Create a build directory for yourself and cd into it. Now, use Subversion to check both projects out from their repositories.

$ svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm-svn -r 42498
$ svn co http://iphone-dev.googlecode.com/svn/trunk/ iphone-dev

The download may take an hour or longer, depending on the speed of your connection. Once both repositories have been checked out, it's time to start building.

The instructions in the next sections presume you know how to use a terminal window. On the Mac, this can be found in your Utilities folder inside Applications. It is also assumed that you have some level of knowledge of Unix.

One convention that may be unfamiliar to you is the use of the built-in shell commands pushd and popd. These are similar to the cd command, but they push and pop directories on a stack. This makes it easy to do some work in a new directory and then return to a previous one without having to remember where you were.

You'll also see references to the sudo command. This is a Unix tool providing limited access to run privileged (root) commands. When you want to run a command that requires privileged access (because it accesses sensitive data on the operating system or could have dangerous effects hurting the operating system), type sudo on the command line followed by the command you wish to run. Mac OS X will then prompt you for the root password to your desktop before allowing the command to run. If you don't have sudo, you can safely leave it off of your commands, but you'll first need to invoke su to become root.

2.2.2.1. Step 1: Build and install the LLVM framework
The LLVM (Low Level Virtual Machine) framework provides a standard infrastructure for building compilers. It provides the necessary hooks and APIs to build a standardized compiler without having to rewrite all of the basic components of a compiler. Issue the following statements to compile and install a release build of the llvm compiler.

$ pushd llvm-svn
$ ./configure --enable-optimized
$ make ENABLE_OPTIMIZED=1
$ sudo make install
$ LLVMOBJDIR=`pwd`
$ popd

2.2.2.2. Step 2: Build and install cross-compiler tools
The following commands build and install the cross-compiler components of the tool chain. These are specific to Mac OS X, so be sure to read the official documentation if you're using a different platform.

$ pushd iphone-dev
$ sudo mkdir /usr/local/arm-apple-darwin
$ mkdir -p build/odcctools
$ pushd build/odcctools
$ ../../odcctools/configure --target=arm-apple-darwin --disable-ld64
$ export INCPRIVEXT="-isysroot /Developer/SDKs/MacOSX10.4u.sdk"
$ make
$ sudo make install
$ popd
$ HEAVENLY=/usr/local/share/iphone-filesystem

2.2.2.3. Step 3: Patch the system headers
The system headers found in your XCode SDK are shared by your desktop and the iPhone platform, but some pre-compiler macros are architecture-specific. Because the iPhone's architecture is different from the desktop's, these headers need to be patched to work for the iPhone. Issue the following commands to patch the headers (don't worry, the originals are automatically backed up).

$ pushd include
$ ./configure --with-macosx-sdk=/Developer/SDKs/MacOSX10.4u.sdk
$ sudo bash install-headers.sh
$ popd

2.2.2.4. Step 4: Install the Csu
The Csu provides C hooks into assembly's "start" entry point, and sets up the stack so that your program's main( ) function can be called. It's essentially glue code.

$ mkdir -p build/csu
$ pushd build/csu
$ ../../csu/configure --host=arm-apple-darwin
$ sudo make install
$ popd

2.2.2.5. Step 5: Build and install llvm-gcc
Now that the LLVM framework, cross-compiler tools, and Csu have been built, the compiler itself can now be built and installed. If you're doing this in stages or have since closed your terminal window, make sure that you've still got the environment variables $LLVMOBJDIR and $HEAVENLY set to the proper directories. The LLVMOBJDIR variable points to the location of LLVM object files, which were compiled when you built LLVM. These are used to build llvm-gcc. The HEAVENLY variable points to the location where you copied the iPhone's libraries onto your desktop. This directory is used by llvm-gcc to link to the iPhone's framework and library files when you compile applications. The name "heavenly" was the code name given by Apple to the 1.0 code base of the iPhone software. The 1.1 code base is code-named "snowbird," but the original name is still used in the tool chain.

$ set | grep -e LLVMOBJDIR -e HEAVENLY

If you don't see output from the previous command, you need to set the environment variables again. Get back into your build directory and run:

$ pushd llvm-svn && LLVMOBJDIR=`pwd` && popd
$ HEAVENLY=/usr/local/share/iphone-filesystem

Once you've ensured that these are set, issue the following commands to build and install the compiler:

$ mv llvm-gcc-4.0-iphone/configure llvm-gcc-4.0-iphone/configure.old
$ sed \
's/^FLAGS_FOR_TARGET=$/FLAGS_FOR_TARGET=${FLAGS_FOR_TARGET-}/g' \
llvm-gcc-4.0-iphone/configure.old > llvm-gcc-4.0-iphone/configure
$ sudo ln -s /usr/local/arm-apple-darwin/lib/crt1.o \
/usr/local/arm-apple-darwin/lib/crt1.10.5.o
$ mkdir -p build/llvm-gcc-4.0-iphone
$ pushd build/llvm-gcc-4.0-iphone
$ export FLAGS_FOR_TARGET="-mmacosx-version-min=10.1"
$ sh ../../llvm-gcc-4.0-iphone/configure \
--enable-llvm=`llvm-config --obj-root` \
--enable-languages=c,c++,objc,obj-c++ \
--target=arm-apple-darwin --enable-sjlj-exceptions \
--with-heavenly=$HEAVENLY \
--with-as=/usr/local/bin/arm-apple-darwin-as \
--with-ld=/usr/local/bin/arm-apple-darwin-ld
$ make LLVM_VERSION_INFO=2.0-svn-iphone-dev-0.3-svn
$ sudo make install
$ popd
$ popd

Congratulations! You've built the free tool chain for iPhone. You're now ready to start compiling iPhone applications. The compiler itself can be invoked directly by calling /usr/local/bin/arm-apple-darwin-gcc. We'll explain how to use it in the next section.

--

2.3. Building and Installing Applications
Now that the tool chain has been installed, the next step is to learn how to use it. There are two essential ways to build an executable: the command line or a makefile.

The examples in this book are simple enough that they can be built using the command line. The tool chain is compliant to standard compiler arguments, and should be familiar if you've ever used gcc in the past. You'll want to make sure /usr/local/bin is in your path before you try to use the cross-compiler.

$ export PATH=$PATH:/usr/local/bin

The anatomy of a typical command line compile is:

$ arm-apple-darwin-gcc -o MyExample MyExample.m -lobjc \
-framework CoreFoundation -framework Foundation


arm-apple-darwin-gcc

The name of the cross-compiler itself. This is located in /usr/local/bin, so be sure you've added it to your path.


-o MyExample

Tells the compiler to output the compiled executable to a file named MyExample.


MyExample.m

The name of the source file(s) being included in the program, separated by spaces. The .m extension tells the compiler that the sources are written in Objective-C.


-lobjc

Tells the compiler to link in the tool chain's Objective-C messaging library, which is needed by all iPhone applications. This library glues C-style function calls to Objective-C messages, among other things.


-framework CoreFoundation -framework Foundation

Two of the base frameworks to be linked into the application. Depending on what components of the operating system are being used in the code, different frameworks provide different layers of functionality. You'll be introduced to many different frameworks throughout this book.

The command line will suffice for most small applications and examples, but for larger applications, it makes sense to write a makefile. A makefile is a simple text file that acts as a manifest for building applications. It is used by a program called make, which is a portable build utility included with most development kits. The make program is responsible for calling the compiler (and linker) and passing them whatever flags and parameters are needed. Makefiles are logical ways to lay out the composition of an application. They also allow the developer to easily clean up the object files in a directory, create application packages, and perform a number of other tasks useful to building applications.

The previous command line example could be rewritten as a makefile like the one below, named Makefile, and placed into the source directory.

CC = /usr/local/bin/arm-apple-darwin-gcc
LD = $(CC)
LDFLAGS = -lobjc \
-framework CoreFoundation
CFLAGS =

all: MyExample

MyExample: MyExample.o
$(LD) $(LDFLAGS) -o $@ $^

%.o: %.m
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@

%.o: %.c
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@

%.o: %.cpp
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@

Once the makefile file is in place, the application's executable can be built with one simple command:

$ make

In addition to building an application, functionality can be added to copy the application's executable into the program folder skeleton you made:

package:
cp -p MyExample ./MyExample.app/

With this added to the makefile, you can run make package to automatically set up your .app directory.

Another popular use for makefiles is to clean the directory so that it can be sent to someone else. You can even tell the makefile to delete the executable that was copied into the program folder.

clean:
rm -f *.o *.gch
rm -f ./MyExample.app/MyExample

2.3.1. Installing an Application
Once an application has been built, it can be installed by copying the entire program directory into the /Applications folder on the iPhone. Using the SSH server you set up in Chapter 1, you can do this over WiFi:

$ scp -r MyExample.app root@iphone:/Applications

Before the iPhone will recognize the application, either the iPhone must be powered down and rebooted, or the SpringBoard application must be restarted on the iPhone itself. Log in to the iPhone using SSH and execute the following command to restart SpringBoard:

$ killall SpringBoard

Once restarted, you should see the application on the SpringBoard. Pressing the icon will launch it.
Powered By Blogger