Configuration actions¶
ZenMake supports some configuration actions. They can be used to check system
libraries, headers, etc. To set configuration actions use the configure parameter
in task params. The value of the configure parameter
must be a list of such actions. An item in the list
can be a dict where do specifies what to do, in other words it is some type of
configuration action. It’s like a function where do describes the name of
a function and others parameters are parameters for the function.
There is another possible value for such an item in python format of buildconf file
and it is a python function which must return True/False on Success/Failure.
If such a function raises some exception then ZenMake interprets it
as if the function returns False. This function can be without arguments or
with named arguments: taskname, buildtype.
It’s better to use **kwargs to have universal way to work with any input arguments.
These actions can be run sequentially or in parallel (see do = parallel).
And they all are called on the configure step (in command configure).
Results of the same configuration actions are cached when it’s possible but not between runnings of ZenMake.
These configuration actions in dict format:
do=check-headersParameters:
names,defname= ‘’,defines= [],mandatory= True.Supported languages: C, C++.
Check existence of C/C++ headers from the
nameslist.The
defnameparameter is a name of a define to set for your code when the action is over. By default the name for each header is generated in the form ‘HAVE_<HEADER NAME>=1’. For example, if you set ‘cstdio’ in thenamesthen the define ‘HAVE_CSTDIO=1’ will be generated. If you set ‘stdio.h’ in thenamesthen the define ‘HAVE_STDIO_H=1’ will be generated.The
definesparameter can be used to set additional C/C++ defines to use in compiling of the action. These defines will not be set for your code, only for the action.The toolchain, includes and libpath task parameters affect this type of action.
do=check-libsParameters:
names= [],fromtask= True,defines= [],autodefine= False,mandatory= True.Supported languages: C, C++.
Check existence of the shared libraries from the
libstask parameter or/and from thenameslist. Iffromtaskis set to False then names of libraries from thelibstask parameter will not be used for checking. Ifautodefineis set to True it generates C/C++ define name likeHAVE_LIB_LIBNAME=1.The
definesparameter can be used to set additional C/C++ defines to use in compiling of the action. These defines will not be set for your code, only for the action.The toolchain, includes and libpath task parameters affect this type of action.
do=check-codeParameters:
text= ‘’,file= ‘’,label= ‘’,defines= [],defname= ‘’,execute= False,mandatory= True.Supported languages: C, C++, D, Fortran.
Provide piece of code for the test. Code can be provided with the
textparameter as a plane text or with thefileparameter as a path to the file with a code. This path can be absolute or relative to the startdir. At least one of thetextorfileparameters must be set.The
labelparameter can be used to mark message of the test. If theexecuteparameter is True it means that the resulting binary will be executed and the result will have effect on the current configuration action.The
defnameparameter is a name of C/C++/D/Fortran define to set for your code when the test is over. There is no such a name by default.The
definesparameter can be used to set additional C/C++/D/Fortran defines to use in compiling of the test. These defines will not be set for your code, only for the test.The toolchain, includes and libpath task parameters affect this type of action.
do=find-programParameters:
names,paths,var= ‘’,mandatory= True.Supported languages: all languages supported by ZenMake.
Find a program. The
namesparameter must be used to specify one or more possible file names for the program. Do not add an extension for portability. This action does nothing ifnamesis empty.The
pathsparameter can be used to set paths to find the program, but usually you don’t need to use it because by default thePATHsystem environment variable is used. Also the Windows Registry is used on MS Windows if the program was not found.The
varparameter can be used to set substitution variable name. By default it’s a first name from thenamesin upper case and without symbols ‘-’ and ‘.’. If this name is found in environment variables, ZenMake will use it instead of trying to find the program. Also this name can be used in parameter run like this:in YAML format:
foo.luac: source : foo.lua configure : [ { do: find-program, names: luac } ] # var 'LUAC' will be set in 'find-program' if 'luac' is found. run: '${LUAC} -s -o $(tgt) $(src)'in Python format:
'foo.luac' : { 'source' : 'foo.lua', 'configure' : [ dict(do = 'find-program', names = 'luac'), ], # var 'LUAC' will be set in 'find-program' if 'luac' is found. 'run': '${LUAC} -s -o $(tgt) $(src)', },do=find-fileParameters:
names,paths,var= ‘’,mandatory= True.Supported languages: all languages supported by ZenMake.
Find a file on file system. The
namesparameter must be used to specify one or more possible file names. This action does nothing ifnamesis empty.The
pathsparameter must be used to set paths to find the file. Each path can be absolute or relative to the startdir. By default it’s ‘.’ which means startdir.The
varparameter can be used to set substitution variable name. By default it’s a first name from thenamesin upper case and without symbols ‘-’ and ‘.’.do=call-pyfuncParameters:
func,mandatory= True.Supported languages: any but only in python format of buildconf file.
Call a python function. It’a another way to use python function as an action. In this way you can use the
mandatoryparameter.do=pkgconfigParameters:
toolname= ‘pkg-config’,toolpaths,packages,cflags= True,libs= True,static= False,defnames= True,def-pkg-vars,tool-atleast-version,pkg-version= False,mandatory= True.Supported languages: C, C++.
Execute
pkg-configor compatible tool (for examplepkgconf) and use results. Thetoolnameparameter can be used to set name of the tool and it is ‘pkg-config’ by default. Thetoolpathsparameter can be used to set paths to find the tool, but usually you don’t need to use it.The
packagesparameter is required parameter to set one or more names of packages in database of pkg-config. Each such a package name can be used with ‘>’, ‘<’, ‘=’, ‘<=’ or ‘>=’ to check version of a package.The parameters named
cflags(default: True),libs= (default: True),static(default: False) are used to set corresponding command line parameters--cflags,--libs,--staticfor ‘pkg-config’ to get compiler/linker options. Ifcflagsorlibsis True then obtained compiler/linker options are used by ZenMake in a build task. Parameterstaticmeans forcing of static libraries and it is ignored ifcflagsandlibsare False.The
defnamesparameter is used to set C/C++ defines. It can be True/False ordict. If it’s True then default names for defines will be used. If it’s False then no defines will be used. If it’sdictthen keys must be names of used packages and values must be dicts with keyshaveandversionand values as names for defines. By default it’s True. Each package can have ‘HAVE_PKGNAME’ and ‘PKGNAME_VERSION’ define where PKGNAME is a package name in upper case. And it’s default patterns. But you can set custom defines. Name of ‘PKGNAME_VERSION’ is used only ifpkg-versionis True.The
pkg-versionparameter can be used to get ‘define’ with version of a package. It can be True of False. If it’s True then ‘define’ will be set. If it’s False then corresponding ‘define’ will not be set. It’s False by default. This parameter will not set ‘define’ ifdefnamesis False.The
def-pkg-varsparameter can be used to set custom values of variables for ‘pkg-config’. It must bedictwhere keys and values are names and values of these variables. ZenMake uses the command line option--define-variablefor this parameter. It’s empty by default.The
tool-atleast-versionparameter can be used to check minimum version of selected tool (pkg-config).Examples in YAML format:
# Elements like 'tasks' and other task params are skipped # ZenMake will check package 'gtk+-3.0' and set define 'HAVE_GTK_3_0=1' configure: - do: pkgconfig packages: gtk+-3.0 # ZenMake will check packages 'gtk+-3.0' and 'pango' and # will check 'gtk+-3.0' version > 1 and <= 100. # Before checking of packages ZenMake will check that 'pkg-config' version # is greater than 0.1. # Also it will set defines 'WE_HAVE_GTK3=1', 'HAVE_PANGO=1', # GTK3_VER="gtk3-ver" and LIBPANGO_VER="pango-ver" where 'gtk3-ver' # and 'pango-ver' are values of current versions of # 'gtk+-3.0' and 'pango'. configure: - do: pkgconfig packages: 'gtk+-3.0 > 1 pango gtk+-3.0 <= 100' tool-atleast-version: '0.1' pkg-version: true defnames: gtk+-3.0: { have: WE_HAVE_GTK3, version: GTK3_VER } pango: { version: LIBPANGO_VER }Examples in Python format:
# Elements like 'tasks' and other task params are skipped # ZenMake will check package 'gtk+-3.0' and set define 'HAVE_GTK_3_0=1' 'configure' : [ { 'do' : 'pkgconfig', 'packages' : 'gtk+-3.0' }, ] # ZenMake will check packages 'gtk+-3.0' and 'pango' and # will check 'gtk+-3.0' version > 1 and <= 100. # Before checking of packages ZenMake will check that 'pkg-config' version # is greater than 0.1. # Also it will set defines 'WE_HAVE_GTK3=1', 'HAVE_PANGO=1', # GTK3_VER="gtk3-ver" and LIBPANGO_VER="pango-ver" where 'gtk3-ver' # and 'pango-ver' are values of current versions of # 'gtk+-3.0' and 'pango'. 'configure' : [ { 'do' : 'pkgconfig', 'packages' : 'gtk+-3.0 > 1 pango gtk+-3.0 <= 100 ', 'tool-atleast-version' : '0.1', 'pkg-version' : True, 'defnames' : { 'gtk+-3.0' : { 'have' : 'WE_HAVE_GTK3', 'version': 'GTK3_VER' }, 'pango' : { 'version': 'LIBPANGO_VER' }, }, }, ],do=toolconfigParameters:
toolname= ‘pkg-config’,toolpaths,args= ‘–cflags –libs’,static= False,parse-as= ‘flags-libs’,defname,var,msg,mandatory= True.Supported languages: any.
Execute any
*-configtool. It can be pkg-config, sdl-config, sdl2-config, mpicc, etc.ZenMake doesn’t know which tool will be used and therefore this action can be used in any task including standalone runcmd task.
The
toolnameparameter must be used to set name of such a tool. Thetoolpathsparameter can be used to set paths to find the tool, but usually you don’t need to use it.The
argsparameter can be used to set command line arguments. By default it is ‘–cflags –libs’.The
staticparameter means forcing of static libraries and it is ignored ifparse-asis not set to ‘flags-libs’.The
parse-asparameter describes how to parse output. If it is ‘none’ then output will not be parsed. If it is ‘flags-libs’ then ZenMake will try to parse the output for compiler/linker options but ZenMake knows how to parse C/C++ compiler/linker options only, other languages are not supported for this value. And if it is ‘entire’ then output will not be parsed but value of output will be set to define name from thedefnameand/orvarif they are defined. By defaultparse-asis set to ‘flags-libs’.The
defnameparameter can be used to set C/C++ define. Ifparse-asis set to ‘flags-libs’ then ZenMake will try to set define name by using value of thetoolnamediscarding ‘-config’ part if it exists. For example if thetoolnameis ‘sdl2-config’ then ‘HAVE_SDL2=1’ will be used. For other values ofparse-asthere is no default value fordefnamebut you can set some custom define name.The
varparameter can be used to set substitution variable name. This parameter is ignored if value ofparse-asis not ‘entire’. By default it is not defined.The
msgparameter can be used to set custom message for this action.Examples in YAML format:
tasks: myapp: # other task params are skipped configure: # ZenMake will get compiler/linker options for SDL2 and # set define to 'HAVE_SDL2=1' - do: toolconfig toolname: sdl2-config # ZenMake will get SDL2 version and put it in the define 'SDL2_VERSION' - do: toolconfig toolname: sdl2-config msg: Getting SDL2 version args: --version parse-as: entire defname: SDL2_VERSIONExamples in Python format:
tasks = { 'myapp' : { # other task params are skipped 'configure' : [ # ZenMake will get compiler/linker options for SDL2 and # set define to 'HAVE_SDL2=1' { 'do' : 'toolconfig', 'toolname' : 'sdl2-config' }, # ZenMake will get SDL2 version and put it in the define 'SDL2_VERSION' { 'do' : 'toolconfig', 'toolname' : 'sdl2-config', 'msg' : 'Getting SDL2 version', 'args' : '--version', 'parse-as' : 'entire', 'defname' : 'SDL2_VERSION', }, ] }, }do=write-config-headerParameters:
file= ‘’,guard= ‘’,remove-defines= True,mandatory= True.Supported languages: C, C++.
Write a configuration header in the build directory after some configuration actions. By default file name is
<task name>_config.h. Theguardparameter can be used to change C/C++ header guard. Theremove-definesparameter means removing the defines after they are added into configuration header file and it is True by default.In your C/C++ code you can just include this file like that:
#include "yourconfig.h"You can override file name by using the
fileparameter.do=parallelParameters:
actions,tryall= False,mandatory= True.Supported languages: all languages supported by ZenMake.
Run configuration actions from the
actionsparameter in parallel. Not all types of actions are supported. Allowed actions arecheck-headers,check-libs,check-codeandcall-pyfunc.If you use
call-pyfuncinactionsyou should understand that python function must be thread safe. If you don’t use any shared data in such a function you don’t need to worry about concurrency.If the
tryallparameter is True then all configuration actions from theactionsparameter will be executed despite of errors. By default thetryallis False.You can control order of the actions by using the parameters
beforeandafterwith the parameterid. For example, one action can haveid = 'base'and then another action can haveafter = 'base'.
Any configuration action has the mandatory parameter which is True by default.
It also has effect for any action inside actions
for parallel actions and for the whole bundle of parallel actions as well.
All results (defines and some other values) of configuration actions
(excluding call-pyfunc) in one build
task can be exported to all dependent build tasks.
Use export with the name config-results
for this ability. It allows you to avoid writing the same config actions in tasks
and reduce configuration actions time run.
Example in python format:
def check(**kwargs):
buildtype = kwargs['buildtype']
# some checking
return True
tasks = {
'myapp' : {
'features' : 'cxxshlib',
'libs' : ['m', 'rt'],
# ...
'configure' : [
# do checking in function 'check'
check,
# Check libs from param 'libs'
# { 'do' : 'check-libs' },
{ 'do' : 'check-headers', 'names' : 'cstdio', 'mandatory' : True },
{ 'do' : 'check-headers', 'names' : 'cstddef stdint.h', 'mandatory' : False },
# Each lib will have define 'HAVE_LIB_<LIBNAME>' if autodefine = True
{ 'do' : 'check-libs', 'names' : 'pthread', 'autodefine' : True,
'mandatory' : False },
{ 'do' : 'find-program', 'names' = 'python' },
{ 'do' : 'parallel',
'actions' : [
{ 'do' : 'check-libs', 'id' : 'syslibs' },
{ 'do' : 'check-headers', 'names' : 'stdlib.h iostream' },
{ 'do' : 'check-headers', 'names' : 'stdlibasd.h', 'mandatory' : False },
{ 'do' : 'check-headers', 'names' : 'string', 'after' : 'syslibs' },
],
'mandatory' : False,
#'tryall' : True,
},
#{ 'do' : 'write-config-header', 'file' : 'myapp_config.h' }
{ 'do' : 'write-config-header' },
],
},
}