CMake Configuration
The COMPAS ShapeOp extension is built with CMake, which configures and generates the C++ build system. The main CMakeLists.txt file contains all the necessary configuration to build the ShapeOp library and its Python bindings.
Project Structure
The CMake configuration is organized as follows:
Basic project configuration and compiler options
Dependency handling (Eigen, nanobind, OpenMP)
ShapeOp library compilation
Precompiled headers setup
Python module definition and linking
Build Options
The CMakeLists.txt file provides several options to customize the build:
option(ENABLE_PRECOMPILED_HEADERS "Enable precompiled headers" ON)
option(FAST_COMPILE "Optimize for faster compilation (-O0) vs execution (-O3)" OFF)
option(USE_OPENMP "Enable OpenMP support for parallel processing" ON)
ENABLE_PRECOMPILED_HEADERS: Enable precompiled headers for faster compilation (default: ON)FAST_COMPILE: Optimize for faster compilation time with -O0 instead of faster execution with -O3 (default: OFF)USE_OPENMP: Enable OpenMP for parallel constraint solving (default: ON)
Dependencies
The project has several external dependencies:
Eigen: A header-only C++ library for linear algebra that is automatically downloaded if not already installed
nanobind: A lightweight library for creating Python bindings, used to expose the C++ ShapeOp implementation to Python
OpenMP: An optional dependency for parallel processing, which significantly improves performance for large meshes
ShapeOp Library
The core ShapeOp library is built as a static library:
add_library(shapeop STATIC
# Core ShapeOp files
${SHAPEOP_SRC_DIR}/Constraint.cpp
${SHAPEOP_SRC_DIR}/Force.cpp
${SHAPEOP_SRC_DIR}/LSSolver.cpp
${SHAPEOP_SRC_DIR}/Solver.cpp
# Custom constraints/forces
${SHAPEOP_SRC_DIR}/custom_constraints/normalforce.cpp
)
This library contains both the core ShapeOp implementation and custom constraints/forces specific to COMPAS ShapeOp.
Python Module
The Python module is built using nanobind:
nanobind_add_module(
_shapeop
STABLE_ABI
NB_STATIC
src/shapeop.cpp
)
The module is named _shapeop and is linked against the ShapeOp static library. It uses the stable ABI to ensure compatibility across Python versions.
Installation
The installation target installs the module to the compas_shapeop package directory:
install(TARGETS _shapeop LIBRARY DESTINATION compas_shapeop)
This allows the Python frontend to import the C++ module as from compas_shapeop import _shapeop.
Adding New Constraints or Forces
To add a new constraint or force:
Add the C++ implementation to
src/shapeop/orsrc/shapeop/custom_constraints/Add the file to the
shapeoplibrary inCMakeLists.txtExpose the new constraint/force in
src/shapeop.cppCreate a Python wrapper in
src/compas_shapeop/shapeop.py
Build Process
The build process is handled by scikit-build-core, which manages the CMake configuration and build process during Python package installation. When you run pip install -e ., scikit-build-core automatically:
Runs CMake to configure the build
Builds the C++ extension
Installs it alongside the Python files