iPhone DNS Servers

November 17th, 2009

I have been bashing my head against the fact that on the iPhone you seemingly cannot access /etc/resolv.conf, or use functions from the Mac such as SCDynamicStore stuff. I have seen many people asking this question, a few related to the same package I was trying to use – ares.

Eventually I managed to find a fix which uses the libresolv to find the DNS servers. This seems to work just fine and I have shown the patch to ares_init.c below for reference.

#if TARGET_OS_IPHONE
#include <resolv.h>
#endif

...

#if TARGET_OS_IPHONE
// XXX: On the iPhone we need to get the DNS servers using resolv.h magic
if ((_res.options & RES_INIT) == 0) res_init();
channel->nservers = _res.nscount;
channel->servers = malloc(channel->nservers * sizeof(struct server_state));
memset(channel->servers, '\0', channel->nservers * sizeof(struct server_state));

int i;
for (i = 0; i < channel->nservers; i++)
{
    memcpy(&channel->servers[i].addr, &_res.nsaddr_list[i].sin_addr, sizeof(struct in_addr));
}
#endif

[As per most of my posts these days, this is just a brain dump. I'll try to pad it out as soon as possible]

3rd party libraries used by iPhone applications are required to be linked statically. In order to build such a library for the device and simulator you need to set up your environment such that it will cross compile for the two different environments. This is as simple as using the following set of ‘exports’ as defined below.

Device:

export DEVROOT=/Developer/Platforms/iPhoneOS.platform/Developer
export SDKROOT=$DEVROOT/SDKs/iPhoneOS3.0.sdk
export CC=$DEVROOT/usr/bin/gcc
export LD=$DEVROOT/usr/bin/ld
export CPP=$DEVROOT/usr/bin/cpp
export CXX=$DEVROOT/usr/bin/g++
export AR=$DEVROOT/usr/bin/ar
export AS=$DEVROOT/usr/bin/as
export NM=$DEVROOT/usr/bin/nm
export CXXCPP=$DEVROOT/usr/bin/cpp
export RANLIB=$DEVROOT/usr/bin/ranlib
export LDFLAGS="-arch armv6 -pipe -Os -gdwarf-2 -no-cpp-precomp -isysroot $SDKROOT -L~$SDKROOT/usr/lib"
export CFLAGS="-arch armv6 -pipe -Os -gdwarf-2 -no-cpp-precomp -isysroot $SDKROOT -I~$SDKROOT/usr/include"
export CXXFLAGS="-arch armv6 -pipe -Os -gdwarf-2 -no-cpp-precomp -isysroot $SDKROOT -I~$SDKROOT/usr/include0"

Simulator:

export DEVROOT=/Developer/Platforms/iPhoneSimulator.platform/Developer
export SDKROOT=$DEVROOT/SDKs/iPhoneSimulator3.0.sdk
export CC=$DEVROOT/usr/bin/gcc
export LD=$DEVROOT/usr/bin/ld
export CPP=$DEVROOT/usr/bin/cpp
export CXX=$DEVROOT/usr/bin/g++
export AR=$DEVROOT/usr/bin/ar
export AS=$DEVROOT/usr/bin/as
export NM=$DEVROOT/usr/bin/nm
export CXXCPP=$DEVROOT/usr/bin/cpp
export RANLIB=$DEVROOT/usr/bin/ranlib
export LDFLAGS="-arch i386 -pipe -Os -gdwarf-2 -no-cpp-precomp -isysroot $SDKROOT -L~$SDKROOT/usr/lib"
export CFLAGS="-arch i386 -pipe -Os -gdwarf-2 -no-cpp-precomp -isysroot $SDKROOT -I~$SDKROOT/usr/include"
export CXXFLAGS="-arch i386 -pipe -Os -gdwarf-2 -no-cpp-precomp -isysroot $SDKROOT -I~$SDKROOT/usr/include"

Once you have set the environment, you just need to use ‘make’ to build the library. If the library is using autoconf, then you will need to use the following ‘./configure’ options:

Device:

./configure --host=arm-apple-darwin9 --prefix=~$SDKROOT --enable-shared=no

Simulator:

./configure --host=i386-apple-darwin --prefix=~$SDKROOT --enable-shared=no

Then just use ‘make’ and ‘make install’ to build the library! It really is as easy as that :-D .

[Other libraries may require other configure options, but I can't cover them all here as they are often different]

Compiling Boost for the iPhone

November 10th, 2009

For a recent project I’ve had to compile the Boost C++ library for the iPhone. Much of the Boost library is header files so they are fine as nothing needs to be done, they just get copied into place, but the bits which do need compiling are a bit trickier. So I thought I’d share my experiences here.

First you need to download Boost (I went for version 1.40) from http://www.boost.org. Then you need to edit some of the Boost.Jam configuration. This involves creating a user-config.jam file in your home directory like so:

~/user-config.jam:
using darwin : 4.2.1~iphone
   : /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/gcc-4.2 -arch armv6
   : <striper>
   : <architecture>arm <target-os>iphone <macosx-version>iphone-3.0
   ;

using darwin : 4.2.1~iphonesim
   : /Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/gcc-4.2 -arch i386
   : <striper>
   : <architecture>x86 <target-os>iphone <macosx-version>iphonesim-3.0
   ;

Then edit tools/build/v2/tools/darwin.jam and add in the following under the macosx-versions variable:

.macosx-versions =
    10.6 10.5 10.4 10.3 10.2 10.1
    iphone-3.1 iphonesim-3.1
    iphone-3.0 iphonesim-3.0
    iphone-2.3 iphonesim-2.3
    iphone-2.2 iphonesim-2.2
    iphone-2.1 iphonesim-2.1
    iphone-2.0 iphonesim-2.0
    iphone-1.x
    ;

Then, you need to use the following lines to build Boost for iPhoneOS and iPhoneSimulator respectively:

./bjam --prefix=~/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.0.sdk/usr toolset=darwin architecture=arm target-os=iphone macosx-version=iphone-3.0 define=_LITTLE_ENDIAN link=static include=/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.0.sdk/usr/include/c++/4.2.1/armv6-apple-darwin9 install
./bjam --prefix=~/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator3.0.sdk/usr toolset=darwin architecture=x86 target-os=iphone macosx-version=iphonesim-3.0 link=static include=/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator3.0.sdk/usr/include/c++/4.2.1/i686-apple-darwin9 install

It’s worth noting that at this stage everything will compile for the simulator but not for the device. This is because the device is missing two header files – ‘bzlib.h’ and ‘crt_externs.h’. To make it compile for the device simply copy these files from ‘/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator3.0.sdk/usr/include/’ into your Boost folder and then everything should compile fine. I have no idea why Apple have omitted these header files from the device. The libraries are there, just the header files missing. I’ve created a bug on Radar for this, so please also do the same if you encounter this problem such that Apple will listen and include them.

That installs the files in ‘~/Developer/Platforms/iPhone(OS|Simulator).platform/Developer/SDKs/iPhone(OS|Simulator)3.0.sdk/usr’ which was where I wanted mine to go, but feel free to change that to wherever you want the libraries to end up. I did it this way because I created a custom SDK and then include that from iPhone projects within XCode.

I’ll try to update this with more information, this is merely a brain dump at the moment but hopefully it will be helpful for other people.

I found an article by Andrew Nusca on ZDNet which caught my eye. He gives 5 points as to why Android will beat other smartphones. I’d like to comment on them:

* Google backs Android, a major pipeline for its cloud services.
Yes, true, but Apple backs the iPhone and clearly has cloudy things in the pipeline with it’s building of a new billion dollar data centre.

* Android is improving rapidly. The Cupcake 1.5 release was well-received, and Donut 1.6 has already been sent over the air to handset owners.
iPhone OS is improving all the time as well. Granted Android is faster, but for developers I think it’s great how Apple release iPhone OS. It means you have time to get ready for each release to make sure all apps work properly on each version.

* Android is open, making it easier to quickly gain developers’ support.
The iPhone SDK is free to download and only £59 to become a member of the full developer program. It’s really not that much of a barrier.

* Android will run on phones from several manufacturers, which will help it quickly spread through the marketplace. HTC, Motorola and Samsung are already supporting handsets.
This is a bad thing in my opinion. I absolutely love the fact that with the iPhone you know exactly what devices the app will run on, and you know every exact specification. Only if the hardware manufacturer is the SDK provider, can this happen 100%.

* Android combines the best of what’s out there. It’s open, but it offers iPhone-like menus and apps, with Windows Mobile-esque icons, with Palm Pre-like multitasking. There’s another arms race afoot — the battle among Android handset makers as to which company can squeeze the most out of the OS.
Is that a good thing to mix-and-match? I prefer having a rock solid, stable OS, built by one of the best software companies in the world. Furthermore, they build the hardware as well so they know how to eek every last bit of power out of the hardware to provide software developers with one of the best platforms to develop for.

UITableViewCell Geometry

August 25th, 2009

I keep needing to find this out, so I thought I’d post it here so I can refer to it. This is the geometry of the UILabels for each of the UITableViewCellStyles:

UITableViewCellStyleValue2
textLabel: 10.000000 : 14.000000 : 68.000000 : 16.000000
detailTextLabel: 83.000000 : 12.000000 : 207.000000 : 0.000000

I had the need to code sign using a different developer accounts and my initial thoughts were that it was going to be tricky. But it seems that Apple have actually made it easy now!

The problem comes that during code-sign, it searches for certificates by the name, which leads to “iPhone Developer: Matthew Galloway” matching both certificates you have installed (one for each developer account). But Apple have at some point changed their certificate signing process and they add a number of the end of the common name on the certificate. This means that each certificate is unique even if it’s for the same physical developer.

One thing to note is that I used the same private key to generate the CSR for both certificates. I’m not sure what the implications would be for using separate private keys, but I can’t imagine it would make a difference.

I guess Apple had to do this really because lots of companies would have ended up with problems I’m sure.

So for anyone wondering if they can use multiple developer certificates, then just go for it, it should work!

I have a theory about Twitter and the iPhone in that once Apple’s push service is released (presumably with 3.0) it will pave the way for things like a Twitter client which informs you of new tweets in much the same way that the iPhone itself does with SMS messages. Therefore I can see the future being that iPhone users will increase their tweeting even more, thus not having to use SMS which has 2 advantages. One is that Twitter is free, and two is that if you happen to be on your PC rather than have your phone in front of you then you can receive messages or send messages using your favourite desktop Twitter client.

The problem comes of course that you still have to have polling in there somewhere because Twitter don’t have a push notification themselves, but perhaps Twitter will try to cash in and create their own iPhone app and add Apple’s push service to their own backend service.

Who knows…

2.x apps on 3.0

May 5th, 2009

Since the release of the first beta of the 3.0 SDK I’ve been checking if apps built for 2.x can run on it. Clearly this is something which Apple really should do, but a hint in the latest (beta4) release notes says this:

FIXED: Previously, the compiler incorrectly allowed synthesis of ivars belonging to a superclass. This caused crashes or other undefined behavior when the size of the superclass changed (such as running an application compiled against an older OS on iPhone OS 3.0.) The fixed compiler now generates an error when it encounters this condition. If you have shipped an application to customers, Apple recommends compiling against the 3.0 SDK and updating your existing application if the problem exists.

Now, does that mean that you’re going to have to release an update for apps which exhibit this problem for people on 3.0 to be able to use the app? Surely that cuts out people who upgrade, and if you update your app then it cuts out people who don’t upgrade? Lose-lost situation?