I got this working for GDAL 2.2.2 and PROJ 4.9.3 several years ago. I'm now converting that project from Objective-C to Swift and I don't have time to figure out how to deal with the build issues I get for newer versions of GDAL and PROJ. but I now have the process working for a Swift project with these older versions.
I use a set of FOUR scripts to manage the GDAL build process, largely based on the old "pseudogreen" script that everybody seems to have used for building GDAL on iOS. I will post them here with just minimal explanation, but feel free to ask questions, and I'll answer them as best I can. Note that some of the items in scripts (particularly some of the environment variable values, such as CFLAGS values) are a bit beyond my understanding.
Note that in all of these scripts, my default prefix is "${HOME}/build", but other people may prefer to use "/usr/local" (or something else).
The first two scripts, one for PROJ and one for GDAL, will automatically download the sources from the web and unpack them if it cannot find what looks like the unpacked directory, already. In the case of GDAL, it also includes automatically fixing a bug in one of the config sources immediately after downloading and unpacking. Without this fix, it will not build for iOS (I had an email list conversation with the GDAL developers about this, but I don't know if it got fixed in later versions or not).
These first two scripts essentially pass the all the "configure" parameters required to a generic script that will build any configure/make package for iOS into a UNIVERSAL binary, including arm64 (for device) and x86_64 (for simulator on mac). It uses "lipo" to combine several architecture-dependent binaries into a single universal binary.
This Universal script runs a loop so that for each architecture, it calls the fourth script which builds for a single architecture.
PROJ SCRIPT - "build_proj_universal.sh":
#!/bin/bash
PREFIX="${HOME}/build"
proj_ver=4.9.3
# download gdal if necesary
if [ ! -e proj-$proj_ver ]
then
echo proj4 missing, downloading
curl -O http://download.osgeo.org/proj/proj-$proj_ver.tar.gz
tar -xzf proj-$proj_ver.tar.gz
fi
startdir="$PWD"
cd proj-$proj_ver
universal_build_for_ios -p "$PREFIX" libproj.a \
| tee "$startdir/$0.log"
GDAL SCRIPT - "build_gdal_universal.sh":
PREFIX="${HOME}/build"
gdal_ver=2.2.2
# download gdal if necesary
if [ ! -e gdal-$gdal_ver ]
then
curl -O http://download.osgeo.org/gdal/$gdal_ver/gdal-$gdal_ver.tar.gz
tar -xzf gdal-$gdal_ver.tar.gz
sed 's/#undef HAVE_LONG_LONG/\/\* #undef HAVE_LONG_LONG \*\/\'$'\n#define HAVE_LONG_LONG 1/' gdal-$gdal_ver/port/cpl_config.h.in > gdal-$gdal_ver/port/cpl_config.h.in.NEW
mv gdal-$gdal_ver/port/cpl_config.h.in gdal-$gdal_ver/port/cpl_config.h.in.ORIG
mv gdal-$gdal_ver/port/cpl_config.h.in.NEW gdal-$gdal_ver/port/cpl_config.h.in
fi
startdir="$PWD"
cd gdal-$gdal_ver
universal_build_for_ios -p "$PREFIX" libgdal.a \
--with-hide-internal-symbols \
--with-unix-stdio-64=no \
--with-geos=no \
--without-pg \
--without-grass \
--without-libgrass \
--without-cfitsio \
--without-pcraster \
--without-netcdf \
--without-ogdi \
--without-fme \
--without-hdf4 \
--without-hdf5 \
--without-jasper \
--without-kakadu \
--without-grib \
--without-mysql \
--without-ingres \
--without-xerces \
--without-odbc \
--without-idb \
--without-sde \
--with-sse=no \
--with-avx=no \
--with-expat="${PREFIX}" \
--with-static-proj4="${PREFIX}" \
--with-sqlite3="${PREFIX}" \
| tee "$startdir/$0.log"
(Note that the exact options you use here will depend on your requirements. If you use the --with-expat
option like I've done here, you'll also need to download and build libexpat similarly to how we do with proj. I need Expat to be able to read GPX and KML. GDAL can write these without Expat, but cannot read them without Expat.)
Script to Build Universal Binary for iOS - "universal_build_for_ios":
default_prefix="${HOME}/build"
while getopts ":p:" opt; do
case $opt in
p ) PREFIX="$OPTARG" ;;
esac
done
shift $(( $OPTIND - 1 ))
if [ $# -lt 1 ]; then
echo "Usage: $0 [-p prefix] <target_library> [configure-options]"
exit 2
fi
library=$1
shift
configopts="${@:1}"
PREFIX="${PREFIX:-$default_prefix}"
libs=""
for i in arm64 x86_64; do
buildcmd="build_for_ios $i ${@:3}"
echo "\n$buildcmd\n"
$buildcmd || exit -2
libs="$libs $PREFIX/$i/lib/$library"
done
mkdir -p "$PREFIX/lib/$library"
lipocmd="lipo -create -output $PREFIX/lib/$library $libs"
echo "\n$lipocmd"
$lipocmd || exit -1
echo "\nUNIVERSAL LIBRARY BUILT AT:\n\n$PREFIX/lib/$library\n"
Script to Build Single Architecture for iOS (device or simulator) - "build_for_ios":
#!/bin/bash
#default_iphoneos_version=14.4
default_iphoneos_version=`xcrun --sdk iphoneos --show-sdk-platform-version`
default_prefix="${HOME}/build"
export IPHONEOS_DEPLOYMENT_TARGET="${IPHONEOS_DEPLOYMENT_TARGET:-$default_iphoneos_version}"
usage ()
{
cat >&2 << EOF
Usage: ${0##*/} [-ht] [-p prefix] target [configure_args]
-h Print help message
-p Installation prefix (default: \$HOME)
-t Use 16-bit Thumb instruction set (instead of 32-bit ARM)
The target must be "device" or "simulator". Any additional arguments
are passed to configure.
The following environment variables affect the build process:
IPHONEOS_DEPLOYMENT_TARGET (default: $default_iphoneos_version)
EOF
}
while getopts ":hp:t" opt; do
case $opt in
h ) usage ; exit 0 ;;
p ) prefix="$OPTARG" ;;
t ) thumb_opt=thumb ;;
\? ) usage ; exit 2 ;;
esac
done
shift $(( $OPTIND - 1 ))
if (( $# < 1 )); then
usage
exit 2
fi
target=$1
shift
arch=$target
host="${arch}-apple-darwin"
case $target in
arm64 )
platform=iPhoneOS
extra_cflags="-m${thumb_opt:-no-thumb}"
host="arm-apple-darwin"
;;
x86_64 )
platform=iPhoneSimulator
extra_cflags="-D__IPHONE_OS_VERSION_MIN_REQUIRED=${IPHONEOS_DEPLOYMENT_TARGET%%.*}0000"
;;
* )
usage
exit 2
esac
xcode="/Applications/Xcode.app"
platform_dir="${xcode}/Contents/Developer/Platforms/${platform}.platform/Developer"
platform_sdk_dir="${platform_dir}/SDKs/${platform}${IPHONEOS_DEPLOYMENT_TARGET}.sdk"
prefix="${prefix:-$default_prefix}"
platform_bin_dir="${platform_dir}/usr/bin"
export CC="${xcode}/Contents/Developer/usr/bin/gcc"
export CFLAGS="-arch ${arch} -pipe -Os -gdwarf-2 -isysroot ${platform_sdk_dir} -Wno-implicit-function-declaration -fembed-bitcode ${extra_cflags}"
export LDFLAGS="${LDFLAGS} -arch ${arch} -isysroot ${platform_sdk_dir}"
export CXX="${xcode}/Contents/Developer/usr/bin/g++"
export CXXFLAGS="${CFLAGS}"
libdir="${prefix}/${arch}/lib"
mkdir -p "$libdir"
echo
echo platform_sdk_dir: $platform_sdk_dir
echo
echo prefix: $prefix
echo
echo
make distclean
echo
echo
./configure \
--prefix="${prefix}" \
--libdir="$libdir" \
--host="${host}" \
--disable-shared \
--enable-static \
"$@" || exit
echo
echo
make install || exit
cat >&2 << EOF
Build succeeded.
Files were installed in:
$prefix
EOF
Incorporate into XCode Project:
Build PROJ and then GDAL using the build_proj_universal.sh
and build_gdal_universal.sh
scripts (above).
Then in XCode (assuming you built to ${HOME}/build/):
- For the target's "Build Settings"
- "Header Search Paths" add: $(HOME)/build/include
- "Library Search Paths" add: $(HOME)/build/lib
- For the target's "Build Phases" -> "Link Binary With Libraries" add:
- libc++.tdb
- libz.tdb
- libiconv.tdb
- libsqlite3.tdb
- libproj.a
- libgdal.a
(these last two will have to be manually selected from the 'lib' directory to which you build them, the rest should be a quick search and select using the search field)
- Then in your code you will need to import the following headers (this may vary, depending on which parts of GDAL you use):
- gdal.h
- ogr_api.h
- ogr_srs_api.h
In Swift, I did this using a "module.map" file as follows:
module CGDAL [system] {
header "/Users/nsands/build/include/gdal.h"
header "/Users/nsands/build/include/ogr_api.h"
header "/Users/nsands/build/include/ogr_srs_api.h"
export *
}
(If you use this module.map method, then you need to also set the target's "Build Settings" -> "Swift Compiler - Search Paths" -> "Import Paths" to include the path to the directory that contains your "module.map" file.)
Now in my swift code, I can just:
import CGDAL
and get access to all the GDAL functions that I need.