Fine-grained Configuration

pkgconf.tcl only provides coarse-grain control over the configuration: the target hardware, the packages that should be built, and the desired startup. Unlike the graphical Configuration Tool, pkgconf.tcl does not provide any facilities for manipulating finer-grained configuration options such as how many priority levels the scheduler should support. There are hundreds of these options, and manipulating them by means of command line arguments would not be sensible.

In the current system the only effect a configuration option can have is to produce either a #define or a #undef in a C header file. System code written in C or C++ can #include the header file, and use the conventional C preprocessor conditionals #ifdef, #ifndef, and #if defined(), to adapt to the settings in the current configuration. In future releases, a configuration option will be able to have other effects, such as controlling which files in a given package will actually get compiled. There will also be support for configuring languages other than C or C++, where the use of #define statements in a header file would be inappropriate.

The build tree generated by pkgconf.tcl contains a pkgconf subdirectory, which contains a header file for every package that is part of the current configuration. Fine-grained configuration using command-line tools involves using a suitable editor on these header files.

The install tree also contains a pkgconf subdirectory (install/include/pkgconf). You should not edit the files in this directory, because they are installed as part of the build process and any changes you make to these files will get overwritten during the next build.

The build tree's pkgconf directory also contains a number of files that should not be edited: makefile, pkgconf.mak and system.h. These files are generated by pkgconf.tcl, and any changes made to these will be overwritten the next time that you invoke pkgconf.tcl. One file you can edit is makevars, which contains settings for the build process. This file is described in the next section.

A typical extract from a configuration header file, in this case kernel.h, would be:

	  
#define CYGSEM_KERNEL_SCHED_MLQUEUE
#undef  CYGSEM_KERNEL_SCHED_BITMAP
#define CYGNUM_KERNEL_SCHED_PRIORITIES          32
#define CYGSEM_KERNEL_SCHED_TIMESLICE
#define CYGNUM_KERNEL_SCHED_TIMESLICE_TICKS      5

Each #define or #undef corresponds to a single configuration option. Three of these options are boolean in nature: the option may be enabled, which means that there is a #define for the corresponding symbol but no value; or the option may be disabled, in which case there is a #undef for the symbol instead. The multilevel queue scheduler is enabled, which means that the bitmap scheduler has to be disabled because there can be only one scheduler in the system. Timeslicing is enabled.

The other two options are numerical in nature. There will always be a #define for the corresponding preprocessor symbols, and this #define will involve a value.

The header file contains additional information that may assist you while editing fine-grained configuration. For example, immediately above this block of #define's the header file contains the following information:


  cdl_option CYGNUM_KERNEL_SCHED_TIMESLICE_TICKS {
      display           "Number of clock ticks between timeslices"
      parent            CYGPKG_KERNEL_SCHED
      type              count
      legal_values      1 to 65535
      description "
          Assuming timeslicing is enabled, how frequently should it
          take place? The value of this option corresponds to the
          number of clock ticks that should occur before a timeslice
          takes place, so increasing the value reduces the frequency
          of timeslices."
  }

This information is part of a large comment block. It is, in fact, the information that is used by the graphical Configuration Tool and allows it to provide a sensible user interface for all the options. The entity CYGNUM_KERNEL_SCHED_TIMESLICE_TICKS is described as an option, rather than as a larger entity such as a component or an entire package. There is a short textual description of the option. Its position within the overall option hierarchy is clearly identified. The type of the option is given as "count", which means that it can only have numerical values. Bounds are placed on the value of the option: the lower bound of 1 means that a timeslice would occur for every single clock interrupt, which would mean 100 times per second if the default clock settings are used. The upper bound would result in a timeslice approximately every 11 minutes, which is unlikely to be useful for most applications. The information provided with the option also includes a fairly detailed description.

A very important property (but not present in this example) is the "requires" property. The option CYGSEM_KERNEL_SCHED_TIMESLICE contains the line "requires CYGVAR_KERNEL_COUNTERS_CLOCK", which means that it is only possible to enable timeslicing if the kernel clock is enabled. This information is very useful when manipulating the timeslice option. However, the configuration data for CYGVAR_KERNEL_COUNTERS_CLOCK does not indicate that it is required by CYGSEM_KERNEL_SCHED_TIMESLICE. Programs such as the graphical Configuration Tool can determine this very easily using the information provided, but it is a bit more difficult for humans. Standard utilities such as grep will prove useful.

It should be noted that the configuration data currently present in the header files is there to support the current graphical Configuration Tool. The location, syntax, and contents of the configuration data is likely to change significantly in future releases.

All the configuration options and their descriptions are listed in the documentation.