diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9027b23c99af390733d399f1a38e195e2182fda6..4fcc1bfdbf38f512c47cf7b43f5087eb4b6c1374 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -17,9 +17,37 @@ cmake_policy( SET CMP0023 OLD )
 # Keep cmake 3.0 quiet
 cmake_policy( SET CMP0043 OLD )
 
+include( MacroOptionalFindPackage )
+include( MacroLogFeature )
+
 find_package( Qt5 5.3.0 CONFIG REQUIRED Core Gui Widgets LinguistTools )
 find_package( YamlCpp 0.5.1 REQUIRED )
 
+option( WITH_PYTHON "Enable Python modules support." ON )
+
+macro_optional_find_package( PythonLibs 3.3 REQUIRED )
+macro_log_feature(
+    PYTHONLIBS_FOUND
+    "Python"
+    "C interface libraries for the Python interpreter."
+    "http://python.org"
+    TRUE ""
+    "Python is used for some Calamares job modules."
+)
+macro_optional_find_package( Boost 1.55.0 COMPONENTS python3 REQUIRED )
+macro_log_feature(
+    Boost_PYTHON3_FOUND
+    "Boost.Python"
+    "A C++ library which enables seamless interoperability between C++ and Python."
+    "http://www.boost.org"
+    TRUE ""
+    "Boost.Python is used for interfacing with Calamares job modules written in Python."
+)
+if( Boost_PYTHON3_NOTFOUND OR PYTHONLIBS_NOTFOUND )
+    set( WITH_PYTHON OFF )
+endif()
+
+
 ###
 ### Calamares application info
 ###
@@ -83,6 +111,8 @@ set( CALAMARES_LIBRARIES calamareslib )
 add_subdirectory( src )
 add_subdirectory( tests )
 
+macro_display_feature_log()
+
 # Add all targets to the build-tree export set
 set( CMAKE_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/Calamares" CACHE PATH  "Installation directory for CMake files" )
 set( CMAKE_INSTALL_FULL_CMAKEDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_CMAKEDIR}" )
diff --git a/CMakeModules/MacroLogFeature.cmake b/CMakeModules/MacroLogFeature.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..45e27b6dff4f17a0a7e65ea56a19888180965b8b
--- /dev/null
+++ b/CMakeModules/MacroLogFeature.cmake
@@ -0,0 +1,157 @@
+# This file defines the Feature Logging macros.
+#
+# MACRO_LOG_FEATURE(VAR FEATURE DESCRIPTION URL [REQUIRED [MIN_VERSION [COMMENTS]]])
+#   Logs the information so that it can be displayed at the end
+#   of the configure run
+#   VAR : TRUE or FALSE, indicating whether the feature is supported
+#   FEATURE: name of the feature, e.g. "libjpeg"
+#   DESCRIPTION: description what this feature provides
+#   URL: home page
+#   REQUIRED: TRUE or FALSE, indicating whether the featue is required
+#   MIN_VERSION: minimum version number. empty string if unneeded
+#   COMMENTS: More info you may want to provide.  empty string if unnecessary
+#
+# MACRO_DISPLAY_FEATURE_LOG()
+#   Call this to display the collected results.
+#   Exits CMake with a FATAL error message if a required feature is missing
+#
+# Example:
+#
+# INCLUDE(MacroLogFeature)
+#
+# FIND_PACKAGE(JPEG)
+# MACRO_LOG_FEATURE(JPEG_FOUND "libjpeg" "Support JPEG images" "http://www.ijg.org" TRUE "3.2a" "")
+# ...
+# MACRO_DISPLAY_FEATURE_LOG()
+
+# Copyright (c) 2006, Alexander Neundorf, <neundorf@kde.org>
+# Copyright (c) 2006, Allen Winter, <winter@kde.org>
+# Copyright (c) 2009, Sebastian Trueg, <trueg@kde.org>
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+
+IF (NOT _macroLogFeatureAlreadyIncluded)
+   SET(_file ${CMAKE_BINARY_DIR}/MissingRequirements.txt)
+   IF (EXISTS ${_file})
+      FILE(REMOVE ${_file})
+   ENDIF (EXISTS ${_file})
+
+   SET(_file ${CMAKE_BINARY_DIR}/EnabledFeatures.txt)
+   IF (EXISTS ${_file})
+      FILE(REMOVE ${_file})
+   ENDIF (EXISTS ${_file})
+
+   SET(_file ${CMAKE_BINARY_DIR}/DisabledFeatures.txt)
+   IF (EXISTS ${_file})
+      FILE(REMOVE ${_file})
+  ENDIF (EXISTS ${_file})
+
+  SET(_macroLogFeatureAlreadyIncluded TRUE)
+
+  INCLUDE(FeatureSummary)
+
+ENDIF (NOT _macroLogFeatureAlreadyIncluded)
+
+
+MACRO(MACRO_LOG_FEATURE _var _package _description _url ) # _required _minvers _comments)
+
+   STRING(TOUPPER "${ARGV4}" _required)
+   SET(_minvers "${ARGV5}")
+   SET(_comments "${ARGV6}")
+
+   IF (${_var})
+     SET(_LOGFILENAME ${CMAKE_BINARY_DIR}/EnabledFeatures.txt)
+   ELSE (${_var})
+     IF ("${_required}" STREQUAL "TRUE")
+       SET(_LOGFILENAME ${CMAKE_BINARY_DIR}/MissingRequirements.txt)
+     ELSE ("${_required}" STREQUAL "TRUE")
+       SET(_LOGFILENAME ${CMAKE_BINARY_DIR}/DisabledFeatures.txt)
+     ENDIF ("${_required}" STREQUAL "TRUE")
+   ENDIF (${_var})
+
+   SET(_logtext "   * ${_package}")
+
+   IF (NOT ${_var})
+      IF (${_minvers} MATCHES ".*")
+        SET(_logtext "${_logtext} (${_minvers} or higher)")
+      ENDIF (${_minvers} MATCHES ".*")
+      SET(_logtext "${_logtext}  <${_url}>\n     ")
+   ELSE (NOT ${_var})
+     SET(_logtext "${_logtext} - ")
+   ENDIF (NOT ${_var})
+
+   SET(_logtext "${_logtext}${_description}")
+
+   IF (NOT ${_var})
+      IF (${_comments} MATCHES ".*")
+        SET(_logtext "${_logtext}\n     ${_comments}")
+      ENDIF (${_comments} MATCHES ".*")
+#      SET(_logtext "${_logtext}\n") #double-space missing features?
+   ENDIF (NOT ${_var})
+
+   FILE(APPEND "${_LOGFILENAME}" "${_logtext}\n")
+
+   IF(COMMAND SET_PACKAGE_INFO)  # in FeatureSummary.cmake since CMake 2.8.3
+     SET_PACKAGE_INFO("${_package}" "\"${_description}\"" "${_url}" "\"${_comments}\"")
+   ENDIF(COMMAND SET_PACKAGE_INFO)
+
+ENDMACRO(MACRO_LOG_FEATURE)
+
+
+MACRO(MACRO_DISPLAY_FEATURE_LOG)
+   IF(COMMAND FEATURE_SUMMARY) # in FeatureSummary.cmake since CMake 2.8.3
+      FEATURE_SUMMARY(FILENAME ${CMAKE_CURRENT_BINARY_DIR}/FindPackageLog.txt
+                      WHAT ALL)
+   ENDIF(COMMAND FEATURE_SUMMARY)
+
+   SET(_missingFile ${CMAKE_BINARY_DIR}/MissingRequirements.txt)
+   SET(_enabledFile ${CMAKE_BINARY_DIR}/EnabledFeatures.txt)
+   SET(_disabledFile ${CMAKE_BINARY_DIR}/DisabledFeatures.txt)
+
+   IF (EXISTS ${_missingFile} OR EXISTS ${_enabledFile} OR EXISTS ${_disabledFile})
+     SET(_printSummary TRUE)
+   ENDIF (EXISTS ${_missingFile} OR EXISTS ${_enabledFile} OR EXISTS ${_disabledFile})
+
+   IF(_printSummary)
+     SET(_missingDeps 0)
+     IF (EXISTS ${_enabledFile})
+       FILE(READ ${_enabledFile} _enabled)
+       FILE(REMOVE ${_enabledFile})
+       SET(_summary "${_summary}\n-----------------------------------------------------------------------------\n-- The following external packages were located on your system.\n-- This installation will have the extra features provided by these packages.\n-----------------------------------------------------------------------------\n${_enabled}")
+     ENDIF (EXISTS ${_enabledFile})
+
+
+     IF (EXISTS ${_disabledFile})
+       SET(_missingDeps 1)
+       FILE(READ ${_disabledFile} _disabled)
+       FILE(REMOVE ${_disabledFile})
+       SET(_summary "${_summary}\n-----------------------------------------------------------------------------\n-- The following OPTIONAL packages could NOT be located on your system.\n-- Consider installing them to enable more features from this software.\n-----------------------------------------------------------------------------\n${_disabled}")
+     ENDIF (EXISTS ${_disabledFile})
+
+
+     IF (EXISTS ${_missingFile})
+       SET(_missingDeps 1)
+       FILE(READ ${_missingFile} _requirements)
+       SET(_summary "${_summary}\n-----------------------------------------------------------------------------\n-- The following REQUIRED packages could NOT be located on your system.\n-- You must install these packages before continuing.\n-----------------------------------------------------------------------------\n${_requirements}")
+       FILE(REMOVE ${_missingFile})
+       SET(_haveMissingReq 1)
+     ENDIF (EXISTS ${_missingFile})
+
+
+     IF (NOT ${_missingDeps})
+       SET(_summary "${_summary}\n-----------------------------------------------------------------------------\n-- Congratulations! All external packages have been found.")
+     ENDIF (NOT ${_missingDeps})
+
+
+     MESSAGE(${_summary})
+     MESSAGE("-----------------------------------------------------------------------------\n")
+
+
+     IF(_haveMissingReq)
+       MESSAGE(FATAL_ERROR "Exiting: Missing Requirements")
+     ENDIF(_haveMissingReq)
+
+   ENDIF(_printSummary)
+
+ENDMACRO(MACRO_DISPLAY_FEATURE_LOG)
diff --git a/CMakeModules/MacroOptionalFindPackage.cmake b/CMakeModules/MacroOptionalFindPackage.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..d4ed48e33a59170d9ed8f9b3223a42b5c4883cfd
--- /dev/null
+++ b/CMakeModules/MacroOptionalFindPackage.cmake
@@ -0,0 +1,48 @@
+# - MACRO_OPTIONAL_FIND_PACKAGE() combines FIND_PACKAGE() with an OPTION()
+# MACRO_OPTIONAL_FIND_PACKAGE( <name> [QUIT] )
+# This macro is a combination of OPTION() and FIND_PACKAGE(), it
+# works like FIND_PACKAGE(), but additionally it automatically creates
+# an option name WITH_<name>, which can be disabled via the cmake GUI.
+# or via -DWITH_<name>=OFF
+# The standard <name>_FOUND variables can be used in the same way
+# as when using the normal FIND_PACKAGE()
+
+# Copyright (c) 2006-2010 Alexander Neundorf, <neundorf@kde.org>
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+
+# This is just a helper macro to set a bunch of variables empty.
+# We don't know whether the package uses UPPERCASENAME or CamelCaseName, so we try both:
+macro(_MOFP_SET_EMPTY_IF_DEFINED _name _var)
+   if(DEFINED ${_name}_${_var})
+      set(${_name}_${_var} "")
+   endif(DEFINED ${_name}_${_var})
+
+   string(TOUPPER ${_name} _nameUpper)
+   if(DEFINED ${_nameUpper}_${_var})
+      set(${_nameUpper}_${_var}  "")
+   endif(DEFINED ${_nameUpper}_${_var})
+endmacro(_MOFP_SET_EMPTY_IF_DEFINED _package _var)
+
+
+macro (MACRO_OPTIONAL_FIND_PACKAGE _name )
+   option(WITH_${_name} "Search for ${_name} package" ON)
+   if (WITH_${_name})
+      find_package(${_name} ${ARGN})
+   else (WITH_${_name})
+      string(TOUPPER ${_name} _nameUpper)
+      set(${_name}_FOUND FALSE)
+      set(${_nameUpper}_FOUND FALSE)
+
+      _mofp_set_empty_if_defined(${_name} INCLUDE_DIRS)
+      _mofp_set_empty_if_defined(${_name} INCLUDE_DIR)
+      _mofp_set_empty_if_defined(${_name} INCLUDES)
+      _mofp_set_empty_if_defined(${_name} LIBRARY)
+      _mofp_set_empty_if_defined(${_name} LIBRARIES)
+      _mofp_set_empty_if_defined(${_name} LIBS)
+      _mofp_set_empty_if_defined(${_name} FLAGS)
+      _mofp_set_empty_if_defined(${_name} DEFINITIONS)
+   endif (WITH_${_name})
+endmacro (MACRO_OPTIONAL_FIND_PACKAGE)
+