Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New attempt at fetching submodules #3957

Merged
merged 4 commits into from
Nov 15, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ IF(COMMAND CMAKE_POLICY)
ENDIF()
ENDIF(COMMAND CMAKE_POLICY)

INCLUDE(CheckSubmodules)
INCLUDE(AddFileDependencies)
INCLUDE(CheckIncludeFiles)
INCLUDE(FindPkgConfig)
Expand Down
138 changes: 138 additions & 0 deletions cmake/modules/CheckSubmodules.cmake
Original file line number Diff line number Diff line change
@@ -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")
10 changes: 6 additions & 4 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I already did this in 0dbdafc (albeit with inconsistent indentation...), it just hasn't been merged back to master yet.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. I think I'll keep it here and we can deal with the minor merge conflict when rebasing.

GET_TARGET_PROPERTY(INCLUDE_DIRS ${LIB} INTERFACE_INCLUDE_DIRECTORIES)
IF(INCLUDE_DIRS)
TARGET_INCLUDE_DIRECTORIES(lmmsobjs PRIVATE ${INCLUDE_DIRS})
ENDIF()
ENDIF()
ENDFOREACH()


Expand Down