Files
create/docs/src/development/gui-build-integration.md
forbes-0023 779e32e24a
All checks were successful
Build and Test / build (pull_request) Successful in 1h20m55s
docs(dev): Gui module build integration
Covers FreeCADGui target definition, dependency chain (fastsignals,
Qt6, Coin3D, PySide6, PyCXX), source file organisation and how to
add new files, theme/stylesheet build-time copying, version constants,
precompiled headers, CMake presets, ccache, and pixi tasks.

Closes #138
2026-02-10 08:36:50 -06:00

8.1 KiB

Gui Module Build Integration

The FreeCADGui shared library is the main GUI module. It contains the origin system, toolbar widgets, 3D viewport, command dispatch, and the Python bridge layer. This page explains how it is built, what it links against, and how to add new source files.

Target overview

add_library(FreeCADGui SHARED)

Built when BUILD_GUI=ON (the default). The output is a shared library installed to ${CMAKE_INSTALL_LIBDIR}.

CMake file: src/Gui/CMakeLists.txt

Dependency chain

FreeCADGui (SHARED)
├── FreeCADApp              (core application module)
├── libfastsignals          (STATIC, from src/3rdParty/FastSignals/)
├── Qt6::Core, Widgets, OpenGL, OpenGLWidgets, Network,
│   PrintSupport, Svg, SvgWidgets, UiTools, Xml
├── Coin3D / Quarter        (3D scene graph)
├── PySide6 / Shiboken6     (Python-Qt bridge, if FREECAD_USE_PYSIDE=ON)
├── PyCXX                   (C++-Python interop, header-only)
├── Boost                   (various components)
├── OpenGL
├── yaml-cpp
├── ICU                     (Unicode)
└── (optional) 3Dconnexion, Tracy profiler, VR

fastsignals

fastsignals is built as a static library with position-independent code:

src/3rdParty/FastSignals/
└── libfastsignals/
    ├── CMakeLists.txt        # builds libfastsignals.a (STATIC, -fPIC)
    ├── include/fastsignals/  # public headers (INTERFACE include dir)
    └── src/                  # implementation

Linked into FreeCADGui via:

target_link_libraries(FreeCADGui ... libfastsignals ...)
target_include_directories(FreeCADGui SYSTEM PRIVATE ${FastSignals_INCLUDE_DIRS})

The fastsignals/signal.h header is also included in src/Gui/PreCompiled.h so it is available without explicit #include in any Gui source file.

Source file organisation

Source files are grouped into named blocks in CMakeLists.txt. Each group becomes a Visual Studio filter / IDE source group.

Group variable Contains Origin system files in this group
Command_CPP_SRCS Command classes CommandOrigin.cpp
Widget_CPP_SRCS Toolbar/dock widgets OriginSelectorWidget.h/.cpp
Workbench_CPP_SRCS Workbench infrastructure OriginManager.h/.cpp, OriginManagerDialog.h/.cpp
FreeCADGui_CPP_SRCS Core Gui classes FileOrigin.h/.cpp, FileOriginPython.h/.cpp

All groups are collected into FreeCADGui_SRCS and added to the target:

target_sources(FreeCADGui PRIVATE ${FreeCADGui_SRCS})

Adding new source files

  1. Create your .h and .cpp files in src/Gui/.

  2. Add them to the appropriate source group in src/Gui/CMakeLists.txt. For origin system code, follow the existing pattern:

    • Widget → Widget_CPP_SRCS
    • Command → Command_CPP_SRCS
    • Manager/infrastructure → Workbench_CPP_SRCS
    • Core class → FreeCADGui_CPP_SRCS
    SET(FreeCADGui_CPP_SRCS
        ...
        MyNewOrigin.cpp
        MyNewOrigin.h
        ...
    )
    
  3. If the file has a Q_OBJECT macro, CMake's AUTOMOC handles MOC generation automatically. No manual steps needed.

  4. If adding Python bindings via PyCXX, add the .pyi stub and register it:

    generate_from_py(MyNewOrigin)
    
  5. If linking a new external library:

    list(APPEND FreeCADGui_LIBS MyNewLibrary)
    
  6. Reconfigure and build:

    pixi run configure
    pixi run build
    

No changes are needed to CommandOrigin.cpp, OriginSelectorWidget.cpp, or Workbench.cpp when adding a new origin — those modules discover origins dynamically through OriginManager at runtime.

Qt integration

Modules linked

QtCore, QtWidgets, QtOpenGL, QtOpenGLWidgets, QtPrintSupport, QtSvg, QtSvgWidgets, QtNetwork, QtUiTools, QtXml. Qt version >=6.8,<6.9 is specified in pixi.toml.

MOC (Meta Object Compiler)

Handled automatically by CMake's AUTOMOC for any header containing Q_OBJECT. Exception: GraphvizView has manual MOC commands due to moc-from-cpp requirements.

UI files

~100 .ui files are compiled by Qt's uic into C++ headers. Declared in the Gui_UIC_SRCS block.

Resources

Icons are embedded via Icons/resource.qrc. Translations use Qt Linguist (.ts.qm) with auto-generated resource files.

Theme and stylesheet build

Stylesheets are copied, not compiled. The canonical stylesheet is src/Gui/Stylesheets/KindredCreate.qss.

src/Gui/Stylesheets/CMakeLists.txt defines a custom target that copies .qss files and SVG/PNG images to the build tree:

fc_copy_sources(Stylesheets_data
    "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_DATADIR}/Gui/Stylesheets"
    ${Stylesheets_Files} ${Images_Files} ...)

src/Gui/PreferencePacks/CMakeLists.txt copies the same stylesheet into the preference pack directory using configure_file(... COPYONLY), avoiding a duplicate source:

configure_file(
    ${CMAKE_CURRENT_SOURCE_DIR}/../Stylesheets/KindredCreate.qss
    ${CMAKE_BINARY_DIR}/.../PreferencePacks/KindredCreate/KindredCreate.qss
    COPYONLY)

Edit only the canonical file in Stylesheets/ — the preference pack copy is generated.

Version constants

Defined in the top-level CMakeLists.txt and injected as compiler definitions:

set(KINDRED_CREATE_VERSION "0.1.0")
set(FREECAD_VERSION "1.0.0")

add_definitions(-DKINDRED_CREATE_VERSION="${KINDRED_CREATE_VERSION}")
add_definitions(-DFREECAD_VERSION="${FREECAD_VERSION}")

Available in C++ code as preprocessor macros. The Python update checker uses version.py generated from version.py.in at build time with configure_file().

Precompiled headers

Controlled by FREECAD_USE_PCH (off by default in conda builds):

if(FREECAD_USE_PCH)
    target_precompile_headers(FreeCADGui PRIVATE
        $<$<COMPILE_LANGUAGE:CXX>:"PreCompiled.h">)
endif()

PreCompiled.h includes <fastsignals/signal.h>, all Qt headers (via QtAll.h), Coin3D headers, Boost, and Xerces. QSint and Quarter sources are excluded from PCH via SKIP_PRECOMPILE_HEADERS.

Build presets

Defined in CMakePresets.json:

Preset Platform Build type
conda-linux-debug Linux Debug
conda-linux-release Linux Release
conda-macos-debug macOS Debug
conda-macos-release macOS Release
conda-windows-debug Windows Debug
conda-windows-release Windows Release

All presets use the conda/pixi environment for dependency resolution.

ccache

Enabled by default (FREECAD_USE_CCACHE=ON). CMake searches the system PATH for ccache at configure time and sets it as the compiler launcher:

set(CMAKE_C_COMPILER_LAUNCHER "${CCACHE_PROGRAM}")
set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_PROGRAM}")

Disable with -DFREECAD_USE_CCACHE=OFF if needed. Clear the cache with ccache -C.

Pixi tasks

Common build workflow:

pixi run initialize    # git submodule update --init --recursive
pixi run configure     # cmake --preset conda-linux-debug (or platform equivalent)
pixi run build         # cmake --build build/debug
pixi run install       # cmake --install build/debug
pixi run freecad       # launch the built binary
pixi run test-kindred  # run Kindred addon tests (no build needed)

Release variants: configure-release, build-release, install-release, freecad-release.

Key CMake variables

Variable Default Effect
BUILD_GUI ON Build FreeCADGui at all
FREECAD_USE_CCACHE ON Compiler caching
FREECAD_USE_PCH OFF (conda) Precompiled headers
FREECAD_USE_PYSIDE auto PySide6 Python-Qt bridge
FREECAD_USE_SHIBOKEN auto Shiboken6 binding generator
BUILD_VR OFF Oculus VR support
BUILD_TRACY_FRAME_PROFILER OFF Tracy profiler integration

See also