1find_package(Git)
2
3if(NOT GIT_FOUND)
4    message(WARNING "Git executable was not found. Git submodule checks will not be executed. "
5        "If you have any build issues at all, start by adding git executable to the PATH and "
6        "rerun cmake to not see this warning again.")
7
8    function(git_submodule_check root_path)
9        # no-op
10    endfunction()
11else()
12
13    function(git_submodule_check root_path)
14        # for internal use:
15        # skip submodule check if running on Gitlab CI and job is configured as not clone submodules
16        if($ENV{IDF_SKIP_CHECK_SUBMODULES})
17            if($ENV{IDF_SKIP_CHECK_SUBMODULES} EQUAL 1)
18                message("skip submodule check on internal CI")
19                return()
20            endif()
21        endif()
22
23        execute_process(
24            COMMAND ${GIT_EXECUTABLE} submodule status
25            WORKING_DIRECTORY ${root_path}
26            OUTPUT_VARIABLE submodule_status
27            )
28
29        # git submodule status output not guaranteed to be stable,
30        # may need to check GIT_VERSION_STRING and do some fiddling in the
31        # future...
32
33        lines2list(submodule_status)
34
35        foreach(line ${submodule_status})
36            string(REGEX MATCH "(.)[0-9a-f]+ ([^\( ]+) ?" _ignored "${line}")
37            set(status "${CMAKE_MATCH_1}")
38            set(submodule_path "${CMAKE_MATCH_2}")
39
40            if("${status}" STREQUAL "-")  # missing submodule
41                message(STATUS "Initialising new submodule ${submodule_path}...")
42                execute_process(
43                    COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive ${submodule_path}
44                    WORKING_DIRECTORY ${root_path}
45                    RESULT_VARIABLE git_result
46                    )
47                if(git_result)
48                    message(FATAL_ERROR "Git submodule init failed for ${submodule_path}")
49                endif()
50
51            elseif(NOT "${status}" STREQUAL " ")
52                message(WARNING "Git submodule ${submodule_path} is out of date. "
53                    "Run 'git submodule update --init --recursive' to fix.")
54            endif()
55
56            # Force a re-run of cmake if the submodule's .git file changes or is changed (ie accidental deinit)
57            get_filename_component(submodule_abs_path ${submodule_path} ABSOLUTE BASE_DIR ${root_path})
58            set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${submodule_abs_path}/.git)
59            # same if the HEAD file in the submodule's directory changes (ie commit changes).
60            # This will at least print the 'out of date' warning
61            set(submodule_head "${root_path}/.git/modules/${submodule_path}/HEAD")
62            if(EXISTS "${submodule_head}")
63                set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${submodule_head})
64            endif()
65
66        endforeach()
67    endfunction()
68
69endif()
70