diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 9ee0ad8c7bfbce1e74201fb247f34b5357be62c2..2f0999e59c595e7ef9f1430515edb58f6ad020de 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -45,4 +45,4 @@ repos:
       exclude: 'scripts/cmake/jedbrown/.*|PackagingMacros.cmake|conan.cmake|CPM.cmake|FindFilesystem.cmake|ConanSetup.cmake|Tests.cmake'
     - id: cmake-lint
       additional_dependencies: ["cmakelang[YAML]"]
-      exclude: 'scripts/cmake/jedbrown/.*|PackagingMacros.cmake|conan.cmake|CPM.cmake|FindFilesystem.cmake|ConanSetup.cmake'
+      exclude: 'scripts/cmake/jedbrown/.*|PackagingMacros.cmake|conan.cmake|CPM.cmake|FindFilesystem.cmake|ConanSetup.cmake|BuildExternalProject.cmake'
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2def4f3049a681aea118ef2ee2b75ee994895b86..ab1d55500e353444cf2d8549d40236fee240a6b1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -77,6 +77,7 @@ include(CompilerSetup)
 include(JobPools)
 include(Find)
 include(CLCacheSetup)
+include(packaging/PackagingDependencies)
 include(Dependencies)
 include(DocumentationSetup)
 include(test/Test)
@@ -188,8 +189,7 @@ option(OGS_USE_MFRONT
        OFF
 )
 
-# Packaging
-include(scripts/cmake/packaging/Pack.cmake)
+include(packaging/Pack)
 
 # ---- Subdirectories ----
 include_directories(${PROJECT_SOURCE_DIR})
diff --git a/ProcessLib/SmallDeformation/Tests.cmake b/ProcessLib/SmallDeformation/Tests.cmake
index 765ce2eddd8dfd68ec7df66d79b5426f4f2f15ff..11f0654811a8e7681602fdf61a94db36b47bd8b2 100644
--- a/ProcessLib/SmallDeformation/Tests.cmake
+++ b/ProcessLib/SmallDeformation/Tests.cmake
@@ -39,10 +39,6 @@ if (NOT OGS_USE_MPI)
     OgsTest(PROJECTFILE Mechanics/InitialStates/non_equilibrium_initial_state.prj)
     OgsTest(PROJECTFILE Mechanics/InitialStates/soil_column_nonequilibrium_sigma_elementwise.prj)
     OgsTest(PROJECTFILE Mechanics/Excavation/time_linear_excavation.prj RUNTIME 4)
-    OgsTest(PROJECTFILE Mechanics/MohrCoulombAbboSloan/slope.prj RUNTIME 50)
-    if(TEST ogs-Mechanics/MohrCoulombAbboSloan/slope)
-        set_tests_properties(ogs-Mechanics/MohrCoulombAbboSloan/slope PROPERTIES WILL_FAIL true)
-    endif()
 endif()
 
 if (OGS_USE_PYTHON)
@@ -59,6 +55,10 @@ if (OGS_USE_MPI)
 endif()
 
 if (OGS_USE_MFRONT)
+    OgsTest(PROJECTFILE Mechanics/MohrCoulombAbboSloan/slope.prj RUNTIME 50)
+    if(TEST ogs-Mechanics/MohrCoulombAbboSloan/slope)
+        set_tests_properties(ogs-Mechanics/MohrCoulombAbboSloan/slope PROPERTIES WILL_FAIL true)
+    endif()
     OgsTest(PROJECTFILE Mechanics/MohrCoulombAbboSloan/load_test_mc.prj)
     OgsTest(PROJECTFILE Mechanics/MohrCoulombAbboSloanAnisotropic/triax_1e0_47.prj)
     OgsTest(PROJECTFILE Mechanics/MohrCoulombAbboSloanAnisotropic/triax_ortho_1e0_47.prj)
diff --git a/Tests/Data/Mechanics/ModifiedCamClay/model_triaxtest.prj b/Tests/Data/Mechanics/ModifiedCamClay/model_triaxtest.prj
index cd17a01139cdbeeb8d9e4329a5667fe558d119ed..824339b7bd6d16e17be2e09c9c66394001da474c 100644
--- a/Tests/Data/Mechanics/ModifiedCamClay/model_triaxtest.prj
+++ b/Tests/Data/Mechanics/ModifiedCamClay/model_triaxtest.prj
@@ -88,7 +88,7 @@
         <parameter>
             <name>YoungModulus</name>
             <type>Constant</type>
-            <value>52e6</value><!--Pa-->
+            <value>52e6</value>            <!--Pa-->
         </parameter>
         <parameter>
             <name>PoissonRatio</name>
@@ -113,7 +113,7 @@
         <parameter>
             <name>InitialPreConsolidationPressure</name>
             <type>Constant</type>
-            <value>2.e5</value><!--Pa-->
+            <value>2.e5</value>            <!--Pa-->
         </parameter>
         <parameter>
             <name>InitialPorosity</name>
@@ -145,12 +145,12 @@
         <parameter>
             <name>loading_value_top</name>
             <type>Constant</type>
-            <value>-625.e3</value> <!--Pa-->
+            <value>-625.e3</value>            <!--Pa-->
         </parameter>
         <parameter>
             <name>confining_pressure_value</name>
             <type>Constant</type>
-            <values>-200.e3</values> <!--Pa-->
+            <values>-200.e3</values>            <!--Pa-->
         </parameter>
         <parameter>
             <name>confining_pressure</name>
@@ -250,7 +250,7 @@
         <vtkdiff>
             <file>triaxtest_output_ts_199_t_1.000000.vtu</file>
             <field>sigma</field>
-            <absolute_tolerance>6e-8</absolute_tolerance>
+            <absolute_tolerance>9e-8</absolute_tolerance>
             <relative_tolerance>0</relative_tolerance>
         </vtkdiff>
         <!--material-specific internal variable-->
diff --git a/Tests/MaterialLib/MFront.cpp b/Tests/MaterialLib/MFront.cpp
index 7edd62e5cb4af4e42fc048876c1b55ee33a20d04..d89efe92bcd0a66be07892531e0a2982f0817e17 100644
--- a/Tests/MaterialLib/MFront.cpp
+++ b/Tests/MaterialLib/MFront.cpp
@@ -121,16 +121,16 @@ struct MaterialLib_SolidModelsMFront : public testing::Test
     MaterialLib_SolidModelsMFront()
     {
         variable_array_prev[static_cast<int>(MPL::Variable::stress)]
-            .emplace<KelvinVector<Dim>>(KelvinVector<Dim>::Zero());
+            .template emplace<KelvinVector<Dim>>(KelvinVector<Dim>::Zero());
         variable_array_prev[static_cast<int>(MPL::Variable::mechanical_strain)]
-            .emplace<KelvinVector<Dim>>(KelvinVector<Dim>::Zero());
+            .template emplace<KelvinVector<Dim>>(KelvinVector<Dim>::Zero());
         variable_array_prev[static_cast<int>(MPL::Variable::temperature)]
-            .emplace<double>(0);
+            .template emplace<double>(0);
 
         variable_array[static_cast<int>(MPL::Variable::mechanical_strain)]
-            .emplace<KelvinVector<Dim>>(KelvinVector<Dim>::Zero());
+            .template emplace<KelvinVector<Dim>>(KelvinVector<Dim>::Zero());
         variable_array[static_cast<int>(MPL::Variable::temperature)]
-            .emplace<double>(0);
+            .template emplace<double>(0);
         constitutive_relation = TestBehaviour::createConstitutiveRelation();
     }
 
diff --git a/scripts/ci/jobs/build-mac.yml b/scripts/ci/jobs/build-mac.yml
index 04eb3319bbb8f945435689b87d7b77f1666905b5..1c3e79ee2feff28f6385f1c6ee6b041ffc268562 100644
--- a/scripts/ci/jobs/build-mac.yml
+++ b/scripts/ci/jobs/build-mac.yml
@@ -12,3 +12,4 @@ build mac:
     CMAKE_ARGS: >-
       -DOGS_INSTALL_DEPENDENCIES=ON
       -DOGS_USE_XDMF=ON
+      -DOGS_USE_MFRONT=ON
diff --git a/scripts/cmake/BuildExternalProject.cmake b/scripts/cmake/BuildExternalProject.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..45e80d6d85d849dcc453103d929bebf301bf8380
--- /dev/null
+++ b/scripts/cmake/BuildExternalProject.cmake
@@ -0,0 +1,95 @@
+# Modified from
+# https://github.com/Sbte/BuildExternalProject/commit/ce1a70996aa538aac17a6faf07db487c3a238838
+macro(BuildExternalProject_find_package target)
+    set(build_dir ${CMAKE_BINARY_DIR}/external/build_${target})
+
+    # Set CMake prefix path so we can look there for the module
+    set(_CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH})
+    mark_as_advanced(_CMAKE_PREFIX_PATH)
+    list(APPEND CMAKE_PREFIX_PATH ${build_dir})
+
+    find_package(${target} MODULE QUIET)
+    if(NOT ${target}_FOUND)
+        # Look for config version if there was no module
+        find_package(
+            ${target} CONFIG REQUIRED HINTS ${build_dir} NO_DEFAULT_PATH
+        )
+    endif()
+
+    # Set CMake prefix path back to what it was
+    set(CMAKE_PREFIX_PATH ${_CMAKE_PREFIX_PATH})
+    unset(_CMAKE_PREFIX_PATH)
+endmacro()
+
+function(BuildExternalProject target)
+    set(build_dir ${CMAKE_BINARY_DIR}/external/build_${target})
+
+    message(STATUS "Building ${target}")
+
+    file(MAKE_DIRECTORY ${build_dir})
+
+    set(CMAKE_LIST_CONTENT
+        "
+    cmake_minimum_required(VERSION ${CMAKE_MINIMUM_REQUIRED_VERSION})
+    project(externalproject_${target})
+
+    include(ExternalProject)
+    ExternalProject_add(${target}
+      PREFIX ${build_dir}
+      CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>
+      LOG_DOWNLOAD ON
+      LOG_UPDATE ON
+      LOG_CONFIGURE ON
+      LOG_BUILD ON
+      LOG_TEST ON
+      LOG_INSTALL ON
+      ${ARGN}
+      )
+
+    add_custom_target(build_${target})
+    add_dependencies(build_${target} ${target})
+    "
+    )
+
+    if(EXISTS ${build_dir}/CMakeLists.txt)
+        file(SHA256 ${build_dir}/CMakeLists.txt file_sha)
+        string(SHA256 new_sha "${CMAKE_LIST_CONTENT}")
+
+        if(NOT file_sha STREQUAL new_sha)
+            file(WRITE ${build_dir}/CMakeLists.txt "${CMAKE_LIST_CONTENT}")
+            BuildExternalProject_configure(${build_dir})
+        endif()
+    else()
+        file(WRITE ${build_dir}/CMakeLists.txt "${CMAKE_LIST_CONTENT}")
+        BuildExternalProject_configure(${build_dir})
+    endif()
+
+    BuildExternalProject_build(${build_dir})
+
+    message(
+        STATUS
+            "Finished building ${target}. Logs in ${build_dir}/src/${target}-stamp"
+    )
+endfunction()
+
+function(BuildExternalProject_configure build_dir)
+    execute_process(
+        COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
+        RESULT_VARIABLE result WORKING_DIRECTORY ${build_dir}
+    )
+
+    if(result)
+        message(FATAL_ERROR "CMake step for external project failed: ${result}")
+    endif()
+endfunction()
+
+function(BuildExternalProject_build build_dir)
+    execute_process(
+        COMMAND ${CMAKE_COMMAND} --build . RESULT_VARIABLE result
+        WORKING_DIRECTORY ${build_dir}
+    )
+
+    if(result)
+        message(FATAL_ERROR "Build step for external project failed: ${result}")
+    endif()
+endfunction()
diff --git a/scripts/cmake/ConanSetup.cmake b/scripts/cmake/ConanSetup.cmake
index 8870d08c2bc1c718799cb2673bcad951d2555df4..0e6e7ed38b35abb8a111f8f963028810e01ea047 100644
--- a/scripts/cmake/ConanSetup.cmake
+++ b/scripts/cmake/ConanSetup.cmake
@@ -14,7 +14,6 @@ endif()
 if(NOT CONAN_CMD
    AND (OGS_USE_PETSC
         OR OGS_USE_LIS
-        OR OGS_USE_MFRONT
         OR OGS_BUILD_GUI
        )
 )
@@ -50,10 +49,6 @@ if(OGS_USE_LIS)
     set(CONAN_REQUIRES ${CONAN_REQUIRES} lis/1.7.37@bilke/stable)
 endif()
 
-if(OGS_USE_MFRONT)
-    set(CONAN_REQUIRES ${CONAN_REQUIRES} tfel/${ogs.minimum_version.tfel-rliv}@bilke/testing)
-endif()
-
 if(OGS_BUILD_GUI)
     set(QT_VERSION ${ogs.minimum_version.qt})
     if(UNIX)
diff --git a/scripts/cmake/Dependencies.cmake b/scripts/cmake/Dependencies.cmake
index bf99342b6ca71b28803b370ca102695d03ea8a6d..3fcaecd4cf4e70192be1499d74475eccc20f5567 100644
--- a/scripts/cmake/Dependencies.cmake
+++ b/scripts/cmake/Dependencies.cmake
@@ -1,3 +1,17 @@
+include(BuildExternalProject)
+
+if(OGS_USE_MFRONT)
+    find_program(MFRONT mfront)
+    if(NOT MFRONT)
+        BuildExternalProject(
+            TFEL GIT_REPOSITORY https://github.com/thelfer/tfel.git GIT_TAG
+            rliv-${ogs.minimum_version.tfel-rliv}
+        )
+        set(ENV{TFELHOME} ${PROJECT_BINARY_DIR}/external/build_TFEL)
+    endif()
+    list(APPEND CMAKE_INSTALL_RPATH $ENV{TFELHOME}/${CMAKE_INSTALL_LIBDIR})
+endif()
+
 set(CMAKE_FOLDER ThirdParty)
 
 # ccache
@@ -126,6 +140,7 @@ if(OGS_USE_MFRONT)
     if(MGIS_ADDED)
         set_target_properties(MFrontGenericInterface PROPERTIES CXX_STANDARD 11)
         list(APPEND DISABLE_WARNINGS_TARGETS MFrontGenericInterface)
+        set(_MFRONT_TFEL_FOUND ON CACHE INTERNAL "")
     endif()
 endif()
 
diff --git a/scripts/cmake/packaging/Pack.cmake b/scripts/cmake/packaging/Pack.cmake
index 9440814d3d66b30af1a968974ece5b037b3def6a..5277252bf1ff519482dfdfce7f55570e320a7f2c 100644
--- a/scripts/cmake/packaging/Pack.cmake
+++ b/scripts/cmake/packaging/Pack.cmake
@@ -88,32 +88,3 @@ install(
     CODE "execute_process(COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR} -t write-licenses)"
 )
 install(FILES ${PROJECT_BINARY_DIR}/third_party_licenses.txt TYPE INFO)
-
-# Install dependencies via GET_RUNTIME_DEPENDENCIES. Available since CMake 3.16.
-if(${CMAKE_VERSION} VERSION_LESS 3.16 OR NOT OGS_INSTALL_DEPENDENCIES)
-    return()
-endif()
-install(
-    CODE [[
-  include(GNUInstallDirs)
-  if(WIN32)
-    set(INSTALL_DIR ${CMAKE_INSTALL_FULL_BINDIR})
-  else()
-    set(INSTALL_DIR ${CMAKE_INSTALL_FULL_LIBDIR})
-  endif()
-  file(GET_RUNTIME_DEPENDENCIES
-    EXECUTABLES $<$<TARGET_EXISTS:ogs>:$<TARGET_FILE:ogs>> $<$<TARGET_EXISTS:DataExplorer>:$<TARGET_FILE:DataExplorer>>
-    RESOLVED_DEPENDENCIES_VAR _r_deps
-    UNRESOLVED_DEPENDENCIES_VAR _u_deps
-    POST_EXCLUDE_REGEXES "/opt/local/lib/lib.*" # Disable macports zlib
-  )
-  file(INSTALL ${_r_deps}
-    DESTINATION ${INSTALL_DIR}
-    FOLLOW_SYMLINK_CHAIN
-  )
-  list(LENGTH _u_deps _u_length)
-  if("${_u_length}" GREATER 0)
-    message(WARNING "Unresolved dependencies detected!\n${_u_deps}")
-  endif()
-]]
-)
diff --git a/scripts/cmake/packaging/PackagingDependencies.cmake b/scripts/cmake/packaging/PackagingDependencies.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..70d7673283fa0e680bed23153c75ab486bc8d51f
--- /dev/null
+++ b/scripts/cmake/packaging/PackagingDependencies.cmake
@@ -0,0 +1,28 @@
+# Install dependencies via GET_RUNTIME_DEPENDENCIES. Available since CMake 3.16.
+if(${CMAKE_VERSION} VERSION_LESS 3.16 OR NOT OGS_INSTALL_DEPENDENCIES)
+    return()
+endif()
+install(
+    CODE [[
+  include(GNUInstallDirs)
+  if(WIN32)
+    set(INSTALL_DIR ${CMAKE_INSTALL_FULL_BINDIR})
+  else()
+    set(INSTALL_DIR ${CMAKE_INSTALL_FULL_LIBDIR})
+  endif()
+  file(GET_RUNTIME_DEPENDENCIES
+    EXECUTABLES $<$<TARGET_EXISTS:ogs>:$<TARGET_FILE:ogs>> $<$<TARGET_EXISTS:DataExplorer>:$<TARGET_FILE:DataExplorer>>
+    RESOLVED_DEPENDENCIES_VAR _r_deps
+    UNRESOLVED_DEPENDENCIES_VAR _u_deps
+    POST_EXCLUDE_REGEXES "/opt/local/lib/lib.*" # Disable macports zlib
+  )
+  file(INSTALL ${_r_deps}
+    DESTINATION ${INSTALL_DIR}
+    FOLLOW_SYMLINK_CHAIN
+  )
+  list(LENGTH _u_deps _u_length)
+  if("${_u_length}" GREATER 0)
+    message(WARNING "Unresolved dependencies detected!\n${_u_deps}")
+  endif()
+]]
+)