Simple keystroke dynamics analyzer/validator written in Ruby-GTK

I have written a simple keystroke dynamics analyzer/validator as a school project. An instance of Analysis can be attached to a widget, and its collected keystroke data can be averaged and compared using class methods in Analysis.
The Validation class holds class methods to manage a password hashes file and save/load encrypted keystroke analysis metrics to/from disk.

Full documentation is provided through RDoc annotations.

The code will be publicly browseable at my code site when I get permission to host it from my teacher. This is now a gem, and the code is available on github!


Using autotools with C++ to make GTK apps

I’ve been playing around with GTK+, specifically gtkmm last week. I love the GTK+ GUI and I want to write some portable desktop applications. Luckily there are great docs for newbies to get started with. Although C++ has never been my language of choice, I really want to learn it. I think I will warm up to it given I can find a style that works for me. First up are Makefiles. Oh, Makefile. How slender and seductive you start out. Such warts you grow. So much does your ass inflate. After hacking away on my own Makefile for about 2 days I still had code that compiled. But along with that feat came an ugly Makefile which needed constant pruning. I decided it was enough, and thought I’d give automake a try, as is recommended in the gtkmm docs. Luckily the docs are good. But I think they need a bit of updating. On a new C++ project, here’s what I do. I’m using the first gtkmm example here.

aczid@homer:~/helloworld_gtk$ ls -lR
.:
total 4
drwxr-xr-x 3 aczid aczid 4096 2008-03-18 20:57 src

./src:
total 12
-rw-r--r-- 1 aczid aczid 362 2008-02-09 11:35 helloworld.cpp
-rw-r--r-- 1 aczid aczid 367 2008-02-09 11:32 helloworld.h
-rw-r--r-- 1 aczid aczid 228 2008-02-09 11:33 main.cpp
aczid@homer:~/helloworld_gtk$

As you see I have a ‘src’ dir conatining my C++ sources, and no Makefile. Now comes the magic.

aczid@homer:~/helloworld_gtk$ autoscan
aczid@homer:~/helloworld_gtk$ ls -l
total 8
-rw-r--r-- 1 aczid aczid    0 2008-03-18 20:59 autoscan.log
-rw-r--r-- 1 aczid aczid  475 2008-03-18 20:59 configure.scan
drwxr-xr-x 3 aczid aczid 4096 2008-03-18 20:57 src
aczid@homer:~/helloworld_gtk$ mv configure.scan configure.ac

Autoscan has generated the input file for autoconf for you. Let’s take a look:

 #                                               -*- Autoconf -*-
 # Process this file with autoconf to produce a configure script.
 
 AC_PREREQ(2.61)
 AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS)
 AC_CONFIG_SRCDIR([src/main.cpp])
 AC_CONFIG_HEADER([config.h])
 
 # Checks for programs.
 AC_PROG_CXX
 AC_PROG_CC
 
 # Checks for libraries.
 
 # Checks for header files.
 
 # Checks for typedefs, structures, and compiler characteristics.
 
 # Checks for library functions.
 
 AC_OUTPUT

Let’s add a few lines.

 #                                               -*- Autoconf -*-
 # Process this file with autoconf to produce a configure script.
  
 AC_PREREQ(2.61)
 FULL-PACKAGE-NAME(Hello World)
 VERSION(1.0)
 BUG-REPORT-ADDRESS(bugs@aczid.nl)
 AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS)
 AC_CONFIG_SRCDIR([src/main.cpp])
 AC_CONFIG_HEADER([config.h])
 AM_INIT_AUTOMAKE
 
 # Checks for programs.
 AC_PROG_CXX
 AC_PROG_CC
  
 # Checks for libraries.
 PKG_CHECK_MODULES(DEPS, gtkmm-2.4 >= 2.4 gtk+-2.0 >= 2.2 glib-2.0 >= 2.2)
 AC_SUBST(DEPS_CFLAGS)
 AC_SUBST(DEPS_LIBS)

 # Checks for header files.
  AC_STDC_HEADERS

 # Checks for typedefs, structures, and compiler characteristics.
 
 # Checks for library functions.
 
 AC_CONFIG_FILES([Makefile src/Makefile])
 AC_OUTPUT

You see I added some GTK libs here. The next 2 lines after that set up the compiler options for them. Also notice I added references to a Makefile in the config files macro. These files need stubs to be processed by automake. There are a lot of macros in autoconf to do all kinds of crazy things. Edit ./Makefile.am and add:

 SUBDIRS = src

And in the src/Makefile.am you put:

 bin_PROGRAMS = helloworld
 helloworld_SOURCES = helloworld.cpp main.cpp
 helloworld_LDADD = $(DEPS_LIBS)
 AM_CPPFLAGS = $(DEPS_CFLAGS)

See, those LDADD and CPPFLAGS macros rely on our DEPS_LIBS and DEPS_CFLAGS variables declared in the configure.ac file. Now all you need to do is run some commands!

aczid@homer:~/helloworld_gtk$ aclocal
/usr/share/aclocal/libmcrypt.m4:17: warning: underquoted definition of AM_PATH_LIBMCRYPT
/usr/share/aclocal/libmcrypt.m4:17:   run info '(automake)Extending aclocal'
/usr/share/aclocal/libmcrypt.m4:17:   or see http://sources.redhat.com/automake/automake.html#Extending-aclocal
aczid@homer:~/helloworld_gtk$ autoconf
aczid@homer:~/helloworld_gtk$ autoheader
aczid@homer:~/helloworld_gtk$ touch NEWS README AUTHORS ChangeLog
aczid@homer:~/helloworld_gtk$ automake --add-missing

Phew, that’s it! Now you can run ./confgure and it will generate a Makefile from the Makefile.in, which was in turn generated by Automake.

aczid@homer:~/helloworld_gtk$ ./configure
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking for g++... g++
checking for C++ compiler default output file name... a.out
checking whether the C++ compiler works... yes
checking whether we are cross compiling... no
checking for suffix of executables...
checking for suffix of object files... o
checking whether we are using the GNU C++ compiler... yes
checking whether g++ accepts -g... yes
checking for style of include used by make... GNU
checking dependency style of g++... gcc3
checking for gcc... gcc
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking dependency style of gcc... gcc3
checking how to run the C preprocessor... gcc -E
checking for grep that handles long lines and -e... /bin/grep
checking for egrep... /bin/grep -E
checking for ANSI C header files... yes
checking for a BSD-compatible install... /usr/bin/install -c
checking for pkg-config... /usr/bin/pkg-config
checking pkg-config is at least version 0.9.0... yes
checking for DEPS... yes
configure: creating ./config.status
config.status: creating Makefile
config.status: creating src/Makefile
config.status: creating config.h
config.status: config.h is unchanged
config.status: executing depfiles commands
aczid@homer:~/helloworld_gtk$ make
cd . && /bin/sh /home/aczid/helloworld_gtk/missing --run autoheader
rm -f stamp-h1
touch config.h.in
cd . && /bin/sh ./config.status config.h
config.status: creating config.h
config.status: config.h is unchanged
make  all-recursive
make[1]: Entering directory `/home/aczid/helloworld_gtk'
Making all in src
make[2]: Entering directory `/home/aczid/helloworld_gtk/src'
g++ -DHAVE_CONFIG_H -I. -I..  -I/usr/include/gtkmm-2.4 -I/usr/lib/gtkmm-2.4/include -I/usr/include/glibmm-2.4 -I/usr/lib/glibmm-2.4/include -I/usr/include/gdkmm-2.4 -I/usr/lib/gdkmm-2.4/include -I/usr/include/pangomm-1.4 -I/usr/include/atkmm-1.6 -I/usr/include/gtk-2.0 -I/usr/include/sigc++-2.0 -I/usr/lib/sigc++-2.0/include -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/lib/gtk-2.0/include -I/usr/include/cairomm-1.0 -I/usr/include/pango-1.0 -I/usr/include/cairo -I/usr/include/freetype2 -I/usr/include/libpng12 -I/usr/include/atk-1.0     -g -O2 -MT helloworld.o -MD -MP -MF .deps/helloworld.Tpo -c -o helloworld.o helloworld.cpp
mv -f .deps/helloworld.Tpo .deps/helloworld.Po
g++ -DHAVE_CONFIG_H -I. -I..  -I/usr/include/gtkmm-2.4 -I/usr/lib/gtkmm-2.4/include -I/usr/include/glibmm-2.4 -I/usr/lib/glibmm-2.4/include -I/usr/include/gdkmm-2.4 -I/usr/lib/gdkmm-2.4/include -I/usr/include/pangomm-1.4 -I/usr/include/atkmm-1.6 -I/usr/include/gtk-2.0 -I/usr/include/sigc++-2.0 -I/usr/lib/sigc++-2.0/include -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/lib/gtk-2.0/include -I/usr/include/cairomm-1.0 -I/usr/include/pango-1.0 -I/usr/include/cairo -I/usr/include/freetype2 -I/usr/include/libpng12 -I/usr/include/atk-1.0     -g -O2 -MT main.o -MD -MP -MF .deps/main.Tpo -c -o main.o main.cpp
mv -f .deps/main.Tpo .deps/main.Po
g++  -g -O2   -o helloworld helloworld.o main.o -lgtkmm-2.4 -lgdkmm-2.4 -latkmm-1.6 -lpangomm-1.4 -lcairomm-1.0 -lglibmm-2.4 -lsigc-2.0 -lgtk-x11-2.0 -lgdk-x11-2.0 -latk-1.0 -lgdk_pixbuf-2.0 -lm -lpangocairo-1.0 -lpango-1.0 -lcairo -lgobject-2.0 -lgmodule-2.0 -ldl -lglib-2.0
make[2]: Leaving directory `/home/aczid/helloworld_gtk/src'
make[2]: Entering directory `/home/aczid/helloworld_gtk'
make[2]: Leaving directory `/home/aczid/helloworld_gtk'
make[1]: Leaving directory `/home/aczid/helloworld_gtk'
aczid@homer:~/helloworld_gtk$

See? :) I’ve quite enjoyed fooling around with this. It beats the hell out of writing your own Makefiles. It’s nice to know your app will be compatible with GNU standards and there is much less to write and consequently maintain. In the future I think I’ll look at other systems that try to ease the same pains. Autotools were made for much bigger projects than mine. Scons is what I might look into next.



Me elsewhere: