******************
Creating Workflows
******************

This project uses three layers of SCons configuration files:

1. SConstruct: the project configuration
2. Workflow SConscript: named after the workflow or simulation, e.g. ``rectangle_compression``
3. Part/Assembly/Simulation SConscript: named after the re-usable task(s) purpose,
   e.g. when creating a part use the part name ``rectangle``

There is one, and only one, SConstruct file, which is located in the project root directory. The project convention is
to place SConscript files in the project root directory. If SConscript files are relocated, the workflow configuration
unpacking for loop in the SConstruct file must be updated to accommodate the file structure change. Every SConscript
file must contain a module level docstring that describes the import/return requirements of that SConscript file. When
updating or adding a new workflow, be sure to update the SConscript docstring to match any requirement changes.

SConstruct
==========

The project configuration SConstruct file is responsible for configuring project wide variables, command line options,
construction environment(s), and workflows. The SConstruct file is reponsible for calling workflow SConscript files with
the workflow's construction environment

.. code-block::

   SConscript(..., exports={"env": env, ...}, ...)

and a unique build directory. By project convention, there is one workflow SConscript file per workflow, so the workflow
SConscript file is used as the build directory name. The SConscript calls are constructed in the
``workflow_configurations`` variable as a list of workflow SConscript file names.

.. admonition:: SConstruct

    .. literalinclude:: SConstruct.txt
       :language: Python
       :lineno-match:
       :start-after: workflow-configurations-start-do-not-remove
       :end-before: workflow-configurations-start-do-not-remove

Because the project assumes that SConscript files are located in the project root, the logic contained in this workflow
configuration loop must be updated if the SConscript files are relocated. The only contraints placed by the project
design is the construction of a unique build directory for every iteration of the for loop.

Workflow SConscript
===================

The workflow configuration SConscript files are named after the workflow, simulation, or assembly that they configure.
They are responsible for defining the workflow parameters and for adding targets to the workflow alias(es). The project
convention is to construct the workflow alias from the build directory supplied by the SConstruct file. The workflow
files should call SConscript files defining the re-usable portions of the workflow, such as parts and assembly
configuration, and may optionally define workflow specific tasks. The workflow configuration files pass the ``env``, and
``parameters`` through to the part or assembly SConscript files. Any task definitions must unpack the workflow
``parameters`` variable.

.. code-block::

   Import("env")

   build_directory = pathlib.Path(Dir(".").abspath)
   workflow_name = build_directory.name

   parameters = {parameter: value, ...}

   SConscript(..., exports={"env": env, "parameters": parameters, ...}, ...)

   env.Command(
       target=[...],
       source=[...],
       action=[...],
       **parameters,
   )

   env.Alias(workflow_name, targets)

Part/Assembly/Simulation SConscript
===================================

The final layer of SConscript files consists of re-usable task definitions. Most commonly, these contain part (or
assembly) configuration files. This layer may also include any re-usable tasks if there are common simulation or
post-processing task definitions that can be shared between workflows. These configuration files should accept the
construction environment ``env`` and workflow ``parameters``. The parameters should be unpacked into the part task
definitions. These files may optionally return a list of target artifacts for the parent workflow SConscript file to use
in alias definitions.

.. code-block::

   Import("env", "parameters")

   env.Command(
       target=[...],
       source=[...],
       action=[...],
       **parameters,
   )

   Return("artifacts")
