Project structure: pitfalls to avoid

I Love Xbase++ (ILX)
The portal for Xbase++ developers worldwide

Till Warweg

Staff member
I am here to help you!
Feb 1, 2021
Customer Identifier
The following is a list of structural issues which should be avoided in a project.

Pitfall: using the same source in multiple targets

This kind of setup is often found in projects using one or more "global" source files containing functionality which is used throughout the project like, for example, a function for connecting to the database server.

Problems: making changes in such a file affects several targets, which all must be rebuilt for consistency. Once the changed file has been compiled and linked into the current target, the file may appear to be unchanged for the other targets. This typically requires rebuilding everything in order to keep the project consistent. Also, in such a scenario it is impossible to determine which version of the file was used for building a given binary (.exe or .dll).

Solution: Put shared source files in a separate DLL which can be used to in other targets. Use the DEPENDS_ON= define to declare such inter-target dependencies.

Pitfall: sources are scattered over several folders and/or drives

Some projects use a complex folder structure which sometimes even spans multiple drives. Often in these projects, the project file (.xpj) is located in a sub-directory of the project tree, yielding a structure similar to this:

<project dir>
 - <source dir>
     - prg #1
     - prg #2
     - ...
 - <target dir>
     - project.xpj
     - ...

Problems: Projects with such a setup can only be maintained by developers with suitable knowledge. For example, relocating the project to another folder is impossible unless the specific requirements and dependencies are known to the person performing the move. Many changes are required because of absolute paths often being used in such projects, in particular when addressing files on other drives.

The batch files or custom build rules (PRE_BUILD, POST_BUILD) which are often used in projects of this kind for making binaries and files available to other targets in the project also increase the complexity of the build process. This causes a steep learning curve for new recruits and a high dependency on the local infrastructure. Also, such a project structure is hard to visualize and maintain and hence is not supported in the Xbase++ Workbench.

Solution: Use a flat folder structure where all parts of the project reside in sub-folders. Use the TARGET_DIR= define to specify the folder your target binaries must be copied to in order for the project to run.

The ideal project structure​

Ideally, a project should use

A flat folder hierarchy with all parts of the project located in sub-folders of the project root

This ensures that relative paths can be used for all files and that the project folder can be moved without hassle.

The DEPENDS_ON= define for specifying inter-target dependencies

This allows pbuild.exe to automatically track dependencies and to build targets in the required order. This ensures rebuilding the whole project is no longer necessary.

The TARGET_DIR= define for specifying the folder containing the files required for execution

This reduces the number of custom build rules and instead relies on functionality automatically provided by the project builder (pbuild.exe)

Source files which are used only in a single target. If functionality is used by multiple targets, this functionality should be made available in a separate DLL which can be included/linked to

This ensures that pbuild.exe can correctly compute dependencies and only builds the targets which are affected by a change. This way, it is always clear which version of a source file was used for building a given binary. If a shared file is changed, these changes are automatically available to all targets.

Such a project set-up ensures full support by pbuild.exe and the Xbase++ Workbench.


The following diagram compares two incarnations of the same project: the original project containing the pitfalls outlined above (left-hand side), and the corrected version (right-hand side).

Last edited: