Programming

From IdefixWiki

Jump to: navigation, search

Contents

Distcc and ccache

http://www.gentoo.org/doc/de/handbook/handbook-amd64.xml?full=1&style=printable

http://gentoo-wiki.com/TIP_AMD64-x86-distcc

http://www.gentoo.org/doc/de/distcc.xml?style=printable

http://www.gentoo.org/doc/en/cross-compiling-distcc.xml?style=printable

I seperate the compiling target with the portnumber.

Overview for ports using crosscompile and distcc
CPU System Port
x86 i686-pc-linux-gnu 3632 (standard)
AMD64 x86_64-pc-linux-gnu 3633

Distcc with AMD64

We use port 3633 for AMD64 compiling, so we need to adapt the configuration:

emerge distcc

Now set the right options in the file /etc/conf.d/distccd:

# /etc/conf.d/distccd: config file for /etc/init.d/distccd

DISTCCD_OPTS=""

# this is the distccd executable 
DISTCCD_EXEC="/usr/bin/distccd"

# this is where distccd will store its pid file
DISTCCD_PIDFILE="/var/run/distccd/distccd.pid"

# set this option to run distccd with extra parameters
# Default port is 3632.  For most people the default is okay.
DISTCCD_OPTS="${DISTCCD_OPTS} --port 3633"

# Logging
# You can change some logging options here:
# --log-file FILE
# --log-level LEVEL  [critical,error,warning, notice, info, debug]
#
# Leaving --log-file blank will log to syslog
# example: --log-file /dev/null --log-level warning
# example: --log-level critical

DISTCCD_OPTS="${DISTCCD_OPTS} --log-level critical"

# SECURITY NOTICE:
# It is HIGHLY recomended that you use the --listen option
# for increased security. You can specify an IP to permit connections 
# from or a CIDR mask
# --listen accepts only a single IP
# --allow is now mandatory as of distcc-2.18.
# example:  --allow 192.168.0.0/24
# example:  --allow 192.168.0.5 --allow 192.168.0.150
# example:  --listen 192.168.0.2
DISTCCD_OPTS="${DISTCCD_OPTS} --allow 192.168.0.0/16"
#DISTCCD_OPTS="${DISTCCD_OPTS} --listen 192.168.0.2"

# set this for niceness
# Default is 15
DISTCCD_NICE="15"

Edit /etc/distcc/hosts:

localhost:3633
or
distcc-config --set-hosts localhost:3633

Then start distcc with:

/etc/init.d/distccd restart

Distcc with X86

I ran here a 64-bit gentoo coompiled for AMD64 (x86_64) so we need to do some configuration to compile for x86. At first we need to generate a port overlay, edit /etc/make.conf:

# To get crossdev running
PORTDIR_OVERLAY="/usr/local/portage"

Create the new directory:

mkdir /usr/local/portage

Install cross-compile environment:

emerge crossdev
crossdev -t i686-pc-linux-gnu

Adapt the configuration:

cd /etc/init.d
cp distccd distccd-x86

Edit /etc/init.d/distccd-x86:

#!/sbin/runscript
# $Header: /var/cvsroot/gentoo-x86/sys-devel/distcc/files/2.18/init,v 1.1 2004/10/12 17:21:43 lisa Exp $

depend() {
       need net
       use ypbind
}

start() {
       [ -e "${DISTCCD_PIDFILE}" ] && rm -f ${DISTCCD_PIDFILE} &>/dev/null

       ebegin "Starting distccd"
       chown distcc `dirname ${DISTCCD_PIDFILE}` &>/dev/null
       TMPDIR="${TMPDIR}" \
       PATH="/usr/i686-pc-linux-gnu/gcc-bin/4.1.1:${PATH}" \
       /sbin/start-stop-daemon --start --quiet --startas ${DISTCCD_EXEC} \
       --pidfile ${DISTCCD_PIDFILE} -- \
       --pid-file ${DISTCCD_PIDFILE} -N ${DISTCCD_NICE} --user distcc \
       ${DISTCCD_OPTS}

       eend $?
}

stop() {
       ebegin "Stopping distccd"
       start-stop-daemon --stop --quiet --pidfile "${DISTCCD_PIDFILE}"
       rm -f "${DISTCCD_PIDFILE}"
       eend $?
}
cd /etc/conf.d
cp distccd distccd-x86

Now set the right options in the file /etc/conf.d/distccd-x86:

# /etc/conf.d/distccd: config file for /etc/init.d/distccd

DISTCCD_OPTS=""

# this is the distccd executable 
DISTCCD_EXEC="/usr/bin/distccd"

# this is where distccd will store its pid file
DISTCCD_PIDFILE="/var/run/distccd/distccd-x86.pid"

# set this option to run distccd with extra parameters
# Default port is 3632.  For most people the default is okay.
DISTCCD_OPTS="${DISTCCD_OPTS} --port 3632"

# Logging
# You can change some logging options here:
# --log-file FILE
# --log-level LEVEL  [critical,error,warning, notice, info, debug]
#
# Leaving --log-file blank will log to syslog
# example: --log-file /dev/null --log-level warning
# example: --log-level critical

DISTCCD_OPTS="${DISTCCD_OPTS} --log-level critical"

# SECURITY NOTICE:
# It is HIGHLY recomended that you use the --listen option
# for increased security. You can specify an IP to permit connections 
# from or a CIDR mask
# --listen accepts only a single IP
# --allow is now mandatory as of distcc-2.18.
# example:  --allow 192.168.0.0/24
# example:  --allow 192.168.0.5 --allow 192.168.0.150
# example:  --listen 192.168.0.2
DISTCCD_OPTS="${DISTCCD_OPTS} --allow 192.168.0.0/16"
#DISTCCD_OPTS="${DISTCCD_OPTS} --listen 192.168.0.2"

# set this for niceness
# Default is 15
DISTCCD_NICE="15"

To configure an i686 computer to use our AMD64 for compiling edit the /etc/distcc/hosts on the i686 computer:

192.168.0.151
or
distcc-config --set-hosts localhost 192.168.0.151

Use localhost only if localhost is fast enough elsewhere omit it.

Start distcc-x86 now with:

/etc/init.d/distccd-x86 restart

To start it at computer restart enter:

rc-update add distccd-x86 default

Get status

View which computer compile on our:

DISTCC_DIR="/var/tmp/portage/.distcc" distccmon-text 1
DISTCC_DIR="/var/tmp/portage/.distcc" distccmon-gui

Enable distcc with Gentoo

Edit /etc/make.conf to enable distcc and ccache for portage:

# for 7 CPUs or PCs (CPU*2 +1)
MAKEOPTS="-j15"
FEATURES="distcc ccache"
CCACHE_SIZE="2G"

Basic Makefile

Autoconf - Automake

http://sources.redhat.com/automake/automake.html

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

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

Valgrind

http://www.cprogramming.com/debugging/valgrind.html

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

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)
<pre>
And a file i2c/CMakeLists.txt:
<pre>
add_executable (readMax6633 readMax6633.c)

Now execute:

CC=ppc_6xx-gcc cmake .
Personal tools