diff --git a/CMakeLists.txt b/CMakeLists.txt
index df3894c1e5be285c896c3073385bc4a1be31786b..11f98abf8488d51fe319d87e806f0d5a120ba8b6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -291,9 +291,23 @@ if(NOT use_external_modcc)
     add_subdirectory(modcc)
 endif()
 
+#----------------------------------------------------------
+# set up for targets that require git submodules.
+#----------------------------------------------------------
+include(GitSubmodule) # required for check_git_submodule
+include(ErrorTarget)  # reguired for add_error_target
+check_git_submodule(rtdtheme "${PROJECT_SOURCE_DIR}/doc/rtd_theme")
+
 add_subdirectory(src)
 add_subdirectory(mechanisms) # after src path so that gpu_mechanism library is last on link line
 add_subdirectory(tests)
 add_subdirectory(example)
 add_subdirectory(lmorpho)
-add_subdirectory(doc)
+if (rtdtheme_avail)
+    add_subdirectory(doc)
+else()
+    add_error_target( docs
+        "Generating Sphinx documentation"
+        "The git submodule for read the docs is not available")
+endif()
+
diff --git a/cmake/ErrorTarget.cmake b/cmake/ErrorTarget.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..6e4a836bd5e4a14d750366eac17ab20799af3315
--- /dev/null
+++ b/cmake/ErrorTarget.cmake
@@ -0,0 +1,11 @@
+# Creates a target that prints an error message and returns 1 when built.
+#   name    : the name of the target
+#   comment : the COMMENT string for the real target, e.g. "Building the Sphinx documentation"
+#   message : the error message
+
+function(add_error_target name comment message)
+    add_custom_target(${name}
+        COMMAND echo "  Error: ${message}."
+        COMMAND exit 1
+        COMMENT "${comment}")
+endfunction()
diff --git a/cmake/GitSubmodule.cmake b/cmake/GitSubmodule.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..b693f37072898ad0fe7aa8e5ddcbd51f7ecc420a
--- /dev/null
+++ b/cmake/GitSubmodule.cmake
@@ -0,0 +1,24 @@
+# Call to ensure that the git submodule in location `path` is loaded.
+# If the submodule is not loaded, an error message that describes
+# how to update the submodules is printed.
+# Sets the variable name_avail to `ON` if the submodule is available,
+# or `OFF` otherwise.
+
+function(check_git_submodule name path)
+    set(success_var "${name}_avail")
+    set(${success_var} ON PARENT_SCOPE)
+
+    if(NOT EXISTS "${path}/.git")
+        message(
+            "\nThe git submodule for ${name} is not available.\n"
+            "To check out all submodules use the following commands:\n"
+            "    git submodule init\n"
+            "    git submodule update\n"
+            "Or download submodules recursively when checking out:\n"
+            "    git clone --recursive https://github.com/eth-cscs/arbor.git\n"
+        )
+
+        # if the repository was not available, and git failed, set AVAIL to false
+        set(${success_var} OFF PARENT_SCOPE)
+    endif()
+endfunction()
diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt
index fbe7d5676cfad896fcdf6d1fc9f31585b6fdb30a..7ca6bd5abde2d1ce4183060ef3f5a19c1a29748e 100644
--- a/doc/CMakeLists.txt
+++ b/doc/CMakeLists.txt
@@ -1,30 +1,3 @@
-# Set up rtd theme as an external project.
-set(rtdtheme_src_dir "${CMAKE_CURRENT_SOURCE_DIR}/rtd_theme")
-
-find_package(Git)
-if(NOT EXISTS "${rtdtheme_src_dir}/.git")
-    set(git_failed)
-
-    if(GIT_FOUND)
-        message(STATUS "Updating the ReadTheDocs theme submodule ${rtdtheme_src_dir}")
-        execute_process(
-            COMMAND "${GIT_EXECUTABLE}" submodule update --init "${rtdtheme_src_dir}"
-            WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
-            ERROR_VARIABLE git_error
-            RESULT_VARIABLE git_result)
-        if(NOT git_result EQUAL 0)
-            set(git_failed "${git_error}")
-        endif()
-    else()
-        set(git_failed "git not found")
-    endif()
-
-    if(git_failed)
-        message(WARNING "Unable to update the ReadTheDocs theme submodule: ${git_failed}")
-    endif()
-
-endif()
-
 # a static path is required to avoid warning messages from sphinx-build
 file(MAKE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/static")
 
@@ -33,9 +6,8 @@ find_package(Sphinx)
 
 set(DOCS_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/html")
 set(DOCS_DOC_TREE_DIR "${CMAKE_CURRENT_BINARY_DIR}/_doctrees")
-set(DOCS_TARGET_NAME docs)
 if (SPHINX_FOUND)
-    add_custom_target( ${DOCS_TARGET_NAME}
+    add_custom_target(docs
         COMMAND
             ${SPHINX_EXECUTABLE}
             -b html
@@ -46,16 +18,10 @@ if (SPHINX_FOUND)
         COMMENT
             "Generating Sphinx documentation")
 else()
-    add_custom_target( ${DOCS_TARGET_NAME}
-        COMMAND
-            echo "Error: Sphinx must be installed to build documentation."
-        COMMAND
-            exit 1  # return error code to let CMake know that the build proccess should fail
-        COMMENT
-            "Generating Sphinx documentation")
+    add_error_target(docs
+        "Generating Sphinx documentation"
+        "Sphinx must be installed to build documentation")
 endif()
 
 # remove generated documentation when make clean is run
 set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "${DOCS_BUILD_DIR}")
-
-unset(git_failed)
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 476d19614a99837ac376705620fb0c603e4561d7..722549068405e3c271cbe9e0ed826f902401b1f0 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -14,7 +14,15 @@ add_subdirectory(global_communication)
 add_subdirectory(performance)
 
 # Microbenchmarks.
-add_subdirectory(ubench)
+# Attempt to update git submodule if required.
+check_git_submodule(google_bench "${CMAKE_CURRENT_SOURCE_DIR}/ubench/google-benchmark")
+if (google_bench_avail)
+    add_subdirectory(ubench)
+else()
+    add_error_target(ubenches
+        "Building micro benchmarks"
+        "The git submodule for google benchmark is not available")
+endif()
 
 # regression / delta tests
 # Employing the full simulator. validated using deltas on output data
diff --git a/tests/ubench/CMakeLists.txt b/tests/ubench/CMakeLists.txt
index 75e4cf905ad2c058b9e1c5169195a52bde638e4d..c0486931d4f0b0d6a75699b6fd4cef0299fc85d4 100644
--- a/tests/ubench/CMakeLists.txt
+++ b/tests/ubench/CMakeLists.txt
@@ -24,30 +24,6 @@ set(gbench_cmake_args
     "-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}"
     "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}")
 
-
-# Attempt to update git submodule if required.
-find_package(Git)
-if(NOT EXISTS "${gbench_src_dir}/.git")
-    set(git_failed)
-    if(GIT_FOUND)
-        message(STATUS "Updating the google-benchmark submodule ${gbench_src_dir}")
-        execute_process(
-            COMMAND "${GIT_EXECUTABLE}" submodule update --init "${gbench_src_dir}"
-            WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
-            ERROR_VARIABLE git_error
-            RESULT_VARIABLE git_result)
-        if(NOT git_result EQUAL 0)
-            set(git_failed "${git_error}")
-        endif()
-    else()
-        set(git_failed "git not found")
-    endif()
-
-    if(git_failed)
-        message(WARNING "Unable to update the google-benchmark submodule: ${git_failed}")
-    endif()
-endif()
-
 ExternalProject_Add(gbench
     # Add dummy DOWNLOAD_COMMAND to stop ExternalProject_Add terminating CMake if the
     # git submodule had not been udpated.
@@ -85,4 +61,3 @@ if(ARB_WITH_CUDA)
 endif()
 
 add_custom_target(ubenches DEPENDS ${bench_exe_list})
-