LCFG Header Development Tips

There are a number of common activities that people do in relation to the LCFG header sources. This topic contains short HOWTOs explaining how best to do various common things:

Header and Package List Naming Conventions

For sake of consistency and in some cases technical reasons a number of naming conventions have been established for header and package list files.

Header File Naming

In general headers should have descriptive names that use full words with underscores used to separate words when required. Exceptions to this rule are the office-*.h and studentlab-*.h header files that have already been referenced in machine profiles using dashes as the word separators.

Package List Naming

Package list files should follow the following naming scheme:

<level name>_<os name>_<list name>.{rpms,pkgs}

For example: dice_fc3_env.rpms.

The <level name> prefix is required to differentiate between package lists at different levels given that the package lists can only be referenced by file basename and not by a more descriptive path when using the @ operator. <list name> should be a descriptive name, using underscores to separate words, that suggests why the packages are grouped together.

Adding a New Component

TODO: Write this.

How to Write <options>.h Headers

TODO: Write this.

How to Decide if Something Should Live in "live/"

Generally speaking, a header file should go into live/ only if it contains resources that are likely to need to be changed at very short notice to preserve the overall stability of DICE. With the introduction of ReleaseManagement all the headers in the lcfg/, ed/ and dice/ levels will be subject to a staging and scrutiny period (testing) prior to being pushed out into production. Consequently, changes to these levels could have a lead time of a few days depending on how many machines the changes effect. For some resources this may not be practical, hence the reason for the live/ hierarchy.

When a header does exist in live/ it is preferable that only the volatile resources be set within it. As much material as possible should be factored back into the standard lcfg/, ed/ and dice/ levels. In some cases it may be possible to rearrange things such that none of the resources need to live in live/ at all (e.g. using dns aliases).

-- CarwynEdwards: Yes I'm making this up as I go along.

Dealing With Operating System Specific Resources

TODO: Finish this.

Operating system dependent resources are selected using the following CPP definitions:

  • #define OS_LINUX
  • #define LINUX_FC3
  • #define LINUX_RH9

  • #define OS_SOLARIS
  • #define SOLARIS_8
  • #define SOLARIS_9

-- CarwynEdwards: Maybe and example pattern?

Multiple Inclusion and How To Deal With It

In a nutshell the issue is this:


For an environment where you have full control of the header hierarchy it is possible to come up with rules and procedures to keep things sane, however it is less clear what to do when you consider external sites. A typical use case is an external site that needs to add a local component that is not in the upstream lcfg/ or ed/ levels. If that component, or even just a componenet with the same name, is later added to lcfg/ or ed/ then you need to be careful.

One could argue that the scenario depicted in the diagram should not happen, but consider the case when an lcfg/ level component is not part of the lcfg/defaults.h base platform. What if there are also defaults modifications to be done at a higher level? We end up with this:

ed/defaults.h includes ed/defaults/thing.h which includes lcfg/defaults/thing.h (if this isn't the case then how else do you do this?)

If component "thing" is then added to the lcfg/defaults.h then the multiple inclusions depicted in the diagram are created. You could then remove the inclusion path from ed/defaults/thing.h to lcfg/defaults/thing.h ? Whatever the solution third parties using the lcfg level need to know what the impact on them will be.

Is multiple inclusion all that bad though when dealing with LCFG resources? If multiple inclusion is allowed then the following discussions apply:

For performance reasons it initially seems prudent to use the following pattern in the defaults/*.h files if multiple inclusion is allowed:

#ifndef <something>
#define <something>

/* stuff */


If this was to be done I think needs to be of the form:

#define SEEN_<level>_<component>

.. as the resource sets are distinct at each level.

However! To ensure the correct behaviour in relation to CCP conditionals it may be better to not guard against mutliple inclusion. For example:

If lcfg/defaults/thing.h contains:

#ifndef GUARD
#define GUARD
#ifdef BLAH
/* do stuff */

and BLAH is not set at the lcfg/ level, "stuff" will not happen.

If then ed/defaults/thing.h includes lcfg/defaults/thing.h and ed/defaults.h includes ed/defaults/thing.h we have then set up a multiple inclusion (not necessarily a bad thing).

If BLAH is then set in ed/defaults.h "stuff" will still not happen as the multiple inclusion guard is blocking the reprocessing. Without the guard things will work as expected, at least in this case.

Another important rule that I think needs to be applied to defaults/*.h files is that they should not define any CPP variables that are used in other defaults/*.h files (preferably none at all). Otherwise this can happen:

  • lcfg/defaults/thing.h - defines MYVAR
  • lcfg/defaults.h - includes lcfg/thing.h
  • ed/defaults/another.h - references MYVAR
  • ed/defaults/thing.h - redefines MYVAR

ed/another.h inclusion comes before ed/thing.h inclusion in ed/defaults.h and hence misses the redefinition.

This problem doesn't exist with LCFG references (<%%>) as they are resolved later.

Performance is another potential issue but it would probably be best to test this rather than assume it's a problem.

-- CarwynEdwards: Isn't this a namespace issue? If components were bound to levels in terms of scope then downstream component clashes wouldn't happen. With a level binding, downsteam components would only inherit upstream component resources if the relationship was explicitly defined. This is the same problem that programming languages solved with local naming prefixes, modules or packages is it not? Summary: Maybe resources need to be bound to levels too.

lcfg.mycomponent.myresource = foo

ed.mycomponent isa lcfg.mycomponent

ed.mycomponent.myresource = bar

With the actual component then being passed all resources that satisfy isa lcfg.mycomponent?

-- CarwynEdwards - 22 Jun 2005

Topic attachments
I Attachment Action Size Date Who Comment
pngpng multiple_inclusion.png manage 22.5 K 22 Jun 2005 - 17:51 CarwynEdwards  
Topic revision: r4 - 07 Feb 2022 - 15:30:13 - ChrisCooke
This site is powered by the TWiki collaboration platformCopyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback
This Wiki uses Cookies