Merge pull request #8070 from dhalbert/port-specific-submodules

Provide port-specific fetch of submodules
This commit is contained in:
Dan Halbert 2023-06-06 14:46:39 -04:00 committed by GitHub
commit e631350b9b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 104 additions and 40 deletions

View File

@ -27,7 +27,11 @@ This project has a bunch of git submodules. You will need to update them regula
In the root folder of the CircuitPython repository, execute the following: In the root folder of the CircuitPython repository, execute the following:
make fetch-submodules make fetch-all-submodules
Or, in the ports directory for the particular port you are building, do:
make fetch-port-submodules
### Required Python Packages ### Required Python Packages

View File

@ -61,7 +61,6 @@ TRANSLATE_SOURCES_EXC = -path "ports/*/build-*" \
help: help:
@echo "Please use \`make <target>' where <target> is one of" @echo "Please use \`make <target>' where <target> is one of"
@echo " fetch-submodules to fetch dependencies from submodules, run this right after you clone the repo"
@echo " html to make standalone HTML files" @echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories" @echo " dirhtml to make HTML files named index.html in directories"
@echo " singlehtml to make a single large HTML file" @echo " singlehtml to make a single large HTML file"
@ -84,6 +83,8 @@ help:
@echo " pseudoxml to make pseudoxml-XML files for display purposes" @echo " pseudoxml to make pseudoxml-XML files for display purposes"
@echo " linkcheck to check all external links for integrity" @echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)" @echo " doctest to run all doctests embedded in the documentation (if enabled)"
@echo " fetch-all-submodules to fetch submodules for all ports"
@echo " remove-all-submodules remove all submodules, including files and .git/ data"
clean: clean:
rm -rf $(BUILDDIR)/* rm -rf $(BUILDDIR)/*
@ -324,25 +325,12 @@ clean-stm:
$(MAKE) -C ports/stm BOARD=feather_stm32f405_express clean $(MAKE) -C ports/stm BOARD=feather_stm32f405_express clean
# If available, do blobless partial clones of submodules to save time and space. .PHONY: fetch-all-submodules
# A blobless partial clone lazily fetches data as needed, but has all the metadata available (tags, etc.) fetch-all-submodules:
# so it does not have the idiosyncrasies of a shallow clone. tools/fetch-submodules.sh
#
# If not available, do a fetch that will fail, and then fix it up with a second fetch.
# (Only works for git servers that allow sha fetches.)
.PHONY: fetch-submodules
fetch-submodules:
git submodule sync
#####################################################################################
# NOTE: Ideally, use git version 2.36.0 or later, to do partial clones of submodules.
# If an older git is used, submodules will be cloned with a shallow clone of depth 1.
# You will see a git usage message first if the git version is too old to do
# clones of submodules.
#####################################################################################
git submodule update --init --filter=blob:none || git submodule update --init -N --depth 1 || git submodule foreach 'git fetch --tags --depth 1 origin $$sha1 && git checkout -q $$sha1' || echo 'make fetch-submodules FAILED'
.PHONY: remove-submodules .PHONY: remove-all-submodules
remove-submodules: remove-all-submodules:
git submodule deinit -f --all git submodule deinit -f --all
rm -rf .git/modules/* rm -rf .git/modules/*

View File

@ -363,11 +363,15 @@ SRC_QSTR_PREPROCESSOR += peripherals/samd/$(PERIPHERALS_CHIP_FAMILY)/clocks.c
all: $(BUILD)/firmware.bin $(BUILD)/firmware.uf2 all: $(BUILD)/firmware.bin $(BUILD)/firmware.uf2
ifeq ($(VALID_BOARD),)
$(BUILD)/firmware.elf: invalid-board
else
$(BUILD)/firmware.elf: $(OBJ) $(GENERATED_LD_FILE) $(BUILD)/firmware.elf: $(OBJ) $(GENERATED_LD_FILE)
$(STEPECHO) "LINK $@" $(STEPECHO) "LINK $@"
$(Q)echo $(OBJ) > $(BUILD)/firmware.objs $(Q)echo $(OBJ) > $(BUILD)/firmware.objs
$(Q)$(CC) -o $@ $(LDFLAGS) @$(BUILD)/firmware.objs -Wl,--print-memory-usage -Wl,--start-group $(LIBS) -Wl,--end-group $(Q)$(CC) -o $@ $(LDFLAGS) @$(BUILD)/firmware.objs -Wl,--print-memory-usage -Wl,--start-group $(LIBS) -Wl,--end-group
$(Q)$(SIZE) $@ | $(PYTHON) $(TOP)/tools/build_memory_info.py $(GENERATED_LD_FILE) $(BUILD) $(Q)$(SIZE) $@ | $(PYTHON) $(TOP)/tools/build_memory_info.py $(GENERATED_LD_FILE) $(BUILD)
endif
$(BUILD)/firmware.bin: $(BUILD)/firmware.elf $(BUILD)/firmware.bin: $(BUILD)/firmware.elf
$(STEPECHO) "Create $@" $(STEPECHO) "Create $@"

View File

@ -142,10 +142,14 @@ all: $(BUILD)/firmware.kernel$(SUFFIX).img $(BUILD)/firmware.disk.img.zip
%.o: %.c %.o: %.c
$(CC) $(CFLAGS) -c $< -o $@ $(CC) $(CFLAGS) -c $< -o $@
ifeq ($(VALID_BOARD),)
$(BUILD)/kernel$(SUFFIX).elf: invalid-board
else
$(BUILD)/kernel$(SUFFIX).elf: $(OBJ) $(BUILD)/kernel$(SUFFIX).elf: $(OBJ)
$(STEPECHO) "LINK $@" $(STEPECHO) "LINK $@"
$(Q)echo $(OBJ) > $(BUILD)/firmware.objs $(Q)echo $(OBJ) > $(BUILD)/firmware.objs
$(Q)$(CC) -o $@ $(LDFLAGS) @$(BUILD)/firmware.objs -Wl,--start-group $(LIBS) -Wl,--end-group $(Q)$(CC) -o $@ $(LDFLAGS) @$(BUILD)/firmware.objs -Wl,--start-group $(LIBS) -Wl,--end-group
endif
$(BUILD)/kernel$(SUFFIX).img: $(BUILD)/kernel$(SUFFIX).elf $(BUILD)/kernel$(SUFFIX).img: $(BUILD)/kernel$(SUFFIX).elf
$(STEPECHO) "Create $@" $(STEPECHO) "Create $@"

View File

@ -183,9 +183,13 @@ $(BUILD)/firmware.elf: $(BUILD)/libmpy.a
$(MKSPK): $(MKSPK):
$(MAKE) -C mkspk $(MAKE) -C mkspk
ifeq ($(VALID_BOARD),)
$(BUILD)/firmware.spk: invalid-board
else
$(BUILD)/firmware.spk: $(BUILD)/firmware.elf $(MKSPK) $(BUILD)/firmware.spk: $(BUILD)/firmware.elf $(MKSPK)
$(ECHO) "Creating $@" $(ECHO) "Creating $@"
$(MKSPK) -c 2 $(BUILD)/firmware.elf nuttx $(BUILD)/firmware.spk $(MKSPK) -c 2 $(BUILD)/firmware.elf nuttx $(BUILD)/firmware.spk
endif
flash: $(BUILD)/firmware.spk flash: $(BUILD)/firmware.spk
$(ECHO) "Writing $< to the board" $(ECHO) "Writing $< to the board"

View File

@ -411,6 +411,7 @@ ESP_IDF_COMPONENTS_EXPANDED += $(BUILD)/esp-idf/esp-idf/esp32-camera/libesp32-ca
#$(error $(ESP_IDF_COMPONENTS_EXPANDED)) #$(error $(ESP_IDF_COMPONENTS_EXPANDED))
endif endif
ifneq ($(VALID_BOARD),)
# BOOTLOADER_OFFSET is determined by chip type, based on the ROM bootloader, and is not changeable. # BOOTLOADER_OFFSET is determined by chip type, based on the ROM bootloader, and is not changeable.
ifeq ($(IDF_TARGET),esp32) ifeq ($(IDF_TARGET),esp32)
BOOTLOADER_OFFSET = 0x1000 BOOTLOADER_OFFSET = 0x1000
@ -423,6 +424,7 @@ BOOTLOADER_OFFSET = 0x1000
else else
$(error unknown IDF_TARGET $(IDF_TARGET)) $(error unknown IDF_TARGET $(IDF_TARGET))
endif endif
endif
IDF_CMAKE_TARGETS = \ IDF_CMAKE_TARGETS = \
bootloader/bootloader.bin \ bootloader/bootloader.bin \
@ -457,8 +459,12 @@ $(BUILD)/circuitpython-firmware.bin: $(BUILD)/firmware.elf | tools/build_memory_
$(Q)esptool.py --chip $(IDF_TARGET) elf2image $(FLASH_FLAGS) --elf-sha256-offset 0xb0 -o $@ $^ $(Q)esptool.py --chip $(IDF_TARGET) elf2image $(FLASH_FLAGS) --elf-sha256-offset 0xb0 -o $@ $^
$(Q)$(PYTHON) tools/build_memory_info.py $< $(BUILD)/esp-idf/sdkconfig $@ $(BUILD) $(Q)$(PYTHON) tools/build_memory_info.py $< $(BUILD)/esp-idf/sdkconfig $@ $(BUILD)
ifeq ($(VALID_BOARD),)
$(BUILD)/firmware.bin: invalid-board
else
$(BUILD)/firmware.bin: $(BUILD)/circuitpython-firmware.bin | esp-idf-stamp $(BUILD)/firmware.bin: $(BUILD)/circuitpython-firmware.bin | esp-idf-stamp
$(Q)$(PYTHON) ../../tools/join_bins.py $@ $(BOOTLOADER_OFFSET) $(BUILD)/esp-idf/bootloader/bootloader.bin $(PARTITION_TABLE_OFFSET) $(BUILD)/esp-idf/partition_table/partition-table.bin $(FIRMWARE_OFFSET) $(BUILD)/circuitpython-firmware.bin $(Q)$(PYTHON) ../../tools/join_bins.py $@ $(BOOTLOADER_OFFSET) $(BUILD)/esp-idf/bootloader/bootloader.bin $(PARTITION_TABLE_OFFSET) $(BUILD)/esp-idf/partition_table/partition-table.bin $(FIRMWARE_OFFSET) $(BUILD)/circuitpython-firmware.bin
endif
UF2_FAMILY_ID_esp32s2 = 0xbfdd4eee UF2_FAMILY_ID_esp32s2 = 0xbfdd4eee
UF2_FAMILY_ID_esp32s3 = 0xc47e5767 UF2_FAMILY_ID_esp32s3 = 0xc47e5767

View File

@ -133,10 +133,14 @@ SRC_QSTR_PREPROCESSOR +=
all: $(BUILD)/firmware.bin $(BUILD)/firmware.dfu all: $(BUILD)/firmware.bin $(BUILD)/firmware.dfu
ifeq ($(VALID_BOARD),)
$(BUILD)/firmware.elf: invalid-board
else
$(BUILD)/firmware.elf: $(OBJ) $(BUILD)/firmware.elf: $(OBJ)
$(STEPECHO) "LINK $@" $(STEPECHO) "LINK $@"
$(Q)$(CC) -o $@ $(LDFLAGS) $^ -Wl,--start-group $(LIBS) -Wl,--end-group $(Q)$(CC) -o $@ $(LDFLAGS) $^ -Wl,--start-group $(LIBS) -Wl,--end-group
$(Q)$(SIZE) $@ | $(PYTHON) $(TOP)/tools/build_memory_info.py $(LD_FILE) $(BUILD) $(Q)$(SIZE) $@ | $(PYTHON) $(TOP)/tools/build_memory_info.py $(LD_FILE) $(BUILD)
endif
$(BUILD)/firmware.bin: $(BUILD)/firmware.elf $(BUILD)/firmware.bin: $(BUILD)/firmware.elf
$(STEPECHO) "Create $@" $(STEPECHO) "Create $@"

View File

@ -200,9 +200,13 @@ SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_M
all: $(BUILD)/firmware.bin $(BUILD)/firmware.uf2 $(BUILD)/firmware.hex all: $(BUILD)/firmware.bin $(BUILD)/firmware.uf2 $(BUILD)/firmware.hex
ifeq ($(VALID_BOARD),)
$(BUILD)/firmware.elf: invalid-board
else
$(BUILD)/firmware.elf: $(OBJ) $(LD_FILES) $(BUILD)/firmware.elf: $(OBJ) $(LD_FILES)
$(STEPECHO) "LINK $@" $(STEPECHO) "LINK $@"
$(Q)$(CC) -o $@ $(LDFLAGS) $(filter-out %.ld, $^) -Wl,--print-memory-usage -Wl,--start-group $(LIBS) -Wl,--end-group $(Q)$(CC) -o $@ $(LDFLAGS) $(filter-out %.ld, $^) -Wl,--print-memory-usage -Wl,--start-group $(LIBS) -Wl,--end-group
endif
# -R excludes sections from the output files. # -R excludes sections from the output files.
$(BUILD)/firmware.bin: $(BUILD)/firmware.elf $(BUILD)/firmware.bin: $(BUILD)/firmware.elf

View File

@ -208,11 +208,15 @@ UF2_FAMILY_ID_nrf52833 = 0x621E937A
all: $(BUILD)/firmware.bin $(BUILD)/firmware.uf2 $(BUILD)/firmware.combined.hex all: $(BUILD)/firmware.bin $(BUILD)/firmware.uf2 $(BUILD)/firmware.combined.hex
ifeq ($(VALID_BOARD),)
$(BUILD)/firmware.elf: invalid-board
else
$(BUILD)/firmware.elf: $(OBJ) $(GENERATED_LD_FILE) $(BUILD)/firmware.elf: $(OBJ) $(GENERATED_LD_FILE)
$(STEPECHO) "LINK $@" $(STEPECHO) "LINK $@"
$(Q)echo $(OBJ) > $(BUILD)/firmware.objs $(Q)echo $(OBJ) > $(BUILD)/firmware.objs
$(Q)$(CC) -o $@ $(LDFLAGS) @$(BUILD)/firmware.objs -Wl,--start-group $(LIBS) -Wl,--end-group $(Q)$(CC) -o $@ $(LDFLAGS) @$(BUILD)/firmware.objs -Wl,--start-group $(LIBS) -Wl,--end-group
$(Q)$(SIZE) $@ | $(PYTHON) $(TOP)/tools/build_memory_info.py $(GENERATED_LD_FILE) $(BUILD) $(Q)$(SIZE) $@ | $(PYTHON) $(TOP)/tools/build_memory_info.py $(GENERATED_LD_FILE) $(BUILD)
endif
$(BUILD)/firmware.bin: $(BUILD)/firmware.elf $(BUILD)/firmware.bin: $(BUILD)/firmware.elf
$(STEPECHO) "Create $@" $(STEPECHO) "Create $@"

View File

@ -434,11 +434,15 @@ endif
LINKER_SCRIPTS += -Wl,-T,link.ld LINKER_SCRIPTS += -Wl,-T,link.ld
ifeq ($(VALID_BOARD),)
$(BUILD)/firmware.elf: invalid-board
else
$(BUILD)/firmware.elf: $(OBJ) $(BOARD_LD) link.ld $(BUILD)/firmware.elf: $(OBJ) $(BOARD_LD) link.ld
$(STEPECHO) "LINK $@" $(STEPECHO) "LINK $@"
$(Q)echo $(OBJ) > $(BUILD)/firmware.objs $(Q)echo $(OBJ) > $(BUILD)/firmware.objs
$(Q)echo $(PICO_LDFLAGS) > $(BUILD)/firmware.ldflags $(Q)echo $(PICO_LDFLAGS) > $(BUILD)/firmware.ldflags
$(Q)$(CC) -o $@ $(CFLAGS) @$(BUILD)/firmware.ldflags $(LINKER_SCRIPTS) -Wl,--print-memory-usage -Wl,-Map=$@.map -Wl,-cref -Wl,--gc-sections @$(BUILD)/firmware.objs -Wl,-lc $(Q)$(CC) -o $@ $(CFLAGS) @$(BUILD)/firmware.ldflags $(LINKER_SCRIPTS) -Wl,--print-memory-usage -Wl,-Map=$@.map -Wl,-cref -Wl,--gc-sections @$(BUILD)/firmware.objs -Wl,-lc
endif
$(BUILD)/firmware.bin: $(BUILD)/firmware.elf $(BUILD)/firmware.bin: $(BUILD)/firmware.elf
$(STEPECHO) "Create $@" $(STEPECHO) "Create $@"

View File

@ -137,9 +137,13 @@ MCU_SECTIONS = $^ $@
# Default goal # Default goal
all: $(OUTPUT_DIR)/firmware.bin all: $(OUTPUT_DIR)/firmware.bin
ifeq ($(VALID_BOARD),)
$(BUILD)/firmware.bin: invalid-board
else
$(OUTPUT_DIR)/firmware.bin: $(SILABS_BUILD)/$(PROJECTNAME).Makefile $(OUTPUT_DIR)/firmware.hex $(OUTPUT_DIR)/firmware.bin: $(SILABS_BUILD)/$(PROJECTNAME).Makefile $(OUTPUT_DIR)/firmware.hex
+@$(MAKE) --no-print-directory $(OUTPUT_DIR)/firmware.out +@$(MAKE) --no-print-directory $(OUTPUT_DIR)/firmware.out
@echo 'Done.' @echo 'Done.'
endif
$(SILABS_BUILD)/$(PROJECTNAME).Makefile: $(SILABS_BUILD)/$(PROJECTNAME).Makefile:
+@$(MAKE) --no-print-directory slc-generate +@$(MAKE) --no-print-directory slc-generate

View File

@ -47,8 +47,8 @@ Ensure your clone of Circuitpython is ready to build by following the [guide on
Clone the source code of CircuitPython from Github: Clone the source code of CircuitPython from Github:
$ git clone https://github.com/SiliconLabs/circuitpython.git $ git clone https://github.com/SiliconLabs/circuitpython.git
$ cd circuitpython $ cd circuitpython/ports/silabs
$ make fetch-submodules $ make fetch-port-submodules
Checkout the branch or tag you want to build. For example: Checkout the branch or tag you want to build. For example:

View File

@ -52,7 +52,7 @@ INC += -I../../supervisor/shared/usb
#Debugging/Optimization #Debugging/Optimization
ifeq ($(DEBUG), 1) ifeq ($(DEBUG), 1)
CFLAGS += -ggdb3 CFLAGS += -ggdb3
# You may want to enable these flags to make setting breakpoints easier. # You may want to enable these flags to make setting breakpoints easier.
CFLAGS += -fno-inline -fno-ipa-sra CFLAGS += -fno-inline -fno-ipa-sra
else else
CFLAGS += -DNDEBUG CFLAGS += -DNDEBUG
@ -264,11 +264,15 @@ endif
all: $(BUILD)/firmware.bin $(BUILD)/firmware.uf2 all: $(BUILD)/firmware.bin $(BUILD)/firmware.uf2
ifeq ($(VALID_BOARD),)
$(BUILD)/firmware.elf: invalid-board
else
$(BUILD)/firmware.elf: $(OBJ) $(BUILD)/firmware.elf: $(OBJ)
$(STEPECHO) "LINK $@" $(STEPECHO) "LINK $@"
$(Q)echo $^ > $(BUILD)/firmware.objs $(Q)echo $^ > $(BUILD)/firmware.objs
$(Q)$(CC) -o $@ $(LDFLAGS) @$(BUILD)/firmware.objs -Wl,--start-group $(LIBS) -Wl,--end-group $(Q)$(CC) -o $@ $(LDFLAGS) @$(BUILD)/firmware.objs -Wl,--start-group $(LIBS) -Wl,--end-group
$(Q)$(SIZE) $@ | $(PYTHON) $(TOP)/tools/build_memory_info.py $(LD_FILE) $(BUILD) $(Q)$(SIZE) $@ | $(PYTHON) $(TOP)/tools/build_memory_info.py $(LD_FILE) $(BUILD)
endif
$(BUILD)/firmware.bin: $(BUILD)/firmware.elf $(BUILD)/firmware.bin: $(BUILD)/firmware.elf
$(STEPECHO) "Create $@" $(STEPECHO) "Create $@"

View File

@ -829,3 +829,15 @@ check-release-needs-clean-build:
# Ignore these errors # Ignore these errors
$(BUILD)/lib/libm/kf_rem_pio2.o: CFLAGS += -Wno-maybe-uninitialized $(BUILD)/lib/libm/kf_rem_pio2.o: CFLAGS += -Wno-maybe-uninitialized
# Fetch only submodules needed for this particular port.
.PHONY: fetch-port-submodules
fetch-port-submodules:
$(TOP)/tools/fetch-submodules.sh data extmod frozen lib tools ports/$(shell basename $(CURDIR))
.PHONY: invalid-board
invalid-board:
$(Q)if [ -z "$(BOARD)" ] ; then echo "ERROR: No BOARD specified" ; else echo "ERROR: Invalid BOARD $(BOARD) specified"; fi && \
echo "Valid boards:" && \
printf '%s\n' $(ALL_BOARDS_IN_PORT) | column -xc $$(tput cols || echo 80) 1>&2 && \
false

View File

@ -24,22 +24,10 @@
# Common Makefile items that can be shared across CircuitPython ports. # Common Makefile items that can be shared across CircuitPython ports.
# Select the board to build for. ALL_BOARDS_IN_PORT := $(patsubst boards/%/mpconfigboard.mk,%,$(wildcard boards/*/mpconfigboard.mk))
define show_board_error # An incorrect BOARD might have been specified, so check against the list.
$(info Valid boards:) # There is deliberately no space after the :=
$(shell printf '%s\n' $(patsubst boards/%/mpconfigboard.mk,%,$(wildcard boards/*/mpconfigboard.mk)) | column -xc $$(tput cols || echo 80) 1>&2) VALID_BOARD :=$(filter $(BOARD),$(ALL_BOARDS_IN_PORT))
$(error Rerun with $(MAKE) BOARD=<board>)
endef
ifeq ($(BOARD),)
$(info No BOARD specified)
$(call show_board_error)
else
ifeq ($(wildcard boards/$(BOARD)/.),)
$(info Invalid BOARD specified)
$(call show_board_error)
endif
endif
# If the flash PORT is not given, use the default /dev/tty.SLAB_USBtoUART. # If the flash PORT is not given, use the default /dev/tty.SLAB_USBtoUART.
PORT ?= /dev/tty.SLAB_USBtoUART PORT ?= /dev/tty.SLAB_USBtoUART
@ -47,16 +35,22 @@ PORT ?= /dev/tty.SLAB_USBtoUART
# If the build directory is not given, make it reflect the board name. # If the build directory is not given, make it reflect the board name.
BUILD ?= build-$(BOARD) BUILD ?= build-$(BOARD)
# First makefile with targets. Defines the default target.
include ../../py/mkenv.mk include ../../py/mkenv.mk
# Board-specific # Board-specific. Skip if the rule requested is not board-specific.
ifneq ($(VALID_BOARD),)
include boards/$(BOARD)/mpconfigboard.mk include boards/$(BOARD)/mpconfigboard.mk
endif
# Port-specific # Port-specific
include mpconfigport.mk include mpconfigport.mk
# Also board-specific. Skip if the rule requested is not board-specific.
ifneq ($(VALID_BOARD),)
# CircuitPython-specific # CircuitPython-specific
include $(TOP)/py/circuitpy_mpconfig.mk include $(TOP)/py/circuitpy_mpconfig.mk
endif
# qstr definitions (must come before including py.mk) # qstr definitions (must come before including py.mk)
QSTR_DEFS = qstrdefsport.h QSTR_DEFS = qstrdefsport.h

24
tools/fetch-submodules.sh Executable file
View File

@ -0,0 +1,24 @@
#!/usr/bin/env sh
# Pass the directories of submodules to fetch as command-line arguments. For example:
# ./fetch-submodules.sh lib tools
# If no arguments are passed, all submodules will be fetched.
# This script handles being called at other than the top level by making the paths
# for the submodules absolute.
TOP=$(git rev-parse --show-toplevel)
git submodule sync --quiet
# Prefix all the args with the absolute path to the top of the repo.
abs_submodules=""
for d in "$@"; do
abs_submodules="${abs_submodules} ${TOP}/${d}"
done
echo ${abs_submodules}
# Fetch submodules as partial clones if possible. If that fails due to an older version of git,
# do a shallow init with no fetch and then check out the proper commit.
git submodule update --init --filter=blob:none ${abs_submodules} || \
git submodule update --init --no-fetch --depth 1 ${abs_submodules} || \
git submodule foreach $* \
'git fetch --tags --depth 1 origin $$sha1 && git checkout -q $$sha1' || \
echo "ERROR: fetch-submodules.sh FAILED"