1# 2# Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) 3# 4# SPDX-License-Identifier: BSD-2-Clause 5# 6 7cmake_minimum_required(VERSION 3.7.2) 8include_guard(GLOBAL) 9 10# This takes a camkes produced dependency file (this means we can assume one dependency 11# per line) and produces a cmake list of dependencies 12function(MakefileDepsToList mdfile output_variable) 13 file(READ "${mdfile}" raw_file) 14 # First remove the target of the dependency list 15 string( 16 REGEX 17 REPLACE 18 "^[^:]*: \\\\\r?\n" 19 "" 20 string_deps 21 "${raw_file}" 22 ) 23 # Now turn the list of dependencies into a cmake list. We have assumed 24 # that this makefile dep file was generated by camkes and so it has one 25 # item per line 26 string( 27 REGEX 28 REPLACE 29 "\\\\\r?\n" 30 ";" 31 deps 32 "${string_deps}" 33 ) 34 # Strip the space from each dep 35 foreach(dep IN LISTS deps) 36 # Strip extra spacing 37 string(STRIP "${dep}" dep) 38 list(APPEND final_deps "${dep}") 39 endforeach() 40 # Write the output to the parent 41 set("${output_variable}" "${final_deps}" PARENT_SCOPE) 42endfunction(MakefileDepsToList) 43 44# Wraps a call to execute_process with checks that only rerun execute_process 45# if the command or input files are changed. It also uses a depfile to track 46# any files that the command touches internally. This function currently won't 47# work without a depfile. 48macro(execute_process_with_stale_check invoc_file deps_file outfile extra_dependencies) 49 # We need to determine if we actually need to regenerate. We start by assuming that we do 50 set(regen TRUE) 51 if((EXISTS "${invoc_file}") AND (EXISTS "${deps_file}") AND (EXISTS "${outfile}")) 52 file(READ "${invoc_file}" old_contents) 53 if("${old_contents}" STREQUAL "${ARGN}") 54 MakefileDepsToList("${deps_file}" deps) 55 # At this point assume we do not need to regenerate, unless we found a newer file 56 set(regen FALSE) 57 foreach(dep IN LISTS deps extra_dependencies) 58 if("${dep}" IS_NEWER_THAN "${outfile}") 59 set(regen TRUE) 60 break() 61 endif() 62 endforeach() 63 endif() 64 endif() 65 if(regen) 66 message(STATUS "${outfile} is out of date. Regenerating...") 67 execute_process(${ARGN}) 68 file(WRITE "${invoc_file}" "${ARGN}") 69 endif() 70 # Add dependencies 71 MakefileDepsToList("${deps_file}" deps) 72 set_property( 73 DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" 74 APPEND 75 PROPERTY CMAKE_CONFIGURE_DEPENDS "${deps};${extra_dependencies}" 76 ) 77 78endmacro(execute_process_with_stale_check) 79 80# For custom commands that invoke other build systems, we can create a depfile 81# based on a find traversal of the directory. This saves using CMake to glob it 82# which is much slower 83macro(create_depfile_by_find ret outfile depfile dir) 84 file(RELATIVE_PATH path ${CMAKE_BINARY_DIR} ${outfile}) 85 list( 86 APPEND 87 ${ret} 88 COMMAND 89 printf 90 "${path}: " 91 > 92 ${depfile} 93 ) 94 list( 95 APPEND ${ret} COMMAND 96 find 97 -L 98 ${dir} 99 -type 100 f 101 -printf 102 "%p " 103 >> 104 ${depfile} 105 ) 106 list(APPEND ${ret} DEPFILE ${depfile}) 107endmacro() 108