2

I'd like implement a function in cmake to search a list of path recursively.

Say given a search_paths: /a/b, /c, /d/e. I want to have a return_list with paths of directories under given search_paths which contains .h files. Here is my function:

FUNCTION(R_SEARCH search_paths return_list)
    FOREACH(search_path ${search_paths})
        # POINT A
        R_SEARCH_INNER(${search_path} inner_return)
        SET(all_list ${all_list} ${inner_return})
    ENDFOREACH()
    SET(${return_list} ${all_list})
ENDFUNCTION(R_SEARCH)


FUNCTION(R_SEARCH_INNER search_path return_list)
    FILE(GLOB_RECURSE new_list ${search_path} *.h)
    SET(dir_list "")
    FOREACH(file_path ${new_list})
        GET_FILENAME_COMPONENT(dir_path ${file_path} PATH)
        SET(dir_list ${dir_list} ${dir_path})
    ENDFOREACH()
    LIST(REMOVE_DUPLICATES dir_list)
    SET(${return_list} ${dir_list})
ENDFUNCTION(R_SEARCH_INNER)        

based on http://public.kitware.com/pipermail/cmake/2012-June/050674.html

However, the inner function call on POINT A will only happen once. Could anybody give me some hints or provide a workable solution.

iLeoDo
  • 397
  • 3
  • 11
  • 1
    A `function()` does open its own variable scope. So one thing that you have to change would be to add `PARENT_SCOPE` to your return values (e.g. `SET(${return_list} ${dir_list} PARENT_SCOPE)`) – Florian Aug 30 '16 at 09:01
  • Can you also show the code where you call the function, and possibly the input scenario (directory and file structure) and the function output? – Antonio Aug 30 '16 at 15:01
  • 1
    @iLeoDo Out of fairness, I think you should mention/link [the source of your code](http://public.kitware.com/pipermail/cmake/2012-June/050674.html). – Florian Aug 30 '16 at 19:21
  • @Florian Thanks for reminding. – iLeoDo Aug 30 '16 at 19:38
  • Possible duplicate of [cmake function, parameter and return](http://stackoverflow.com/questions/22487215/cmake-function-parameter-and-return) – usr1234567 Aug 31 '16 at 06:55
  • 1
    @usr1234567 That was not the only issue with this function – Antonio Aug 31 '16 at 08:03

1 Answers1

4

You should change this:

FILE(GLOB_RECURSE new_list ${search_path} *.h)

into

FILE(GLOB_RECURSE new_list ${search_path}/*.h)

See documentation:

Examples of recursive globbing include:

/dir/*.py  - match all python files in /dir and subdirectories

Also, as already suggested (see also here), change:

SET(${return_list} ${all_list})
[...]
SET(${return_list} ${dir_list})

into:

SET(${return_list} ${all_list} PARENT_SCOPE)
[...]
SET(${return_list} ${dir_list} PARENT_SCOPE)

So the corrected code becomes:

FUNCTION(R_SEARCH search_paths return_list)
    FOREACH(search_path ${search_paths})
        # POINT A
        R_SEARCH_INNER(${search_path} inner_return)
        SET(all_list ${all_list} ${inner_return})
    ENDFOREACH()
    SET(${return_list} ${all_list} PARENT_SCOPE)
ENDFUNCTION(R_SEARCH)


FUNCTION(R_SEARCH_INNER search_path return_list)
    FILE(GLOB_RECURSE new_list ${search_path}/*.h)
    SET(dir_list "")
    FOREACH(file_path ${new_list})
        GET_FILENAME_COMPONENT(dir_path ${file_path} PATH)
        SET(dir_list ${dir_list} ${dir_path})
    ENDFOREACH()
    LIST(REMOVE_DUPLICATES dir_list)
    SET(${return_list} ${dir_list} PARENT_SCOPE)
ENDFUNCTION(R_SEARCH_INNER)       
Community
  • 1
  • 1
Antonio
  • 19,451
  • 13
  • 99
  • 197