-
Notifications
You must be signed in to change notification settings - Fork 7
FwTemplateCWalkthrough
fw-template-C is a C development template for framewerk. It features:
- automake setup: libtool and compiler setup done for you.
- pkg-config integration: pkg-config files for your project are made for you. In addition, if any dependencies provide pkg-config files they are used, generally eliminating the need for AC_CHECK_LIBS and AC_CHECK_HEADERS.[1]
- valgrind integration: standard targets for running make check with valgrind.
- coverage integration: standard configure and make check support for enabling coverage analysis. guards against releasing packages with coverage enabled.
This walkthrough demonstrates fw-template-c.
It's very helpful to have done the framewerk walkthrough.
First, set up the project with fw-init in the usual way.
% env CVSROOT="YOURCVSROOT" fw-init --name myproject --template C --revision cvs
Changing directory into the project,
% cd myproject/
% cvs -n -q up
A .cvsignore
A AUTHORS
A ChangeLog
A Makefile.am.local
A NEWS
A README
A bootstrap
A configure.ac.local
A fw-pkgin/.cvsignore
A fw-pkgin/Makefile.am.local
A fw-pkgin/config
A fw-pkgin/post-install
A fw-pkgin/post-remove
A fw-pkgin/pre-install
A fw-pkgin/pre-remove
A fw-pkgin/start
A fw-pkgin/stop
A src/.cvsignore
A src/Makefile.am.local
A src/mylib.c
A src/mylib.h
A src/myprog.c
A tests/.cvsignore
A tests/Makefile.am.local
A tests/testprog.c
The root directory of the project now looks like:
% ls
AUTHORS ChangeLog NEWS bootstrap doc fw-pkgin tests
CVS Makefile.am.local README configure.ac.local fw src
Here's a breakdown:
-
AUTHORS, CVS, ChangeLog, NEWS, README, bootstrap, fw, fw-pkgin, configure.ac.local, Makefile.am.local
: these have the same meanings as in other framewerk templates. -
src, tests
: C source code (.c, .h) is placed insrc/
, and unit tests intests/
.
As with other framewerk templates, fw-pkgin/config
is used to configure the project. However some new variables are available with this template.
% cat fw-pkgin/config
# The FW_PACKAGE_MAINTAINER field is populated with the
# environment variable FW_PACKAGE_DEFAULT_MAINTAINER if non-empty
FW_PACKAGE_NAME="myproject"
FW_PACKAGE_VERSION="0.0.0"
FW_PACKAGE_MAINTAINER="Paul Mineiro <paul-fw@mineiro.com>"
FW_PACKAGE_SHORT_DESCRIPTION="A short description."
FW_PACKAGE_DESCRIPTION=`cat README`
FW_PACKAGE_ARCHITECTURE_DEPENDENT="1"
# Dependency information. The native syntax corresponds to Debian,
# http://www.debian.org/doc/debian-policy/ch-relationships.html
# Section 7.1 "Syntax of Relationship Fields"
#
# For other packaging systems, the syntax is translated for you.
FW_PACKAGE_DEPENDS=""
FW_PACKAGE_CONFLICTS=""
FW_PACKAGE_PROVIDES=""
FW_PACKAGE_REPLACES=""
FW_PACKAGE_SUGGESTS=""
FW_PACKAGE_BUILD_DEPENDS=""
FW_PACKAGE_BUILD_CONFLICTS=""
# uncomment and set to specify additional pkg-config packages on the Requires:
# line of the generated .pc file
# FW_PKGCONFIG_REQUIRES_EXTRA=""
# uncomment and set to specify additional content for the Libs:
# line of the generated .pc file
# FW_PKGCONFIG_LIBS_EXTRA=""
# uncomment and set to specify additional content for the Cflags:
# line of the generated .pc file
# FW_PKGCONFIG_CFLAGS_EXTRA=""
# uncomment and set to add arbitrary additional content to the
# generated .pc file
# FW_PKGCONFIG_EXTRA=""
The extra variables are related to the creation of a pkg-config file. This mostly just works (via scanning your source code directory) but in case it doesn't you have additional control via these variables.
Build the project the usual way,
% ./bootstrap && ./build
fw-template-c supports "hardcore" compilation mode, wherein a bunch of
warnings are enabled and warnings are treated as errors. These are basically
the warnings that I have noticed over the years to take seriously.
Unfortunately setting warnings as errors causes alot of configure tests to
fail; fortunately, framewerk is smart enough to set the compiler options
at the very end so it doesn't cause problems during configure.
hardcore mode is enabled by default, but you can disable it by passing --disable-hardcore to build, e.g.,
% ./bootstrap && ./build --disable-hardcore
fw-template-c supports coverage testing compilation mode. Basically, a bunch of compiler flags are set and compiler optimization flags are unset (these can frustrate coverage analysis). The test driver in coverage testing mode will run gcov for you and output coverage summaries during 'make check'.
coverage mode is disabled by default, but you can enable it by passing --enable-coverage to build, e.g.,
% ./bootstrap && ./build --enable-coverage
fw-template-c will detect whether a package is being created with coverage compiled code in it. It is an error to release a package in this state so 'make release' will error out; in that case 'make clean' and rerun build without the --enable-coverage argument.
The top level Makefile.am has some useful rules in it:
% cat Makefile.am
include $(top_srcdir)/fw/build/automake/Makefile_dot_am
SUBDIRS += src tests
memcheck:
cd tests && $(MAKE) memcheck
memcheck-%:
cd tests && $(MAKE) memcheck-$*
leakcheck:
cd tests && $(MAKE) leakcheck
leakcheck-%:
cd tests && $(MAKE) leakcheck-$*
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = @FW_PACKAGE_NAME@-@FW_PACKAGE_MAJOR_VERSION@.0.pc
@FW_PACKAGE_NAME@-@FW_PACKAGE_MAJOR_VERSION@.0.pc: pkgconfig-template.pc
@ln -f $< $@
srcmakefileamfiles := $(shell find src -name '*.am' -or -name '*.am.local')
pkgconfig-template.pc.in: $(srcmakefileamfiles)
@fw-exec "template/C/make-pkgconfig-template" $^ > $@
CLEANFILES += \
pkgconfig-template.pc \
@FW_PACKAGE_NAME@-@FW_PACKAGE_MAJOR_VERSION@.0.pc
MAINTAINERCLEANFILES += \
pkgconfig-template.pc.in
The memcheck and leakcheck family of targets run unit tests using valgrind (if installed). These basically proxy to the versions in the tests directory for your convenience.
The other rules are related to pkg-config file generation.
### pkgconfig file generationThere should now be a myproject-0.0.pc
file in the root directory of the
project.
% cat myproject-0.0.pc
prefix=/usr
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
Name: myproject
Description: A short description.
Version: 0.0.0
Requires:
Libs: -L${exec_prefix}/lib -lmylib
Cflags: -I${includedir}/myproject-0/
Some notes:
- The major version number is embedded in the filename; thus possibly multiple major versions can be installed at the same time. The minor version number is always set to 0 in the filename, e.g., for version a.b.c of the myproject package the filename would be
myproject-a.0.pc
. - Packages listed as build dependency that contain .pc files in their manifest will have entries added to Requires: corresponding to their .pc files . Additional Requires data can be added via FW_PKGCONFIG_REQUIRES_EXTRA.
- Libraries listed in a Makefile.am or Makefile.am.local under
src/
via LTLIBRARIES will have entries added to the Libs: line. Additional Libs data can be added via FW_PKGCONFIG_LIBS_EXTRA. - The Cflags: line is automatically populated with an include line corresponding to the location of installed headers. Additional Cflags data can be added via FW_PKGCONFIG_CFLAGS_EXTRA.
- The contents of the FW_PKGCONFIG_EXTRA variable is appended verbatim to this file.[2]
A "include everything" header is automatically generated in src as
PROJECTNAME.h, in this case src/myproject.h
. It and the other
.h files in src/
are installed in
% ls tests/
CVS/ Makefile.am.local test-wrapper.sh.in@
Makefile Makefile.in testprog.c
Makefile.am@ test-wrapper.sh*
tests/test-wrapper.sh
is used to run the tests without valgrind.
If coverage checking is enabled then it analyzes the test output with
gcov and produces a summary of the test coverage. If tests are being
run under valgrind then coverage analysis is skipped. The (make) variables
VALGRIND_OPTS, MEMCHECK_OPTS, and LEAKCHECK_OPTS can be used to modify
the (reasonable) default arguments to valgrind, e.g.,
% cd tests/
% make memcheck-testprog
/bin/bash ../libtool \
--mode=execute valgrind \
-q \
--tool=memcheck \
--num-callers=20 \
./testprog
% make VALGRIND_OPTS="" memcheck-testprog
/bin/bash ../libtool \
--mode=execute valgrind \
\
--tool=memcheck \
--num-callers=20 \
./testprog
==4386== Memcheck, a memory error detector.
==4386== Copyright (C) 2002-2006, and GNU GPL'd, by Julian Seward et al.
==4386== Using LibVEX rev 1658, a library for dynamic binary translation.
==4386== Copyright (C) 2004-2006, and GNU GPL'd, by OpenWorks LLP.
==4386== Using valgrind-3.2.1-Debian, a dynamic binary instrumentation framework.
==4386== Copyright (C) 2000-2006, and GNU GPL'd, by Julian Seward et al.
==4386== For more details, rerun with: -v
==4386==
==4386==
==4386== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 8 from 1)
==4386== malloc/free: in use at exit: 0 bytes in 0 blocks.
==4386== malloc/free: 0 allocs, 0 frees, 0 bytes allocated.
==4386== For counts of detected errors, rerun with: -v
==4386== All heap blocks were freed -- no leaks are possible.
Note in the second run the "-q" option to VALGRIND_OPTS was eliminated, thus valgrind output a banner and summary.
Look at tests/Makefile.am
for a complete understanding of what
the template provides.
Making a package is done the usual way, as is releasing a package.
Congratulations! You've made it through the fw-template-c walkthrough. Hopefully you found it helpful.
## 1
So I've discovered this is true if you and all your consumers are using a packaging format (because pkg-config files are found by querying the package system for files ending in .pc provided by a dependency). Once you start making dist tarballs that you want to work anywhere, you have to start manually finding the .pc files again. :(
## 2In case of need for extreme customization, you can create a file
fw.local/template/C/make-pkgconfig-template
in your project
and it will be called instead of the (installed)
fw/template/C/make-pkgconfig-template
. This is a general
framewerk tip: anytime you see fw-exec foo/bar/baz
that means
that fw.local/foo/bar/baz
will be looked for first, followed
by fw/foo/bar/baz
; framewerk never puts things in fw.local
,
that space is for you.