Files
common/Makefile.shared
Patrick McCarty d2d8b886bd Restrict query to spec sections above %files
In Clear Linux OS, all package spec files define their header fields
(and other required sections, like %description) above the first %files
section. Restricting the `rpmspec` queries to sections of %files speeds
up the command significantly, most notably for `texlive`, which has the
largest spec file.

Signed-off-by: Patrick McCarty <patrick.mccarty@intel.com>
2020-12-14 04:01:31 +00:00

268 lines
9.2 KiB
Makefile

#-*-makefile-*-
define loopup
@[ "$(DEVICE)" ] || exit -1
@set -x; [ -z "$(FORCE)" ] || rm -rf $(TOPLVL)/image
@if [ -d $(TOPLVL)/image ]; then \
echo "Previous image mount in place at $(TOPLVL)/image. Run \`make loop-down\` to clean up first!"; \
exit 1; \
fi
@echo "Setting up loopback and mounting image..."
@mkdir -p $(TOPLVL)/image
@sudo losetup -d /dev/loop$(DEVICE) &> /dev/null || true
@sudo losetup /dev/loop$(DEVICE) $(TARGET)
@sudo partprobe /dev/loop$(DEVICE)
@sleep 1
@if [ -e /dev/loop$(DEVICE)p3 ]; then \
sudo mount /dev/loop$(DEVICE)p3 $(TOPLVL)/image; \
else \
sudo mount /dev/loop$(DEVICE)p2 $(TOPLVL)/image; \
fi
@sudo mount /dev/loop$(DEVICE)p1 $(TOPLVL)/image/boot
endef
define loopdown
@if [ ! -d $(TOPLVL)/image ]; then \
echo "Nothing to clean up."; \
exit 1; \
fi
@echo "Unmounting image and tearing down loopback..."
@sudo losetup -d /dev/loop$(DEVICE)p3 2>/dev/null || true
@sudo losetup -d /dev/loop$(DEVICE)p2 2>/dev/null || true
@sudo losetup -d /dev/loop$(DEVICE)p1 2>/dev/null || true
@sudo losetup -d /dev/loop$(DEVICE) 2>/dev/null || true
@sudo umount -l $(TOPLVL)/image/proc 2>/dev/null || true
@sudo umount -l $(TOPLVL)/image/sys 2>/dev/null || true
@sudo umount -l $(TOPLVL)/image/dev 2>/dev/null || true
@sudo umount -l $(TOPLVL)/image/boot 2>/dev/null || true
@sudo umount -l -R $(TOPLVL)/image; if [ $$? != 0 ]; then \
sudo umount -l $(TOPLVL)/image; \
fi
@sync
@sleep 1
@rmdir $(TOPLVL)/image
endef
define subjectprefix
git config format.subjectPrefix "PATCH $(1)"
endef
# Query the spec file (or spec files) listed in argument 2 for the field(s)
# specified in argument 1. The fields are derived from the source rpm(s)
# generated by the specs. Queried fields that are declared within the spec file
# must be declared above the first %files section.
define queryspec
rpmspec --define='_vendor clr' --srpm --query --queryformat='$(1)' <(sed -n '1,/%files/p' $(2))
endef
# If GITOLITE_BASE_URL is defined, sets a repo's push URL for that gitolite
# instance. Accepts one argument: the path to the repo on gitolite. If
# GITOLITE_BASE_URL is not defined, no push URL is set -- the shell's null
# command is executed to act as a no-op.
define gitoliteurl
$(if $(GITOLITE_BASE_URL),git remote set-url --push origin $(GITOLITE_BASE_URL):$(1),:)
endef
# If USE_PACKAGE_MAPPING is defined, looks up the remote repo name for the
# local repo name (passed as the argument) according to the mapping found in
# the "pkg-mapping" file. Otherwise, return the local repo name.
define remotepkgname
$(if $(USE_PACKAGE_MAPPING),$$(awk -v P="$(1)" '$$1 == P { res=$$2 } END { print res ? res : P }' $(TOPLVL)/projects/common/pkg-mapping),$(1))
endef
# Clone repo from the configured gitolite instance, but only if the repo exists
# on that instance and matches the pattern "packages/..*".
define try-clone-gitolite
rpkg=$(call remotepkgname,$(1)); \
if ssh $(GITOLITE_BASE_URL) info "packages/$$rpkg" | grep --quiet "packages/$$rpkg$$"; then \
git clone $(PKG_BASE_URL)/$$rpkg packages/$(1); \
cd packages/$(1); \
$(call gitoliteurl,packages/$(1)); \
$(call subjectprefix,$(1)); \
fi
endef
# Clone repo from the configured package repo hosting location, as defined by
# the PKG_BASE_URL variable, but only if the repo exists.
define try-clone-other
rpkg=$(call remotepkgname,$(1)); \
if git ls-remote $(PKG_BASE_URL)/$$rpkg &> /dev/null; then \
git clone $(PKG_BASE_URL)/$$rpkg packages/$(1); \
cd packages/$(1); \
$(call subjectprefix,$(1)); \
fi
endef
# First, try running `make clone_PKG`, where PKG is the first argument. If that
# fails, proceed with fallback cloning strategies.
define clone-if-available
$(MAKE) clone_$(1) || { \
$(if $(GITOLITE_BASE_URL),$(call try-clone-gitolite,$(1)),$(call try-clone-other,$(1))); \
}
endef
$(TOPLVL)/repo:
@echo "Creating local RPM repository $(TOPLVL)/repo"
mkdir $(TOPLVL)/repo
# Enables the local RPM repo by installing package manager and Mock configs.
# First argument is the path to the package manager config, and the second
# argument is the path to the mock config. Each of these config files is
# augmented for local repo support.
localrepoenable: $(TOPLVL)/repo
@if grep -qx '\[localrepo\]' ${PM_CONF}; then \
echo "[ERROR] ${PM_CONF} contains section named [localrepo]."; \
echo "[ERROR] Remove that section and try again."; \
exit 1; \
fi >&2
@if grep -qx '\[localrepo\]' ${MOCK_CONF}; then \
echo "[ERROR] ${MOCK_CONF} contains section named [localrepo]."; \
echo "[ERROR] Remove that section and try again."; \
exit 1; \
fi >&2
@last="$$(tail -n 1 ${MOCK_CONF})"; \
if [[ "$$last" != "\"\"\"" ]]; then \
echo "[ERROR] Last line of ${MOCK_CONF} is malformed; expected: \"\"\"; actual: $$last"; \
echo "[ERROR] Fix that line and try again."; \
exit 1; \
fi >&2
@pm_new=$$(mktemp -p $< yum.conf.XXXXXXX); \
pm_orig=$</yum.conf; \
mock_new=$$(mktemp -p $< clear.cfg.XXXXXXX); \
mock_orig=$</clear.cfg; \
cp ${PM_CONF} $$pm_new; \
printf "\n\n[localrepo]\nname=localrepo\nfailovermethod=priority\nenabled=1\ngpgcheck=0\npriority=1\n" >> $$pm_new; \
printf "baseurl=file://$$(realpath $<)/\n\n" >> $$pm_new; \
if ! cmp -s $$pm_new $$pm_orig; then \
flock $</repo.lock mv $$pm_new $$pm_orig; \
fi; \
rm -f $$pm_new; \
cp ${MOCK_CONF} $$mock_new; \
sed -i '$$d' $$mock_new; \
printf "\n\n[localrepo]\nname=localrepo\nfailovermethod=priority\nenabled=1\ngpgcheck=0\npriority=1\n" >> $$mock_new; \
printf "baseurl=file://$$(realpath $<)/\n\n" >> $$mock_new; \
sed -i '$$a"""' $$mock_new; \
if ! cmp -s $$mock_new $$mock_orig; then \
flock $</repo.lock mv $$mock_new $$mock_orig; \
fi; \
rm -f $$mock_new
# Disables the local RPM repo by removing the installed package manager and
# Mock configuration files.
localrepodisable: $(TOPLVL)/repo
flock $</repo.lock rm -f $</yum.conf $</clear.cfg
# Runs createrepo_c for the local RPM repo
localrepocreate: $(TOPLVL)/repo
cd $< && flock repo.lock createrepo_c .
# Remove all RPMs from the local RPM repo
localrepoclean: $(TOPLVL)/repo
flock $</repo.lock find $< -maxdepth 1 -name '*.rpm' -delete
# Summarizes the local RPM repo status
localrepostatus:
@if [ ! -d $(TOPLVL)/repo ]; then \
echo '** Local repo not found'; \
exit 0; \
fi; \
if [ -f $(TOPLVL)/repo/yum.conf ]; then \
echo '** Local repo enabled for Yum/DNF.'; \
else \
echo '** Local repo not enabled for Yum/DNF.'; \
fi; \
if [ -f $(TOPLVL)/repo/clear.cfg ]; then \
echo '** Local repo enabled for Mock.'; \
else \
echo '** Local repo not enabled for Mock.'; \
fi; \
echo -n '** Local repo package list: '; \
( \
cd "$(TOPLVL)/repo"; \
LC_COLLATE="C"; \
shopt -s nullglob; \
set -- *.rpm; \
if [ -n "$$1" ]; then \
printf '\n'; printf '%q\n' "$$@"; \
else \
printf 'none found\n'; \
fi; \
)
# Detection of whether to use the local RPM repo occurs on-the-fly. Normally,
# variable definitions appear in Makefile.config, but these variables are not
# intended to be user-modifiable.
ifeq ($(wildcard $(TOPLVL)/repo/clear.cfg),)
MOCK_CONFIG_VAL = $(realpath $(MOCK_CONF))
else
MOCK_CONFIG_VAL = $(realpath $(TOPLVL)/repo/clear.cfg)
USE_LOCAL_REPO = 1
endif
localreponotice:
@if [ -n "${USE_LOCAL_REPO}" ]; then \
printf '\n\n** NOTICE: Using local repo for the build. Continuing after 3 seconds.\n'; \
printf '** If this is not desired, run `make repodisable`.\n'; \
printf '** The repo can be re-enabled later with `make repoenable`.\n'; \
printf '** Run `touch $(TOPLVL)/repo/opt-in-build` to prevent the 3 second delay.\n\n\n'; \
[ -f $(TOPLVL)/repo/opt-in-build ] || sleep 3; \
fi >&2
.PHONY: clean-old-rpms clean-old-logs clean-old-content
clean-old-rpms:
rm -rf ./rpms
rm -f ./results/*.rpm
clean-old-logs:
rm -f ./results/*.log
clean-old-content: clean-old-rpms clean-old-logs
.PHONY: require-pkg-repo-dir link-new-rpms
require-pkg-repo-dir:
@if [ -z ${PKG_REPO_DIR} ]; then \
echo "Please specify PKG_REPO_DIR to indicate package repo location."; \
exit 1; \
fi
link-new-rpms: require-pkg-repo-dir
mkdir -p ${PKG_REPO_DIR}/rpms
rm -f ${PKG_REPO_DIR}/rpms/*.rpm
find ${PKG_REPO_DIR}/results -maxdepth 1 -name '*.rpm' -exec ln {} ${PKG_REPO_DIR}/rpms/ \;
rm -f ${PKG_REPO_DIR}/rpms/*.src.rpm
.PHONY: help
##### Code
# Make sure that HELPSPACE has exactly HELPLEN spaces in it
EMPTY:= # An empty string
HELPSPACE :=${EMPTY} ${EMPTY}
HELPLEN := 18
define HELPSCRIPTBODY :=
# Skip all non help lines
/^#help[ \t]/!d
# see if this is a target, defined to be "#help" a single space or tab a word
# and then a ":". You can therefore escape something like http://localhost
# by adding an extra space. We lose extra indent, but we will anyhow
# as we will feed this to fmt -t
s/^#help[ \t]\([^ \t]*:\)[ \t]*/\1\n/
ttarget
# This is a continuation line
s/^#help[ \t]*/${HELPSPACE}/
b
:target
# Add on spaces to pad it out, then remove extra ones and the newline
# almost does the correct thing if there are not enough spaces
s/[\t ]*\n[ \t]*/${HELPSPACE}\n/
s/^\(.\{${HELPLEN}\}\) */\1/
s/\n//
endef
# Debugging hint, add '@echo "$${HELPSCRIPT}" | hexdump -C'
help: export HELPSCRIPT=${HELPSCRIPTBODY}
help:
@printf "%s\n" "The output below describes commands that can be invoked in this directory."
@printf "\n\nPossible commands:\n\n"
@sed "$${HELPSCRIPT}" ${MAKEFILE_LIST} | { fmt -t -w $${COLUMNS:-75} || cat ; }