icmconf - Configuration file for the icmbuild(1) program
maintenance script
The icmconf configuration file is used to configure program
maintenance performed by icmbuild(1). It uses various directives
determining how the program or library maintenance is performed.
Icmconf’s directives are biased towards the
construction of C++ programs, but program maintenance for other
languages (e.g., C) can also easily be configured.
The icmbuild(1) script ignores empty lines and lines whose
first non-blank characters are two consecutive forward slashes (//) or start
with a hash-character (#). Long lines can be split over multiple
lines by writing a final backslash character at lines continuing at the next
line.
Traditional make-utilities recompile all dependent sources once
header files are modified. When developing C++ programs this is
hardly ever requird, as adding new member functions to classes does not
require you to recompile already existing source files. Recompilation
is required when the data member organization of classes is
altered.
To handle class dependencies in a more sensible way,
icmake(1) checks class dependencies using its support programs
icm-dep, visiting the classes listed in the CLASSES file if
icmconf’s USE_ALL directive was specified. If a directory
mentioned in the CLASSES file contains a file having a name equal to
the name specified at the USE_ALL parameter, then all sources of
classes that depend on that particular class are also recompiled. In
practice this means that when you change the data organization of a class
you only need to touch it that directory the file whose name was
specified by the USE_ALL directive. E.g., if your class is named
Data, its sources are in the sub-directory ./data, and
#define USE_ALL "a" was specified then after modifying the
data organization of the class Data you only need to issue the
command touch data/a. Subsequently, at the next icmbuild call
all sources in ./data as well as all sources in directories whose
(header) files include data.h are recompiled as well.
Likewise, if #define SPCH or (deprecated) #define
PRECOMP was used, a similar action is performed for the precompiled
headers: if a local file that’s (directly or indirectly) included by
internal header files has changed, then the Single Pre-Compiled Header
(SPCH) file is recompiled (or (deprecated), having specified PRECOMP
the modified class headers are recompiled).
The icmbuild(1) script itself does not inspect these
dependencies, but calls the support programs icm-spch and
icm-dep to perform the requird tests. The usage summaries of these
programs are written to the standard output stream when calling,
respectively icmake -S and icmake -d.
The following #defines, except for those that are shown as
commented (e.g., //#define REFRESH) are required.
- o
- //#define ADD_LIBRARIES ""
when a program must be linked against additional libraries (other than the
name of the program’s library itself (cf. LIBRARY, below)
then those libraries should be specified here. E.g., when a program is
linked against libbobcat then the specification is:
#define ADD_LIBRARIES "bobcat"
If your program is linked against multiple libraries, then use a
blank-separated list of libraries (like #define ADD_LIBRARIES
"bobcat math");
- o
- //#define ADD_LIBRARY_PATHS ""
this directtive must be specified if ADD_LIBRARIES is also specified,
although it may be specified as an empty string. When additional libraries
(specified at ADD_LIBRARIES) are located in non-standard library
locations (e.g., not in /lib and /usr/lib) then these
additional paths are (blank space separated) specified here. Specify only
the paths, not the -L flags.
- It is stronly advised to specify full pathnames here. Relative path
specifications can be used by specify paths relative to the directory that
is specified at the TMP_DIR directive (see below);
- o
- //#define CLS
the clear screen directive. If defined tput clear is called to
clear the terminal screen before starting compilations. By default it is
not defined. Alternatively the -c option can be passed to
icmbuild;
- o
- #define CXX "g++"
the C++ compiler to use. For a C compiler specify, e.g.,
#define CC "gcc". Their settings are overruled by
identically named environment variables. If only C files are
compiled then #define CXX can be omitted.
- By specifying, e.g., #define CXX "ccache g++"
compilations use caching facilities, which may impressively reduce
recompilation times. Refer to the cccache(1) man-page for
details.
- o
- #define CXXFLAGS "-Werror -Wall -O2"
C++ compiler options to use (here showing the default options). When
the C compiler is used, use #define CFLAGS rather than
CXXFLAGS. Their settings are overruled by identically named
environment variables. If only C files are compiled then #define
CXXFLAGS can be omitted.
- Additional options can be defined by adding them to the CXXFLAGS
definition. In addition, compilations use the environment variable
ICMAKE_CPPSTD to set the C++ standard to use. E.g., after
defining
ICMAKE_CPPSTD=--std=c++26
the compiler uses the options
--std=c++26 -Werror -Wall -O2
- o
- //#define DEFCOM "..."
a DEFCOM directive may be added to the icmconf file (the
icmstart(1) script can do this for you). It can be specified as:
#define DEFCOM "program"
in which case icmbuild does program maintenance, or as
#define DEFCOM "library"
in which case icmbuild does library maintenance.;
- o
- //#define ICM_DEP "-V go"
the existence and implied existence of USE_ALL files (see the
description of the USE_ALL directive). When the (deprecated)
PRECOMP directive is specified the recency of precompiled headers
is ensured (see also the SPCH description, below). By default
icm_dep is called with the shown default arguments. If
icm_dep should not be called define ICM_DEP as an empty
string (""). Icmake(1)’s man-page contains
a separate section about the icm_dep support program;
- o
- #define IH ".ih"
the extension used for internal header files. See #define SPCH below.
If SPCH is specified the ttI#define H) directive must also be
specified;
- o
- //#define LDFLAGS ""
linker options to use. By default no options are passed to the linker. Its
setting is overruled by an identically named environment variable;
- o
- //#define LIBRARY "ofiles"
by defining this directive a local library (libofiles.a) is
constructed. When a binary program is built it is linked against this
library rather than to the individual object files.
- If a library instead of a program must be constructed (see also the
DEFCOM directive), then the LIBRARY directive specifies the
library’s base name (without the lib prefix and without the
.a extension). In that case source files are expected in
sub-directories of the project’s main directory (i.e., the
directory containing icmconf). In that case avoid having source and
header files in the project’s main directory. Instead, move such
files to a separate sub-directory;
- o
- //#define MAIN "main.cc"
the source file in which the int main function is defined. This
directive is required when doing program (rather than library)
maintenance.
- Note: if source files are located in the project’s main directory
but library maintenance is intended (e.g., by specifying #define
DEFCOM library) then define MAIN to specify a pseudo
main source, whose base name is the base name of the header file in the
project’s main directory. This, however, is considered a kludge,
and should be avoided by moving those source and header files to a
separate sub-directory;
- o
- //#define MULTICOMP "..."
Example: #define MULTICOMP "jobs -q"
- This directive activates threaded compilation of source files. When used
its first word specifies the name of a file to contain information about
which files must be compiled. This must be a plain filename, not
containing directory specifiers (like /). Refer to the
icmake(1) man-page’s section ICM-MULTICOMP covering
options, arguments, and usage of icm-multicomp which is called when
#define MULTICOMP is specified;
- o
- //#define NO_PRECOMP_WARNING"
when #define PRECOMP (now deprecated) is specified (see below) a
warning is issued when a class-directory does not contain a IH
file. Such warnings are suppressed by defining NO_PRECOMP_WARNING.
This option is only considered when #define PRECOMP is
specified;
- o
- #define OBJ_EXT ".o"
this directive specifies the extension of object modules created by the
compiler;
- o
- //#define PRECOMP "-x c++-header"
(deprecated, consider declaring #define SPCH instead)
define this directive to construct class-specific pre-compiled headers (in
which case the IH) directive must also be specified. Dependencies
between (precompiled) headers are automatically considered.
Existing precompiled headers are removed by icmbuild cleangch (or
icmbuild clean. When source files of other languages are compiled
the PRECOMP’s -x argument must be adapted to those
languages;
- o
- //#define REFRESH
define REFRESH to relink the binary program when icmbuild
program is called, even when no file was (re)compiled. This is
useful when the program links to external libraries which were updated
separately from the currrent project;
- o
- //#define SHARED
this directive is only interpreted when LIBRARY is also specified. If
defined a shared library (extension .so*) is built in addition to a
static library (extension .a);
The shared library receives VERSION as its version number while soft
links using VERSION’s (see below) major version number an no
version number are also made available. E.g., if VERSION is defined
as 1.02.03 and #define LIBRARY "demo" then the
shared library becomes libdemo.so.1.02.03, with libdemo.so.1
soft-linking to it, and libdemo.so soft-linking to
libdemo.so.1;
- o
- //#define SHAREDREQ ""
when creating a shared library SHAREDREQ specifies the names of
libraries and library paths that are required by the constructed shared
library itself. E.g., if a library is found in /usr/lib/special,
assuming that the name of the required library is libspecial.so,
then use the specification #define SHAREDREQ
"-L/usr/lib/special -lspecial". The /lib and
/usr/lib paths are usually automatically visited by the linker and
do not have the be specified. This directive is required (possibly as an
empty string) if SHARED is defined;
- o
- #define SOURCES "*.cc"
the pattern to locate sources in directories;
- o
- //#define SPCH "..."
Example: #define SPCH ""
If #define SPCH is specified then #define IH must also be
specified.
This directive activates using Single Pre-Compiled Headers (refer to the
icmake(1) man-page for details). The argument string can be empty,
or it can contain specifications which are used when constructing a SPCH.
Refer to the icmake(1) man-page, section ICM-SPCH for
details;
- o
- //#define SPCH_FILE "..."
Example: #define SPCH_FILE "specs"
This directive can be used in combination with the #define SPCH
directive. By default the headers used to construct the SPCH are written
to the file spch. If that name should not be used then the
SPCH_FILE directive can be used to specify another filename. The
specified name must be a plain filename, not containing directory
specifiers (like / or an extension).
- o
- #define TMP_DIR "tmp"
the directory in which intermediate results are stored. To avoid
cross-device communications it’s probably best to define
TMP_DIR as a sub-directory of the project’s main
directory;
- o
- //#define USE_ALL "a"
when defining this directive icmbuild looks for directories
containing files having the names defined by the USE_ALL
specification. All source files in those directories as well as all source
files in directories that (recursively) depend on the set of directories
under consideration are recompiled, after which the USE_ALL files
are removed;
- o
- //#define USE_ECHO ON
when defined as ON (rather than OFF) (system) commands
executed by icmbuild are echoed;
- o
- //#define USE_VERSION
when defined (it is defined by default) a file VERSION is read by
icmconf to determine the program’s or library’s
version, and the project’s release years. The file VERSION
must be available in the project’s main directory and should
contain lines like these:
VERSION=11.01.00
YEARS=1992-2024
)
The following directives are available in cases where a program
uses a parser generator creating a parser class from a grammar
specification. By default they’re all commented out, and can be
removed if a parser generator is not used.
- o
- //#define PARSER_DIR ""
the sub-directory containing the parser’s specification file. If the
PARSER_DIR directory is specified then all other directives in this
section must also be specified;
- o
- //#define PARSFILES ""
if the parser specification file named at PARSSPEC itself includes
additional specification files, then patterns matching these additional
grammar specification files should be specified here. The pattern is
interpreted in the directory specified at PARSER_DIR and could
contain a subdirectory name (e.g. specs/*). When files matching the
pattern are modified then a new parser is created;
- o
- //#define PARSFLAGS "-V"
the flags that are used when calling the program specified at
PARSGEN;
- o
- //#define PARSGEN "bisonc++"
the name of the program generating the parser;
- o
- //#define PARSOUT "parse.cc"
the name of the file generated by the parser generator (used by
icmbuild when checking the timestamps of parser specification
s);
- o
- //#define PARSSPEC "grammar"
the name of the parser specification file. This file is expected in the
directory specified by the PARSER_DIR directive.
The following directives are available in cases where a program
uses a scanner generator creating a lexical scanner class from a set of
regular expressions. By default they’re all commented out, and can be
removed if a scanner generator is not used.
- o
- #define SCANNER_DIR ""
the subdirectory containing the scanner’s specification file. If the
SCANNER_DIR directory is specified then all other directives in
this section must also be specified;
- o
- #define SCANFILES ""
if the lexical scanner specification file named at SCANSPEC itself
includes additional specification files, then patterns matching these
additional lexer specification files should be specified here. The pattern
is interpreted in the directory specified at SCANNER_DIR and could
contain a subdirectory name (e.g. specs/*). When files matching the
pattern are modified then a new lexical scanner is created. By default no
additional specification files are used;
- o
- #define SCANFLAGS ""
the flags that are used when calling the program specified at
SCANGEN;
- o
- #define SCANGEN "flexc++"
the name of the program generating the lexical scanner;
- o
- #define SCANOUT "lex.cc"
the name of the file generated by the lexical scanner (which is used by
icmbuild when checking the timestamps of scanner specification
s).
- o
- #define SCANSPEC "lexer"
the name of the lexical scanner specification file. This file is expected in
the directory specified by the SCANNER_DIR directive.
The mentioned paths are sugestive only and may be installation
dependent:
- o
- /usr/share/icmake/CLASSES
: example of an icmconf CLASSES file;
- o
- /usr/share/icmake/icmconf
: default (skeleton) icmbuild resource files, like main.cc,
usage.cc, etc.;
- o
- /etc/icmake
: directory containing the default system-wide icmstart(1)
configuration file;
- o
- $HOME/.icmake
: optional user-defined directory containing user-defined specifications
overruling the system-wide definitions. This directory is the proper
location for a file AUTHOR defining the AUTHOR directive
with the user’s name. E.g., my .icmake/AUTHOR file contains:
#define AUTHOR "Frank B. Brokken (f.b.brokken@rug.nl)";
ccache(1), icmake(1), icmbuild(1),
icmstart(1), icmstart.rc(7).
This is free software, distributed under the terms of the GNU
General Public License (GPL).
Frank B. Brokken (f.b.brokken@rug.nl).