### Utility/Convenience functionality:

## From https://stackoverflow.com/a/39971448 (modified):
# Compare the new contents with the existing file, if it exists and is the 
# same we don't want to trigger a make by changing its timestamp.
function(update_file path content)
    set(old_content "")
    if(EXISTS "${path}")
        file(READ "${path}" old_content)
    endif()
    if(NOT old_content STREQUAL content)
        file(WRITE "${path}" "${content}")
    endif()
endfunction()

# Normalize the list so it's the same on every machine
function(normalize_file_list ret input_list)
    set(result "")
    list(REMOVE_DUPLICATES input_list)
    foreach(item IN LISTS input_list)
        if(IS_ABSOLUTE ${item})
            file(RELATIVE_PATH item ${CMAKE_CURRENT_SOURCE_DIR} ${item})
        endif()
        list(APPEND result ${item})
    endforeach()
    list(SORT result)
    set(${ret} ${result} PARENT_SCOPE)
endfunction()

# Creates a file called CMakeDeps.cmake next to your CMakeLists.txt with 
# the list of dependencies in it - this file should be treated as part of 
# CMakeLists.txt (source controlled, etc.).
function(update_deps_file deps)
    set(deps_file "CMakeDeps.cmake")
    normalize_file_list(rel_deps "${deps}")
    # Update the deps file
    set(content "# File generated by CMake process\nset(sources ${rel_deps})\n")
    update_file(${deps_file} "${content}")
    # Include the file so it's tracked as a generation dependency we don't
    # need the content.
    include(${deps_file})
endfunction()
