1# 2# Copyright 2017-2018 Nest Labs Inc. All Rights Reserved. 3# Copyright 2018 Google LLC. All Rights Reserved. 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16# 17 18# 19# Description: 20# This file is a make "footer" or post make header that defines make 21# convenience targets and templates for interacting with and managing 22# "foreign" (e.g., those outside of this project) git projects in the 23# context of managing project dependencies. 24# 25 26ifneq ($(REPOS),) 27# Stem for git clones and submodules 28 29__REPOS_GIT_STEM := /.git 30 31# Stem for the git configuration file for a git repository. 32 33__REPOS_GIT_CONFIG_STEM := $(__REPOS_GIT_STEM)/config 34 35# Stem for the git cache directory for a git submodule 36 37__REPOS_GIT_MODULE_CACHE_STEM := $(__REPOS_GIT_STEM)/modules 38 39# git submodule configuration file and path 40 41__REPOS_GIT_MODULES_FILE := .gitmodules 42__REPOS_GIT_MODULES_PATH := $(top_srcdir)/$(__REPOS_GIT_MODULES_FILE) 43 44# Stem for the git configuration file for a git clone or submodule. 45 46__REPOS_GIT_CLONE_STEM := $(__REPOS_GIT_STEM) 47__REPOS_GIT_SUBMODULE_STEM := $(__REPOS_GIT_STEM) 48 49# Git "pull" method to use for retrieving repositories on which this 50# package may depend. 51# 52# This defaults to 'clone' if no configuration value is present. 53 54__REPOS_MAYBE_PULL_METHOD := $(call nlGitGetMethodForPullFromFile,$(REPOS_CONFIG)) 55__REPOS_DEFAULT_PULL_METHOD := clone 56REPOS_PULL_METHOD := $(if $(__REPOS_MAYBE_PULL_METHOD),$(__REPOS_MAYBE_PULL_METHOD),$(__REPOS_DEFAULT_PULL_METHOD)) 57 58# Git repository configuration for this package, if it exists. 59# 60# This value is only relevant when the pull method is 'submodule'. 61 62ifeq ($(REPOS_PULL_METHOD),submodule) 63REPOS_PACKAGE_GIT_PATH := $(top_srcdir)$(__REPOS_GIT_CONFIG_STEM) 64else 65REPOS_PACKAGE_GIT_PATH := 66endif 67 68# Sentinel Files 69 70REPOS_GIT_INIT_SENTINEL := $(top_srcdir)/.repos-git-init-stamp 71REPOS_GIT_MODULES_SENTINEL := $(top_srcdir)/.repos-git-modules-stamp 72REPOS_WARNING_SENTINEL := $(top_builddir)/.repos-warning-stamp 73 74# 75# REPOS_template <repo file> <repo name> 76# 77# This template defines variables and targets used for inlining optional and 78# required third-party packages as package-internal copies. 79# 80# <repo file> - Path to the repo configuration file from which to get 81# values for named repo. 82# <repo name> - Name of the repository in <repo file> for which to get 83# values for branch, local path, and URL. 84# 85define REPOS_template 86$(2)_repo_NAME := $(2) 87$(2)_repo_BRANCH := $$(call nlGitGetBranchForRepoFromNameFromFile,$(1),$(2)) 88$(2)_repo_COMMIT := $$(call nlGitGetCommitForRepoFromNameFromFile,$(1),$(2)) 89$(2)_repo_PATH := $$(call nlGitGetPathForRepoFromNameFromFile,$(1),$(2)) 90$(2)_repo_URL := $$(call nlGitGetURLForRepoFromNameFromFile,$(1),$(2)) 91 92$(2)_repo_GIT := $$(addsuffix $(__REPOS_GIT_STEM),$$($(2)_repo_PATH)) 93$(2)_repo_CACHE := $(top_srcdir)$(__REPOS_GIT_MODULE_CACHE_STEM)/$$($(2)_repo_PATH) 94 95REPO_NAMES += $$($(2)_repo_NAME) 96REPO_GITS += $$($(2)_repo_GIT) 97REPO_PATHS += $$($(2)_repo_PATH) 98REPO_URLS += $$($(2)_repo_URL) 99REPO_CACHES += $$($(2)_repo_CACHE) 100 101# Allow a repo to be made with a path target (e.g., third_party/foo/repo) or 102# with its actual git target (e.g., third_party/foo/repo/.git). 103 104$$($(2)_repo_PATH): | $$($(2)_repo_GIT) 105 106$$($(2)_repo_GIT): $(REPOS_PACKAGE_GIT_PATH) | repos-warning 107 $(NL_V_AT)case "$(REPOS_PULL_METHOD)" in \ 108 submodule) echo " SUBMODULE $$(subst $(__REPOS_GIT_SUBMODULE_STEM),,$$(@))"; \ 109 if ! test -f $(__REPOS_GIT_MODULES_PATH); then \ 110 touch $(REPOS_GIT_MODULES_SENTINEL); \ 111 fi; \ 112 $(GIT) -C $(top_srcdir) submodule -q add -f -b $$($(2)_repo_BRANCH) -- $$($(2)_repo_URL) $$($(2)_repo_PATH);; \ 113 clone) echo " CLONE $$(subst $(__REPOS_GIT_CLONE_STEM),,$$(@))"; \ 114 $(GIT) -C $(top_srcdir) clone -q -b $$($(2)_repo_BRANCH) -- $$($(2)_repo_URL) $$($(2)_repo_PATH);; \ 115 *) echo "$(REPOS_CONFIG): Unknown or unsupported pull method '$(REPOS_PULL_METHOD)'.";; \ 116 esac 117 $(NL_V_AT)if ! test -z "$$($(2)_repo_COMMIT)"; then \ 118 $(GIT) -C $$($(2)_repo_PATH) checkout -q $$($(2)_repo_COMMIT); \ 119 fi 120endef # REPOS_template 121 122$(REPOS_PACKAGE_GIT_PATH): 123 $(NL_V_PROGRESS_GIT_INIT) 124 $(GIT) -C $(top_srcdir) init -q $(top_srcdir) 125 $(NL_V_AT)touch $(REPOS_GIT_INIT_SENTINEL) 126 127define PrintReposWarning 128$(NL_V_AT)echo "The 'repos' target requires external network connectivity to" 129$(NL_V_AT)echo "reach the following upstream GIT repositories:" 130$(NL_V_AT)echo "" 131$(NL_V_AT)for url in $(REPO_URLS); do echo " $${url}"; done 132$(NL_V_AT)echo "" 133$(NL_V_AT)echo "and will fail if external network connectivity is not" 134$(NL_V_AT)echo "available. This package may still be buildable without these" 135$(NL_V_AT)echo "packages but may require disabling certain features or" 136$(NL_V_AT)echo "functionality." 137$(NL_V_AT)echo "" 138endef # PrintReposWarning 139 140$(REPOS_WARNING_SENTINEL): 141 $(NL_V_AT)touch $(@) 142 $(call PrintReposWarning) 143 144.PHONY: repos-warning 145repos-warning: $(REPOS_WARNING_SENTINEL) 146 147.PHONY: repos-local 148repos-local: repos-warning 149 $(NL_V_AT)$(MAKE) -f $(firstword $(MAKEFILE_LIST)) --no-print-directory $(REPO_GITS) 150 151.PHONY: repos-hook 152repos-hook: repos-local 153 154.PHONY: repos 155repos: repos-local repos-hook 156 157.PHONY: clean-repos-hook 158clean-repos-hook: 159 160.PHONY: clean-repos-local 161clean-repos-local: clean-repos-hook 162 @echo " CLEAN" 163 $(NL_V_AT)case "$(REPOS_PULL_METHOD)" in \ 164 submodule) $(GIT) -C $(top_srcdir) submodule -q deinit -f -- $(REPO_PATHS) 2> /dev/null || true; \ 165 if test -f $(REPOS_GIT_MODULES_SENTINEL); then \ 166 $(RM) $(REPOS_GIT_MODULES_SENTINEL); \ 167 $(GIT) -C $(top_srcdir) rm -f -q $(__REPOS_GIT_MODULES_PATH) 2> /dev/null; \ 168 fi ; \ 169 if test -f $(REPOS_GIT_INIT_SENTINEL); then \ 170 $(RM) -r $(dir $(REPOS_PACKAGE_GIT_PATH)); \ 171 $(RM) $(REPOS_GIT_INIT_SENTINEL); \ 172 fi; \ 173 $(RM) $(REPOS_WARNING_SENTINEL); \ 174 $(GIT) -C $(top_srcdir) rm -rf -q --cached $(REPO_PATHS) 2> /dev/null || true; \ 175 $(RM) -r $(addprefix $(top_srcdir)/,$(REPO_PATHS)); \ 176 $(RMDIR) -p $(addprefix $(top_srcdir),$(dir $(REPO_PATHS))) 2> /dev/null || true; \ 177 $(RM) -r $(REPO_CACHES) 2> /dev/null;; \ 178 clone) $(GIT) -C $(top_srcdir) rm -rf -q --cached $(REPO_PATHS) 2> /dev/null || true; \ 179 $(RM) $(REPOS_WARNING_SENTINEL); \ 180 $(RM) -r $(addprefix $(top_srcdir)/,$(REPO_PATHS)); \ 181 $(RMDIR) -p $(addprefix $(top_srcdir),$(dir $(REPO_PATHS))) 2> /dev/null || true;; \ 182 *) echo "$(REPOS_CONFIG): Unknown or unsupported pull method '$(REPOS_PULL_METHOD)'.";; \ 183 esac 184 185.PHONY: clean-repos 186clean-repos: clean-repos-local 187 188# Invoke the REPOS_template for each defined optionally-inlined package repo 189 190$(foreach repo,$(REPOS),$(eval $(call REPOS_template,$(REPOS_CONFIG),$(repo)))) 191 192define MaybePrintReposHelp 193$(NL_V_AT)echo " repos" 194$(NL_V_AT)echo " Clone any upstream, dependent git repositories that this package" 195$(NL_V_AT)echo " regards as required or optional rather than using '--with-<package>'" 196$(NL_V_AT)echo " options to specify external instances of those packages." 197$(NL_V_AT)echo 198$(NL_V_AT)echo " clean-repos" 199$(NL_V_AT)echo " This is the opposite of the 'repos' target. This removes, in their" 200$(NL_V_AT)echo " entirety, any clones of any upstream, dependent git repositories that" 201$(NL_V_AT)echo " this package regards as required or optional." 202$(NL_V_AT)echo 203endef # MaybePrintReposHelp 204 205else 206 207define MaybePrintReposHelp 208endef # MaybePrintReposHelp 209 210endif # REPOS 211 212define PrintReposHelp 213$(call MaybePrintReposHelp) 214endef # PrintReposHelp 215 216.PHONY: help-repos-local 217help-repos-local: 218 $(call PrintReposHelp) 219 220.PHONY: help-repos-hook 221help-repos-hook: help-repos-local 222 223.PHONY: help-repos 224help-repos: help-repos-local help-repos-hook 225 226.PHONY: help 227help: help-repos 228