Resync
[CMakeLuaTailorHgBridge.git] / CMakeLua / Modules / GetPrerequisites.cmake
blobe7457d61b52071781a886ae04bd7684f1dc4c044
1 # GetPrerequisites.cmake
3 # This script provides functions to list the .dll, .dylib or .so files that an
4 # executable or shared library file depends on. (Its prerequisites.)
6 # It uses various tools to obtain the list of required shared library files:
7 #   dumpbin (Windows)
8 #   ldd (Linux/Unix)
9 #   otool (Mac OSX)
11 # The following functions are provided by this script:
12 #   gp_append_unique
13 #   gp_file_type
14 #   is_file_executable
15 #   gp_item_default_embedded_path
16 #     (projects can override with gp_item_default_embedded_path_override)
17 #   gp_resolve_item
18 #     (projects can override with gp_resolve_item_override)
19 #   get_prerequisites
20 #   list_prerequisites
21 #   list_prerequisites_by_glob
23 # Requires CMake 2.6 or greater because it uses function, break, return and
24 # PARENT_SCOPE.
27 # gp_append_unique list_var value
29 # Append value to the list variable ${list_var} only if the value is not
30 # already in the list.
32 function(gp_append_unique list_var value)
33   set(contains 0)
35   foreach(item ${${list_var}})
36     if("${item}" STREQUAL "${value}")
37       set(contains 1)
38       break()
39     endif("${item}" STREQUAL "${value}")
40   endforeach(item)
42   if(NOT contains)
43     set(${list_var} ${${list_var}} "${value}" PARENT_SCOPE)
44   endif(NOT contains)
45 endfunction(gp_append_unique)
48 # gp_file_type original_file file type_var
50 # Return the type of ${file} with respect to ${original_file}. String
51 # describing type of prerequisite is returned in variable named ${type_var}.
53 # Possible types are:
54 #   system
55 #   local
56 #   embedded
57 #   other
59 function(gp_file_type original_file file type_var)
60   set(is_embedded 0)
61   set(is_local 0)
62   set(is_system 0)
64   string(TOLOWER "${original_file}" original_lower)
65   string(TOLOWER "${file}" lower)
67   if("${file}" MATCHES "^@(executable|loader)_path")
68     set(is_embedded 1)
69   endif("${file}" MATCHES "^@(executable|loader)_path")
71   if(NOT is_embedded)
72     if(UNIX)
73       if("${file}" MATCHES "^(/lib/|/lib32/|/lib64/)")
74         set(is_system 1)
75       endif("${file}" MATCHES "^(/lib/|/lib32/|/lib64/)")
76     endif(UNIX)
78     if(APPLE)
79       if("${file}" MATCHES "^(/System/Library/|/usr/lib/)")
80         set(is_system 1)
81       endif("${file}" MATCHES "^(/System/Library/|/usr/lib/)")
82     endif(APPLE)
84     if(WIN32)
85       string(TOLOWER "$ENV{SystemRoot}" sysroot)
86       string(REGEX REPLACE "\\\\" "/" sysroot "${sysroot}")
88       string(TOLOWER "$ENV{windir}" windir)
89       string(REGEX REPLACE "\\\\" "/" windir "${windir}")
91       if("${lower}" MATCHES "^(${sysroot}/system|${windir}/system|msvc[^/]+dll)")
92         set(is_system 1)
93       endif("${lower}" MATCHES "^(${sysroot}/system|${windir}/system|msvc[^/]+dll)")
94     endif(WIN32)
96     if(NOT is_system)
97       get_filename_component(original_path "${original_lower}" PATH)
98       get_filename_component(path "${lower}" PATH)
99       if("${original_path}" STREQUAL "${path}")
100         set(is_local 1)
101       endif("${original_path}" STREQUAL "${path}")
102     endif(NOT is_system)
103   endif(NOT is_embedded)
105   # Return type string based on computed booleans:
106   #
107   set(type "other")
109   if(is_system)
110     set(type "system")
111   else(is_system)
112     if(is_embedded)
113       set(type "embedded")
114     else(is_embedded)
115       if(is_local)
116         set(type "local")
117       endif(is_local)
118     endif(is_embedded)
119   endif(is_system)
121   set(${type_var} "${type}" PARENT_SCOPE)
122 endfunction(gp_file_type)
125 # is_file_executable file result_var
127 # Return 1 in ${result_var} if ${file} is a binary executable.
129 # Return 0 in ${result_var} otherwise.
131 function(is_file_executable file result_var)
132   #
133   # A file is not executable until proven otherwise:
134   #
135   set(${result_var} 0 PARENT_SCOPE)
137   get_filename_component(file_full "${file}" ABSOLUTE)
138   string(TOLOWER "${file_full}" file_full_lower)
140   # If file name ends in .exe or .dll on Windows, *assume* executable:
141   #
142   if(WIN32)
143     if("${file_full_lower}" MATCHES "\\.(exe|dll)$")
144       set(${result_var} 1 PARENT_SCOPE)
145       return()
146     endif("${file_full_lower}" MATCHES "\\.(exe|dll)$")
148     # A clause could be added here that uses output or return value of dumpbin
149     # to determine ${result_var}. In 99%+? practical cases, the exe|dll name
150     # match will be sufficient...
151     #
152   endif(WIN32)
154   # Use the information returned from the Unix shell command "file" to
155   # determine if ${file_full} should be considered an executable file...
156   #
157   # If the file command's output contains "executable" and does *not* contain
158   # "text" then it is likely an executable suitable for prerequisite analysis
159   # via the get_prerequisites macro.
160   #
161   if(UNIX)
162     if(NOT file_cmd)
163       find_program(file_cmd "file")
164     endif(NOT file_cmd)
166     if(file_cmd)
167       execute_process(COMMAND "${file_cmd}" "${file_full}"
168         OUTPUT_VARIABLE file_ov
169         OUTPUT_STRIP_TRAILING_WHITESPACE
170         )
172       # Replace the name of the file in the output with a placeholder token
173       # (the string " _file_full_ ") so that just in case the path name of
174       # the file contains the word "text" or "executable" we are not fooled
175       # into thinking "the wrong thing" because the file name matches the
176       # other 'file' command output we are looking for...
177       #
178       string(REPLACE "${file_full}" " _file_full_ " file_ov "${file_ov}")
179       string(TOLOWER "${file_ov}" file_ov)
181       #message(STATUS "file_ov='${file_ov}'")
182       if("${file_ov}" MATCHES "executable")
183         #message(STATUS "executable!")
184         if("${file_ov}" MATCHES "text")
185           #message(STATUS "but text, so *not* a binary executable!")
186         else("${file_ov}" MATCHES "text")
187           set(${result_var} 1 PARENT_SCOPE)
188           return()
189         endif("${file_ov}" MATCHES "text")
190       endif("${file_ov}" MATCHES "executable")
191     else(file_cmd)
192       message(STATUS "warning: No 'file' command, skipping execute_process...")
193     endif(file_cmd)
194   endif(UNIX)
195 endfunction(is_file_executable)
198 # gp_item_default_embedded_path item default_embedded_path_var
200 # Return the path that others should refer to the item by when the item
201 # is embedded inside a bundle.
203 # Override on a per-project basis by providing a project-specific
204 # gp_item_default_embedded_path_override function.
206 function(gp_item_default_embedded_path item default_embedded_path_var)
207   #
208   # The assumption here is that all executables in the bundle will be
209   # in same-level-directories inside the bundle. The parent directory
210   # of an executable inside the bundle should be MacOS or a sibling of
211   # MacOS and all embedded paths returned from here will begin with
212   # "@executable_path/../" and will work from all executables in all
213   # such same-level-directories inside the bundle.
214   #
216   # By default, embed things right next to the main bundle executable:
217   #
218   set(path "@executable_path/../../Contents/MacOS")
220   set(overridden 0)
222   # Embed .dylibs right next to the main bundle executable:
223   #
224   if(item MATCHES "\\.dylib$")
225     set(path "@executable_path/../MacOS")
226     set(overridden 1)
227   endif(item MATCHES "\\.dylib$")
229   # Embed frameworks in the embedded "Frameworks" directory (sibling of MacOS):
230   #
231   if(NOT overridden)
232     if(item MATCHES "[^/]+\\.framework/")
233       set(path "@executable_path/../Frameworks")
234       set(overridden 1)
235     endif(item MATCHES "[^/]+\\.framework/")
236   endif(NOT overridden)
238   # Provide a hook so that projects can override the default embedded location of
239   # any given library by whatever logic they choose:
240   #
241   if(COMMAND gp_item_default_embedded_path_override)
242     gp_item_default_embedded_path_override("${item}" path)
243   endif(COMMAND gp_item_default_embedded_path_override)
245   set(${default_embedded_path_var} "${path}" PARENT_SCOPE)
246 endfunction(gp_item_default_embedded_path)
249 # gp_resolve_item context item exepath dirs resolved_item_var
251 # Resolve an item into an existing full path file.
253 # Override on a per-project basis by providing a project-specific
254 # gp_resolve_item_override function.
256 function(gp_resolve_item context item exepath dirs resolved_item_var)
257   set(resolved 0)
258   set(resolved_item "${item}")
260   # Is it already resolved?
261   #
262   if(EXISTS "${resolved_item}")
263     set(resolved 1)
264   endif(EXISTS "${resolved_item}")
266   if(NOT resolved)
267     if(item MATCHES "@executable_path")
268       #
269       # @executable_path references are assumed relative to exepath
270       #
271       string(REPLACE "@executable_path" "${exepath}" ri "${item}")
272       get_filename_component(ri "${ri}" ABSOLUTE)
274       if(EXISTS "${ri}")
275         #message(STATUS "info: embedded item exists (${ri})")
276         set(resolved 1)
277         set(resolved_item "${ri}")
278       else(EXISTS "${ri}")
279         message(STATUS "info: embedded item does not exist '${ri}'")
280       endif(EXISTS "${ri}")
281     endif(item MATCHES "@executable_path")
282   endif(NOT resolved)
284   if(NOT resolved)
285     if(item MATCHES "@loader_path")
286       #
287       # @loader_path references are assumed relative to the
288       # PATH of the given "context" (presumably another library)
289       #
290       get_filename_component(contextpath "${context}" PATH)
291       string(REPLACE "@loader_path" "${contextpath}" ri "${item}")
292       get_filename_component(ri "${ri}" ABSOLUTE)
294       if(EXISTS "${ri}")
295         #message(STATUS "info: embedded item exists (${ri})")
296         set(resolved 1)
297         set(resolved_item "${ri}")
298       else(EXISTS "${ri}")
299         message(STATUS "info: embedded item does not exist '${ri}'")
300       endif(EXISTS "${ri}")
301     endif(item MATCHES "@loader_path")
302   endif(NOT resolved)
304   if(NOT resolved)
305     set(ri "ri-NOTFOUND")
306     find_file(ri "${item}" ${dirs})
307     if(ri)
308       #message(STATUS "info: found item in dirs (${ri})")
309       set(resolved 1)
310       set(resolved_item "${ri}")
311       set(ri "ri-NOTFOUND")
312     endif(ri)
313   endif(NOT resolved)
315   if(NOT resolved)
316     if(item MATCHES "[^/]+\\.framework/")
317       set(fw "fw-NOTFOUND")
318       find_file(fw "${item}"
319         "~/Library/Frameworks"
320         "/Library/Frameworks"
321         "/System/Library/Frameworks"
322       )
323       if(fw)
324         #message(STATUS "info: found framework (${fw})")
325         set(resolved 1)
326         set(resolved_item "${fw}")
327         set(fw "fw-NOTFOUND")
328       endif(fw)
329     endif(item MATCHES "[^/]+\\.framework/")
330   endif(NOT resolved)
332   # Using find_program on Windows will find dll files that are in the PATH.
333   # (Converting simple file names into full path names if found.)
334   #
335   if(WIN32)
336   if(NOT resolved)
337     set(ri "ri-NOTFOUND")
338     find_program(ri "${item}" PATHS "${dirs}")
339     if(ri)
340       set(resolved 1)
341       set(resolved_item "${ri}")
342       set(ri "ri-NOTFOUND")
343     endif(ri)
344   endif(NOT resolved)
345   endif(WIN32)
347   # Provide a hook so that projects can override item resolution
348   # by whatever logic they choose:
349   #
350   if(COMMAND gp_resolve_item_override)
351     gp_resolve_item_override("${context}" "${item}" "${exepath}" "${dirs}" resolved_item resolved)
352   endif(COMMAND gp_resolve_item_override)
354   if(NOT resolved)
355     message(STATUS "warning: cannot resolve item '${item}'")
356   endif(NOT resolved)
358   set(${resolved_item_var} "${resolved_item}" PARENT_SCOPE)
359 endfunction(gp_resolve_item)
362 # get_prerequisites target prerequisites_var exclude_system recurse dirs
364 # Get the list of shared library files required by ${target}. The list in
365 # the variable named ${prerequisites_var} should be empty on first entry to
366 # this function. On exit, ${prerequisites_var} will contain the list of
367 # required shared library files.
369 #  target is the full path to an executable file
371 #  prerequisites_var is the name of a CMake variable to contain the results
373 #  exclude_system is 0 or 1: 0 to include "system" prerequisites , 1 to
374 #   exclude them
376 #  recurse is 0 or 1: 0 for direct prerequisites only, 1 for all prerequisites
377 #   recursively
379 #  exepath is the path to the top level executable used for @executable_path
380 #   replacment on the Mac
382 #  dirs is a list of paths where libraries might be found: these paths are
383 #   searched first when a target without any path info is given. Then standard
384 #   system locations are also searched: PATH, Framework locations, /usr/lib...
386 function(get_prerequisites target prerequisites_var exclude_system recurse exepath dirs)
387   set(verbose 0)
388   set(eol_char "E")
390   if(NOT IS_ABSOLUTE "${target}")
391     message("warning: target '${target}' is not absolute...")
392   endif(NOT IS_ABSOLUTE "${target}")
394   if(NOT EXISTS "${target}")
395     message("warning: target '${target}' does not exist...")
396   endif(NOT EXISTS "${target}")
398   # <setup-gp_tool-vars>
399   #
400   # Try to choose the right tool by default. Caller can set gp_tool prior to
401   # calling this function to force using a different tool.
402   #
403   if("${gp_tool}" STREQUAL "")
404     set(gp_tool "ldd")
405     if(APPLE)
406       set(gp_tool "otool")
407     endif(APPLE)
408     if(WIN32)
409       set(gp_tool "dumpbin")
410     endif(WIN32)
411   endif("${gp_tool}" STREQUAL "")
413   set(gp_tool_known 0)
415   if("${gp_tool}" STREQUAL "ldd")
416     set(gp_cmd_args "")
417     set(gp_regex "^[\t ]*[^\t ]+ => ([^\t ]+).*${eol_char}$")
418     set(gp_regex_cmp_count 1)
419     set(gp_tool_known 1)
420   endif("${gp_tool}" STREQUAL "ldd")
422   if("${gp_tool}" STREQUAL "otool")
423     set(gp_cmd_args "-L")
424     set(gp_regex "^\t([^\t]+) \\(compatibility version ([0-9]+.[0-9]+.[0-9]+), current version ([0-9]+.[0-9]+.[0-9]+)\\)${eol_char}$")
425     set(gp_regex_cmp_count 3)
426     set(gp_tool_known 1)
427   endif("${gp_tool}" STREQUAL "otool")
429   if("${gp_tool}" STREQUAL "dumpbin")
430     set(gp_cmd_args "/dependents")
431     set(gp_regex "^    ([^ ].*[Dd][Ll][Ll])${eol_char}$")
432     set(gp_regex_cmp_count 1)
433     set(gp_tool_known 1)
434     set(ENV{VS_UNICODE_OUTPUT} "") # Block extra output from inside VS IDE.
435   endif("${gp_tool}" STREQUAL "dumpbin")
437   if(NOT gp_tool_known)
438     message(STATUS "warning: gp_tool='${gp_tool}' is an unknown tool...")
439     message(STATUS "CMake function get_prerequisites needs more code to handle '${gp_tool}'")
440     message(STATUS "Valid gp_tool values are dumpbin, ldd and otool.")
441     return()
442   endif(NOT gp_tool_known)
444   set(gp_cmd_paths ${gp_cmd_paths}
445     "C:/Program Files/Microsoft Visual Studio 9.0/VC/bin"
446     "C:/Program Files (x86)/Microsoft Visual Studio 9.0/VC/bin"
447     "C:/Program Files/Microsoft Visual Studio 8/VC/BIN"
448     "C:/Program Files (x86)/Microsoft Visual Studio 8/VC/BIN"
449     "C:/Program Files/Microsoft Visual Studio .NET 2003/VC7/BIN"
450     "C:/Program Files (x86)/Microsoft Visual Studio .NET 2003/VC7/BIN"
451     "/usr/local/bin"
452     "/usr/bin"
453     )
455   find_program(gp_cmd ${gp_tool} PATHS ${gp_cmd_paths})
457   if(NOT gp_cmd)
458     message(STATUS "warning: could not find '${gp_tool}' - cannot analyze prerequisites...")
459     return()
460   endif(NOT gp_cmd)
462   if("${gp_tool}" STREQUAL "dumpbin")
463     # When running dumpbin, it also needs the "Common7/IDE" directory in the
464     # PATH. It will already be in the PATH if being run from a Visual Studio
465     # command prompt. Add it to the PATH here in case we are running from a
466     # different command prompt.
467     #
468     get_filename_component(gp_cmd_dir "${gp_cmd}" PATH)
469     get_filename_component(gp_cmd_dlls_dir "${gp_cmd_dir}/../../Common7/IDE" ABSOLUTE)
470     if(EXISTS "${gp_cmd_dlls_dir}")
471       # only add to the path if it is not already in the path
472       if(NOT "$ENV{PATH}" MATCHES "${gp_cmd_dlls_dir}")
473         set(ENV{PATH} "$ENV{PATH};${gp_cmd_dlls_dir}")
474       endif(NOT "$ENV{PATH}" MATCHES "${gp_cmd_dlls_dir}")
475     endif(EXISTS "${gp_cmd_dlls_dir}")
476   endif("${gp_tool}" STREQUAL "dumpbin")
477   #
478   # </setup-gp_tool-vars>
480   # Track new prerequisites at each new level of recursion. Start with an
481   # empty list at each level:
482   #
483   set(unseen_prereqs)
485   # Run gp_cmd on the target:
486   #
487   execute_process(
488     COMMAND ${gp_cmd} ${gp_cmd_args} ${target}
489     OUTPUT_VARIABLE gp_cmd_ov
490     )
492   if(verbose)
493     message(STATUS "<RawOutput cmd='${gp_cmd} ${gp_cmd_args} ${target}'>")
494     message(STATUS "gp_cmd_ov='${gp_cmd_ov}'")
495     message(STATUS "</RawOutput>")
496   endif(verbose)
498   get_filename_component(target_dir "${target}" PATH)
500   # Convert to a list of lines:
501   #
502   string(REGEX REPLACE ";" "\\\\;" candidates "${gp_cmd_ov}")
503   string(REGEX REPLACE "\n" "${eol_char};" candidates "${candidates}")
505   # Analyze each line for file names that match the regular expression:
506   #
507   foreach(candidate ${candidates})
508   if("${candidate}" MATCHES "${gp_regex}")
509     # Extract information from each candidate:
510     string(REGEX REPLACE "${gp_regex}" "\\1" raw_item "${candidate}")
512     if(gp_regex_cmp_count GREATER 1)
513       string(REGEX REPLACE "${gp_regex}" "\\2" raw_compat_version "${candidate}")
514       string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\1" compat_major_version "${raw_compat_version}")
515       string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\2" compat_minor_version "${raw_compat_version}")
516       string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\3" compat_patch_version "${raw_compat_version}")
517     endif(gp_regex_cmp_count GREATER 1)
519     if(gp_regex_cmp_count GREATER 2)
520       string(REGEX REPLACE "${gp_regex}" "\\3" raw_current_version "${candidate}")
521       string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\1" current_major_version "${raw_current_version}")
522       string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\2" current_minor_version "${raw_current_version}")
523       string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\3" current_patch_version "${raw_current_version}")
524     endif(gp_regex_cmp_count GREATER 2)
526     # Use the raw_item as the list entries returned by this function. Use the
527     # gp_resolve_item function to resolve it to an actual full path file if
528     # necessary.
529     #
530     set(item "${raw_item}")
532     # Add each item unless it is excluded:
533     #
534     set(add_item 1)
536     if(${exclude_system})
537       set(type "")
538       gp_file_type("${target}" "${item}" type)
540       if("${type}" STREQUAL "system")
541         set(add_item 0)
542       endif("${type}" STREQUAL "system")
543     endif(${exclude_system})
545     if(add_item)
546       list(LENGTH ${prerequisites_var} list_length_before_append)
547       gp_append_unique(${prerequisites_var} "${item}")
548       list(LENGTH ${prerequisites_var} list_length_after_append)
550       if(${recurse})
551         # If item was really added, this is the first time we have seen it.
552         # Add it to unseen_prereqs so that we can recursively add *its*
553         # prerequisites...
554         #
555         # But first: resolve its name to an absolute full path name such
556         # that the analysis tools can simply accept it as input.
557         #
558         if(NOT list_length_before_append EQUAL list_length_after_append)
559           gp_resolve_item("${target}" "${item}" "${exepath}" "${dirs}" resolved_item)
560           set(unseen_prereqs ${unseen_prereqs} "${resolved_item}")
561         endif(NOT list_length_before_append EQUAL list_length_after_append)
562       endif(${recurse})
563     endif(add_item)
564   else("${candidate}" MATCHES "${gp_regex}")
565     if(verbose)
566       message(STATUS "ignoring non-matching line: '${candidate}'")
567     endif(verbose)
568   endif("${candidate}" MATCHES "${gp_regex}")
569   endforeach(candidate)
571   list(LENGTH ${prerequisites_var} prerequisites_var_length)
572   if(prerequisites_var_length GREATER 0)
573     list(SORT ${prerequisites_var})
574   endif(prerequisites_var_length GREATER 0)
575   if(${recurse})
576     set(more_inputs ${unseen_prereqs})
577     foreach(input ${more_inputs})
578       get_prerequisites("${input}" ${prerequisites_var} ${exclude_system} ${recurse} "${exepath}" "${dirs}")
579     endforeach(input)
580   endif(${recurse})
582   set(${prerequisites_var} ${${prerequisites_var}} PARENT_SCOPE)
583 endfunction(get_prerequisites)
586 # list_prerequisites target all exclude_system verbose
588 #  ARGV0 (target) is the full path to an executable file
590 #  optional ARGV1 (all) is 0 or 1: 0 for direct prerequisites only,
591 #   1 for all prerequisites recursively
593 #  optional ARGV2 (exclude_system) is 0 or 1: 0 to include "system"
594 #   prerequisites , 1 to exclude them
596 #  optional ARGV3 (verbose) is 0 or 1: 0 to print only full path
597 #   names of prerequisites, 1 to print extra information
599 function(list_prerequisites target)
600   if("${ARGV1}" STREQUAL "")
601     set(all 1)
602   else("${ARGV1}" STREQUAL "")
603     set(all "${ARGV1}")
604   endif("${ARGV1}" STREQUAL "")
606   if("${ARGV2}" STREQUAL "")
607     set(exclude_system 0)
608   else("${ARGV2}" STREQUAL "")
609     set(exclude_system "${ARGV2}")
610   endif("${ARGV2}" STREQUAL "")
612   if("${ARGV3}" STREQUAL "")
613     set(verbose 0)
614   else("${ARGV3}" STREQUAL "")
615     set(verbose "${ARGV3}")
616   endif("${ARGV3}" STREQUAL "")
618   set(count 0)
619   set(count_str "")
620   set(print_count "${verbose}")
621   set(print_prerequisite_type "${verbose}")
622   set(print_target "${verbose}")
623   set(type_str "")
625   get_filename_component(exepath "${target}" PATH)
627   set(prereqs "")
628   get_prerequisites("${target}" prereqs ${exclude_system} ${all} "${exepath}" "")
630   if(print_target)
631     message(STATUS "File '${target}' depends on:")
632   endif(print_target)
634   foreach(d ${prereqs})
635     math(EXPR count "${count} + 1")
637     if(print_count)
638       set(count_str "${count}. ")
639     endif(print_count)
641     if(print_prerequisite_type)
642       gp_file_type("${target}" "${d}" type)
643       set(type_str " (${type})")
644     endif(print_prerequisite_type)
646     message(STATUS "${count_str}${d}${type_str}")
647   endforeach(d)
648 endfunction(list_prerequisites)
651 # list_prerequisites_by_glob glob_arg glob_exp
653 #  glob_arg is GLOB or GLOB_RECURSE
655 #  glob_exp is a globbing expression used with "file(GLOB" to retrieve a list
656 #   of matching files. If a matching file is executable, its prerequisites are
657 #   listed.
659 # Any additional (optional) arguments provided are passed along as the
660 # optional arguments to the list_prerequisites calls.
662 function(list_prerequisites_by_glob glob_arg glob_exp)
663   message(STATUS "=============================================================================")
664   message(STATUS "List prerequisites of executables matching ${glob_arg} '${glob_exp}'")
665   message(STATUS "")
666   file(${glob_arg} file_list ${glob_exp})
667   foreach(f ${file_list})
668     is_file_executable("${f}" is_f_executable)
669     if(is_f_executable)
670       message(STATUS "=============================================================================")
671       list_prerequisites("${f}" ${ARGN})
672       message(STATUS "")
673     endif(is_f_executable)
674   endforeach(f)
675 endfunction(list_prerequisites_by_glob)