(guide_project_integration)=
Project and Build System Integration
(config_module)=
Project-Wide Settings using Configuration Modules
When embedding pystencils-sfg into a C++ project or build system, you might want to set a project-wide base configuration for all generator scripts. In addition, it might be necessary to pass various details about the project and build setup to the generator scripts. Both can be achieved by the use of a configuration module.
A configuration module is a Python file that defines up to two functions:
-
def configure_sfg(cfg: SfgConfig)
is called to set up the project-wide base configuration. It takes an {any}SfgConfig
object which it may modify to establish the project-wide option set. -
def project_info() -> Any
is called by pystencils-sfg to retrieve an object that encapsulates any custom project-specific information. This information is passed on to the generator scripts through the {any}sfg.context.project_info <SfgContext.project_info>
attribute.
An example configuration module might look like this:
from pystencilssfg import SfgConfig
def configure_sfg(cfg: SfgConfig):
cfg.extensions.header = "h++"
cfg.extensions.impl = "c++"
cfg.clang_format.code_style = "llvm"
...
def project_info():
return {
"project_name": "my-project",
"float_precision": "float32",
"use_cuda": False,
...
}
Here, project_info
returns a dictionary, but this is just for illustration;
the function may return any type of arbitrarily complex objects.
For improved API safety, {any}dataclasses
might be a good tool for setting up
project info objects.
When invoking a generator script, the path to the current configuration module must be passed to it
using the --sfg-config-module
command-line parameter.
This can be automated by an adequately set up build system, such as GNU Make or CMake.
If you are using pystencils-sfg with CMake through the provided CMake module, see below on how to specify a configuration module for your project.
(cmake_integration)=
CMake Integration
pystencils-sfg is shipped with a CMake module for on-the-fly code generation during the CMake build process.
Add the module
To include the module in your CMake source tree, you must first add the pystencils-sfg Find-module to your CMake module path. To create the Find-module, navigate to the directory it should be placed in and run the following command:
sfg-cli cmake make-find-module
This will create the FindPystencilsSfg.cmake
file.
Make sure that its containing directory is added to the CMake module path.
To load pystencils-sfg into CMake, we first need to set the Python interpreter of the environment SFG is installed in. There are several ways of doing this:
Set Python via a Find-Module Hint
Set the PystencilsSfg_PYTHON_PATH
hint variable inside your CMakeLists.txt
to point at the
Python executable which should be used to invoke pystencils-sfg, e.g.:
set(PystencilsSfg_PYTHON_PATH ${CMAKE_SOURCE_DIR}/.venv/bin/python)
This is the recommended way, especially when other parts of your project also use Python.
Set Python via a Cache Variable
On the command line or in a CMake configure preset,
set the PystencilsSfg_PYTHON_INTERPRETER
cache variable to point at the Python executable to be used to invoke pystencils-sfg;
e.g.:
cmake -S . -B build -DPystencilsSfg_PYTHON_INTERPRETER=`pwd`/.venv/bin/python
If both the cache variable and the PystencilsSfg_PYTHON_PATH
hint are set, the cache variable takes precedence,
so you can use the cache variable to override the hint.
Automatically Find a Python Installation
If none of the above is provided, pystencils-sfg will invoke FindPython
to determine the Python interpreter it should use.
You can affect this process through any of the hints listed in the FindPython
documentation.
Find pystencils-sfg
Finally, call find_package( PystencilsSfg )
from your CMakeLists.txt
to load the SFG module.
If SFG as a dependency is not optional, add the REQUIRED
flag such that the call will fail if
the package cannot be found.
(cmake_add_generator_scripts)=
Adding Generator Scripts
The primary interaction point in CMake is the function pystencilssfg_generate_target_sources
,
with the following signature:
pystencilssfg_generate_target_sources( <target>
SCRIPTS script1.py [script2.py ...]
[SCRIPT_ARGS arg1 [arg2 ...]]
[DEPENDS dependency1.py [dependency2.py...]]
[FILE_EXTENSIONS <header-extension> <impl-extension>]
[OUTPUT_MODE <standalone|inline|header-only>]
[CONFIG_MODULE <path-to-config-module.py>]
[OUTPUT_DIRECTORY <output-directory>]
)
It registers the generator scripts script1.py [script2.py ...]
to be executed at compile time using add_custom_command
and adds their output files to the specified <target>
.
Any changes in the generator scripts, or any listed dependency, will trigger regeneration.
The function takes the following options:
-
SCRIPTS
: A list of generator scripts -
SCRIPT_ARGS
: A list of custom command line arguments passed to the generator scripts; see -
DEPENDS
: A list of dependencies for the generator scripts -
FILE_EXTENSION
: The desired extensions for the generated files -
OUTPUT_MODE
: Sets the output mode of the code generator; see {any}SfgConfig.output_mode
. -
CONFIG_MODULE
: Set the configuration module for all scripts registered with this call. If set, this overrides the value ofPystencilsSfg_CONFIG_MODULE
in the current scope (see ) -
OUTPUT_DIRECTORY
: Custom output directory for generated files. IfOUTPUT_DIRECTORY
is a relative path, it will be interpreted relative to the current build directory.
If OUTPUT_DIRECTORY
is not specified, any C++ header files generated by the above call
can be included in any files belonging to target
via:
#include "gen/<file1.hpp>"
#include "gen/<file2.hpp>"
/* ... */
:::{attention}
If you change the code generator output directory using the OUTPUT_DIRECTORY
argument,
you are yourself responsible for placing that directory--or any of its parents--on the
include path of your target.
:::
(cmake_set_config_module)=
Set a Configuration Module
There are two ways of specifying a configuration module for generator scripts registered with CMake:
- To set a configuration module for scripts registered with a single call to
pystencilssfg_generate_target_sources
, use theCONFIG_MODULE
function parameter (see ). - To set a config module for all generator scripts within the current CMake directory and its subdirectories,
set the scoped variable
PystencilsSfg_CONFIG_MODULE
to point at the respective Python file, e.g.set( PystencilsSfg_CONFIG_MODULE ProjectConfig.py )
.
You might want to populate your configuration module with information about the current build setup and environment. For this purpose, take a look at the configure_file CMake function.