RSS Atom Add a new post titled:

I recently faced an environment where there is no MTA.

WTF? The reason is that people who work there get security audits on a regular basis, and the security people are usually mo...deratly skilled guys who blindly run a set of scripts, e.g. by ordering to disable Apache modules that "where seen enabled in /etc/apache2/mods-available/"...

To avoid spending days arguing with them and nitpicking with non-technical managers, the system is trimmed to the minimum - and there is no MTA. No MTA, so no cron output, so difficulty to understand why last night's cron job failed miserably.

Since it was not my role to reshape the whole business unit, I decided to hack a super-light, but functional way to get my cron output:

cat <<'EOF' > /usr/sbin/sendmail
#!/bin/bash
(
    echo "From me  $(LANG=C date)"
    cat
    echo
) >> /var/mail/all
EOF
chmod 755 /usr/sbin/sendmail

It works! :)

There is a companion logrotate script, to avoid filling the file system:

cat <<'EOF' > /etc/logrotate.d/mail-all
/var/mail/all {
  daily
  rotate 10
  compress
  delaycompress
  notifempty
  create 622 root mail
}
EOF

Bootstrap with:

touch /var/mail/all
logrotate -f /var/mail/all

You now can check your sys-mails with:

mutt -f /var/mail/all

;)

Posted Mon Feb 13 22:18:46 2012 Tags:

I'm working on porting FreeGLUT to Android!

Since I don't have access so the repository (I'm not a regular contributor), and since it will be a BIG patch, I thought I'd try a git-svn branch. So this won't be a post on OpenGL for once ;)

I'm not an expert at managing Git branch but here's how I set it up.

In this case, let's forget about importing tags: they don't have the same directory branch point in the hierarchy (sometimes the freeglut/ module, sometimes the parent directory), and git-svn only correctly supports set of sane tags that track the same initial directory.

SVN is SLOW, especially remotely. I suggest you make a rsync copy of the repository first, it will greatly speed up the import :

rsync -avHSP freeglut.svn.sourceforge.net::svn/freeglut/ freeglut.svn/

Then start the import with git-svn :

git svn clone --trunk=trunk/freeglut/freeglut file://$(pwd)/freeglut.svn/ freeglut-git/

And edit .git/config to point to https://freeglut.svn.sourceforge.net/svnroot/freeglut :

[svn-remote "svn"]
    url = https://freeglut.svn.sourceforge.net/svnroot/freeglut
    fetch = trunk/freeglut/freeglut:refs/remotes/trunk

I work with 2 branches:

  • master : the SVN on-going sync - may be rebased to push with git svn dcommit
  • android : my feature branch - not rebased and hence trackable by contributors

Here's how I synchronize the upstream repository and merge it regularly with my feature branch:

git svn fetch
git checkout master
git merge remotes/trunk

git checkout android  # my feature branch
git merge master
# if conflict
git add .../sthing.c
git commit -m "Merge master"
git push

Any better way?

The ongoing work is available at https://gitorious.org/freeglut/android :)

Posted Sun Feb 12 22:43:13 2012 Tags:

If you ever get this cryptic error when loading an Android native app:

FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo{org.wikibooks.OpenGL/android.app.NativeActivity}: java.lang.IllegalArgumentException: Unable to load native library: /data/data/org.wikibooks.OpenGL/lib/libnative-activity.so
       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1768)
       at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1784)
       at android.app.ActivityThread.access$1500(ActivityThread.java:123)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:939)
       at android.os.Handler.dispatchMessage(Handler.java:99)
       at android.os.Looper.loop(Looper.java:130)
       at android.app.ActivityThread.main(ActivityThread.java:3835)
       at java.lang.reflect.Method.invokeNative(Native Method)
       at java.lang.reflect.Method.invoke(Method.java:507)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:847)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:605)
       at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.IllegalArgumentException: Unable to load native library: /data/data/org.wikibooks.OpenGL/lib/libnative-activity.so
       at android.app.NativeActivity.onCreate(NativeActivity.java:199)
       at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1722)
       ... 11 more

This may mean that Java couldn't find the ANativeActivity_onCreate function in your code, because it was stripped by the compiler.

If you use the native_app_glue NDK module, you may have noticed this strange code:

    // Make sure glue isn't stripped.
    app_dummy();

Let's experiment what happens with and without this line:

Calling app_dummy:

$ arm-linux-androideabi-objdump -T libs/armeabi/libnative-activity.so  | grep ANativeActivity_onCreate
000067fc g    DF .text  000000f8 ANativeActivity_onCreate

Not calling app_dummy :

$ arm-linux-androideabi-objdump -T libs/armeabi/libnative-activity.so | grep ANativeActivity_onCreate
$   # nothing

native_app_glue mainly defines Android callbacks. Since none of them are called directly by your code, the compiler strips the android_native_app_glue.o module entirely. If you use app_dummy however, it embeds it. Fortunately the compiler cannot strip the module on a per-function basis ;)

That's why you need to call app_dummy when using the native_app_glue NDK module.

This looks like a ugly work-around though - isn't there a cleaner way?

Posted Tue Feb 7 21:12:05 2012 Tags:

If you want to use FreeType in your native C/C++ Android app, you'll need to cross-compile it. The Android system uses FreeType internally but it doesn't expose it to native apps.

First, prepare the cross-compiler from the NDK:

/usr/src/android-ndk-r7/build/tools/make-standalone-toolchain.sh \
  --platform=android-9 \
  --install-dir=/usr/src/ndk-standalone-9
PATH=/usr/src/ndk-standalone-9/bin:$PATH

Then use it to cross-compile freetype:

tar xf freetype-2.4.8.tar.bz2
cd freetype-2.4.8/
CFLAGS="-std=gnu99" ./configure --host=arm-linux-androideabi --prefix=/freetype \
  --without-zlib
make
make install DESTDIR=$(pwd)

See this discussion for the --std option.

--without-zlib uses the internal copy of zlib inside freetype rather than one independently recompiled for Android. Otherwise you'd get errors such as:

./obj/local/armeabi/libfreetype.a(ftgzip.o): In function `ft_gzip_file_init':
ftgzip.c:(.text+0x3c4): undefined reference to `inflateInit2_'
./obj/local/armeabi/libfreetype.a(ftgzip.o): In function `ft_gzip_file_done':
ftgzip.c:(.text+0x43c): undefined reference to `inflateEnd'
./obj/local/armeabi/libfreetype.a(ftgzip.o): In function `ft_gzip_file_reset':
ftgzip.c:(.text+0x514): undefined reference to `inflateReset'
./obj/local/armeabi/libfreetype.a(ftgzip.o): In function `ft_gzip_file_fill_output':
ftgzip.c:(.text+0x780): undefined reference to `inflate'

Then write an Android.mk file in the new freetype/ directory:

#####
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := freetype
LOCAL_SRC_FILES := lib/libfreetype.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include $(LOCAL_PATH)/include/freetype2
include $(PREBUILT_STATIC_LIBRARY)
#####

See docs/STANDALONE-TOOLCHAIN.html and docs/PREBUILTS.html in the NDK for details. The CLEAR_VARS bit is not documented, but is necessary to avoid mixed-up paths; it is used in the native_app_glue NDK module.

To use FreeType in your project, edit your Android.mk:

...
LOCAL_STATIC_LIBRARIES := ... freetype
...
$(call import-module,freetype)

You will need to specify the freetype directory location as well, using the NDK_MODULE_PATH variable. For instance, you can copy freetype in your project directory and build using:

    ndk-build NDK_MODULE_PATH=. ...

[Latest version of these instructions can be found at the OpenGL Wikibook]

Posted Sun Jan 29 17:24:39 2012 Tags:

Teapot on Android I got myself a second-hand Samsung Galaxy S at last, and started hacking on it!

The very first thing I wanted to try was porting the OpenGL wikibook C++ samples, that we wrote with OpenGL ES 2 in mind.

I started writing a minimal GLUT-compatible wrapper to run the samples as-is, using the Android NDK, and I'm making progress :) The Android NDK is getting nicer with Android 2.3, though it still feels less supported than Java apps (e.g. the resize events seem buggy and the keycodes header is incomplete...). Nonetheless, it's nice to be able to write C++ portable apps.

You can see how to use the wrapper, and how it works internally, at:

http://en.wikibooks.org/wiki/OpenGL_Programming/Installation/Android

One of the limitations is that GLES2 is not a true subset of OpenGL 2.1, in particular:

  • the shader version is declared differently (#version 100 vs. #version 120)
  • GLES2 shaders require float precision hints, but OpenGL 2.1 doesn't support them at all

I needed to pre-process these differences away, checking on GL_ES_VERSION_2_0 in the C++ source code to define a GLES2 macro in the shaders:

#ifdef GLES2
varying lowp vec4 f_color;
# else
varying vec4 f_color;
#endif

Is there a better way?

Posted Tue Jan 24 21:45:07 2012 Tags:

If you ever need to check a CVS history file's timestamp:

A4eb172bd|myaccount||Module/Dir|1.1|yopla.c

$ perl -e 'print unpack("N", pack("H8", "4eb172bd")) . "\n"'
1320252093
$ date -d "@1320252093"
Wed Nov  2 17:41:33 CET 2011
Posted Sun Nov 6 14:39:48 2011 Tags:

[Latest version of these instructions can be found at the SFML Wiki]

CMake allows your project to be built in various environments, including command-line make, Code::Blocks project files, Eclipse project files, etc. It's used in SFML 2.0.

In this tutorial we'll write a simple CMake configuration file with centralized version numbering, and see how to integrate SFML in it.

The source files

First, create a cmake_modules directory and copy FindSFML.cmake in it. FindXXXX is automatically searched by CMake's find_package command.

Then create a main.cpp, for instance:

#include "config.h"
#include <iostream>
#include <SFML/Window.hpp>
using namespace std;

int main(int argc, char* argv[]) {
  cout << "Version " << myproject_VERSION_MAJOR << "." << myproject_VERSION_MINOR << endl;

  sf::Window screen(sf::VideoMode(800, 600), "myproject");
  bool running = true;
  while (running) {
    screen.Display();
  }
}

We use a config.h file that is built by CMake, let's also create a config.h.in file:

#define myproject_VERSION_MAJOR @myproject_VERSION_MAJOR@
#define myproject_VERSION_MINOR @myproject_VERSION_MINOR@

And place your project license (such as the GNU GPL) in a file named COPYING.

CMake configuration

Let's describe our project configuration in the CMakeLists.txt file:

cmake_minimum_required(VERSION 2.6)
project(myproject)

# Set version information in a config.h file
set(myproject_VERSION_MAJOR 1)
set(myproject_VERSION_MINOR 0)
configure_file(
  "${PROJECT_SOURCE_DIR}/config.h.in"
  "${PROJECT_BINARY_DIR}/config.h"
  )
include_directories("${PROJECT_BINARY_DIR}")

# Define sources and executable
set(EXECUTABLE_NAME "myproject")
add_executable(${EXECUTABLE_NAME} main.cpp)


# Detect and add SFML
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake_modules" ${CMAKE_MODULE_PATH})
find_package(SFML 1.6 REQUIRED system window graphics network audio)
target_link_libraries(${EXECUTABLE_NAME} ${SFML_LIBRARIES})


# Install target
install(TARGETS ${EXECUTABLE_NAME} DESTINATION bin)


# CPack packaging
include(InstallRequiredSystemLibraries)
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING")
set(CPACK_PACKAGE_VERSION_MAJOR "${myproject_VERSION_MAJOR}")
set(CPACK_PACKAGE_VERSION_MINOR "${myproject_VERSION_MINOR}")
include(CPack)

The interesting part is:

# Detect and add SFML
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake_modules" ${CMAKE_MODULE_PATH})
find_package(SFML 1.6 REQUIRED system window graphics network audio)
target_link_libraries(${EXECUTABLE_NAME} ${SFML_LIBRARIES})
  • First we specify where we stored the FindSFML.cmake module.
  • Then we request CMake to look for it in the system, and search for the specified modules (here I specified them all).
  • Last, we tell CMake to link our executable with the SFML libraries that it just found.

Compilation

To build with Make and the GCC compiler on the command-line:

cd build/  # a separate directory so we can easily remove all the CMake work files
cmake ..  # generate Makefile's
make

To create Code::Blocks project files:

cmake .. -G "CodeBlocks - Unix Makefiles"

and open project.cbp with Code::Blocks.

Installation

CMake supports the classic:

make install

It also supports DESTDIR, useful in packaging:

make install DESTDIR=`pwd`/myworkdir

You can also define CMAKE_INSTALL_PREFIX when invoking cmake to change the default install path (/usr/local under Unix). DESTDIR would still override this setting.

Packaging

You then can use cpack to make a project release:

# Binary package:
cpack -C CPackConfig.cmake
# Source package:
cpack -C CPackSourceConfig.cmake

You will get a nice myproject-1.0.tar.gz, among others.

Further information

  • CMake has built-in help, for instance:
$ cmake --help-variable CMAKE_SOURCE_DIR
cmake version 2.8.5
  CMAKE_SOURCE_DIR
       The path to the top level of the source tree.

       This is the full path to the top level of the current CMake source
       tree.  For an in-source build, this would be the same as
       CMAKE_BINARY_DIR.
Posted Tue Nov 1 20:13:45 2011 Tags:

Valve's Portal game introduced an innovative teleporter system - where you basically can see through the teleporter and even walk seamlessly through it.

Ever wondered how this is implemented? Check this Mini-Portal demo, along with its companion tutorials!

http://en.wikibooks.org/wiki/OpenGL_Programming/Mini-Portal

In this first part, we cover a basic working version that we will improve over the next few days.

[Find more tutorials at the OpenGL wikibook.]

Posted Sun Oct 23 16:24:21 2011 Tags:

Quickie OpenGL wikibook tutorial to show how to display a bounding box around your object :)

http://en.wikibooks.org/wiki/OpenGL_Programming/Bounding_box

Posted Thu Oct 20 22:01:07 2011 Tags:

Wave effect

Manipulating meshes and lights is nice, but sometimes we want to manipulate the good old pixels, in particular for post-processing effects such as blur.

But how can we do that in OpenGL? In this new OpenGL wikibook tutorial, we'll explore a solution: render to a texture through a framebuffer object!

http://en.wikibooks.org/wiki/OpenGL_Programming/Post-Processing

For our first effect, we'll implement the wave system previewed a few days ago in the video capture tutorial.

Posted Sat Oct 15 18:07:14 2011 Tags:

This blog is powered by ikiwiki.