The KMake utility

KMake is a utility program to build KCML libraries. It uses an XML based file to describe the libraries, the source file components for each library and the library dependencies. It then executes the kc compiler to assemble each library from its source files building only those that are necessary.

KMake uses the file times of source files to determine whether a library needs rebuilding allowing a single source file to be changed, kmake executed and only the minimum rebuilding done.

Using kconf.xml

KMake can run using a simple bespoke build file, but is best run using kconf.xml as part of a system. If a service called XYZ is defined in kconf.xml, then the libraries may be built with

kmake -b XYZ

A number of elements and environment variables need to be defined in kconf.xml:

kcmltype

The service must indicate the type of libraries to be built, by adding the following XML element to that service.

<kcmltype>6</kcmltype>

Valid values for kcmltype are:

6use kc6 to build KCML6 interpreted libraries
7use kc to build KCML7 compiled libraries
NF7build libraries for browser client
PDBbuild JIT compilable libraries for workbench
NFPDBbuild JIT compilable libraries for workbench and browser client

Environment variables

The service should also specify these environment variables

BUILD This defines the filename of the XML build file.
SOFTWARE This defines the directory of source files. Where absolute filenames are not specified in the build file, they are relative to this directory.
KBIN This defines the destination for where generated files are built. Names may include separator characters to place them in sub-directories. Where directories do not exist they are created automatically.
MANIFEST This defines the name of the manifest XML file that allows for conditional compilation. This value is optional and if not specified then all conditions evaluate to TRUE.

The XML build file

The build file lists all the libraries and programs (KCML7 only) to be compiled. Each library and program has a list of its components (specified by the src tag) and dependencies (specified by the uselibrary and reflibrary tags). The include tag can be used to insert subsidiary XML fragments at any point. The if tag allows for a measure of conditional compilation.

Compiling a KCML7 program is a two pass process. In the first pass the build file is read and a tree is built of the target libraries and program. For each target kmake examines the uselibrary tags which declare the dependencies on other libraries and the tree is ordered such that these must be built before the target. This process determines the eventual build order. Clearly there cannot be circular dependencies on things like records, fields or constants.

In the second pass KCML generates the code for the targets in the correct order and when doing so it needs to check that the right number of arguments and the right types are used on DEFSUB calls. To do this it uses the reflibrary tags for a target which list the libraries that contain functions this target might call.

A simple XML containing all the key elements is presented here:

<?xml version="1.0" encoding="UTF-8"?>
<build>
    <flag name="KCML6Decoration"/>
    <flag name="SearchVars"/>
    <flag name="SearchModuleVars"/>
    <flag name="CodeAnywhere"/>
    <library name="Boot">
        <src file="PROGRAMS/GB/MAING.src"/>
    </library>
    <library name="Constants">
        <src file="PROGRAMS/GB/CONST.src"/>
        <src file="PROGRAMS/CG/CONST.src"/>
        <src file="PROGRAMS/GB/CNW32.src"/>
    </library>
    <library name="DataStructure">
        <src file="GENPROGS/GB/IRECS.src" altfile="PROGRAMS/GB/IRECS.src"/>
    </library>
    <library name="CoreFunctions">
        <uselibrary name="Constants"/>
        <uselibrary name="DataStructure"/>
        <uselibrary name="Boot"/>
        <src file="PROGRAMS/GB/libGN.src"/>
        <src file="PROGRAMS/GB/libKI.src"/>
        <src file="PROGRAMS/GB/libKD.src"/>
        <src file="PROGRAMS/GB/libR8.src"/>
        <src file="PROGRAMS/GB/libSF.src"/>
        <src file="PROGRAMS/GB/libPR.src"/>
    </library>
    <library name="Administrator">
        <uselibrary name="Constants"/>
        <uselibrary name="CoreFunctions"/>
        <src file="PROGRAMS/GB/ADMIN.src"/>
        <src file="PROGRAMS/GB/libAD.src"/>
    </library>
    <program name="GB/INIT">
        <uselibrary name="CoreFunctions"/>
        <src file="programs/GB/INIT.src"/>
    </program>
    <program name="GB/LDMOD">
        <uselibrary name="CoreFunctions"/>
        <src file="programs/GB/LDMOD.src"/>
    </program>
    <program name="GB/MENU">
        <uselibrary name="CoreFunctions"/>
        <uselibrary name="Administrator"/>
        <uselibrary name="CommercialGlobal"/>
        <src file="programs/GB/MENU.src"/>
    </program>
</build>

XML Elements

Element Parent Description and attributes
build N/A Always the root element
error if Used to force an error if some conditionally compiled requirements could not be met.
flag build There are no flags in KCML6.x and these flag elements are ignored. They may be specified to allow a common source file between KCML6.10 and future KCML systems.
AttributePurpose
name Name the flag.

Current KCML7 flags can be used to relax the rules for compatibility with previous KCML versions. They include
NamePurpose
CodeAnywhereAllow code between functions and relax the requirement for a 'main() entry point function.
CompileWithErrorsTreat some strict type errors as informational so that the build completes
GenerateViewInfoGenerate an additional .k7view field for each .kbin file. These XML files can be used as input to the kviewinfo utility to generate a cross reference of where and how DEFVIEWs are used.
KCML6DecorationTreat a and a$ as different variables. KCML7 does not need the $ decoration as all variables must be declared and typed.
SearchVarsIf a variable is not found in the current scope or as a library variable then look for it further up the return stack in outer scopes. Intended for legacy code that does not obey scoping rules.
SearchModuleVarsIf a variable is not in current scope but is found in an outer scoped function and also as a library variable, then prefer the scoped locally version over the globally scoped library variable
forwardlibrary library This can be used to resolve some specific forward references on records that reflibrary was unable to satisfy. It should not be used as a general synonym for reflibrary. forwardlibrary is ignored by kc6 in interpreted builds.
AttributePurpose
name Library name. Will match the name attribute of a library element.
generated build Specify source code that is generated by running the KCML program defined in the child uselibrary element. This generated code may be used as the source code to build other programs or libraries by specifying it using the child element gensrc rather than the more normal src element. For more information see the section on Generated Code below.
AttributePurpose
name The name of the source file that will be generated. A .src extension is implied.
geninclude any tag Specifies an include file that is generated using xslt. Both xml and xslt child elements must be specified. After generating the xml file it is loaded into the build view to replace the geninclude element. It is then scanned for further geninclude elements found in the included file
AttributePurpose
name Name of the include file that is generated and then included.
gensrc library Specifies the filename for a generated source file rather than a pre-existing source file
AttributePurpose
filename Name of a source file that was generated by some generated element elsewhere in the build file. Can use environment variables, specified using $ notation, that will be expanded.
if any tag Conditional building. This element may be used around any other elements for conditional building based on the manifest. If the condition is true then everything inside the tag is used however if the condition is false then the build will disregard the tag and all its contents. Thus several programs, libraries or individual src file components may be included or excluded based on a testable condition.
AttributePurpose
test Condition to test. Evaluates TRUE iff the name appears in the manifest file.
include any tag Include a subsidiary XML file obeying the same schema. Allows for a more structured build and permits generated build files.
AttributePurpose
filename Name of the included XML build file. Can use environment variables, specified using $ notation, that will be expanded. This file must exist or the build will fail.
library build Define a library. The library may contain uselibrary, reflibrary, forwardlibrary and src elements among others.
AttributePurpose
nameName of library. It must be a valid relative filename. The extension ".kbin" is applied automatically.
descDescription. Not used by kmake. Provided for application use.
preloadA true or false boolean. Not used by kmake. Provided for application use.
requiredA true or false boolean. Not used by kmake. Provided for application use.

The preload, required and desc attributes are provided purely for application use and the internal DEFSUB 'KCML_Build_GetLibraries() call can be used to extract them.
librarygroup build Now obsolete. Do not use.
make build Invoke a child make process.
minversion build Specifiy the minimum version of KCML that must be used. The build will fail if the KCML is too old.
AttributePurpose
full Full version number, such as 07.10.00.21099. If this attribute is specified it takes precedence over all other attributes.
build Build number, such as 21099. This attribute requires the version attributes to be specified as well.
version Version number, such as 70 (For 7.09). This attrubute is the major and first digit of the minor version number. It requires the build attribute to be specified as well. This attribute is now deprecated and the full attribute should be used instead.
program build Define a program. May contain the same elements as a library. In KCML 6.10 program elements are ignored, but may be defined for use by future versions of KCML sharing a common build file.
AttributePurpose
name Name of program. It must be a valid relative filename. The extension ".kbin" is applied automatically.
reflibrary library Name a library that contains functions that this library may reference. This is weaker than uselibrary and does not affect build order. It is possible that the referenced library is built after this library. reflibrary is ignored by kc6 in interpreted builds.
AttributePurpose
name Library name. Will match the name attribute of a library element.

The reflibrary element replaces the deprecated refmodule element of KCML 6.10. Both are supported.
src library
program
Specifies a KCML source file (either ascii or compiled) that is a component of this library or program.
AttributePurpose
fileSource file component. If a relative pathname is specified, then it is relative to the environment variable SOFTWARE.
altfileOptional. Alternative source file if the specified source file does not exist. Unless the -i option is specified it is an error if neither of these files exists.
rev8Optional. Turns on compiler flags to allow legacy code to be compiled.
target build
uselibrary library
program
generated
Name a library that this program or library depends upon at the time of building. This must specify the name of a library within the build file. When kmake executes, it will always build a library's dependencies before building the library itself. The order of the libraries in the build file does not matter. KMake will fail if there are circular dependencies in the build file.
AttributePurpose
name Library name. Will match the name attribute of a library element.

The uselibrary element replaces the deprecated usemodule element of KCML 6.10. Both are supported.

This tag is also used to specify the KCML program to be run in a generated element.
xml geninclude
generated
Specify an xml file to be used to generate xml build statements or src code. An xslt must also be specified.
xslt geninclude
generated
Specify an xslt file to be used to trasform xml to generate xml build statements or src code. An xml must also be specified.

Command line switches

These may be listed with kmake -?

Option Parameter Description
-6   Build KCML 6 libraries using the kc6 compiler
-a   Build all. All targets in the system are rebuilt, regardless of file times.
-b system Build system. Build using the specified system from kconf.xml. It is recommended that this method is used.
-c   Clean up. Delete all generated files before building.
-d   Parallel build on multiprocessor platforms that support it.
-f srcfile Build targets containing this file. This option may be repeated to specify multiple source files.
-i   Ignore missing source files rather than error. If this option is specified, then even where neither the file= or optional altfile= exists then no error will be generated. The library is built using the other files that do exist. If no components exist then the library is not built.
-k   Continue after errors. Normally kmake stops at an error. This option allows it to continue as far as possible, building libraries that do not depend on other libraries that have failed to build.
-l   Make all libraries targets. This will build all the libraries but not any of the programs (except those executed in the build process).
-m   Build help files for use in khelp.
-n   Rebuild all targets. Given one or more named targets, this file builds them having built all target dependencies regardless of file timestamps
-o   Only named targets are rebuilt and dependencies that may need rebuilding are not.
-p   Print commands before executing them.
-q   Build using temporary files. This allows the building of libraries while some library files are currently in use. Without this option the build would normally fail because of the files being in use. Using this option, libraries are built to temporary files and then moved over the library file in an operating-system specific manner to avoid this error.

NB This option is not recommended and should not be used. An existing process may end up using previous and new libraries as an inconsistent set leading to random and unpredictable problems. It is intended for use where background processes need to continue executing and are known never to load extra libraries after they have started.
-s   Build silently.
-t target Build targets. This option may be specified many times. If no targets are specified on the command-line then all libraries and programs are built. If targets are specified then only these libraries (and any libraries they depend on) are built. This allows for faster build times during the software development process.
-u build.xml Specify the build file
-v   Display kmake version information
-x directory Build to specified alternative directory rather than the one target directory specified for the system.
-y level Deferred compilation for PDB. The level determines which types of compilations are deferred until runtime.
0compile only
1defer for programs
2defer for libraries
-z   More verbose output.

Exit codes

When kmake terminates it indicates success or failure by setting an exit code which can be tested as the return value of SHELL. There are predefined KCML constants for these:

Constant nameValueMeaning
_KMAKE_RETURN_SUCCESS0Build succeeded
_KMAKE_RETURN_ERROR2Build failed

Generated code

If the build needs to include libraries or programs that are themselves generated by KCML programs then there should be a generated tag specifying the source file that is generated and the KCML program or XML and XSLT transform pair to do it. This generated code may be later used as source code to build other programs or libraries. The child element gensrc is used in place of src to specify a generated source file component in library and program elements.

Generating code from a program

For example, in the build file fragment below, the program WPGEN is compiled as a consequence of the program tag. The generated tag causes it to be executed by a child KCML process launched by kmake with the command-line argument GENSRC/PLUGINS.src (with path attached). This program should create and write the file specified (use $ARG() to get command-line arguments). It must return an exit code using $END with one of the same KCML constant values used by kc. Following that the library PLUGINS can be generated using GENSRC/PLUGINS.src as one of the component source files.

<-- compiles the generating program WPGEN.kbin -->
<program name="WPGEN">
	<uselibrary name="BaseFunctions2"/>
	<src file="WPGEN.src"/>
</program>
<-- Causes generating program WPGEN.kbin to be run to produce GENSRC/PLUGINS.src -->
<generated name="GENSRC/PLUGINS">
	<uselibrary name="WPGEN"/>
</generated>
<-- Builds a library  that exposes the code in GENSRC/PLUGINS.src -->
<library name="Plugins" desc="Plugins Library">
	<gensrc name="GENSRC/PLUGINS"/>
	<src file="PROGRAMS/WPMESS.src"/>
</library>

The GENSRC subdirectory mentioned in the example is presumed to exist in the $KBIN directory but it will be silently created if necessary.

Generating code using xml data and xslt

Alternatively an xslt transform may be used to transform an xml file to generated src code. In the following simple example, xml and xslt files convert the data to a sequence of function calls.

<!-- build fragment -->
<generated name="GENSRC/DATA">
	<xml file="data.xml"/>
	<xslt file="data.xslt"/>
</generated>

data.xml

<?xml version="1.0"?>
<data>
	<contact name="David" telephone="01234 111111"/>
	<contact name="Peter" telephone="01234 222222"/>
</data>

data.xslt

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	<xsl:output method="text"/>
	<xsl:template match="/">
		<xsl:value-of select="'&#x0a;DEFSUB 'AddContacts()&#x0a;'"/>
		<xsl:call-template name="rules"/>
		<xsl:value-of select="'&#x0a;ENDSUB&#x0a;'"/>
	</xsl:template>
	<xsl:template name="rules">
		<xsl:for-each select="//data/contact">
			<xsl:value-of select="''AddContact('"/>
			<xsl:value-of select="@name"/>
			<xsl:value-of select="','"/>
			<xsl:value-of select="@telephone"/>
			<xsl:value-of select="')&#x0a;'"/>
		</xsl:for-each select>
	</xsl:template>
</xsl:stylesheet>

The manifest

The manifest is an XML file that conditionally controls the build process. An complete example is shown below. In this example, the names CS-GB and ST-COMM are defined (by combining the UserExitCategory and UserExitCategoryCode with "-" as a separator). These names may be used in if elements in the build file. For instance <if test="ST-COMM"> would be TRUE and <if test="ST_AUTO"> would be FALSE.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Manifest>
	<UserExits>
		<UserExitCategory Name="CS">
			<UserExitCategoryCode>GB</UserExitCategoryCode>
		</UserExitCategory>
		<UserExitCategory Name="ST">
			<UserExitCategoryCode>COMM</UserExitCategoryCode>
		</UserExitCategory>
	</UserExits>
</Manifest>