[gdal-dev] Building GDAL from source for android under cygwin

Petr Kitashov hilmekrhu at gmail.com
Mon Apr 16 17:42:48 EDT 2012


Hi everyone,

Some reason, I needed to build gdal for android on windows, so I'll be glad
if this helps someone - it's not very obvious.
I don't like the script, which edits libgdal.la file, but due to the lack
of experience with libtool I don't know, how to do it in a better way.

This procedure was developed on a Windows 7 system using Android NDK r7c
and is based on information from this manual:
http://trac.osgeo.org/gdal/wiki/BuildingForAndroid

We need:
 - Android NDK r7c (I think, all the versions from r5b will fit fine, but
didn't test it)
 - Cygwin 1.7 or higher
 - Gdal 1.9.0


1. NDK preparation
It's useful to have "PATH=$PATH:<path/to/android-ndk-r7c>" in your cygwin
.profile, but you can add it manually as the first step after ndk unzip:
$ export PATH=$PATH:/cygdrive/c/dev/Android/android-ndk-r7c

As in linux, we should create a standalone toolchain somewhere, i made it
from the "/cygdrive/c/dev/Android/" directory
$ android-ndk-r7c/build/tools/make-standalone-toolchain.sh
--platform=android-8 --install-dir=android-8-toolchain

Add toolchain bin directory to PATH:
$ export PATH=$PATH:/cygdrive/c/dev/Android/android-8-toolchain/bin

Since android g++ or gcc can't understand cygwin path like
/cygdrive/c/path/to, we need to correct them. Create a file and fill it
with:

#! /bin/sh

#Notice space at the end
RUN_COMMAND="/bin/sh "

if [[ "$1" == "" ]]
then exit
fi

for x in "$@"
do
    if [[ ${x: -7} == "libtool" ]]
        then
    RUN_COMMAND=$RUN_COMMAND' '$x

else
if [[ ${x: -11} == "/libgdal.la" ]]
    then
sed -i.bak 's/libgdal.so.1.16.0 libgdal.so.1 libgdal.so/libgdal.so libgdal.so.1
libgdal.so.1.16.0/' $x
fi
RUN_COMMAND=$RUN_COMMAND' '${x/\/cygdrive\/c\//C:\/}

    fi
done

$RUN_COMMAND

I placed this file in "/cygdrive/c/dev/Android/android-8-toolchain/bin" as
it's already in the PATH. Script will turn all the "/cygdrive/c/" into
"C:/" except libtool invoke command. The sed command will be explained a
bit later.


2. Gdal configure
Go to gdal 1.9.0 source directory. Ndk-build, in future, expect your ndk
gdal module to be in path/to/<tag>/, where <tag> is gdal for us, so we use
something like "/cygdrive/c/dev/lib/gdal-1.9.0/gdal" as the prefix for our
build:
$ CFLAGS="-mthumb" CXXFLAGS="-mthumb" ./configure
--host=arm-linux-androideabi --prefix=/cygdrive/c/dev/lib/gdal-1.9.0/gdal

Note, that we don't need to mention -lstdc++ or -lsupc++. Btw, the last one
is not placed in the toolchain since ndk-7 release (it's a known bug).

Now we need to edit GDALMake.opt:
After "SHELL    =   /bin/sh" line add this: "CORRECT = correct_path".
Two lines down, change "LIBTOOL = $(SHELL) $(top_builddir)/libtool"
to "LIBTOOL = $(CORRECT) $(top_builddir)/libtool"

Now simply make:
$ make

There is a problem with generated libtool.la file - it has line:
"library_names='libgdal.so.1.16.0 libgdal.so.1 libgdal.so'", so libgdal.so
will be passed to g++. It will fail, but the sed command in the script
changes this line to "library_names='libgdal.so libgdal.so.1
libgdal.so.1.16.0'" and it links fine.

Now, just install:
$ make install


3. Creaing Android application.

Now just set path to gdal module (path must contain 'gdal' folder - tag
name):

$ export NDK_MODULE_PATH=/cygdrive/c/dev/lib/gdal-1.9.0

In the gdal-tag module directory ($NDK_MODULE_PATH/gdal) create an
Android.mk file:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := gdal
LOCAL_SRC_FILES := lib/libgdal.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_EXPORT_LDLIBS := -lz
include $(PREBUILT_STATIC_LIBRARY)


Create some android app, let it be HelloGdal.
In the project's jni directory, create hello-jdal.cpp with the following
contents:

#include <jni.h>
#include <ogr_api.h>
#include <sstream>

extern "C" {
JNIEXPORT jstring
JNICALL Java_org_gdal_HelloGdal_stringFromGDAL(JNIEnv*env, jobject thiz);
}

JNIEXPORT jstring
JNICALL Java_org_gdal_HelloGdal_stringFromGDAL(JNIEnv* env, jobject thiz)
{
OGRRegisterAll();
std::ostringstream drivers;
drivers << "OGR Drivers:\n";
for (int i = 0; i < OGRGetDriverCount(); ++i)
drivers << "\t" << OGR_Dr_GetName(OGRGetDriver(i)) << "\n";

return env->NewStringUTF(drivers.str().c_str());
}


The corresponding Android.mk, which should be placed in the same folder:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := hello-gdal
LOCAL_SRC_FILES := hello-gdal.cpp
LOCAL_STATIC_LIBRARIES := gdal

include $(BUILD_SHARED_LIBRARY)
$(call import-module,gdal)


You should also create Application.mk with a single line inside:
APP_STL := gnustl_shared

Now, from the jni directory simply run ndk build:
$ ndk-build

Two libraries - libgnustl_shared.so and libhello-gdal.so will be created as
result.

Java code of the app:

package org.gdal;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class HelloGdal extends Activity
{
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        TextView tv = new TextView(this);
        tv.setText( stringFromGDAL() );
        setContentView(tv);
    }

    public native String stringFromGDAL();

    static { System.loadLibrary("hello-gdal"); }
}

-- 
Best Regards,
Petr Kitashov
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.osgeo.org/pipermail/gdal-dev/attachments/20120417/95d73c2c/attachment.html


More information about the gdal-dev mailing list