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:
@@ -13,6 +13,7 @@ IF(COMMAND CMAKE_POLICY)
|
||||
ENDIF()
|
||||
ENDIF(COMMAND CMAKE_POLICY)
|
||||
|
||||
INCLUDE(CheckSubmodules)
|
||||
INCLUDE(AddFileDependencies)
|
||||
INCLUDE(CheckIncludeFiles)
|
||||
INCLUDE(FindPkgConfig)
|
||||
|
||||
138
cmake/modules/CheckSubmodules.cmake
Normal file
138
cmake/modules/CheckSubmodules.cmake
Normal 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")
|
||||
@@ -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()
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user