2012-01-11 06:56:37 +01:00
|
|
|
SCons Build-System
|
|
|
|
|
==================
|
|
|
|
|
:author: Ichthyo
|
|
|
|
|
:date: 2012
|
|
|
|
|
|
|
|
|
|
//MENU: label SCons Build
|
|
|
|
|
|
2025-09-02 19:42:49 +02:00
|
|
|
Lumiera uses a build system based on https://scons.org/[SCons]
|
2012-01-11 06:56:37 +01:00
|
|
|
|
|
|
|
|
SCons is an open source software construction tool based on Python build definition scripts.
|
|
|
|
|
Within these build scripts, we define a data structure to describe the parts and dependencies
|
|
|
|
|
of our software. When executed, SCons evaluates those definitions and the actual files in
|
|
|
|
|
the source tree to derive a build strategy, which is then performed.
|
|
|
|
|
|
|
|
|
|
SCons core concepts
|
|
|
|
|
-------------------
|
2025-09-02 19:42:49 +02:00
|
|
|
^_this section is based on the introductory pages on the https://github.com/SCons/scons/wiki/BasicConcepts[SCons Wiki]_^
|
2012-01-11 06:56:37 +01:00
|
|
|
|
|
|
|
|
.SCons Environment
|
|
|
|
|
When SCons starts building the project, it creates its own environment with dependency trees,
|
|
|
|
|
helper functions, builders and other stuff. The SCons environment is created in memory and some parts of it
|
|
|
|
|
are saved to disk to speed up things on the next start. The definition of the build happens within this
|
|
|
|
|
artificial build environment. This often confuses people who used Makefiles, where environment is actually
|
|
|
|
|
the System Environment.
|
|
|
|
|
|
|
|
|
|
.System Environment
|
|
|
|
|
the familiar operating system container with environment variables such as PATH, HOME etc.
|
|
|
|
|
It is usually accessible via os.environ mapping in Python and therefore in SCons too.
|
|
|
|
|
SCons doesn't import any settings from System Environment automatically (like flags for compilers,
|
|
|
|
|
or paths for tools), because it's designed to be a cross platform tool with _predictable behaviour._
|
|
|
|
|
That's why, if you rely on any system PATHs or environment variables -- you need to extract
|
|
|
|
|
those settings explicitly in your build definition.
|
|
|
|
|
|
|
|
|
|
.SConstruct
|
2025-06-07 23:59:57 +02:00
|
|
|
when SCons executes, it performs a build definition python script written by the user.
|
2012-01-11 06:56:37 +01:00
|
|
|
By convention, this main script is called 'SConstruct' and is located in the root of the source tree.
|
|
|
|
|
It is a full featured Python module executed within a specifically prepared environment.
|
|
|
|
|
|
|
|
|
|
.SConscript
|
|
|
|
|
these files are also SCons scripts, but they are placed in subdirectories of the project.
|
|
|
|
|
Typically they are used to organize hierarchical builds and are included from the main SConstruct file
|
|
|
|
|
from the project root. Often, all of the actual build definitions reside in SConscript files in
|
|
|
|
|
the sub-trees of the project.
|
|
|
|
|
|
|
|
|
|
.Builder
|
|
|
|
|
The SCons buildsystem revolves around the metaphor of a _Builder_. This is a SCons object that you explicitly
|
|
|
|
|
invoke from the scripts to _define_ that there is something to build, transforming a _source_ into a _target_.
|
|
|
|
|
So the target depends on the sources, and typically those _source nodes_ were created by previous builder invocations.
|
2025-06-07 23:59:57 +02:00
|
|
|
The power of SCons is in the fact that dependencies are tracked automatically. When source files change, the system
|
2012-01-11 06:56:37 +01:00
|
|
|
is able to derive which targets to rebuild.
|
|
|
|
|
|
|
|
|
|
.Scanner
|
|
|
|
|
when defining a builder, SCons relies on modular scanner components to ``understand'' the source of the build step.
|
|
|
|
|
They may scan source files to discover additional dependencies referenced inside. Thus, SCons comes with built-in
|
|
|
|
|
knowledge about the source files and artefacts to be created by a typical build, and further types can be added
|
|
|
|
|
through plug-ins.
|
|
|
|
|
|
|
|
|
|
.Tool
|
|
|
|
|
any further, external component that adds Builders, Scanners and other helpers to SCons environments
|
|
|
|
|
for use within scripts. There are special tools for _configuring the platform_ to detect libraries and
|
|
|
|
|
further requirements. Relying on those tools. the build environment will be outfitted to reflect the
|
|
|
|
|
needs of the specific build. Sub-environments with special configuration may be created.
|
|
|
|
|
|
|
|
|
|
.Target
|
|
|
|
|
any _node_ or ``build step'' encountered through the definition of the build is a _target_. The actual build
|
|
|
|
|
will be triggered by requesting a target, which typically might be just an executable known to reside at some
|
|
|
|
|
location in the tree. Special _alias targets_ may be defined, based on other targets, to trigger off standard
|
|
|
|
|
build situations. Especially, a _default_ target may be defined.
|
|
|
|
|
|
|
|
|
|
''''
|
|
|
|
|
|
|
|
|
|
Organisation of the Lumiera SCons build
|
|
|
|
|
---------------------------------------
|
2014-10-01 01:19:56 +02:00
|
|
|
Within our build system, we build upon the power of the Python programming language to create abstractions
|
|
|
|
|
tailored to the needs of our project. Located in the `admin/scons` subdirectory, you'll find a collection
|
|
|
|
|
of Python modules to provide these building blocks.
|
2012-01-11 06:56:37 +01:00
|
|
|
|
|
|
|
|
- the *LumieraEnvironment* is created as a subclass of the standard SCons build environment; it is
|
|
|
|
|
outfitted with pre-configured custom builders for executables, libraries, extension module, Lumiera plug-in
|
|
|
|
|
and icon resources.
|
|
|
|
|
- all these *custom builders* implement a set of conventions and directory locations within the tree.
|
|
|
|
|
These are defined (and can be adjusted) in the *Setup.py* module. This way, each builder automatically
|
|
|
|
|
places the generated artefacts at standard build and installation locations.
|
|
|
|
|
- for defining individual targets and builder invocations, we rely on *build helpers* to process whole
|
|
|
|
|
*source sub trees* rather than individual files. Mostly, just placing a source file into the appropriate
|
|
|
|
|
sub tree is sufficient to get it compiled, linked and installed in a standard way.
|
|
|
|
|
|
|
|
|
|
Sub-trees
|
|
|
|
|
~~~~~~~~~
|
|
|
|
|
.the source tree
|
|
|
|
|
All sourcecode of the core application resides below `src/`. Building these components is controlled by
|
|
|
|
|
the SConscript residing in this application source root. By convention, this is also the root for header
|
|
|
|
|
includes -- _all headers should be included relative_ to `src/`.
|
|
|
|
|
|
|
|
|
|
.the three layers
|
|
|
|
|
Within this application core tree, there are sub-trees for the main layers comprising the application.
|
|
|
|
|
Each of these sub-trees will be built into a shared library and then linked against the application framework
|
2014-10-01 01:19:56 +02:00
|
|
|
and common services residing in `src/common`. These common services in turn are also built into a shared
|
|
|
|
|
library `liblumieracommon.so`, as is the collection of helper classes and support facilities, known as
|
|
|
|
|
our 'support library' `liblumierasupport.so`. Besides, there is a sub-tree for core plug-ins and helper tools.
|
2012-01-11 06:56:37 +01:00
|
|
|
|
|
|
|
|
.the GTK Gui
|
2018-11-16 22:38:29 +01:00
|
|
|
one of the sub-trees, residing in `src/stage` forms the _upper layer_ or _user-interaction layer_. Contrary to
|
|
|
|
|
the lower layers, the Stage Layer (GUI) is _optional_ and the application is fully operational _without GUI._
|
|
|
|
|
Thus, the GTK Gui is built and loaded as Lumiera a plug-in.
|
2012-01-11 06:56:37 +01:00
|
|
|
|
|
|
|
|
.unit tests
|
2015-05-27 04:01:09 +02:00
|
|
|
Since our development is test-driven, about half of the overall code can be found in unit- and integration
|
|
|
|
|
tests, residing below `test/`. There is a separate SConscript file, to define the various
|
|
|
|
|
link:{ldoc}/technical/infra/TestSupport.html[kinds of test artefacts] to be created.
|
2012-01-11 06:56:37 +01:00
|
|
|
|
|
|
|
|
- plain-C tests are defined in _test-collections_, grouped thematically into several subdirectories.
|
|
|
|
|
Here, each translation unit provides a separate +main()+ function and is linked into a stand-alone
|
|
|
|
|
executable (yet still linked against the appropriate shared libraries of the main application layers)
|
|
|
|
|
- the tests covering C++ components are organised into test-suites, residing in separate sub-trees.
|
2015-05-27 04:01:09 +02:00
|
|
|
Currently (as of 5/2015), we link each sub-tree into a shared test library. Here
|
|
|
|
|
individual translation units define individual test case classes. At the end, all these unit tests
|
|
|
|
|
are linked together with a testrunner `main()` into the `test-suite` executable.
|
2012-01-11 06:56:37 +01:00
|
|
|
|
|
|
|
|
.research
|
|
|
|
|
There is a separate subtree for research and experiments. The rationale being to avoid re-building most
|
|
|
|
|
of the core application when it comes to experimenting and trying out new technologies.
|
|
|
|
|
|
|
|
|
|
.icons and resources
|
2018-11-16 22:38:29 +01:00
|
|
|
the +data/+ subtree holds resources, configuration files and icons for the GUI. Most of our icons
|
2012-01-11 06:56:37 +01:00
|
|
|
are defined as SVG graphics. The build process creates a helper executable (+rsvg_convert+) to render
|
|
|
|
|
these vector graphics with the help of lib Cairo into icon collections of various sizes.
|
|
|
|
|
|
|
|
|
|
.documentation
|
2025-09-02 19:42:49 +02:00
|
|
|
Largely, the documentation is written in Asciidoc and provided online at link:{ldoc}/[the documentation section]
|
2012-01-11 06:56:37 +01:00
|
|
|
of our website. The plain-text sources of this documentation tree is shipped alongside with the code.
|
|
|
|
|
Besides, we build *Doxygen* API documentation there, and we create design and technical specs and drawings
|
|
|
|
|
in SVG and in UML.
|
|
|
|
|
|
|
|
|
|
.the target directory
|
|
|
|
|
This is where the results of the build process are created. Lumiera is organised into a
|
2025-06-07 23:59:57 +02:00
|
|
|
_self contained folder structure_. As long as the relative locations, as found within +target/+,
|
2012-01-11 06:56:37 +01:00
|
|
|
are kept intact, the Application will be able to start up and find all its resources. Consequently,
|
|
|
|
|
there is no need to ``install'' Lumiera (and the ``install'' target just copies this folder structure
|
|
|
|
|
into the standard installation locations of a typical Unix system)
|
|
|
|
|
|
2014-10-01 01:19:56 +02:00
|
|
|
Unfortunately SCons is a bit weird regarding the object files created during the build process.
|
|
|
|
|
So, for the time being, we're just building in-tree. Apologies for that.
|
2012-01-11 06:56:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
Invoking the Build
|
|
|
|
|
~~~~~~~~~~~~~~~~~~
|
2025-06-07 23:59:57 +02:00
|
|
|
All of the build process is launched through the `scons` python script, usually installed into
|
2012-01-11 06:56:37 +01:00
|
|
|
`/usr/bin` when installing the SCons package onto the system. Just invoking
|
|
|
|
|
|
|
|
|
|
scons -h
|
2025-06-07 23:59:57 +02:00
|
|
|
|
2012-01-11 06:56:37 +01:00
|
|
|
prints a summary of all custom options, targets and toggles defined for our build.
|
|
|
|
|
|
|
|
|
|
Targets
|
|
|
|
|
^^^^^^^
|
2018-11-16 22:38:29 +01:00
|
|
|
- *build* is the default target: it creates the shared libs, the application, core plug-ins and the GUI.
|
2014-10-01 01:19:56 +02:00
|
|
|
- *testcode* additionally builds the research and unit test code
|
|
|
|
|
- *check* builds test code and runs our test-suites
|
2012-01-11 06:56:37 +01:00
|
|
|
- *research* builds just the research tree
|
|
|
|
|
- *doc* builds documentation (currently just Doxygen)
|
2014-10-01 01:19:56 +02:00
|
|
|
- *all* builds the Application, test-suites and documentation
|
2012-01-11 06:56:37 +01:00
|
|
|
- *install* builds and installs the Lumiera Application
|
|
|
|
|
|
2014-10-01 01:19:56 +02:00
|
|
|
By convention, invoking `scons -c` <TARGET> will _clean up_ everything the given target _would_ build.
|
|
|
|
|
Thus, invoking `scons -c /` is the most global clean operation: it will clean up al build artefacts and
|
2012-01-11 06:56:37 +01:00
|
|
|
will un-install Lumiera (recall: every defined node, or directory is also a target).
|
|
|
|
|
|
|
|
|
|
Configure checks
|
|
|
|
|
^^^^^^^^^^^^^^^^
|
2014-10-01 01:19:56 +02:00
|
|
|
SCons does not support the concept of a separate ``configure'' step. The necessary dependency detection is
|
|
|
|
|
performed before each build. Currently, we expect _all dependencies to be installed first-class_ into
|
|
|
|
|
the system. We do not (yet) support custom libraries in strange locations. Please use your package manager.
|
2012-01-11 06:56:37 +01:00
|
|
|
|
|
|
|
|
Caching and MD5 sums
|
|
|
|
|
^^^^^^^^^^^^^^^^^^^^
|
|
|
|
|
SCons stores MD5 sums of all source files, all configure checks and all the command lines used
|
|
|
|
|
to invoke compilers and external tools. The decision, what needs to be rebuilt is based entirely
|
|
|
|
|
on these checksums. For one, this means that configure checks are re-run only when necessary.
|
|
|
|
|
It also means that changes to some compiler switches will automatically cause all affected parts
|
|
|
|
|
of the application to be re-built. And of course it means, that you only ever compile what is
|
|
|
|
|
necessary.
|
|
|
|
|
|
2014-10-01 01:19:56 +02:00
|
|
|
With SCons, there is no need for the usual ``cleaning paranoia''. Similarly, there is no need
|
|
|
|
|
for CCache (but using DistCC rocks !). Unfortunately, calculating those MD5 sums requires some
|
2012-01-11 06:56:37 +01:00
|
|
|
time on each build, even if the net result is that nothing will happen at all.
|
|
|
|
|
|
|
|
|
|
Configuration options
|
|
|
|
|
^^^^^^^^^^^^^^^^^^^^^
|
2014-10-01 01:19:56 +02:00
|
|
|
We provide several custom configuration options (run `scons -h` to get a summary). All of these
|
2012-01-11 06:56:37 +01:00
|
|
|
options are *sticky*: once set, the build system will recall them in a file '.optcache' and apply
|
|
|
|
|
them the same way in subsequent builds. It is fine to edit '.optcache' with a text editor.
|
|
|
|
|
|