Friday, November 23, 2012

Two problems with android-ndk-r8c

I've been trying to get back in to Android development, and the first thing to do was update all the build tools to the latest releases. This revealed 2 irritating problems in the current NDK when using ndk-build.

The first one is that your native code now rebuilds all the time. Whenever you run ndk-build, it compiles everything from scratch again. This is a known bug that looks like it will fixed in an update in the near future, but it is a bit irritating. The cause is that the object directory is a dependency of each object file, which means make will execute the rule to create the directory before it builds the objects. But writing the objects into the directory causes the modification time of the directory to change, forcing a rebuild of the depending objects. A vicious cycle that causes make to think your objects are always out of date. How nobody spotted this bug before release is a mystery to me. Anyway, the fix is easy - open up android-ndk/build/core/ and change line 289 to the following:

$1: | $$(__ndk_file_dir)
That adds in a | symbol before the $$. It's a GNU Make feature designed specifically for this problem.

The second issue is not such a clear cut bug. It is definitely a regression, but whether the bug is in the NDK or the Eclipse Android plugin is up for debate. This only affects you if you are trying to support older versions of Android and use native code.

When you want to support old releases and still use the latest SDK, you must specify the minimum SDK in your manifest XML file and specify the latest target platform in the file. Sadly with the r8c release the NDK part of the build spits out a warning like this:

WARNING: APP_PLATFORM android-8 is larger than android:minSdkVersion 4 in AndroidManifest.xml
Eclipse sees this warning and prevents you from launching the emulator with the usual "Run" command.

The easiest workaround is to add NDK_NO_WARNINGS=1 to the ndk-build invocation of your native part of the build. Right click your project and select Preferences > C/C++ Build. Uncheck the default option and change it to ndk-build NDK_NO_WARNINGS=1. This is just a workaround - if you have other warnings in your build then maybe you need to fix them :-) but as far as I can tell, the only other warning that could appear would be if you built with NDK_DEBUG set to something other than true or false.

Of course you mustn't actually use any new Android features at run time, or the application will crash.

Anyway I hope that helps someone out.

Oh, bit of editorialising now. It's interesting to see Google introduce Clang in this version of the NDK too. I fully expect them to bit-by-bit remove all the GPL code in the NDK and SDK, and GCC is the biggest piece there. Then they'll release the SDK binary-only with secret sauce. Similar to the way Chrome is a closed version of Chromium that includes Flash, and Google and co develop Android behind closed doors before releasing it to the Open Handset Alliance, but devices all ship with closed-source proprietary drivers. Currently the SDK is one of the few parts of Android that's developed in the open. I can't see that lasting, especially after Google added the recent "no fork" clause to the terms.