The optional autoconfiguration step is useful whenever developers require automatic generation of Makefile or header file variables (typically installation paths or macros which are used for conditional compilation of features).
The most basic template for a configuration script follows:
#!/bin/sh . $MAKL_DIR/cf/makl.init makl_args_init "$@" makl_args_handle "$@" . $MAKL_DIR/cf/makl.term
Create a new working directory and place the code above into a file called configure. Make the file executable:
$chmod u+x configure
That’s it! Now test the configure script by running:
$maklconf
You should find two automatically generated files in your current directory:
Makefile.conf, which can be included in Makefilesconf.h, which can be included in C/C++ code
Have a peek at these files. You will see that the only variables generated automatically are related to default installation paths. For example, the default value for CONFDIR is /usr/local/etc.
Now you can use these variables both in C/C++ code or Makefiles (MaKL template files also make wide usage of these variables).
First of all let’s use a MaKL feature which sets a variable to reflect the project version. Add the following two lines to the configure script (after the makl_args_init command):
makl_pkg_name "makl_test" makl_pkg_version
Now create a plain text file called VERSION in the current directory containing the version of the project in dotted notation, such as 1.2.3b4. By rerunning the script, you will find a new variable MAKL_TEST_VERSION = 1.2.3b4.
As a side-effect, the makl_pkg_version command creates four CF variables called:
''__ver__'', ''__ver_major__'', ''__ver_minor__'' and ''__ver_teeny__''
CF variables are private configuration variables which can be retrieved or stored by using the makl_get and makl_set commands.
Now lets create our own Makefile variable: a string which displays a short description of the current version.
makl_set_var_mk "VER_STRING" "The current major is `makl_get __ver_major__`"
makl_set_var_mk sets a Makefile variable. Otherwise we may choose to create only a C macro instead as follows:
makl_set_var_h "VER_STRING" "The current major is `makl_get __ver_major__`" 1
Note that in this case there is an extra parameter which indicates that the header variable is to be interpreted as a string, and hence must be wrapped by quotes. Hence for numeric values, such parameter should be omitted.
To generate both Makefile and header variables, simple use the makl_set_var, function which has a similar interface to makl_set_var_h.
This command is used to force a dependency on a feature. In case of failure the configure script will exit. The following example forces a dependency on library foo (don’t try it right now!):
makl_require "lib" "foo"
This will try to link against a dynamic library called foo by passing the argument -lfoo to the compiler. If you require more control over CFLAGS and LDFLAGS you can set them in the third and fourth arguments respectively.
To check compilation of such library, one must define a custom programme which makes use of such library in file build/libfoo.c. For example simply:
int main()
{
foo_test();
return 0; /* return value is important - must exit with 0 on success */
}
A more strict library test programme may perform a check on the version, and return a value != 0 if the version doesn’t match the requirement.
An optional dependency requirement differs in that execution of the configure script does not end in case of failure, but it results in creating a constant in the generated header file for inclusion in C code. Note that there is an extra argument. For example:
makl_optional 1 "lib" "ssl"
is equivalent the optional equivalent of the previous library example. The first argument indicates whether or not the dependency is enabled by default.
Some other utilities are provided for checking presence of executables, headers, types, symbols and functions.
The first argument of such checks indicates whether the dependency is compulsory or optional. If it has value 1 and the check fails, the script will exit with error status. Otherwise, if it has value 0 a simple warning will be printed, and the configuration script execution will continue.
As a side effect, when optional requirements are specified, the checks result in the definition (or undef) of a macro called HAVE_<second_argument>.
The makl_require and makl_optional utility functions can also be used to check existence of executables.
For example:
makl_optional 1 "featx" "fooexec" "PATH_FOOEXEC"
declares an optional dependency called “fooexec” which is enabled by default. If the executable is detected during configuration the following Makefile variables (and similar header variables) will be declared:
HAVE_FOOEXEC = 1 PATH_FOOEXEC = /path/to/found/fooxec
The path to such executable can be changed by setting the maklconf argument –featx-fooexec. (Otherwise MaKL will search in the default search path “/usr:/usr/local”).
The presence of specific headers can be checked before compilation as in the following example.
makl_checkheader 1 "foobar" "<foo/bar.h>"
If the header file foo/bar.h is not found in the search path, the configuration script will exit with failure status.
The interface for type checking is similar to header checking.
For example:
makl_checktype 0 "foo_t" "<foo/bar.h>"
The file foo/bar.h is the header function in which the structure foo_t is defined. Since the first argument to the function is 0 the configure script will not exit if the check fails. If the check passes, the following line will be added to the generated header:
#define HAVE_FOO_T
Otherwise, it will show:
#undef HAVE_FOO_T
One may wish to check the existence of a given SYMBOL in an included header. To do this:
makl_checksymbol 0 "FOO" <foo/bar.h>
The following line adds an optional check on function foo():
makl_checkfunc 0 "foo"
MaKL provides a simple mechanism to extend configure command-line arguments. The most common reason to do this may be simply to define a Makefile and/or header value.
Let us illustrate this though an example
# Define argument "myarg" with any number of extra info strings to be passed to --help.
# Normally it will look something like the following:
makl_args_def "myarg" "<arguments>" "<defaults>" "define a custom makefile variable"
# The custom handler. Two variables are provided automatically, the argument identifier
# (string after dash) and the argument value (value string).
__makl_setmacro ()
{
argid="$1"
argval="$2"
# 3rd argument = set macro as string value
makl_set_var_h "${argid}" "${argval}" 1
}
Now, configuring your package with the foollowing argument:
maklconf --setmacro-MYMACRO="my macro value"
will result in the following definition (default conf.h):
#define MYMACRO "my macro value"
A more advanced usage of command-line arguments may be to manipulate internal dependencies, but note that some of this functionality is already provided (e.g. enabling/disabling features). For more info please refer to makl_args_handle() docs.