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
orarm-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?
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?