Programming
From IdefixWiki
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.
| 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 .
