QEF home page

Chapter 7: Getting Started, Really

The Guide's Table of Contents Previous Chapter Bottom Of Page Next Chapter

This chapter discusses converting simple or straight forward projects to QEF using out-of-the-box tools and a simple understanding of the material presented in the first six chapters. Its intention is to get the new user started.


To use QEF's full power to produce an optimized build that promotes a really effective software process will require knowledge beyond the scope of this chapter and the material thus far presented. Hence this chapter will concentrate on the application of relatively straight forward QEF tools and procedures to similar projects that require little, if any, restructuring or modification of the source. Issues to be considered when dealing with a large or complicated project are presented in Chapter 12: QEF and Large Projects.

What is described in this chapter is not the simplest application of QEF in that we are considering a multi-directory project that may need to be built by multiple people, possibly on different platforms. The simplest application is a single directory as illustrated in the first tutorial in Chapter 4.1: Tutorial 1. The only required file is the qeffile. All the other infrastructure files are optional. The settings that would normally be done in root.vrs and the other files are either not required or can be done in the qeffile. However, a single directory project is just an application of the approach described in Section 4 and Section 5 below and will not be discussed any further.

Creating the QEF files required to use qef to do the project's construction is basically a matter of the following:

Note:Most of this chapter's material also applies to the creation of a sub-project within a larger project, as discussed in Chapter 12. The only exception is that a sub-project will not usually have its own root.vrs, confdefl.vrs, or QefAdm/* files, but will use the containing project's versions of those files.

7.1) Creating the Project Infrastructure

The typical QEF project will contain the following files:
root.vrs
Contains the project's name (@Project), revision (@Revision), and the tree's type (@TreeType).
tree.vrs
Contains project default controls, search paths, and various flags.
qeffile
The top level qeffile will usually be a script to run qef in the other sub-directories.
QefAdm/confvrs/confdefl.vrs
The default user configuration file -- should be annotated, as it serves as the prototype for a user's conf.vrs file created at the top of an object tree.
QefAdm/relinfo/qeffile
A qeffile to create and install a release information file.
QefAdm/touchdir/qeffile
A qeffile which serves as a place holder and provides documentation on the current state of the touchfiles files and path.
QefAdm/treedirs/treedirs.lst
The list of qvrs files and qeffiles for the project which is used to create the shadow trees. This file is usually created by treedirs with the --L flag or by the FSIC package described in Chapter 10.
The easiest way to create initial versions of the above files is to run the following command in the top level directory of your source tree.
    % dirsetup newproj
    -- create qeffile
    -- create read.me
    ...
In addition to the files named above, four additional files will be created. These are read.me files in the current, QefAdm/treedirs, and QefAdm/confvrs directories, and QefAdm/treedirs/example.lst. Their purpose should be obvious, given their names. They can be removed if necessary or desirable.

The modification of the tree.vrs and confdefl.vrs files is discussed in Section 7.2 and the qeffile is discussed in Section 7.3.

Other than the root.vrs file, the other files do not need to be modified.

Setting Necessary root.vrs Variables

The root.vrs file in the root of the baseline or master tree, unlike a root.vrs file in an object tree, is actually a source file. It provides important base information. The following variables probably need to be set.
Variable Flag Description
Project--pThe name of the project or product.
QefAdm--ZThe name of the QefAdm directory -- can be changed if desirable. Defaults to QefAdm if it exists, or . if it doesn't.
Revision--rThe revision number.
TreeType--tThe type of the tree -- should be baseline or master for a construction project.
VCSys--vThe version system (e.g., rcs, cvs, sccs).
VCRoot--VThe root of the version system tree if not this directory.
Note:rootvrs allows one to set a variable using a plus sign ('+') followed by the variable name followed by the new value as illustrated below.

Assuming that the current settings of the Project, Revision, and VCSys variables have to be set to "myproj", "4.5", and "rcs" respectively, one would use the command:

    % rootvrs +Project myproj -r4.5 -vrcs
    # output to root.vrs
    addpath RootPath     # none
    cset    RootAlias    @NotSet
    cset    Project      myproj
    cset    Revision     4.5
    cset    TreeType     baseline
    cset    BuildHost    @NotSet
    cset    BuildSys     @NotSet
    cset    QremoteEnv   @NotSet  # defaults to qremote
    cset    _DestDir_    @NotSet
    cset    ConfigName   @NotSet
    cset    ConfVrs      @NotSet  # defaults to conf.vrs
    cset    SysVrs       @NotSet  # defaults to linux2.vrs
    cset    TreedirsList @NotSet  # defaults to treedirs.lst
    cset    QefAdm       QefAdm
    cset    VCSys        rcs
    cset    VCRoot       @NotSet  # defaults to @LastRoot
    cset    VCBranch     @NotSet
    cset    OldRoot      @NotSet
    cset    EditBranches @NotSet  # defaults to 0
    qdupd: Added: 31 myproj 4.5 baseline you host -
	/home/myproj/src
If you don't remember what a "cset Variable @NotSet" statement does, see the Chapter 4 note on the subject.

7.2) Creating the Project Wide Configuration Files

Modifying the tree.vrs and QefAdm/confvrs/confdefl.vrs files are not quite so simple.
Fixing tree.vrs

The tree.vrs file that was created should be examined, as it does contain comments and example settings. Initially the tree.vrs file does not need to be changed as it will work as is, but eventually the @ProdDir value should be set to an appropriate directory. @ProdDir will usually be set to the name of the production version of the product to be used for header files, libraries, and tools, but it should be set in the tree.vrs file to a reasonable default so that various search tools such as libs and incls have useful search paths even when not in an object tree (i.e., even when @_DestDir_ is not set). Given that the @ProdDir setting will depend on the release and system, its setting is sometimes done in a project specific configuration file (see <psysvrs>.vrs(x-qvrs)) or explicitly set by users in their conf.vrs file.

Ultimately, as the QEF files evolve, there might be settings that are used by numerous directories that would be best done in the top level tree.vrs file, but at this time it is best to add then to the individual directory's qeffile.

Fixing confdefl.vrs The QefAdm/confvrs/confdefl.vrs file serves as both the default user configuration file and the annotated prototype for the users' conf.vrs files in the root of their object trees. As such the QefAdm/confvrs/confdefl.vrs file should contain the default settings for the variables that would normally be subject to user tastes or preferences, or are required to specify the necessary controls of the configuration that cannot be determined automagically. The dirsetup command will have created a QefAdm/confvrs/confdefl.vrs file somewhat like the following:
    % cat QefAdm/confvrs/confdefl.vrs
    options   # e.g., DEBUGGING, NO_MAN, PURIFY
              # STAND_ALONE if not to use ProdDir directories
              # Run ``x-qvrs opt-vars'' for standard list
    
    cset ProdDir    @NotSet # the project's product directory
    cset _F_cc      @NotSet # flag to all cc executions
    cset _F_cc_c    @NotSet # flags to cc -c executions
    cset _F_cc_o    @NotSet # flags to cc -o executions
    cset _F_instal  -qIs # instal(1) flags
    cset _T_cc      @NotSet # name of cc
Again, the above will work for the time being, but as options and/or required user settings evolve they should be added in the file.

7.3) Creating the Multi-directory Tree Walk

For most reasonably structured projects, the root directory's processing will be to invoke builds in some of its sub-directories. In fact QEF does tend to work best with project structures in which directories are either collections of sub-directories to be processed or collections of source files with associated actions. It can handle directories that are a mixture of sub-directories, other directories, and source to be processed, but at this time we'll keep it simple.

Assuming that the root directory's processing is to control the execution of sub-directories' processing, the qeffile that was created was a qefdirs specification.

    % cat qeffile
    set _DefaultArgs_   All  # Normal default in root directory
    set SaveQefTrack    1  # Save the qef track if build fails

    Begin   qefdirs

    P = Post        apply post processing passes

    All = Install Man Post

    # add directories and operations after this line

    +
    # last level should consist of file system integrity package
    # (if available) and the relinfo directory

    # QefAdm/fsic           P
    QefAdm/relinfo          P
The necessary modifications will be to add the names of the directories to be processed and the constructions that are supported. This may require the addition of new action keys, such as the "P = Post" in the above. By default the qefdirs provides I (for Install), L (for Local), M (for Man), R (for no Remove), and N (for Lint).

The new directories should be inserted in the qeffile before the entries for fsic (currently commented out) and relinfo.

For example, to add a directory called cmd that has Local, Install, and Man constructions, one would add the line:

    cmd ILM
to the file where indicated.
Note:qefdirs has a --X flag which will output a brief description of the syntax and semantics of q qefdirs file, as in:
    % qefdirs -X
    Input formats:

    +	to start new level
    ...
There is also an x_db database x-qefdirs that has the following items:
% x-qefdirs
x-qefdirs : qefdirs eXplanatory D.B.

  qefdirs-intro : Introduction to qefdirs
  qefdirs-input : qefdirs input syntax
   qefdirs-keys : specifying construction keys
qefdirs-all-key : specifying All constructions in qefdirs
qefdirs-dirline : standard qefdirs directory line
   qefdirs-deps : directory line dependencies
 qefdirs-levels : dividing qefdirs directories into levels
qefdirs-targets : qefdirs generated targets and controls

See also: qefdirs qefdirs(1) x_db
If the Man construction is to be suppressed if the NO_MAN option is set, then one would add:
    cmd ILm
If the Man pass within the cmd is actually just to invoke processing in a subdirectory man one could add:
    cmd	IL
    cmd/man m
instead, thereby saving eliminating the unnecessary processing of cmd during the Man pass.

If there is another directory example that depends on tools built within cmd one could add a dependency as in:

    example   IL   cmd
Finally, if there is processing to be done in the current directory, one adds the directory . as in:
    .   ILM
In this case, the current directory's construction script is put into the file qeffile2, instead of qeffile, as the latter is already being used for the multi-directory control.

7.4) Creating a qeffile For Each Directory

Creating the controls for an individual directory is primarily the creation of a qeffile that controls the following:
The preamble controls that might be required before processing higher directory qvrs files
Suffixes sets the Suffixes of source files
SrcPath the source search path
InclPath the include search path
LibPath the library search path
Libraries the libraries to be used for individual programs
Other Flags universal or file specific flags and controls
The Begin line the script control command
The construction script the back-end input or input to the script generator
Source Modification desirable, but usually optional and benign modifications to source files
Note that in many directories, the qeffile will just consist of a one or two settings before the Begin line, the Begin line, and the construction script which is usually two or three lines.

The lines of the qeffile up to and including the Begin line are qvrs lines. They begin with a qvrs keyword, followed by arguments that might incorporate variables and functions. The first three sections of Appendix F: The QEF Specialist's Reference Card cover Qvrs Keywords, Qvrs Variables, and Qvrs Functions respectively.

The preamble The optional preamble section is used to set options that need to be set before the higher directory tree.vrs file or the system configuration files are processed. In most cases this means specifying the DEBUGGING of PROFILING options. If specified, the preamble section must constitute the first significant lines of the qeffile. The preamble section consists of a "preamble" line, the settings, and a terminating "endpreamble" line, as in:
    preamble
	options DEBUGGING    # indentation is optional
    endpreamble
Note:The "options" statement above is equivalent to:
    set DEBUGGING 1
Suffixes The @Suffixes variable is used to specify the suffixes of source files to be found by sls in the source path. Usually this list is saved in the srclist._ file.

If @Suffixes is not specified, the default setting (c, y, l, and sh) is used. However, if additional or different suffixes are required, one sets the @Suffixes, as in:

    set Suffixes 1 qh cpp
If one wanted the standard suffixes or the `idl' suffixes one uses the flags --s or --i, as in:
    set Suffixes -std -i 1 qh
The @Suffixes variable can also specify the files produced by processing a file of a particular suffix. For example, "c/s" or "/(*).c/&.s" both specify that X.c may produce X.s. A more complicated example is "/(*).y/&.c;y.tab.c" which specifies that a f.y file may produce f.c and y.tab.c. Note that usually there is no @Suffixes setting or it is simply "-s" plus a list of simple suffixes.

In preparing a qeffile, one determines the list of primary files to be processed and/or installed and set the @Suffixes variable to the suffixes that would generate that list. If does not need to be complete, as individual files can be named within the construction script, or files can be ignored or removed from the list within the construction script.

SrcPath The @SrcPath is initially set to the @Branch sub-directories of the @RootPath. @Branch is the current directory's displacement from the root. @SrcPath rarely needs to be modified. The exception is when other directories need to be spliced into the source path, as will be illustrated in a later example.
InclPath @InclPath specifies the directories to be searched for C #include files. Usually @InclPath is initialized in the top directory's tree.vrs and local modifications are made in the qeffile file to add additional directories. Most frequently this will be to add the @SrcPath directories (i.e., corresponds to the current directory) as in:
    addpath InclPath @SrcPath
Note that the addpath keyword will usually insert its arguments at the beginning of the current list. If adding something like the X11 directories, one wants those directories to be added after the project's directories. Furthermore the name of the X11 include directory should have been configured in the host's sysnm.vrs file. To add the X11 include directory to @InclPath add the line:
    addpath InclPath -s @InclDirs[X11]
The --s specifies that the directories that follow should be inserted into the @InclPath list in the system header files portion of the list.
LibPath @LibPath specifies the directories to be searched for libraries. It will be initialized in the system's sysnm.vrs file to the list of standard library directories. As is the case with @InclPath, addpath is used to insert or append new directories to the current list, as in:
    addpath LibPath -s @LibDirs[X11]
Libraries In addition to the @LibPath library search path, there is a variety of settings that control the libraries linked with a program.
    set LIBS[echo.c] -lsocket # libraries linked with echo.c
	# better to put it in echo.c itself -- see below
    set LibMap[-lxxx] -lxxx -ltermcap # additional -lxxx mappings
	# such mappings usually done in sysnm.vrs file
    set LibStatic[-lxxx] pat*  # use static version for -lxxx
	# for programs that match pat*
Use libs --X for a list of library search controls, and examples and short descriptions for each control. Use qvrs --l for library search controls for the current directory. Use libs echo.c for list of libraries that will be linked with echo.c after library mapping and searches.
Other Flags There are a variety of other flags, options, and controls that might be required. The most common class of flags will be Cc flags, install modes, and tool names, as in:
    set _F_cc_c[echo.c] -DMACRO_DEF
    if @(sys hpux*) && ! @(option DEBUGGING)
	# if system is hpux* and DEBUGGING is not set
	# then make compilation of qsglib.c safe
	set _Optimize_index_[qsglib.c] Safe
    fi
    if @(sys unix5.4-mx300i)
	# on mx300 install qmsg setgid, group tty
	set _F_instal[qmsg] -g tty -M 2755
    fi
    cset _T_tclsh @PrereqRoot[tcl]/bin/tclsh
Note:If a setting is to apply over all the directories of a sub-project or project, the settings should be done in the common parent or ancestor directory's tree.vrs.

Similarly, @InclPath or @LibPath settings shared by the directories of a project should be done within such a tree.vrs file.

The Begin line The Begin line can take a number of forms as described by Begin(x-qvrs), qvrs(1), and many other documents. Basically it defines the input script and the processor, or the command that generates the script. The most common forms (greater than 98% of qeffiles) are:
    Begin    # defaults to qsg --M
    Begin qefdirs
    Begin qsg other flags
The first form is used for most directories with constructions. Given the qsg --M form, qef will automatically invoke sls to build the source database. The qefdirs form was discussed in Section 7.3. The third form is used when the source database is not required or additional flags are required. If the qsg invocation is to have either the --M or --S flags, they must be the first flag to be recognized by qef as forcing sls to be run.
Note:The sls command itself can be forced or changed by setting the variable @SLScmd.
The next section covers the more difficult aspect of the construction script, which in most instances starts immediately after the Begin line.

7.5) The Construction Script

We have already introduced qefdirs type scripts in Section 7.3 above. That covers about 10 to 20% of qeffiles. Nearly all other qeffiles are qsg scripts.

qsg is introduced in Chapter 9 and fully documented in qsg(1) and the x_db database x-qsg. Appendix F: The QEF Specialist's Reference Card lists qsg keywords, functions, list operators, and standard scripts.

qsg is a programming language specifically designed to generate input to other programs.
Note:This guide itself is produced using qsg, coupled with the html qsg script library.
qsg statements are of the form:

    keyword arguments
    script flags arguments
For example, in
    # If on windows, link sls to sls.exe
    if @(sys winnt* win9[58]*)
	    mklink -d _DestDir_/bin sls sls.exe
    else @# drop rc.sh and msdev.sh
	    remove argv rc.sh msdev.sh  @# not needed if not windows
    fi
the if, else, remove, and fi are qsg keywords. The "@#" is used to begin a comment in the middle of a statement. The `#' is treated literally anywhere other than at the beginning of a line. The mklink statement is a script from the standard qsg script library. The documentation for mklink can be retrieved using:
    % x-qsg mklink
    mklink : create qef script to create links
    
    Synopsis: mklink [-slcC] [-d dir] [-T construct] [-] file
	link_names ...
    
    -c      suppress default inclusion of target in Target group
    -C      applies condln -c flag - aborts if file writable
    ...
Similarly the documentation for any keyword, such as remove can be retrieved using:
    % x-qsg keyword
There are five special keywords to simplify output, as in:
    >this line, other than leading `>' output to stdout
    <\1>arguments output with long lines split at white space@
	with second and subsequent lines preceded by a@
	backslash, a newline, and one tab.  The backslash is@
	optional and the 1 can be replaced by 0 through 8.
    <<
    lines following "<<" up to ">>" output
    ><message This is a command inside HERE-IS output.
    Any embedded expressions, such as @<b bold> are interpreted.
    >>
however, their use within qeffiles files is discouraged.

Before going into the programming of a qeffile's qsg script any further, a brief discussion of the `@' magic is required. See Appendix E: Special @ Sequences in QSG in the reference card for a list of the special `@' interpretations. Immediately above it you will also see a list of the special @ sequences in qvrs.
Note: For an explanation of the use and overloading of the `@' as an operator and pre-cursor escape in both qvrs and qsg, see faq2(x-qmisc) and faq3(x-qmisc).

The item @(x-qsg) will give an extended description of the syntax and input conventions employed with qsg scripts:

    % x-qsg @
    qsg-input : qsg input conventions and the @ escape

    qsg scripts should consist of printable ASCII characters,
    tabs, spaces and newlines.  Any occurrence of a control
    character or DEL (octal 177) raises a fatal error.
    ...

Another powerful feature of the qsg language is the use of the ~ operators that can be used to modify a value of a variable or function call. For a complete description see qsg-listopts(x-qsg). For a list of the ~ operators see Qsg Listops in the specialist's reference card.

Although qsg is a fairly complete, albeit unconventional, programming language, most of its programming facilities are provided to implement the scripts. Within qeffiles the qsg scripts are usually limited to simple variable manipulation, if and set statements and calls to standard scripts.
Note:In the 210 qsg script qeffiles of the full Q-Tree, there are 916 statements, an average of 4.36 commands per script. Of those statements, 508 are script calls and 408 are qsg keywords. The vast majority (80%) of the keywords are if, fi, set, and remove (removes elements from a variable list). Of the script calls, 73% (374) are among the scripts briefly introduced below.
The standard qsg library contains 75 scripts as listed in Qsg Standard Scripts in the specialist's reference card. Many of those scripts are for use by other scripts and are not used within qeffiles. A large majority of the scripts (73% in the Q-Tree qeffiles) will be one of the following. The count column indicates the number of uses within the Q-Tree build to indicate relative importance.

 
NameCountShort Description
program74 create qef script to convert argument files into a program
commands56 create qef script to process and install practically anything
generic46 create qef generic script
mklink38 create qef script to create links
library33 create qef script to create archive object library
finstall33 create qef script to install a file
instfls28 create qef script to build instfls recipes
manlink27 create qef script to create links in the man directories
cmds_man22 create qef script to install manual sections
putdeps17 output dependencies

The description of any of the above scripts can be obtained using:

    % x-qsg script
Brief introductions to the listed scripts follow.
program This script is used for multiple module programs, as in:
    program -v prog.c parser.y lexer.l
This command outputs a qef script to create and install the program prog. An alternative name may be specified using a --n flag. The libraries for the program are specified in prog.c, @LIBS[prog.c], or the module named by the --M flag. Directives are output to create each intermediate file (e.g., parser.c, lexer.c, prog.o). If the option @GOT_PURIFY is true, directives needed to produce the purify, quantify, purecov, and purelink versions of the program are also produced with targets: prog_{p,q,v,l} respectively -- see pureeh(x-qsg).

program provides flags to suppress installation (--L), suppress construction unless explicitly named (--c), to specify the aggregate group to which the object is bound (--T -- defaults to Install), and to name the destination directory (--d -- default _DestDir_/_BinDir_).

The processing of each individual module is selected by the suffix which will usually be done by the script mkobj_X, where X is the suffix. Furthermore suffixes can be mapped to specific handlers -- see qsg-sfxmaps(x-qsg).

The --v flag illustrated in the example command is one of the useful options. If specified, a version file is created and linked with the modules to embed a link time version string into the resulting binary. program also provides significant support for window specific features such as creating dlls, handling precompiled header files, and registering the constructed file.

This script is the most commonly used. In fact the statistics given above are misleading in that the 56 commands script invocations invoke program about 400 times (albeit in loops) to produce the directives to produce the programs of the Q-Tree.

commands The commands script is used to handle a list of single module programs, man pages, shell scripts, and other files. Most often it is included in a qeffile as the last command to process all those files in the argument list not already processed, as in:
    commands @argv
Note that if an argument has already been processed by a previous script, such as program, it will not be re-processed.

commands does not actually do any of the processing. For each argument source it invokes the appropriate qsg script, as determined by suffix, and that script will typically generate the qef directives to build and install the appropriate files. The selection of which script is done using the suffix as described in commands(x-qsg). Briefly for a suffix X, if script mkobj_X exists, then program is used to process the file. If cmds_X exists, it is invoked. Note that suffixes can be mapped to handlers via settings of the qsg global variable QsgCmdProc[Sfx] which is usually set by the individual qsg library's initialization script.

generic This qsg script is used to output qef directives and recipes to build and optionally install a file with a specified recipe. This script is commonly used when the file's processing is non-standard. Flags are provided to specify prerequisites, touch files, attributes, various other controls, the destination directory (if any), the target and the recipe, as in:
    generic -P prereq -S source_prereq -d _DestDir_/bin @
	target_name <recipe ...>

Individual commands in the recipe should be separated by semi-colons.

finstall (see below) is invoked to install the file if the --d flag is specified.

mklink This script creates qef script to make links from first argument file to other argument files, using condln. For instance, the example script at the beginning of this section contained:
    mklink sls sls.exe
which will output directives to link sls to a name that can be recognized by MicroSoft's Visual Studio. The --d argument (default _DestDir_/_BinDir_) is used as the directory for either the target or link file when a file does not contain a slash.
library Building libraries for which the source is spread across multiple directories will be covered in a later section. Most libraries for which the entire source is within a single directory can be built with a command similar to the following:
    library -v -n exmpl c.c y.y l.l x.x ...
which creates and installs a library called "libexmpl.a" (or "exmpl.lib" on DOS or windows). Like program, the argument modules are processed using mkobj_X, where X is the module's suffix or the script to which it is mapped by the qsg global variable QsgCmdProc[suffix]. The --v flag specifies that a version module is to be created, compiled, and added to the library. Note that any modules added to a library will be marked such that if passed as arguments to commands or program, they are ignored. This means that one can build a library and programs as in:
    # Must map -lexmpl explicitly as it won't exist
    # when search for libraries done.
    set Library[-lexmpl] lib.@LibSuffix
    set LIBS[*] -lexmpl

    Begin

    library -L mod1.c mod2.c mod3.c @# -L suppresses installation
    commands @argv  @# no need to remove mod[123].c as
	@# will be ignored since processed by library
finstall finstall is used to specify the installation of a single file. Multiple files can be installed using instfls or install. The latter script just calls finstall in a loop. The following are a series of example finstall invocations:
    finstall F @# install `sls F` as _DestDir_/_LibDir_/F
    finstall -l F @# same but uses local F
    finstall -d dir F @# install `sls F` as dir/F
    finstall -s -d dir F.dat @# strip suffix so install as dir/F
    finstall -n X -d dir F @# install `sls F` as dir/X
    finstall F -P -M555 @# add instal flags -P and -M555
Note:The generated script will contain a alias for the installed file which is its basename followed by "~I", as in "file~I" so:
    % qef file~I # build and install file
If the installation is bound to an aggregate other than Install (e.g., Map) the "~I" affix is changed to a "~" followed by the key named by the global Key[Man]).
Note:instal will not install an empty file unless the --e flag is specified.
instfls instfls creates a script and the instfls input file to do installations. instfls uses instal to do the actual installations, but only if the source file differs from the target file. It is most often used to install header files so that gratuitous changes will not be made. The flags for instfls are almost the same as those for finstall except for the addition of a --M mode flag.
manlink This script is used to link a previously installed man section to a new name in the same directory. So
    manlink bp.1 howto.1 qfunc.1
outputs a script to link bp.1 to howto.1 and qfunc.1 in the appropriate man directory.
cmds_man cmds_man handles manual sections, installing its argument files in the appropriate man or docs directory. This is the script invoked by commands to process *.[1-9] files.
putdeps This script is used to output dependencies that cannot be deduced by incls or the qsg scripts. For example:
    putdeps -AV T1 T2 ... : D1 D2 ...
    # outputs dependencies
    T1 T2 ...:V: D1 D2 ...
This is obviously a fairly simple conversion, yet it is recommended that putdeps be used instead of raw output so that future changes to the back-end or retargeting to an alternative back-end will not require changing the qeffiles.
Checking the Construction Scripts Once the qeffile and qvrs files are prepared there are a number of steps that can be used to validate settings:
    % qef -Ptargets # output list of Targets
    % qef -Pscript # output generated script
    % qef -Pppscript # output post-processed script
    % qvrs # output all qvrs settings
    % qvrs -W var # show where var set
    % qef -n # show scripts for default targets
    % libs -a echo.c # show libraries for echo
    % qef -n echo # shows what would be done

7.6) Source Modification

There are two recommended modifications to C and C++ source files:
  1. Changing #include statements that use "file" to <file>
  2. Add LIBS line to main modules.
Fixing the #include "file"s The C ANSI standard does not define the behaviour of
    #include "file"
thus its interpretation varies from system to system, whereas the <file> form does not. That fact alone should be sufficient reason to avoid the "form", however, the real dangers of the "form" are the inability to map an #include file out of context and the potential of two different files using two different versions of an included file.
Note:Actually it's surprising how many programmers do not actually know the conventional interpretation of the "file" form. Most think that it means to search the current directory, whereas it actually means to insert the directory of the containing file at the beginning of the include directory search list.
Consider the situation in which we have two files f.c and g.c, both of which include a header file h.h using the "file" syntax.

If f.c and h.h are copied to a user's working directory for modification, when f.c is compiled it will use the working directory version of h.h. However, g.c use the h.h in the original directory.

The incls parsers do support the "file" form, but the potential ambiguities may lead to problems due to version skew or user confusion.

Finding all the includes, provided programmers have not embedded comments in between the `#', the "include", and the "file", is simply a matter of:

    % rep -rF '^\-#\-include\-"' srclist
where srclist contains a list of the files to be checked. The output should be saved, and edited to replace the "file" forms by appropriate <file> forms. To apply the changes run the following with the changes file as the standard input:
    % rpl -vr
Note:incls can be used to check the include lists of a list of files. The command:
    % incls -f srclist
will produce a tree form of the includes for all the files named in srclist.

A more complete and comprehensive discussion of this subject may be retrieved using:

    % x-qmisc \#includes
Adding LIBS comment Adding the LIBS line to the main source module is optional, but it is convenient and reduces the number of lines that need to be added to the qeffile. The LIBS line should be a comment within the first 1024 characters of the file. A colon (`:') must immediately follow LIBS. The list of libraries should be a space separated list of --lsym symbols naming the libraries required by the program.
Note:Sometimes libraries may be required on one system that are folded into the standard C library on other systems. For example, --lsocket is required on some systems but not on others. The --lsocket should be added to the LIBS line. The qvrs files will map this library to "-l" on the systems on which it is not required. On sun5s --lsocket is mapped to --lsocket --lnsl.
The following are example LIBS line:
    /* LIBS: */

    /* another comment
     * LIBS: -lsocket -lX11
     */

    /* Back slashes can be used to split up long lists
     * LIBS:	-lsocket \
     *		-lX11 */

7.7) Example Sub-Projects

The dirsetup dir-set qegappl contains a simple example application, complete with its qeffiles and qvrs files. To extract the files use:
    % dirsetup -d eg qegappl
    - create eg/read.me
    - create eg/appl/appl.h
    ...
The created tree contains directories appl, cmd, lib, and man, containing a header, a command file, a library, and man page respectively. It also contains the qeffiles to build and install all the components and read.me files to explain everything. The qvrs files are all annotated to explain the various commands and settings. This simple system should be examined as a prototype for bigger sub-projects.

The dirsetup dir-set qeglibeg contains the qeffiles, qvrs files, and the source for three libraries, each built using a different directory architecture. To extract these prototypes, use:

    % dirsetup -d libeg qeglibeg
The three architectures are:
flat In the flat scheme a single directory lib contains the source and the controls to build the regular and shared versions of the library. The debugging and profiling versions of the library are built in sibling directories in which the @SrcPath is modified to splice in the lib directory. This is a typical structure for small to medium sized libraries.
nested This is similar to the flat scheme except that the debugging and profiling directories are sub-directories of lib. The qeffile in lib contains the following:
    if ! @(option NO_DEBUGLIBS) && ! @(option DEBUGGING)
	subdir -IL glib
    fi
    if ! @(option NO_PROFLIBS)
	subdir -IL plib
    fi
to invoke the builds in the debugging and profiling directories, given that the suppressing options are not set. These schemes can be used in the same places as the flat scheme, but its major use is for situations where there are lots of sibling library directories and the creation of debugging and profiling directories at the same level would create an overly crowded directory.
merge The merge architecture is used for large, if not huge, libraries in which the source is partitioned into multiple sub-directories. Each directory's qeffile compiles its source modules and creates a list of its object modules. The qeffile file in a merge directory then uses these object lists to create the standard, debugging, and profiling libraries. An optional extension is to allow the specification of a master library that is also combined with the local modules to create the new library. This scheme has the advantage that a developer need only build those subsets (i.e., sub-directories) in which changes are being made. The balance of the library is extracted from the production version maintained by the project administrator or librarian. The example given illustrates this architecture, albeit with a very small library, using a masterlibrary from the Q-Tree itself.
Summary
At this time you should be able to create simple qeffiles and the necessary qvrs files and project infrastructure. The balance of this guide is intended for the advanced user and project administrator and at this time can probably wait until you have accumulated some experience using QEF and its 214 tools.

c063.qh - 9.4 - 03/10/22 QEF Home The Guide's Table of Contents Previous Chapter Top Of Page Next Chapter