diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2d2ef573a582c83e5fdc273326b7111e2594cfeb..2003d01535c7a3869e8b482836d95f1c32d2c283 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -68,6 +68,9 @@ endif()
 
 # function definitions
 include(commons/GetFilenameComponent) # overwrite CMake command
+include(BornAgain/SwigLib)
+
+# main settings
 
 include(BornAgain/Directories)
 
diff --git a/cmake/BornAgain/SwigLib.cmake b/cmake/BornAgain/SwigLib.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..2d4b008bbb519fd7eb349bd2539143cf37cdce55
--- /dev/null
+++ b/cmake/BornAgain/SwigLib.cmake
@@ -0,0 +1,96 @@
+function(SwigLib name lib)
+
+    if(NOT BORNAGAIN_PYTHON)
+        return()
+    endif()
+
+    file(MAKE_DIRECTORY ${AUTO_DIR})
+
+    if(CONFIGURE_BINDINGS)
+
+        set(TMP_DIR ${CMAKE_CURRENT_BINARY_DIR}/Wrap)
+        file(MAKE_DIRECTORY ${TMP_DIR})
+
+        GeneratePythonDocs(${AUTO_DIR}/doxygen${name}.i ${WRAP_DIR}/swig)
+
+        set(swig_dependencies
+            ${WRAP_DIR}/swig/lib${lib}.i
+            ${WRAP_DIR}/swig/directors.i
+            ${WRAP_DIR}/swig/extend${name}.i
+            ${WRAP_DIR}/swig/ignores.i
+            ${WRAP_DIR}/swig/shared_pointers.i
+            ${WRAP_DIR}/swig/warnings.i
+            )
+        foreach(FNAM ${swig_dependencies})
+            if(NOT EXISTS ${FNAM})
+                message(FATAL_ERROR "Could NOT find SWIG input ${FNAM}")
+            endif()
+        endforeach()
+        list(APPEND swig_dependencies ${AUTO_DIR}/doxygen${name}.i)
+
+        set(SWIG_FLAGS "-c++;-python;-o;${AUTO_DIR}/lib${lib}_wrap.cpp;-outdir;${TMP_DIR}"
+                               ";-I${CMAKE_SOURCE_DIR};-I${CMAKE_BINARY_DIR}/inc")
+
+        add_custom_command(
+            OUTPUT ${AUTO_DIR}/lib${lib}.py
+            COMMAND ${Python3_EXECUTABLE} ${WRAP_DIR}/swig/tweaks.py
+                   ${TMP_DIR}/lib${lib}.py
+                   ${AUTO_DIR}/lib${lib}.py
+            DEPENDS ${TMP_DIR}/lib${lib}.py
+            )
+        add_custom_command(
+            OUTPUT ${TMP_DIR}/lib${lib}.py
+                   ${AUTO_DIR}/lib${lib}_wrap.h
+                   ${AUTO_DIR}/lib${lib}_wrap.cpp
+            COMMAND ${SWIG_EXECUTABLE} ${SWIG_FLAGS} ${WRAP_DIR}/swig/lib${lib}.i
+            DEPENDS ${swig_dependencies} ${include_files}
+            )
+
+    endif(CONFIGURE_BINDINGS)
+
+    add_custom_target(
+        ${lib}_python
+        COMMAND ${CMAKE_COMMAND}
+            -E copy ${AUTO_DIR}/lib${lib}.py ${CMAKE_BINARY_DIR}/lib/lib${lib}.py
+        COMMAND ${CMAKE_COMMAND}
+            -E copy ${AUTO_DIR}/lib${lib}.py ${CMAKE_BINARY_DIR}/lib/bornagain/lib${lib}.py
+        DEPENDS ${AUTO_DIR}/lib${lib}.py
+        )
+    add_dependencies(${lib} ${lib}_python)
+
+    if((CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
+            OR (CMAKE_CXX_COMPILER_ID STREQUAL "GNU"))
+        # suppress warnings from auto-generated code (last updated for Swig 4.0.1)
+        set_source_files_properties(${AUTO_DIR}/lib${lib}_wrap.cpp
+            PROPERTIES COMPILE_OPTIONS
+            "-Wno-unused-parameter;-Wno-missing-field-initializers;-Wno-sometimes-uninitialized;\
+-Wno-deprecated-declarations")
+    endif()
+
+    target_compile_definitions(${lib} PUBLIC -DBORNAGAIN_PYTHON)
+    target_include_directories(${lib} PUBLIC ${Python3_INCLUDE_DIRS} ${Python3_NumPy_INCLUDE_DIRS})
+    target_link_libraries(${lib} ${Python3_LIBRARIES})
+
+    install(FILES ${CMAKE_BINARY_DIR}/lib/lib${lib}.py
+        DESTINATION ${destination_lib} COMPONENT Libraries)
+
+    if(WIN32)
+        add_custom_command(
+            TARGET ${lib}
+            POST_BUILD
+            COMMAND ${CMAKE_COMMAND} -E copy
+            ${CMAKE_BINARY_DIR}/bin/${libprefix}${lib}${libsuffix}
+            ${CMAKE_BINARY_DIR}/lib/${libprefix}${lib}".pyd"
+            )
+        install(FILES ${CMAKE_BINARY_DIR}/lib/${libprefix}${lib}.pyd
+            DESTINATION ${destination_lib} COMPONENT Libraries)
+        add_custom_command(
+            TARGET ${lib}
+            POST_BUILD
+            COMMAND ${CMAKE_COMMAND} -E copy
+            ${CMAKE_BINARY_DIR}/bin/${libprefix}${lib}${libsuffix}
+            ${CMAKE_BINARY_DIR}/lib/${libprefix}${lib}${libsuffix}
+            )
+    endif()
+
+endfunction()