I'm working on porting FreeGLUT for Android, and FreeGLUT is switching to CMake.

I'm more familiar with the GNU Autotools myself, and I'm used to cross-compile with a simple:

./configure --host=arm-linux-androideabi

Can we do that with CMake? Well, it's not well-documented, but yes :) Let's see how to do that for Android (smartphones) and MinGW (.exe for windows).


The principle is:

  • write a "toolchain" CMake script that defines the cross-compiler,

  • mention you're using a "GNU" compiler (a.k.a. GCC) so CMake automatically looks for prefixed cross-compilers tools such as arm-linux-androideabi-cpp or arm-linux-androideabi-ld.

  • pass the toolchain script to CMake using the predefined CMAKE_TOOLCHAIN_FILE variable.

  • REMOVE all the CMake-generated files when you change anything, CMake does not rebuild its cache when the toolchain script or PATH is modified, this creates misleading errors. Hence, building in a subdirectory is crucial.

Here's a simple toolchain script:

SET(CMAKE_SYSTEM_NAME Linux)  # Tell CMake we're cross-compiling
include(CMakeForceCompiler)
# Prefix detection only works with compiler id "GNU"
# CMake will look for prefixed g++, cpp, ld, etc. automatically
CMAKE_FORCE_C_COMPILER(arm-linux-androideabi-gcc GNU)
SET(ANDROID TRUE)

Note: SET(ANDROID TRUE) is not mandatory for CMake, it's just used to detect an Android build in the particular case of FreeGLUT development.

Here's how to invoke it:

PATH=/usr/src/ndk-standalone-9/bin:$PATH
cd /usr/src/freeglut-3.0.0/
mkdir cross-android/ && cd cross-android/
cmake \
  -D CMAKE_TOOLCHAIN_FILE=../android_toolchain.cmake \
  -D CMAKE_INSTALL_PREFIX=/freeglut \
  ..
make -j4
make install DESTDIR=$(pwd)

Now here's a slightly more complex toolchain for MinGW.

The main issue with MinGW is that there are at least 4 possible prefixes depending on which version and which distro you're using. So I ask the user to specify it with GNU_HOST:

SET(CMAKE_SYSTEM_NAME Windows)
include(CMakeForceCompiler)
IF("${GNU_HOST}" STREQUAL "")
    SET(GNU_HOST i586-mingw32msvc)
ENDIF()
# Prefix detection only works with compiler id "GNU"
CMAKE_FORCE_C_COMPILER(${GNU_HOST}-gcc GNU)
# CMake doesn't automatically look for prefixed 'windres', do it manually:
SET(CMAKE_RC_COMPILER ${GNU_HOST}-windres)

I wanted to print an error when GNU_HOST is not specified, but the toolchain script is loaded multiple times, and the command-line variables are not always set (CMake is not super-clean in that regard). So I defined a default, that works.

Sample invocation:

  apt-get install mingw-w64

  mkdir cross-woe/ && cd cross-woe/
  cmake \
    -D GNU_HOST=x86_64-w64-mingw32 \
    -D CMAKE_TOOLCHAIN_FILE=../mingw_cross_toolchain.cmake \
    -D CMAKE_INSTALL_PREFIX=/freeglut \
    ..
  make -j4
  make install DESTDIR=$(pwd)

I used this technique to cross-compile my projects, or other projects that use CMake. mingw-cross-env uses this technique (abeilt with explicit definition of all compiler tools) to provide pre-built windows libraries without altering the existing CMake scripts.

Do you people have tips or a better technique to cross-compile with CMake?

Posted Sat Mar 3 13:38:45 2012 Tags:

FreeGLUT on Android

The OpenGL ES port of FreeGLUT is progressing :)

Now we have:

  • Basic Android/EGL port

  • Full X11/EGL port (using Mesa EGL), so we can test GLES on desktop :)

  • Geometry functions: upgrade from glBegin to glVertexPointer and GLES compatibility (triangulation). We also plan to provide shaders-compatible (OpenGL >= 2) geometry functions.

In addition, the work is available in the official repository! http://freeglut.svn.sourceforge.net/viewvc/freeglut/trunk/freeglut/freeglut/

Question: Mesa and Android ship GLES 1&2 in separate libraries. So at first glance, we'll have to ship 3 FreeGLUT builds:

  • freeglut.so / .a

  • freeglut-gles2.so / .a with -DFREEGLUT_GLES2 (-lGLESv2 + GLES2/gl2.h)

  • freeglut-gles1.so / .a with -DFREEGLUT_GLES1 (-lGLESv1_CM + GLES/gl.h)

Though, EAGL (on iPhone) can initialize either GLES 1 or 2 at run-time. Maybe it's possibly to do that by dlopen'ing the GLES library dynamically, but this won't work for static builds - and make distro packagers cringe unless I'm mistaken ;)

Do you think there's a way to provide a unified version?

Posted Sun Mar 18 12:51:28 2012 Tags: