Use CMake to fetch submodules

Custom CMake module which attempts to automatically clone submodules when they're missing.  Uses the `--depth` option if supported, which should be faster than running `--recursive` on initial clone.
This commit is contained in:
Tres Finocchiaro
2017-11-15 14:23:04 -05:00
committed by GitHub
parent 0f7d192681
commit 0dab4aea06
3 changed files with 145 additions and 4 deletions

View File

@@ -13,6 +13,7 @@ IF(COMMAND CMAKE_POLICY)
ENDIF()
ENDIF(COMMAND CMAKE_POLICY)
INCLUDE(CheckSubmodules)
INCLUDE(AddFileDependencies)
INCLUDE(CheckIncludeFiles)
INCLUDE(FindPkgConfig)

View File

@@ -0,0 +1,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, <tres.finocchiaro@gmail.com>
#
# 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")

View File

@@ -160,10 +160,12 @@ TARGET_LINK_LIBRARIES(lmms
)
FOREACH(LIB ${LMMS_REQUIRED_LIBS})
GET_TARGET_PROPERTY(INCLUDE_DIRS ${LIB} INTERFACE_INCLUDE_DIRECTORIES)
if (INCLUDE_DIRS)
TARGET_INCLUDE_DIRECTORIES(lmmsobjs PRIVATE ${INCLUDE_DIRS})
ENDIF()
IF(TARGET ${LIB})
GET_TARGET_PROPERTY(INCLUDE_DIRS ${LIB} INTERFACE_INCLUDE_DIRECTORIES)
IF(INCLUDE_DIRS)
TARGET_INCLUDE_DIRECTORIES(lmmsobjs PRIVATE ${INCLUDE_DIRS})
ENDIF()
ENDIF()
ENDFOREACH()