diff --git a/Applications/ApplicationsLib/CMakeLists.txt b/Applications/ApplicationsLib/CMakeLists.txt
index b4e25fcce00823533822eabe6ff7a846a60e8462..9da6fe882cc1ab7286a0facdf4da05e6c69a49dc 100644
--- a/Applications/ApplicationsLib/CMakeLists.txt
+++ b/Applications/ApplicationsLib/CMakeLists.txt
@@ -9,7 +9,12 @@ target_link_libraries(
     ApplicationsLib
     PUBLIC BaseLib GeoLib NumLib
            $<$<TARGET_EXISTS:VTK::ParallelMPI>:VTK::ParallelMPI>
-    PRIVATE CMakeInfoLib MathLib MeshLib MeshGeoToolsLib MeshToolsLib pybind11::pybind11
+    PRIVATE CMakeInfoLib
+            MathLib
+            MeshLib
+            MeshGeoToolsLib
+            MeshToolsLib
+            pybind11::pybind11
             $<$<BOOL:${OGS_USE_PETSC}>:PkgConfig::PETSC>
 )
 
@@ -18,7 +23,9 @@ if(OGS_BUILD_CLI OR OGS_BUILD_UTILS OR OGS_BUILD_TESTING)
         ApplicationsLib PUBLIC Processes PRIVATE ParameterLib ProcessLib
     )
 elseif(OGS_BUILD_GUI)
-    target_link_libraries(ApplicationsLib PRIVATE MeshToolsLib nlohmann_json::nlohmann_json)
+    target_link_libraries(
+        ApplicationsLib PRIVATE MeshToolsLib nlohmann_json::nlohmann_json
+    )
 endif()
 
 if(OGS_USE_LIS)
diff --git a/Applications/CMakeLists.txt b/Applications/CMakeLists.txt
index 2ff44d65b130328015b9dc074905a05d8e8eb662..f781271c4842ce922cc9c9deffaedd1e784ba97a 100644
--- a/Applications/CMakeLists.txt
+++ b/Applications/CMakeLists.txt
@@ -20,6 +20,4 @@ if(OGS_USE_INSITU)
     add_subdirectory(InSituLib)
 endif()
 
-if(OGS_BUILD_WHEEL)
-    add_subdirectory(Python)
-endif()
+add_subdirectory(Python)
diff --git a/Applications/Python/CMakeLists.txt b/Applications/Python/CMakeLists.txt
index 018b4afffc9caa749bc30862e31072d00ba5de71..06e3d7a9283a8fb12b87928f206856646506ebb4 100644
--- a/Applications/Python/CMakeLists.txt
+++ b/Applications/Python/CMakeLists.txt
@@ -1,3 +1,11 @@
+# wheel: Install into Python module root dir (enables 'import ogs.simulator')
+set(_py_install_location ogs)
+if(NOT OGS_BUILD_WHEEL)
+    set(_py_install_location
+        "${CMAKE_INSTALL_LIBDIR}/python${Python_VERSION_MAJOR}.${Python_VERSION_MINOR}/site-packages/ogs"
+    )
+endif()
+add_subdirectory(ogs)
 add_subdirectory(ogs.simulator)
 add_subdirectory(ogs.mesh)
 add_subdirectory(ogs.callbacks)
diff --git a/Applications/Python/ogs.callbacks/CMakeLists.txt b/Applications/Python/ogs.callbacks/CMakeLists.txt
index 67cc96bc550bf6a9598efb75c3cb2d9d7d396256..978b2a1e8e7c0f32d853cb409e6bd03f06ade82e 100644
--- a/Applications/Python/ogs.callbacks/CMakeLists.txt
+++ b/Applications/Python/ogs.callbacks/CMakeLists.txt
@@ -11,5 +11,4 @@ target_link_libraries(
     callbacks PRIVATE ProcessLibBoundaryConditionAndSourceTermPythonModule
 )
 
-# Install into Python module root dir (enables 'import ogs.callbacks')
-install(TARGETS callbacks LIBRARY DESTINATION ogs)
+install(TARGETS callbacks LIBRARY DESTINATION ${_py_install_location})
diff --git a/Applications/Python/ogs.mesh/CMakeLists.txt b/Applications/Python/ogs.mesh/CMakeLists.txt
index 5b5704a8dacde5f8b10ea7d54601b5f02718dc3f..4e7279710c8457f2c12fe7dc6c9909d0aecbc7e6 100644
--- a/Applications/Python/ogs.mesh/CMakeLists.txt
+++ b/Applications/Python/ogs.mesh/CMakeLists.txt
@@ -17,5 +17,4 @@ endif()
 
 target_link_libraries(mesh PRIVATE _python_mesh)
 
-# Install into Python module root dir (enables 'import ogs.mesh')
-install(TARGETS mesh LIBRARY DESTINATION ogs)
+install(TARGETS mesh LIBRARY DESTINATION ${_py_install_location})
diff --git a/Applications/Python/ogs.simulator/CMakeLists.txt b/Applications/Python/ogs.simulator/CMakeLists.txt
index c87b10ad6ea246c54d3c5e8f47e6f1c541c634df..2d6c737792c957c266882d08a73692a4bf5b172f 100644
--- a/Applications/Python/ogs.simulator/CMakeLists.txt
+++ b/Applications/Python/ogs.simulator/CMakeLists.txt
@@ -18,5 +18,4 @@ target_link_libraries(
 )
 target_include_directories(simulator PRIVATE ../../CLI)
 
-# Install into Python module root dir (enables 'import ogs.simulator')
-install(TARGETS simulator LIBRARY DESTINATION ogs)
+install(TARGETS simulator LIBRARY DESTINATION ${_py_install_location})
diff --git a/Applications/Python/ogs/CMakeLists.txt b/Applications/Python/ogs/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..c4b4914fa8a02099e6325f5d933ad109b7964706
--- /dev/null
+++ b/Applications/Python/ogs/CMakeLists.txt
@@ -0,0 +1,10 @@
+if(OGS_BUILD_WHEEL)
+    return()
+endif()
+
+install(
+    DIRECTORY .
+    DESTINATION ${_py_install_location}
+    PATTERN "__pycache__" EXCLUDE
+    PATTERN "CMakeLists.txt" EXCLUDE
+)
diff --git a/scripts/cmake/ProjectSetup.cmake b/scripts/cmake/ProjectSetup.cmake
index 48a8de63789145fcd290db66580f4975005a06f7..de5cedbc269db29a0cf4c4e389cb107a9e36da32 100644
--- a/scripts/cmake/ProjectSetup.cmake
+++ b/scripts/cmake/ProjectSetup.cmake
@@ -26,8 +26,13 @@ endif()
 file(RELATIVE_PATH relDir ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}
      ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}
 )
+
+set(_py_module_rpath ${BASEPOINT}/${CMAKE_INSTALL_LIBDIR})
+if(NOT OGS_BUILD_WHEEL)
+    set(_py_module_rpath ${BASEPOINT}/../../..)
+endif()
 list(APPEND CMAKE_INSTALL_RPATH ${BASEPOINT} ${BASEPOINT}/${relDir}
-     ${BASEPOINT}/${CMAKE_INSTALL_LIBDIR} # Python modules
+     ${_py_module_rpath} # Python modules
 )
 list(APPEND CMAKE_BUILD_RPATH ${BASEPOINT} ${BASEPOINT}/${relDir}
      ${BASEPOINT}/${CMAKE_INSTALL_LIBDIR} # Python modules