-
-
Notifications
You must be signed in to change notification settings - Fork 1k
/
Copy pathCheckSubmodules.cmake
138 lines (120 loc) · 4.28 KB
/
CheckSubmodules.cmake
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# Utility for validating and, if needed, cloning all submodules
#
# Looks for a .gitmodules in the root project folder
# Loops over all modules looking well-known configure/build scripts
#
# Usage:
# INCLUDE(CheckSubmodules)
#
# Options:
# SET(SKIP_SUBMODULES "foo;bar")
#
# Or via command line:
# cmake -DSKIP_SUBMODULES=foo;bar
#
# Copyright (c) 2017, Tres Finocchiaro, <[email protected]>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
# Files which confirm a successful clone
SET(VALID_CRUMBS "CMakeLists.txt;Makefile;Makefile.in;Makefile.am;configure.ac;configure.py;autogen.sh")
# Try and use the specified shallow clone on submodules, if supported
SET(DEPTH_VALUE 100)
# Number of times git commands will retry before failing
SET(MAX_ATTEMPTS 2)
MESSAGE("\nValidating submodules...")
FILE(READ "${CMAKE_SOURCE_DIR}/.gitmodules" SUBMODULE_DATA)
# Assume alpha-numeric paths
STRING(REGEX MATCHALL "path = [-0-9A-Za-z/]+" SUBMODULE_LIST ${SUBMODULE_DATA})
FOREACH(_part ${SUBMODULE_LIST})
STRING(REPLACE "path = " "" SUBMODULE_PATH ${_part})
# Remove submodules from validation as specified in -DSKIP_SUBMODULES=foo;bar
SET(SKIP false)
IF(SKIP_SUBMODULES)
FOREACH(_skip ${SKIP_SUBMODULES})
IF(${SUBMODULE_PATH} MATCHES ${_skip})
MESSAGE("-- Skipping ${SUBMODULE_PATH} matches \"${_skip}\"")
SET(SKIP true)
ENDIF()
ENDFOREACH()
ENDIF()
LIST(REMOVE_ITEM SUBMODULE_LIST ${_part})
IF(NOT SKIP)
LIST(APPEND SUBMODULE_LIST ${SUBMODULE_PATH})
ENDIF()
ENDFOREACH()
LIST(SORT SUBMODULE_LIST)
# Once called, status is stored in GIT_RESULT respectively.
# Note: Git likes to write to stderr. Don't assume stderr is error; Check GIT_RESULT instead.
MACRO(GIT_SUBMODULE SUBMODULE_PATH FORCE_DEINIT)
FIND_PACKAGE(Git REQUIRED)
IF(${FORCE_DEINIT})
MESSAGE("-- Resetting ${SUBMODULE_PATH}")
EXECUTE_PROCESS(
COMMAND ${GIT_EXECUTABLE} submodule deinit -f ${CMAKE_SOURCE_DIR}/${SUBMODULE_PATH}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_QUIET
)
# Recurse
GIT_SUBMODULE(${SUBMODULE_PATH} false)
ELSE()
# Try to use the depth switch
SET(DEPTH_CMD "")
MESSAGE("-- Fetching ${SUBMODULE_PATH}")
IF(DEPTH_VALUE)
SET(DEPTH_CMD "--depth" )
MESSAGE("-- Fetching ${SUBMODULE_PATH} @ --depth ${DEPTH_VALUE}")
ENDIF()
EXECUTE_PROCESS(
COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive ${DEPTH_CMD} ${DEPTH_VALUE} ${CMAKE_SOURCE_DIR}/${SUBMODULE_PATH}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
RESULT_VARIABLE GIT_RESULT
OUTPUT_VARIABLE GIT_STDOUT
ERROR_VARIABLE GIT_STDERR
)
SET(GIT_MESSAGE "${GIT_STDOUT}${GIT_STDERR}")
MESSAGE("${GIT_MESSAGE}")
ENDIF()
ENDMACRO()
SET(RETRY_PHRASES "Failed to recurse;unadvertised object;cannot create directory")
# Attempt to do lazy clone
FOREACH(_submodule ${SUBMODULE_LIST})
STRING(REPLACE "/" ";" PATH_PARTS ${_submodule})
LIST(REVERSE PATH_PARTS)
LIST(GET PATH_PARTS 0 SUBMODULE_NAME)
MESSAGE("-- Checking ${SUBMODULE_NAME}...")
SET(CRUMB_FOUND false)
FOREACH(_crumb ${VALID_CRUMBS})
IF(EXISTS "${CMAKE_SOURCE_DIR}/${_submodule}/${_crumb}")
SET(CRUMB_FOUND true)
MESSAGE("-- Found ${_submodule}/${_crumb}")
ENDIF()
ENDFOREACH()
IF(NOT CRUMB_FOUND)
GIT_SUBMODULE(${_submodule} false)
SET(COUNTED 0)
SET(COUNTING "")
# Handle edge-cases where submodule didn't clone properly or re-uses a non-empty directory
WHILE(NOT GIT_RESULT EQUAL 0 AND COUNTED LESS MAX_ATTEMPTS)
LIST(APPEND COUNTING "x")
LIST(LENGTH COUNTING COUNTED)
FOREACH(_phrase ${RETRY_PHRASES})
IF("${GIT_MESSAGE}" MATCHES "${_phrase}")
MESSAGE("-- Retrying ${_submodule} using 'deinit' (attempt ${COUNTED} of ${MAX_ATTEMPTS})...")
# Shallow submodules were introduced in 1.8.4
# Shallow commits can fail to clone from non-default branches, only try once
IF(GIT_VERSION_STRING VERSION_GREATER "1.8.3" AND COUNTED LESS 2)
# Try a shallow submodule clone
ELSE()
UNSET(DEPTH_VALUE)
ENDIF()
GIT_SUBMODULE(${_submodule} true)
ENDIF()
ENDFOREACH()
ENDWHILE()
IF(NOT GIT_RESULT EQUAL 0)
MESSAGE(FATAL_ERROR "${GIT_EXECUTABLE} exited with status of ${GIT_RESULT}")
ENDIF()
ENDIF()
ENDFOREACH()
MESSAGE("-- Done validating submodules.\n")