Coding conventions and packaging

1.Introduction

Two types of contributions can be made to Mathemagix: purely external packages and packages which should be included and maintained into the main Mathemagix source tree. Purely external packages can typically be distributed along with a software library or scripting language. If you want to include your package inside the main Mathemagix source tree, then you should scrupulously follow a certain number of conventions.

2.Conventions for the C++ source code

The following conventions are used throughout the C++ source code:

There are probably more convention; please follow the style of existing code when writing new packages.

3.Convention for packaging

Writing packages which compile on all platforms and can easily be maintained is a complex task. The Mathemagix philosophy is to be as standard and simple as possible, by using the following guidelines:

  1. Systematically use Automake/Autoconf, even though these tools are very bureaucratic.
  2. Keep configure.ac and the Makefile.am as striaghtforward as possible.
  3. Use a uniform organization for the directory structure.

More precisely, the directory structure of a new package foox should be as follows:

foox
| configure.ac
| Makefile.am
| macros
| | ac_prefix_config_h.m4
| | mmx_module.m4
| | dependency.m4
| src
| | foox
| | | include
| | | glue
| | | | foox_glue.cpp
| | | script
| | | | foox-config.in
| | subdir
| | | bench
| | | glue
| | | include
| | | src
| | | test
| | target
| | | Makefile.am

Of course, there may be multiple dependency: any external dependency of your package should come with a separate .m4 file. Similarly, you also have one subdir for each type of functionality of your package. A configuration file foox/src/foox/include/foox-config.h.in should be created automatically using autoheader and AC_PREFIX_CONFIG_H. The file foox/Makefile.am is very short and mainly refers to the global makefile foox/src/target/Makefile.am.

3.1.The file configure.ac

The file configure.ac should be modeled on the corresponding file of basix. In particular, you have to start with something like

AC_INIT([foox], [0.2.2], [bugs@mathemagix.org])
AM_INIT_AUTOMAKE([-Wall -Werror foreign])
AC_CONFIG_HEADER(src/foox/include/config.hpp)

AC_PROG_CC
AC_PROG_CXX
AC_LANG_CPLUSPLUS
AC_PROG_INSTALL
AC_PROG_LIBTOOL
AC_PROG_RANLIB

and end with something like

AC_OUTPUT([
  Makefile
  src/target/Makefile
  src/foox/script/foox-config
],[chmod +x src/foox/script/foox-config])

AC_PREFIX_CONFIG_H(FOOX,[
  src/foox/include/config.hpp
],[
  src/foox/include/foox-config.hpp
])

The file mmx_module.m4 defines a convenient macro AC_MMX_MODULE. When calling this macro inside your configure.ac, the following common options for Mathemagix packages will be supported.

–enable-debug
Enable debugging (disabled by default).
–enable-optimize
Enable optimization (enabled by default).
–enable-exceptions
Support exceptions for high level routines (enabled by default).
–enable-verify
Enable security checks for low level routines (disabled by default).
–enable-glue
Build the glue libraries for use with the interpreter (enabled by default).
–enable-test
Build suite of test programs (disabled by default).
–enable-bench
Build suite of benchmark programs (disabled by default).

Additional dependencies should all come with a corresponding m4 file. For instance, gnumerix tests for gmp in the following way:

AC_WITH_GMP
AC_LIB_GMP

The macro AC_WITH_GMP provides an option to specify the install path for gmp. The macro AC_LIB_GMP tests whether it is possible to execute some functionality of the library. Notice that the m4 files of some of the Mathemagig packages provide similar macros AC_WITH_BASIX, AC_LIB_BASIX, etc.

3.2.The file Makefile.am

Each package should come with a global Makefile.am which should be kept as straightforward as possible. First of all, all include files in foox/src/*/include/ should be put into the mathemagix subdirectory of includedir:

mmxincludedir = $(includedir)/mathemagix

mmxinclude_HEADERS = \
  ../subdir1/include/file1.hpp \
  ../subdir1/include/file2.hpp \
  ../subdir2/include/file3.hpp \
  ...

One next has to specify the Libtool library libfoox.la

lib_LTLIBRARIES = libfoox.la

and the corresponding sources to be built:

libfoox_la_CPPFLAGS = \
  -I../subdir1/include \
  -I../subdir2/include \
  ... \
  @CPPFLAGS@

libfoox_la_SOURCES = \
  ../subdir1/src/foo1.cpp \
  ../subdir1/src/foo2.cpp \
  ...

We also have to provide a configuration script foox/src/foox/script/foox-config.in on the same model as basix-config.in and distribute it with our package:

dist_bin_SCRIPTS = ../basix/script/basix-config
EXTRA_DIST = ../basix/script/basix-config.in

In addition to the above required sources and targets, additional libraries and binaries may have to be built as a function of the configuration options –enable-glue, –enable-test and –enable-bench. For instance, in order to build the library which has to be glued to the interpreter, one typically adds the following lines:

if GLUE_OPT
  mmxinclude_HEADERS += \
  ../subdir1/glue/file1.hpp \
  ../subdir2/glue/file2.hpp \
  ...    

  lib_LTLIBRARIES += libmmxfoox.la

  libmmxbasix_la_CPPFLAGS = \
    -I../subdir1/glue \
    -I../subdir2/glue \
    ... \
    $(libfoox_la_CPPFLAGS)

  libmmxfoox_la_SOURCES = \
    ../subdir1/glue/glue1.cpp \
    ../subdir1/glue/glue2.cpp \
    ...
endif

For the other options, and as a more general rule, we recommend to mimick the code in the existing files */target/Makefile.am.

3.3.Inclusion in the global Mathemagix project

When your package is finished, according to the above guidelines, then we can inlcude it in the main Mathemagix tree. This involves some additional copy and pasting in the files configure.in, Makefile.in and set-devel-paths. Although we will take care of that at the end, you may wish to make the necessary modifications yourself in order to compile all your packages at once.