Building a hello world application

From Openmoko

(Difference between revisions)
Jump to: navigation, search
(configure.ac)
(Makefile.am)
Line 228: Line 228:
 
  # Checks for library functions that we really need.
 
  # Checks for library functions that we really need.
 
  AC_FUNC_MALLOC
 
  AC_FUNC_MALLOC
 
# Check for doxygen, so we can decide if we create a "doc" make target
 
# that depends on doxygen-
 
AC_CHECK_PROG([DOXYGEN], [doxygen], [doc], [])
 
AC_SUBST(DOXYGEN)
 
 
   
 
   
 
  # A list of all configuration files we have to generate
 
  # A list of all configuration files we have to generate
  AC_CONFIG_FILES([Makefile src/Makefile src/images/Makefile po/Makefile.in doc/Makefile]) #help/Makefile  
+
  AC_CONFIG_FILES([Makefile src/Makefile src/images/Makefile po/Makefile.in]) #help/Makefile  
 
   
 
   
 
  # Tell autoconf to start outputting whatever it has to.
 
  # Tell autoconf to start outputting whatever it has to.
 
  AC_OUTPUT
 
  AC_OUTPUT
 +
===== Makefile.am =====
 +
This file is a template top-level-Makefile that will be filled with life by the configure script.
  
 +
One thing that is added to the standard Makefile is code for automatically generate the '''_control'''-file mentioned above on a '''make dist'''
 +
# A list of all subdirectories.
 +
SUBDIRS = src po # help
 +
 +
# Allow automake to interpret m4 macros (needed for interpreting
 +
# gettext's makefile.in
 +
ACLOCAL_AMFLAGS = -I m4
 +
# Files that aren't source files and still have to be in the tarball
 +
EXTRA_DIST = @PACKAGE_NAME@_control
 +
 +
# An (currently unused) extension to the "install" target
 +
install-data-local:
 +
 +
@PACKAGE_NAME@_control: Makefile.am configure.ac
 +
echo "Package: @PACKAGE_NAME@">$@
 +
echo "Version: @PACKAGE_VERSION@">>$@
 +
echo "Description: An voice recorder that can stop recording during silence">>$@
 +
echo "Section: openmoko/applications">>$@
 +
echo "Priority: optional">>$@
 +
echo "Maintainer: your_name">>$@
 +
echo "Architecture: armv4t">>$@
 +
echo "Homepage: (The homepage of this project)">>$@
 +
echo "Depends: gtk+ alsa-lib libogg libvorbis gnome-vfs libgnomeui">>$@
 +
echo "Source: \$${SRC}">>$@
 +
 
{{Languages|Building_a_hello_world_application}}
 
{{Languages|Building_a_hello_world_application}}
 
[[Category:Software]]
 
[[Category:Software]]
 
[[Category:Guides]]
 
[[Category:Guides]]

Revision as of 11:42, 4 May 2008

Contents

Preparation

This guide assumes that you have performed the steps in Building_OpenMoko_from_scratch

The commandline program

Store the following more or less standard hello world code in hello.c

#include <stdio.h>

int main()
{
  printf ("Hello World\n");
  return 0;
}

Compiling it the wrong / easy way

Assuming your current working directory is /home/moko, and that you stored the code in /home/moko/hello.c it should now be possible to compile the application using

./build/tmp/cross/arm-linux/bin/gcc -o hello hello.c

Testing it

Assuming you have followed Setting up USB connection and you have a working network connection to either a qemu Neo or a real Neo.

scp hello root@192.168.0.202:/tmp/
ssh root@192.168.0.202 /tmp/hello

This sequence of commands ought to give you a nice Hello World, btw. the default root password is blank, just press return.

GDK the Wrong / Easy Way

Building a GDK application the wrong way is slightly more complex, but is still fun to try. It requires using pkg-config to specify including and linking with the ARM header files and libraries.

Given the following program as main.c:

#include <gtk/gtk.h>

gchar *hello = "Howdy";
gchar *world = "World";
GtkWidget *label;
gchar *labeltext;

void buttoncb(GtkWidget *widget, gpointer data)
{
if (labeltext == hello)
   {
   labeltext = world;
   gtk_label_set_text(GTK_LABEL(label), labeltext);
   }
else if (labeltext == world)
   gtk_main_quit();
}

int main(int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *button;

gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
button = gtk_button_new();
labeltext = hello;
label = gtk_label_new(labeltext);
gtk_container_add(GTK_CONTAINER(button), label);
g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(buttoncb), NULL);
gtk_container_add(GTK_CONTAINER(window), button);
gtk_widget_show_all(window);
gtk_main();

return 0;
}

You must first point pkg-config to the proper directory:

export PKG_CONFIG_PATH=/home/username/moko/build/tmp/staging/arm-linux/lib/pkgconfig

And set up an environment variable to make things easier:

export OMDIR=/home/username/moko

The compile/link line is rather long - you will only want to do this once before you decide to create a shell script or make file:

$OMDIR/build/tmp/cross/arm-angstrom-linux-gnueabi/bin/gcc -L $OMDIR/build/tmp/staging/arm-angstrom-linux-gnueabi/lib/ \
                   -Wl, rpath-link, $OMDIR/build/tmp/staging/arm-angstrom-linux-gnueabi/lib/ -Wl, -O1 -g -o hw main.c \
                   '$OMDIR/build/tmp/staging/i686-linux/bin/pkg-config --cflags --libs openmoko-libs gtk+-2.0'


Then copy and run as in the original hello world command line program above.

Why was it the wrong way?

OpenMoko provides a precompiled Toolchain package for that. It also comes with some scripts that make your life much easier. Besides, you don't need OpenEmbedded to build applications. If you do want to customize your complete distribution, then read on how to use bitbake when building stuff. In any way, at least you now know that you can easily cross compile for OpenMoko.

The Right Way: Using the gnome build system

Even if I am no expert in this - somebody had to make a start so I'll write down everything I still believe to remember from my 1st 'real' gnome application that used the autotools and all: I have never been able to find a good tutorial for making a "canonical" gnome application - and such a tutorial is urgently needed.

Since I know that many of these things will be missing or even inaccurate in the 1st step - if You find out to make it work better or at all - please document how to do this.

Creating the necessary documentation files and directory structure

First of all go into the directory you want to be the topmost application of yout new application, and create the following files:

AUTHORS||A list of all authors that took part in developing this project COPYING||The copyright notice. Favourably the GPL INSTALL||This file should contain the information how to build and install this program README||This file should contain all important information about the program including what the program was written for. NEWS||The name of this file should be self-describing TODO||The wishlist of your project Changelog||A list of the major changes to your project

I remember that some of these files were mandatory - it's better create them all

Then create a directory named 'src - and copy the source code of the program there.


The configuration of the autotools
autogen.sh

This file is a shell script that calls all autotools in the right order and with the right parameters so they will in the end generate the standard configure script that will detect how to build our program.

#! /bin/sh
#
# Most if not all of the contents of this file was taken from the openmoko
# sample application as it was shipped with the openmoko toolchain on
# January 31st, 2008
#

srcdir=`dirname $0`
test -z "$srcdir" && srcdir=.

PKG_NAME="helloworld"

(test -f $srcdir/configure.ac) || {
        echo -n "**Error**: Directory "\`$srcdir\'" does not look like the"
        echo " top-level $PKG_NAME directory"
        exit 1
}

which gnome-autogen.sh || {
        echo "You need to install gnome-common from the GNOME CVS"
        exit 1
}

REQUIRED_AUTOMAKE_VERSION=1.7 USE_GNOME2_MACROS=0 REQUIRED_GETTEXT_VERSION=0.10.36 . gnome-autogen.sh
configure.ac

This file tells what the configure script has to do - and which parts of the intelligence delivered with the tools that generate the configure script we need.

I documented every line of which I found out what it actually does. The first line is for to tell the emacs text editor that it has to treat this file as an autoconf file.

#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

# Tell autoconf to check what version of autoconf we need.
AC_PREREQ(2.61)

# Initialize autoconf and tell it what program we wrote, the version
# of our program, and the address bug reports have to be sent to.
AC_INIT([audiorec],[0.2],[audiorec.projects.openmoko.org])

# tell autoconf where to put the temporary files it generates 
AC_CONFIG_AUX_DIR([build-aux])

# This one is thaken from the "Migrationg to gnome Documentation Build
# utilities". No Idea, what it does.
AC_CONFIG_MACRO_DIR([m4])

# give autoconf the name of a file whose existence is a hint that
# autoconf has been started from the right directory. 
AC_CONFIG_SRCDIR([src/diskusagemeter.c])

# Tell autoconf where to put the output file that contains all
# definitions our C program will need
AC_CONFIG_HEADER([src/config.h:src/config.hin])

# Initialize automake, and tell it to tell the C compiler to output as
# many warnings as it can
AM_INIT_AUTOMAKE([-Wall foreign])

# The GNU Gettext version we used for internationalization of our
# program... 
AM_GNU_GETTEXT_VERSION([0.16.1])
# ...Or alternatively the local gnu gettext installation
AM_GNU_GETTEXT([external])

# Check for a C compiler
AC_PROG_CC

# Include all m4 macros that have to do with the language C
AC_LANG_C

# ???
AC_ISC_POSIX

# ???
AC_HEADER_STDC

# Checks for programs.
AC_PROG_CC

# We need the following type definitions from autoconf - or somebody else.
AC_TYPE_INT8_T
AC_TYPE_INT16_T
AC_TYPE_INT32_T

# AC_CHECK_LIB(libgnome-2.0, gnome_help_display_uri, [AC_DEFINE(HAVE_LIBGNOME, 1)])

# Prepare building the gnome documentation of this program
#GNOME_DOC_INIT

# Checks for libraries.
dnl Checking for the required libraries.
GTK_REQUIRED_VERSION=2.0.0
LIBGNOMEUI_REQUIRED_VERSION=2.0.0
GCONF_REQUIRED_VERSION=2.0.0
GNOMEVFS_REQUIRED_VERSION=2.0.0
ALSA_REQUIRED_VERSION=1.0.0
OGG_REQUIRED_VERSION=1.0.0
VORBIS_REQUIRED_VERSION=1.0.0
VORBISENC_REQUIRED_VERSION=1.0.0
PKG_CHECK_MODULES(DEPEND, gtk+-2.0 >= $GTK_REQUIRED_VERSION gconf-2.0 >= $GCONF_REQUIRED_VERSION gnome-vfs-2.0 >= $GNOMEVFS_REQUIRED_VERSION libgnomeui-2.0 >= $LIBGNOMEUI_REQUIRED_VERSION alsa >= $ALSA_REQUIRED_VERSION ogg >= $OGG_REQUIRED_VERSION vorbis >= $VORBIS_REQUIRED_VERSION vorbisenc >= $VORBISENC_REQUIRED_VERSION)

AC_SUBST(DEPEND_CFLAGS)
AC_SUBST(DEPEND_LIBS)

# Gettext wants to know the path to the top directory and such things...
top_builddir=`pwd`
AC_SUBST(top_builddir)
AC_SUBST(PACKAGE)
AC_SUBST(LOCALEDIR)

# Checks for the header files we include.
AC_HEADER_STDC
AC_CHECK_HEADERS([fcntl.h stdlib.h string.h sys/vfs.h])

# Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST

# Checks for library functions that we really need.
AC_FUNC_MALLOC

# A list of all configuration files we have to generate
AC_CONFIG_FILES([Makefile src/Makefile src/images/Makefile po/Makefile.in]) #help/Makefile 

# Tell autoconf to start outputting whatever it has to.
AC_OUTPUT
Makefile.am

This file is a template top-level-Makefile that will be filled with life by the configure script.

One thing that is added to the standard Makefile is code for automatically generate the _control-file mentioned above on a make dist

# A list of all subdirectories.
SUBDIRS = src po # help

# Allow automake to interpret m4 macros (needed for interpreting
# gettext's makefile.in
ACLOCAL_AMFLAGS = -I m4
# Files that aren't source files and still have to be in the tarball
EXTRA_DIST = @PACKAGE_NAME@_control

# An (currently unused) extension to the "install" target
install-data-local:

@PACKAGE_NAME@_control: Makefile.am configure.ac
	echo "Package: @PACKAGE_NAME@">$@
	echo "Version: @PACKAGE_VERSION@">>$@
	echo "Description: An voice recorder that can stop recording during silence">>$@
	echo "Section: openmoko/applications">>$@
	echo "Priority: optional">>$@
	echo "Maintainer: your_name">>$@
	echo "Architecture: armv4t">>$@
	echo "Homepage: (The homepage of this project)">>$@
	echo "Depends: gtk+ alsa-lib libogg libvorbis gnome-vfs libgnomeui">>$@
	echo "Source: \$${SRC}">>$@

Personal tools

Preparation

This guide assumes that you have performed the steps in Building_OpenMoko_from_scratch

The commandline program

Store the following more or less standard hello world code in hello.c

#include <stdio.h>

int main()
{
  printf ("Hello World\n");
  return 0;
}

Compiling it the wrong / easy way

Assuming your current working directory is /home/moko, and that you stored the code in /home/moko/hello.c it should now be possible to compile the application using

./build/tmp/cross/arm-linux/bin/gcc -o hello hello.c

Testing it

Assuming you have followed Setting up USB connection and you have a working network connection to either a qemu Neo or a real Neo.

scp hello root@192.168.0.202:/tmp/
ssh root@192.168.0.202 /tmp/hello

This sequence of commands ought to give you a nice Hello World, btw. the default root password is blank, just press return.

GDK the Wrong / Easy Way

Building a GDK application the wrong way is slightly more complex, but is still fun to try. It requires using pkg-config to specify including and linking with the ARM header files and libraries.

Given the following program as main.c:

#include <gtk/gtk.h>

gchar *hello = "Howdy";
gchar *world = "World";
GtkWidget *label;
gchar *labeltext;

void buttoncb(GtkWidget *widget, gpointer data)
{
if (labeltext == hello)
   {
   labeltext = world;
   gtk_label_set_text(GTK_LABEL(label), labeltext);
   }
else if (labeltext == world)
   gtk_main_quit();
}

int main(int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *button;

gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
button = gtk_button_new();
labeltext = hello;
label = gtk_label_new(labeltext);
gtk_container_add(GTK_CONTAINER(button), label);
g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(buttoncb), NULL);
gtk_container_add(GTK_CONTAINER(window), button);
gtk_widget_show_all(window);
gtk_main();

return 0;
}

You must first point pkg-config to the proper directory:

export PKG_CONFIG_PATH=/home/username/moko/build/tmp/staging/arm-linux/lib/pkgconfig

And set up an environment variable to make things easier:

export OMDIR=/home/username/moko

The compile/link line is rather long - you will only want to do this once before you decide to create a shell script or make file:

$OMDIR/build/tmp/cross/arm-angstrom-linux-gnueabi/bin/gcc -L $OMDIR/build/tmp/staging/arm-angstrom-linux-gnueabi/lib/ \
                   -Wl, rpath-link, $OMDIR/build/tmp/staging/arm-angstrom-linux-gnueabi/lib/ -Wl, -O1 -g -o hw main.c \
                   '$OMDIR/build/tmp/staging/i686-linux/bin/pkg-config --cflags --libs openmoko-libs gtk+-2.0'


Then copy and run as in the original hello world command line program above.

Why was it the wrong way?

OpenMoko provides a precompiled Toolchain package for that. It also comes with some scripts that make your life much easier. Besides, you don't need OpenEmbedded to build applications. If you do want to customize your complete distribution, then read on how to use bitbake when building stuff. In any way, at least you now know that you can easily cross compile for OpenMoko.

The Right Way: Using the gnome build system

Even if I am no expert in this - somebody had to make a start so I'll write down everything I still believe to remember from my 1st 'real' gnome application that used the autotools and all: I have never been able to find a good tutorial for making a "canonical" gnome application - and such a tutorial is urgently needed.

Since I know that many of these things will be missing or even inaccurate in the 1st step - if You find out to make it work better or at all - please document how to do this.

Creating the necessary documentation files and directory structure

First of all go into the directory you want to be the topmost application of yout new application, and create the following files:

AUTHORS||A list of all authors that took part in developing this project COPYING||The copyright notice. Favourably the GPL INSTALL||This file should contain the information how to build and install this program README||This file should contain all important information about the program including what the program was written for. NEWS||The name of this file should be self-describing TODO||The wishlist of your project Changelog||A list of the major changes to your project

I remember that some of these files were mandatory - it's better create them all

Then create a directory named 'src - and copy the source code of the program there.


The configuration of the autotools
autogen.sh

This file is a shell script that calls all autotools in the right order and with the right parameters so they will in the end generate the standard configure script that will detect how to build our program.

#! /bin/sh
#
# Most if not all of the contents of this file was taken from the openmoko
# sample application as it was shipped with the openmoko toolchain on
# January 31st, 2008
#

srcdir=`dirname $0`
test -z "$srcdir" && srcdir=.

PKG_NAME="helloworld"

(test -f $srcdir/configure.ac) || {
        echo -n "**Error**: Directory "\`$srcdir\'" does not look like the"
        echo " top-level $PKG_NAME directory"
        exit 1
}

which gnome-autogen.sh || {
        echo "You need to install gnome-common from the GNOME CVS"
        exit 1
}

REQUIRED_AUTOMAKE_VERSION=1.7 USE_GNOME2_MACROS=0 REQUIRED_GETTEXT_VERSION=0.10.36 . gnome-autogen.sh
configure.ac

This file tells what the configure script has to do - and which parts of the intelligence delivered with the tools that generate the configure script we need.

I documented every line of which I found out what it actually does. The first line is for to tell the emacs text editor that it has to treat this file as an autoconf file.

#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

# Tell autoconf to check what version of autoconf we need.
AC_PREREQ(2.61)

# Initialize autoconf and tell it what program we wrote, the version
# of our program, and the address bug reports have to be sent to.
AC_INIT([audiorec],[0.2],[audiorec.projects.openmoko.org])

# tell autoconf where to put the temporary files it generates 
AC_CONFIG_AUX_DIR([build-aux])

# This one is thaken from the "Migrationg to gnome Documentation Build
# utilities". No Idea, what it does.
AC_CONFIG_MACRO_DIR([m4])

# give autoconf the name of a file whose existence is a hint that
# autoconf has been started from the right directory. 
AC_CONFIG_SRCDIR([src/diskusagemeter.c])

# Tell autoconf where to put the output file that contains all
# definitions our C program will need
AC_CONFIG_HEADER([src/config.h:src/config.hin])

# Initialize automake, and tell it to tell the C compiler to output as
# many warnings as it can
AM_INIT_AUTOMAKE([-Wall foreign])

# The GNU Gettext version we used for internationalization of our
# program... 
AM_GNU_GETTEXT_VERSION([0.16.1])
# ...Or alternatively the local gnu gettext installation
AM_GNU_GETTEXT([external])

# Check for a C compiler
AC_PROG_CC

# Include all m4 macros that have to do with the language C
AC_LANG_C

# ???
AC_ISC_POSIX

# ???
AC_HEADER_STDC

# Checks for programs.
AC_PROG_CC

# We need the following type definitions from autoconf - or somebody else.
AC_TYPE_INT8_T
AC_TYPE_INT16_T
AC_TYPE_INT32_T

# AC_CHECK_LIB(libgnome-2.0, gnome_help_display_uri, [AC_DEFINE(HAVE_LIBGNOME, 1)])

# Prepare building the gnome documentation of this program
#GNOME_DOC_INIT

# Checks for libraries.
dnl Checking for the required libraries.
GTK_REQUIRED_VERSION=2.0.0
LIBGNOMEUI_REQUIRED_VERSION=2.0.0
GCONF_REQUIRED_VERSION=2.0.0
GNOMEVFS_REQUIRED_VERSION=2.0.0
ALSA_REQUIRED_VERSION=1.0.0
OGG_REQUIRED_VERSION=1.0.0
VORBIS_REQUIRED_VERSION=1.0.0
VORBISENC_REQUIRED_VERSION=1.0.0
PKG_CHECK_MODULES(DEPEND, gtk+-2.0 >= $GTK_REQUIRED_VERSION gconf-2.0 >= $GCONF_REQUIRED_VERSION gnome-vfs-2.0 >= $GNOMEVFS_REQUIRED_VERSION libgnomeui-2.0 >= $LIBGNOMEUI_REQUIRED_VERSION alsa >= $ALSA_REQUIRED_VERSION ogg >= $OGG_REQUIRED_VERSION vorbis >= $VORBIS_REQUIRED_VERSION vorbisenc >= $VORBISENC_REQUIRED_VERSION)

AC_SUBST(DEPEND_CFLAGS)
AC_SUBST(DEPEND_LIBS)

# Gettext wants to know the path to the top directory and such things...
top_builddir=`pwd`
AC_SUBST(top_builddir)
AC_SUBST(PACKAGE)
AC_SUBST(LOCALEDIR)

# Checks for the header files we include.
AC_HEADER_STDC
AC_CHECK_HEADERS([fcntl.h stdlib.h string.h sys/vfs.h])

# Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST

# Checks for library functions that we really need.
AC_FUNC_MALLOC

# Check for doxygen, so we can decide if we create a "doc" make target
# that depends on doxygen- 
AC_CHECK_PROG([DOXYGEN], [doxygen], [doc], [])
AC_SUBST(DOXYGEN)

# A list of all configuration files we have to generate
AC_CONFIG_FILES([Makefile src/Makefile src/images/Makefile po/Makefile.in doc/Makefile]) #help/Makefile 

# Tell autoconf to start outputting whatever it has to.
AC_OUTPUT