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.

# Defines to set up environment
export DEVROOT=${ROOTDIR}/Platforms/${PLATFORM}.platform/Developer
export SDKROOT=${DEVROOT}/SDKs/${PLATFORM}${MAX_VERSION}.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 LIBTOOL=$DEVROOT/usr/bin/libtool
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 OPTFLAG="-O${OPT}"
export COMMONFLAGS="${ARCH} -pipe $OPTFLAG -gdwarf-2 -no-cpp-precomp -mthumb -isysroot ${SDKROOT} -miphoneos-version-min=${MIN_VERSION}"
export LDFLAGS="${COMMONFLAGS} -L${HOME}${SDKROOT}/usr/lib"
export CFLAGS="${COMMONFLAGS} -fvisibility=hidden"
export CXXFLAGS="${COMMONFLAGS} -fvisibility=hidden -fvisibility-inlines-hidden"

This uses a few defines which need to be different for the device vs. simulator. Below are what you might want to use for each one. Note that MIN_VERSION, MAX_VERSION and OPT can all be set to control what SDK versions and the level of optimisation is used.

Device:

# Variables
export ROOTDIR="/Developer"
export PLATFORM="iPhoneOS"
export ARCH="-arch armv6 -arch armv7"
export MIN_VERSION="3.1"
export MAX_VERSION="4.0"
export OPT="3"

Simulator:

# Variables
export ROOTDIR="/Developer"
export PLATFORM="iPhoneSimulator"
export ARCH="-arch i386"
export MIN_VERSION="3.1"
export MAX_VERSION="4.0"
export OPT="3"

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 --disable-dependency-tracking

[Note: --disable-dependency-tracking is required because gcc can't use dependency tracking when building for 2 architectures at the same time (i.e. armv6 and armv7).]

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]

EDIT: I’ve edited the defines above to be a bit clearer and factor out the common bits from the device/simulator.

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.

boost-1.42:
Since Boost has been updated, I thought I’d extend this article to explain how to compile boost-1.42 for the iPhone. Boost themselves have gone a long way to do everything for you now, so there’s much less that needs to be done. You now need to do this:

~/user-config.jam
using darwin : 4.2.1~iphone
   : /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/gcc-4.2 -arch armv7 -mthumb -fvisibility=hidden -fvisibility-inlines-hidden
   : <striper>
   : <architecture>arm <target-os>iphone <macosx-version>iphone-3.1.3
   ;

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

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

tools/build/v2/tools/darwin.jam
## The MacOSX versions we can target.
.macosx-versions =
    10.6 10.5 10.4 10.3 10.2 10.1
    iphone-3.2 iphonesim-3.2
    iphone-3.1.3 iphonesim-3.1.3
    iphone-3.1.2 iphonesim-3.1.2
    iphone-3.1 iphonesim-3.1
    iphone-3.0 iphonesim-3.0
    iphone-2.2.1 iphonesim-2.2.1
    iphone-2.2 iphonesim-2.2
    iphone-2.1 iphonesim-2.1
    iphone-2.0 iphonesim-2.0
    iphone-1.x
    ;
# <grab source from boost.org>
tar xzf boost_1_42_0.tar.gz
cd boost_1_42_0
./bootstrap.sh

# Install for device:
./bjam --prefix=${HOME}/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.1.3.sdk/usr toolset=darwin architecture=arm target-os=iphone macosx-version=iphone-3.1.3 define=_LITTLE_ENDIAN link=static install

# Install for simulator
./bjam –-prefix=${HOME}/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator3.1.3.sdk/usr toolset=darwin architecture=x86 target-os=iphone macosx-version=iphonesim-3.1.3 link=static install