Cross Compile for AVR
emerge crossdev
crossdev -t avr
ln -s /usr/i686-pc-linux-gnu/avr/lib/ldscripts /usr/libexec/gcc/avr/ldscripts
Cross Compile for PPC
First install eldk described here .
Automake and Autoconf
We use automake and autoconf, because cmake cannot cross compile yet. At first we need some files for automake:
touch NEWS
touch README
touch AUTHORS
touch ChangeLog
Create a autogen.sh:
#!/bin/sh
rm -f config.cache
rm -f acconfig.h
autoreconf --force --install -I config -I m4
#autoconf
#autoheader
#automake --add-missing
./configure "$@"
echo
echo "Now type 'make' to compile."
We have the following directory structure:
/
-> i2c
Now create a file called configure.ac:
AC_INIT(icecube, 0.1)
AC_PREREQ(2.5)
AC_CONFIG_SRCDIR([i2c/readMax6633.c])
AC_CONFIG_AUX_DIR(config)
AM_INIT_AUTOMAKE(1.8)
AC_PROG_CC
dnl Checks for header files.
AC_CONFIG_HEADER(config.h)
AC_HEADER_STDC
AC_CONFIG_FILES([Makefile i2c/Makefile])
AC_OUTPUT
And a file Makefile.am:
EXTRA_DIST = autogen.sh configure
SUBDIRS = i2c
In the directory i2c create a file Makefile.am:
INCLUDES = -I/usr/local/eldk/ppc_6xx/usr/include
bin_PROGRAMS = readMax6633
readMax6633_SOURCES = readMax6633.c
Now execute the script autogen.sh with:
./autogen.sh --host=ppc-6xx --prefix=/usr/local/eldk/ppc_6xx/usr/local
To cross-compile now do the following:
export CROSS_COMPILE=ppc_6xx-
make
cmake
Create a file CMakeLists.txt:
project (ICECUBE)
SET(CMAKE_C_FLAGS "-O")
add_subdirectory(i2c)
And a file i2c/CMakeLists.txt:
add_executable (readMax6633 readMax6633.c)
Now execute:
CC=ppc_6xx-gcc cmake .
Kernel Module for 2.6
With Normal Makefile
The hello world program. With normal Makefile, the Makefile:
ARCH := i386
CROSS_COMPILE :=
#CROSS_COMPILE := ppc_6xxx-
INSTALL := install -c
INSTALL_DATA := $(INSTALL) -m 644
KERNELVERSION := $(shell uname -r)
# KERNELVERSION := 2.6.16-mpc52xx-gc92bc8e3
EXTRA_CFLAGS := -g -I/usr/realtime/include -I/usr/include/ -ffast-math -mhard-float
KDIR := /lib/modules/$(KERNELVERSION)/build
PWD := $(shell pwd)
obj-m := hello_world.o
all:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE)
# gcc -o scope scope.c
clean:
rm -f *.o *.ko *.mod.o *.mod.c .*.{cmd,flags} Modules.symvers
rm -rf config.status config.log autom4te*.cache .tmp_versions
The hello_world.c:
#include <linux/module.h>
#include <asm/io.h>
#include <rtai.h>
#include <rtai_sched.h>
#include <rtai_fifos.h>
MODULE_LICENSE("GPL");
int init_module(void)
{
printk("in init_module\n");
return 0;
}
void cleanup_module(void)
{
printk("in cleanup_module\n");
return;
}
With Automake and Autoconf
create the directory structure:
mkdir test
cd test
mkdir src
mkdir m4
touch NEWS
touch README
touch AUTHORS
touch ChangeLog
Now we create the Makefile.am:
ACLOCAL_AMFLAGS = -I m4
SUBDIRS = src
EXTRA_DIST = autogen.sh
- ACLOCAL_AMFLAGS says aclocal where to look for additional m4 macros
- SUBDIRS are processed
- EXTRA_DIST says to include the autogen.sh in our distribution tar
Now we create a m4 script to get the kernel-source named m4/acinclude.m4:
dnl check for kernel source
AC_DEFUN([AC_PATH_KERNEL_SOURCE_SEARCH],
[
kerneldir=missing
kernelext=ko
no_kernel=yes
if test `uname` != "Linux"; then
kerneldir="not running Linux"
else
for dir in /usr/src/kernel-source-`uname -r` /usr/src/linux-`uname -r` /usr/src/linux /lib/modules/`uname -r`/build ${ac_kerneldir}; do
if test -d $dir; then
kerneldir=`dirname $dir/Makefile`/
no_kernel=no
fi;
done
fi
if test x${no_kernel} != xyes; then
if test -f ${kerneldir}/Makefile; then
if test "${ac_pkss_mktemp}" = "yes"; then
ac_pkss_makefile=`mktemp /tmp/LIRCMF.XXXXXX`
else
ac_pkss_makefile=/tmp/LIRCMF.XXXXXX
fi
cat ${kerneldir}/Makefile >${ac_pkss_makefile}
echo "lirc_tell_me_what_cc_is:" >>${ac_pkss_makefile}
echo " echo \$(CC)" >>${ac_pkss_makefile}
kernelcc=`make -s -C ${kerneldir} -f ${ac_pkss_makefile} lirc_tell_me_what_cc_is`
echo "lirc_tell_me_what_version_is:" >>${ac_pkss_makefile}
echo " echo \$(VERSION)" >>${ac_pkss_makefile}
echo "lirc_tell_me_what_patchlevel_is:" >>${ac_pkss_makefile}
echo " echo \$(PATCHLEVEL)" >>${ac_pkss_makefile}
version=`make -s -C ${kerneldir} -f ${ac_pkss_makefile} lirc_tell_me_what_version_is`
patchlevel=`make -s -C ${kerneldir} -f ${ac_pkss_makefile} lirc_tell_me_what_patchlevel_is`
if test ${version} -eq 2; then
if test ${patchlevel} -lt 5; then
kernelext=o
fi
fi
rm -f ${ac_pkss_makefile}
else
kerneldir="no Makefile found"
no_kernel=yes
fi
fi
ac_cv_have_kernel="no_kernel=${no_kernel} \
kerneldir=\"${kerneldir}\" \
kernelext=\"${kernelext}\" \
kernelcc=\"${kernelcc}\""
]
)
AC_DEFUN([AC_PATH_KERNEL_SOURCE],
[
AC_CHECK_PROG(ac_pkss_mktemp,mktemp,yes,no)
AC_PROVIDE([AC_PATH_KERNEL_SOURCE])
AC_MSG_CHECKING(for Linux kernel sources)
AC_ARG_WITH(kerneldir,
[ --with-kerneldir=DIR kernel sources in DIR],
ac_kerneldir=${withval}
AC_PATH_KERNEL_SOURCE_SEARCH,
ac_kerneldir=""
AC_CACHE_VAL(ac_cv_have_kernel,AC_PATH_KERNEL_SOURCE_SEARCH)
)
eval "$ac_cv_have_kernel"
AC_SUBST(kerneldir)
AC_SUBST(kernelcc)
AC_SUBST(kernelext)
AC_MSG_RESULT(${kerneldir})
]
)
Create now the file configure.ac:
dnl Proccess this file with autoconf to produce a configure script.
AC_INIT(hello_world, 0.1)
AC_PREREQ(2.5)
AC_CONFIG_SRCDIR(src/hello_world.c)
AC_CONFIG_AUX_DIR(config)
AM_INIT_AUTOMAKE(1.8)
dnl Checks for programms
AC_PROG_CC
AC_PATH_KERNEL_SOURCE
default_moduledir=/lib/modules/`uname -r`/misc
AC_ARG_WITH(moduledir,
[ --with-moduledir=DIR kernel modules in DIR (/lib/modules/`uname -r`/misc)],
moduledir=${withval},
moduledir=${default_moduledir})
AC_SUBST(moduledir)
AC_OUTPUT(Makefile src/Makefile)
- AC_INIT init the file with project name, version and email address
- AC_CONFIG_AUX_DIR says autoconf to store tmp file in the dir config to keep the main dir clean
- AC_CONFIG_SRCDIR where is the program to compile
- AM_INIT_AUTOMAKE directive to generate the Makefile
- AC_PROC_CC check for gcc
- AC_OUTPUT generate the following files from the *.in or *.am files
Now generate the src/Makefile.am:
EXTRA_DIST = Makefile.kernel Makefile.common
EXTRA_PROGRAMS = automake_dummy
automake_dummy_SOURCES = hello_world.c
module_DATA = hello_world.o
include ./Makefile.common
- “PROGRAMS” is called a primary. Other primaries include:
- LIBRARIES for static libraries (.a)
- LTLIBRARIES for Libtool-based shared libraries (.la)
- HEADERS
- …
- The prefix “bin_” tells Automake where to copy the resulting program when the user runs make install. Known directory prefixes include:
- bin_ - for programs, e.g., /usr/local/bin
- lib_ - where libraries are placed, e.g., /usr/local/lib
- include_ - where header files are placed, e.g., /usr/local/include
- pkginclude_ - e.g., /usr/local/include/foobar
- noinst_ - files that will not be copied anywhere by make install
- …
Note: The user can specify the locations of these directories when running the configure script. For more info, run configure --help.
- “SOURCES” is a variable that lists the source files of the program. For programs and libraries, possible variables include:
- CFLAGS, CPPFLAGS, CXXFLAGS - extra arguments passed to the compiler/preprocessor
- LIBADD - extra objects for a library
- LDADD - extra objects for a program
- LDFLAGS - extra arguments passed to the linker
- …
Create the Makefile.common:
KERNEL_LOCATION=@kerneldir@
KBUILD_VERBOSE = 1
ARCH := i386
CROSS_COMPILE :=
#CROSS_COMPILE := ppc_6xxx-
#KERNELVERSION := $(shell uname -r)
# KERNELVERSION := 2.6.16-mpc52xx-gc92bc8e3
HELLO_WORLD_EXTRA_CFLAGS = -g -I/usr/realtime/include -I/usr/include/ -ffast-math -mhard-float
PWD := $(shell pwd)
export HELLO_WORLD_EXTRA_CFLAGS module_DATA
$(module_DATA): $(automake_dummy_SOURCES)
mv Makefile Makefile.automake
cp Makefile.kernel Makefile
$(MAKE) -C $(KERNEL_LOCATION) SUBDIRS=$(PWD) modules \
KBUILD_VERBOSE=$(KBUILD_VERBOSE) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE)
mv Makefile.automake Makefile
CLEANFILES = $(module_DATA) .$(module_DATA).{cmd,flags} .$(module_DATA:.o=.@kernelext@).cmd \
$(module_DATA:.o=.mod.c) .$(module_DATA:.o=.mod.o.cmd) $(module_DATA:.o=.@kernelext@) \
Modules.symvers *~
clean:
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
rm -rf .tmp_versions
Create Makefile.kernel:
EXTRA_CFLAGS += $(HELLO_WORLD_EXTRA_CFLAGS)
obj-m=$(module_DATA)
MI_OBJS = $(module_DATA)
all clean:
$(warning **************************************************)
$(warning *** Makefile trick not undone, trying to recover *)
$(warning **************************************************)
mv Makefile.automake Makefile
$(MAKE) $@
# The following is needed for 2.5 kernels and also let's the makefile work
# when things get screwed.
ifneq (,$(wildcard $(KERNEL_LOCATION)/Rules.make))
include $(KERNEL_LOCATION)/Rules.make
endif
Print Source Code
To have a nice output the following command can be used to generate a nice files.pdf with the complete project print in highlighted colors:
find . -name '*.js' -or -name '*.json' -or -name '*.html'\
|xargs enscript -r -2 --file-align=1 --highlight --color --line-numbers -o - |ps2pdf - files.pdf
-r print landscape
-2 two pages by side
--file-align=1 every file on one page
--highlight and --color highlight the code with color
--line-numbers include line numbers
-o - print the output to stdout
Test-Framework
Installation
To install it type:
emerge sys-devel/automake
emerge sys-devel/autoconf
emerge dev-libs/check
or
apt-get install autoconf automake check
Setting up with autoconf and automake
Create a directory for your project and create a file autogen.sh:
#!/bin/sh
if [ -n "$CHECK_DIR" ]; then
aclocal -I $CHECK_DIR
else
aclocal
fi
autoconf
autoheader
automake --add-missing
./configure "$@"
echo
echo "Now type 'make check' to compile."
Create the file Makefile.am:
INCLUDES=@CHECK_CFLAGS@
if HAVE_CHECK
TESTS=check_money
else
TESTS=
endif
noinst_PROGRAMS=$(TESTS)
lib_LIBRARIES= libmoney.a
libmoney_a_SOURCES= \
money.h\
money.c
check_money_SOURCES= \
money.h\
money.c\
check_money.c
check_money_LDADD= @CHECK_LIBS@
Now create the file configure.in:
dnl Process this file with autoconf to produce a configure script.
AC_INIT(money.h)
AM_INIT_AUTOMAKE(money,0.2)
dnl Checks for programs.
AC_PROG_AWK
AC_PROG_CC
AC_PROG_INSTALL
AC_PROG_LN_S
dnl This macro is defined in check.m4 and tests if check.h and libcheck.a
dnl can be found. It sets CHECK_CFLAGS and CHECK_LIBS accordingly.
dnl AM_PATH_CHECK([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
AM_PATH_CHECK(,[have_check="yes"],
AC_MSG_WARN([Check not found; cannot run unit tests!])
[have_check="no"])
AM_CONDITIONAL(HAVE_CHECK, test x"$have_check" = "xyes")
dnl Checks for header files.
AM_CONFIG_HEADER(config.h)
dnl Checks for typedefs, structures, and compiler characteristics.
dnl Checks for library functions.
AC_OUTPUT(Makefile)
Create the programm itself
Create the file money.c:
#include <money.h>
Create the file money.h:
#ifndef MONEY_H
#define MONEY_H
#endif
Create the file check_money.c:
#include <check.h>
#include <stdlib.h>
#include "money.h"
START_TEST (test1)
{
}
END_TEST
int main(void)
{
return 0;
}
Create the testroutines
Edit check_money.c:
#include <check.h>
#include <stdlib.h>
#include "money.h"
Money *five_dollars;
void setup(void)
{
five_dollars=money_create(5, "USD");
}
void teardown(void)
{
money_free(five_dollars);
}
START_TEST (test_create)
{
fail_unless(money_amount(five_dollars)==5,
"Amount not set correctly on creation");
fail_unless(strcmp(money_currency(five_dollars), "USD") == 0,
"Currency not set correctly on creation");
}
END_TEST
START_TEST (test_neg_create)
{
Money *m=money_create(-1, "USD");
fail_unless(m == NULL,
"NULL should be returned on attempt to create with a negative amount");
}
END_TEST
START_TEST (test_zero_create)
{
Money *m=money_create(0,"USD");
fail_unless(money_amount(m)==0,"Zero is a valid amount of money");
}
END_TEST
Suite *money_suite(void)
{
Suite *s=suite_create("Money");
TCase *tc_core=tcase_create("Core");
TCase *tc_limits=tcase_create("Limits");
suite_add_tcase (s, tc_core);
suite_add_tcase (s, tc_limits);
tcase_add_test(tc_core, test_create);
tcase_add_checked_fixture(tc_core, setup, teardown);
tcase_add_test(tc_limits, test_neg_create);
tcase_add_test(tc_limits, test_zero_create);
return s;
}
int main(void)
{
int nf;
Suite *s=money_suite();
SRunner *sr=srunner_create(s);
srunner_set_log(sr, "test.log");
srunner_run_all(sr, CK_NORMAL);
nf=srunner_ntests_failed(sr);
srunner_free(sr);
return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}
Create the functions
Edit money.h:
#ifndef MONEY_H
#define MONEY_H
typedef struct Money Money;
Money *money_create(int amount, char *currency);
int money_amount(Money *m);
char *money_currency(Money *m);
void money_free(Money *m);
#endif
Edit money.c:
#include <stdlib.h>
#include <money.h>
struct Money
{
int amount;
char *currency;
};
Money *money_create(int amount, char *currency)
{
if(amount <0)
return NULL;
Money *m = malloc(sizeof(Money));
if(m == NULL)
return NULL;
m->amount=amount;
m->currency=currency;
return m;
}
int money_amount(Money *m)
{
return m->amount;
}
char *money_currency(Money *m)
{
return m->currency;
}
void money_free(Money *m)
{
free(m);
}
Performing the checks
To prepare the compilation type:
./autogen.sh
./configure
To check if everything is fine and compile it type:
make check
Using Cmake
We create a simple program from two object files which are link to some external libraries. Create the file CMakeLists.txt:
PROJECT(measure)
ADD_EXECUTABLE(measure video.c Xgraphics.c)
Now we need to create the Makefile with:
cmake .
Now easily compile with:
make