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:
6 | use kc6 to build KCML6 interpreted libraries |
7 | use kc to build KCML7 compiled libraries |
NF7 | build libraries for browser client |
PDB | build JIT compilable libraries for workbench |
NFPDB | build 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.
Current KCML7 flags can be used to relax the rules for compatibility with previous KCML versions. They include
|
||||||||||||||||||
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.
|
||||||||||||||||||
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.
|
||||||||||||||||||
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
|
||||||||||||||||||
gensrc | library | Specifies the filename for a generated source file rather than a pre-existing source file
|
||||||||||||||||||
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.
|
||||||||||||||||||
include | any tag | Include a subsidiary XML file obeying the same schema. Allows for a more structured build and permits generated build files.
|
||||||||||||||||||
library | build | Define a library. The library may contain uselibrary, reflibrary, forwardlibrary and src elements among others.
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.
|
||||||||||||||||||
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.
|
||||||||||||||||||
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.
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.
|
||||||||||||||||||
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.
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.
|
||||||
-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 name | Value | Meaning |
---|---|---|
_KMAKE_RETURN_SUCCESS | 0 | Build succeeded |
_KMAKE_RETURN_ERROR | 2 | Build 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="'
DEFSUB 'AddContacts()
'"/> <xsl:call-template name="rules"/> <xsl:value-of select="'
ENDSUB
'"/> </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="')
'"/> </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>