Coding conventions and packaging |
Two types of contributions can be made to
The following conventions are used throughout the C++ source code:
Use the following naming and case conventions:
When defining a data type my_type which is really a pointer to the representation class my_type_rep, use the standard mechanism for defining reference counted pointer classes. In the case of a simple class my_type, this is done using the following kind of code:
class string {
INDIRECT_PROTO (string, string_rep)
...
};
INDIRECT_IMPL (string, string_rep)
In the case of template classes, one should use similar macros INDIRECT_PROTO_1, etc.
To increase conciseness, we systematically abbreviate template definitions and template type names when defining new template classes. For instance, the code of the list<C> class is enclosed in a block of the form:
namespace mmx {
#define TMPL_DEF template<typename C>
#define TMPL template<typename C>
#define List list<C>
#define List_rep list_rep<C>
...
#undef TMPL_DEF
#undef TMPL
#undef List
#undef List_rep
} // namespace mmx
There are probably more convention; please follow the style of existing code when writing new packages.
Writing packages which compile on all platforms and can easily be
maintained is a complex task. The
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.
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
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
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
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.
When your package is finished, according to the above guidelines, then
we can inlcude it in the main