Package: setprogramoptions
DEPRECATION NOTICE:This package was forked by the original author and
is now maintained under the nameActiveConfigProgramOptions:GitLabPyPIDocsUsers ofSetProgramOptionsshould switch to the new package.SetProgramOptionsTheSetProgramOptionspackage extendsConfigParserEnhancedto enable the
processing of.inifiles that specifycommand line program options.As a subclass of ConfigParserEnhanced, SetProgramOptions supports all
theoperationsthatConfigParserEnhancedsupports and adds some of its
own. The following table notes the newoperationsthat SetProgramOptions adds:OperationFormatDefined Byuseuse <section>ConfigParserEnhancedopt-setopt-set Param1 [Param2..ParamN] [: <VALUE>]SetProgramOptionsopt-removeopt-remove Param [SUBSTR]SetProgramOptionsGenerally speaking, when we parse a section from a .ini file, the following
steps are taken:Parse the section, resolving anyuseoperations to fully parse the DAG
generated by the section and its dependents.This generates alist of actionsthat are specified in the configuration
file. Anyremoveoperations encountered will execute their removal search
during parsing to ensure they only remove matches that arepreviouslydefined.Once parsed, ageneratorcan be invoked to process the actions-list and generate
the requested back-end format. Currently, SetProgramOptions only generates output
forbashscripts but this can easily be extended to support other formats such
as Windows batch or Powershell files, or other kinds of shell commands.
Subclasses can also be extended to include their own generator types as well.Supported OperationsuseTheuseoperation is inherited fromConfigParserEnhanced. Please see its documentation
on this command and its use.opt-setSets a genericcommand linestyle option.The format of this isopt-set Param1 [Param2] [Param3] ... [ParamN] : [VALUE]In abashcontext, this operation attempts to generate an option for some command
that will be executed.SetProgramOptionswill concactenate theParamstogether and then append=VALUEif a VALUE field is present.
For example,opt-set Foo Bar : Bazwill becomeFooBar=Baz.opt-removeRemovesexisting entries that have been processed up to the point theopt-removeis
encountered that match a pattern.The format of this isopt-remove Param [SUBSTR]When aremoveis encountered,SetProgramOptionswill search through all processed
options and will delete any that contain anyParam-ithat matchesParam.
By default the parameters much be anexact matchofParam, but if the optionalSUBSTRparameter is provided thenSetProgramOptionswill treatParamas a
substring and will remove all existing options ifany parameter contains Param.SetProgramOptions Config FilesA.inifile that can be processed bySetProgramOptionscan be formatted like this:[COMMAND_LS]opt-set lsThis is perhaps the most simple thing we could do.
Usinggen_option_list('COMMAND_LS', generator="bash")this operation would generate the commandlswhen processed.A more complex section which creates a CMake command call might look like this:[COMMAND_CMAKE]opt-set cmakeopt-set -G:Ninjaopt-set -D CMAKE_CXX_FLAGS:"-O3"and this would generate the commandcmake -G=Ninja -DCMAKE_CXX_FLAGS="-O3"when
processed forbashoutput.Variable Expansion within VALUE fieldsVariables can be added to the VALUE fields in handled instructions, but they have their
own format that must be used:${VARNAME|VARTYPE}VARNAMEis the variable name that you might expect for a bash style environment variable
that might be defined like this:export VARNAME=VALUE.VARTYPEis thetypeof the variable that is being declared. ForSetProgramOptionsthe only recognized type isENVwhich definesenvironment variables. Subclasses such
asSetProgramOptionsCMakedefine their own types.We do not provide adefaulttype for this because we wish it to beexplicitthat this
is a pseudo-type and do not want it to be confused with some specific variable type since that
meaning can change depending on the kind of generator being used. For example,${VARNAME}is anenvironment variablewithin a bash context but in a CMake fragment file it would be
aninternal CMake variableand$ENV{VARNAME}would be anenvironment variable.
By not providing a default we force type consideration to be made explicitly during the creation
of the .ini file.Linked ProjectsConfigParserEnhanced- required by SetProgramOptions -RTD,GitHubSetProgramOptions ExamplesExample 1example-01.ini[BASH_VERSION]opt-set bashopt-set --version[LS_COMMAND]opt-set ls[LS_LIST_TIME_REVERSED]opt-set "-l -t -r"[LS_CUSTOM_TIME_STYLE]opt-set --time-style:"+%Y-%m-%d %H:%M:%S"[MY_LS_COMMAND]use LS_COMMANDuse LS_LIST_TIME_REVERSEDuse LS_CUSTOM_TIME_STYLEexample-01.py#!/usr/bin/env python3importsetprogramoptionsfilename="example-01.ini"section="MY_LS_COMMAND"# Create SetProgramOptions instancepopts=setprogramoptions.SetProgramOptions(filename)# Parse sectionpopts.parse_section(section)# Generate the list of bash options for the commandbash_options=popts.gen_option_list(section,generator="bash")# Print out the commandsprint(" ".join(bash_options))generates the output:ls-l-t-r--time-style="+%Y-%m-%d %H:%M:%S"Example 2We can utilize theuseoperation to create a more complex configuration file
that provides some sort of common sections and then point-of-use sections that
would generate customized configurations for a particular use:[CMAKE_COMMAND]opt-set cmakeopt-set -G:Ninja[CMAKE_OPTIONS_COMMON]opt-set -D CMAKE_CXX_FLAGS:"-fopenmp"[CMAKE_OPTIONS_APPLICATION]opt-set -D MYAPP_FLAG1:"foo"opt-set -D MYAPP_FLAG2:"bar"[APPLICATION_PATH_TO_SOURCE]opt-set /path/to/source/.[APPLICATION_CMAKE_PROFILE_01]use CMAKE_COMMANDuse CMAKE_OPTIONS_COMMONuse CMAKE_OPTIONS_APPLICATIONuse APPLICATION_PATH_TO_SOURCE[APPLICATION_CMAKE_PROFILE_02]use APPLICATION_PROFILE_01opt-remove MYAPP_FLAG2This example follows a pattern that larger projects might wish to use
when there are many configurations that may be getting tested.
Here, we set up some common option groups and then create aggregation sections
that will include the other sections to compose a full command line.Using this .ini file, if we generatebashoutput for sectionAPPLICATION_CMAKE_PROFILE_01the resulting command generated would be:cmake -G=Ninja -DCMAKE_CXX_FLAGS="-fopenmp" -DMYAPP_FLAG1="foo" -DMYAPP_FLAG2="bar" /path/to/source/.Alternatively, we can generatebashoutput for sectionAPPLICATION_CMAKE_PROFILE_02which first clonesAPPLICATION_CMAKE_PROFILE_01and thenremovesall entries containing the parameterMYAPP_FLAG2using theopt-removeoperation.
This will result in a generated comandcmake -G=Ninja -DCMAKE_CXX_FLAGS="-fopenmp" -DMYAPP_FLAG1="foo" /path/to/source/..This example shows how theopt-removeoperation will fully
remove occurrences that contain that substring from the list
of actions.This example shows some of the capabilities thatSetProgramOptionsprovides for managing many build configurations within a single .ini
file.SetProgramOptionsCMakeSetProgramOptionsCMakeis a subclass ofSetProgramOptionsthat adds additional
operations and generators to handle processingCMakeoptions:Addsopt-set-cmake-var.Addscmake_fragmentgenerator.AddsCMAKEtype to variables.New operations defined inSetProgramOptionsCMake:OperationFormatDefined Byopt-set-cmake-varopt-set-cmake-var VARNAME [TYPE] [FORCE] [PARENT_SCOPE]: VALUESetProgramOptionsCMakeSupported Operationsopt-set-cmake-varThis adds a CMake variable program option. These have a special syntax inbashthat looks like-DVARNAME:TYPE=VALUEwhere the:TYPEis an optional parameter. If thetypeis left out then CMake assumes the value is aSTRING.We may not wish to generate bash only output though. For CMake files, we might wish to generate acmake fragmentfile which is
basically a snippet of CMake that can be loaded during a CMake call using the-Soption:cmake -S cmake_fragment.cmake. The
syntax within a CMake fragment file is the same as in a CMake script itself.If the back-end generator is creating a CMake fragment file, thesetcommand generated will use [CMake set syntax].
This looks something likeset(<variable> <value>)but can also contain additional options. These extra options can
be provided in theopt-set-cmake-varoperation in the .ini file:FORCE-By default, aset()operation does not overwrite entries in a CMake file. This can be added toforcethe value to be saved.This is only applicable to generatingcmake fragmentfiles.PARENT_SCOPE- If provided, this option instructs CMake to set the variable in the scope that is above the current scope.This is only applicable to generatingcmake fragmentfiles.TYPE- Specifies theTYPEthe variable can be.This is apositionalargument and must always come afterVARNAME.Valid options for this areSTRING(default),BOOL,PATH,INTERNAL,FILEPATH.Adding aTYPEoption implies that theCACHEanddocstringparameters will be added to aset()command
in a CMake fragment file according to the syntax:set(<variable> <value> CACHE <type> <docstring> [FORCE])as illustrated on theCMakeset()documentation.This is applicable to bothcmake fragmentandbashgeneration.SetProgramOptionsCMake Config FilesHere is an example of what a .ini file may look like using the
CMake operations provided by this class:[SECTION_A]opt-set cmakeopt-set-cmake-var MYVARIABLENAME:VALUEopt-set-cmake-var MYVARIABLENAME2 PARENT_SCOPE:VALUEHandling CMake VariablesACMake variablein this context would be aninternal variablethat is known to CMake.
Because this is not a variable that would be known outside of the context of.cmakefiles,
this kind of variable is only applicable when generating CMake fragment files.It is necessary to provide a CMake variant for variable expansions because the CMake
syntax for variables is different than that used by Bash, and CMake fragments have
a specialized syntax forenvironmentvariables as well. In CMake fragment files:environment variables are written as$ENV{VARNAME}internal CMake variables are written as:${VARNAME}We saw variables inSetProgramOptionsfollow the syntax:${VARNAME|ENV}whereENVspecifies the kind of variable we're declaring. We extend this inSetProgramOptionsCMakeby adding a${VARNAME|CMAKE}variation which
indicates that the variable is expected to be aninternalcmake variable
and is more suited towards being used within a CMake fragment file since
it has no meaning at the command line.You can still use aCMakevariable expansion entry when generatingbashoutput but there is a catch. The variablemustbe resolvable to something
that isnota CMake variable through its transitive closure.
This is achieved by caching thelast known valueof a variable as we process
a .ini file and provided that the value ultimately resolves to either a string
or an environment variable we can still use it.
If it cannot be resolved to something that isn't a CMake variable then an
exception should be generated.For example, if we have a .ini file that sets upCMAKE_CXX_FLAGSto include-O0in a
common section like this:[COMMON]opt-set-cmake-var CMAKE_CXX_FLAGS STRING FORCE:"-O0"and then we have a later section that adds an OpenMP flag to it like this:[ADD_OPENMP]
use COMMON
opt-set-cmake-var CMAKE_CXX_FLAGS STRING FORCE: "${CMAKE_CXX_FLAGS|CMAKE} -fopenmp"This is valid since${CMAKE_CXX_FLAGS|CMAKE}will get replaced with-O0so the
resultingCMAKE_CXX_FLAGSvariable would be set to-O0 -fopenmpafter processing.
If we generatebashoutput for theADD_OPENMPsection we'll get
a-Doption that looks like-DCMAKE_CXX_FLAGS:STRING="-O0 -fopenmp".But what if we have a .ini file with a CMake variable that can't be resolved to
something that is not a CMake flag, such as:[COMMON]opt-set-cmake-var FOO:${SOME_CMAKE_VAR|CMAKE}If we tried to process this and write out the resulting script using thebashgenerator
an exception should be raised citing that we don't know what to do with that unresolved
CMake variable. This would be the equivalent to a bash option-DFOO=<SOME_CMAKE_VAR>and bash can't handle that because it has no idea what it should put in that cmake var
field.Note: if the same CMake option is provided in multiple lines they will all be included
in the generated output. In that case, the behaviour will match what will occur if
one called cmake directly with the same option multiple times. In that case, thelast one winssince all-Doptions are treated as though they both haveFORCEandCACHEflags set.SetProgramOptionsCMake ExamplesExampleThis example shows a configuration file that can be used to generate
build files using Ninja or Makefile. In the .ini file we set up some
common sections that contain the arguments and then the point-of-use
sections (MYPROJ_CONFIGURATION_NINJAandMYPROJ_CONFIGURATION_MAKEFILES)
can compose their command lines by importing the argument definition sections
viause.example-02.ini## example-02.ini#[CMAKE_COMMAND]opt-set cmake[CMAKE_GENERATOR_NINJA]opt-set -G:Ninja[CMAKE_GENERATOR_MAKEFILES]opt-set -G:"Unix Makefiles"[MYPROJ_OPTIONS]opt-set-cmake-var  MYPROJ_CXX_FLAGS       STRING:"-O0 -fopenmp"opt-set-cmake-var  MYPROJ_ENABLE_OPTION_A BOOL   FORCE:ONopt-set-cmake-var  MYPROJ_ENABLE_OPTION_B BOOL:ON[MYPROJ_SOURCE_DIR]opt-set /path/to/source/dir[MYPROJ_CONFIGURATION_NINJA]use CMAKE_COMMANDuse CMAKE_GENERATOR_NINJAuse MYPROJ_OPTIONSuse MYPROJ_SOURCE_DIR[MYPROJ_CONFIGURATION_MAKEFILES]use CMAKE_COMMANDuse CMAKE_GENERATOR_MAKEFILESuse MYPROJ_OPTIONSuse MYPROJ_SOURCE_DIRexample-02.pyThis python code shows generating a bash script and a CMake fragment
of the configuration specified in the .ini file.#!/usr/bin/env python3# -*- mode: python; py-indent-offset: 4; py-continuation-offset: 4 -*-frompathlibimportPathimportsetprogramoptionsprint(80*"-")print(f"-{Path(__file__).name}")print(80*"-")filename="example-02.ini"popts=setprogramoptions.SetProgramOptionsCMake(filename)section="MYPROJ_CONFIGURATION_NINJA"popts.parse_section(section)# Generate BASH outputprint("")print("Bash output")print("-----------")bash_options=popts.gen_option_list(section,generator="bash")print("\\\n".join(bash_options))# Generate a CMake Fragmentprint("")print("CMake fragment output")print("---------------------")cmake_options=popts.gen_option_list(section,generator="cmake_fragment")print("\n".join(cmake_options))print("\nDone")OutputUsing theNinjaspecialization from the above code, we generate the following
output:$python3example-02.py
--------------------------------------------------------------------------------
-example-02.py
--------------------------------------------------------------------------------

**Bashoutput**
cmake\-G=Ninja\-DMYPROJ_CXX_FLAGS:STRING="-O0 -fopenmp"\-DMYPROJ_ENABLE_OPTION_A:BOOL=ON\-DMYPROJ_ENABLE_OPTION_B:BOOL=ON\/path/to/source/dir

CMakefragmentoutput
---------------------
set(MYPROJ_CXX_FLAGS"-O0 -fopenmp"CACHESTRING"from .ini configuration")set(MYPROJ_ENABLE_OPTION_AONCACHEBOOL"from .ini configuration"FORCE)set(MYPROJ_ENABLE_OPTION_BONCACHEBOOL"from .ini configuration")Done