mirror of
https://github.com/clearlinux/common.git
synced 2026-04-28 19:13:35 +00:00
703 lines
27 KiB
Makefile
703 lines
27 KiB
Makefile
#-*-makefile-*-
|
|
|
|
all: build
|
|
|
|
TOPLVL = ../..
|
|
|
|
include $(TOPLVL)/projects/common/Makefile.config
|
|
include $(TOPLVL)/projects/common/Makefile.shared
|
|
|
|
SHELL = /bin/bash
|
|
|
|
CURRENT_BRANCH := $(shell git rev-parse --abbrev-ref HEAD)
|
|
|
|
SPECFILE = $(addsuffix .spec, $(PKG_NAME))
|
|
|
|
SRPMVERS = $(shell [ ! -f $(SPECFILE) ] || $(call queryspec,%{NVR}\n,$(SPECFILE)))
|
|
SRPMFILE = results/$(SRPMVERS).src.rpm
|
|
|
|
LATEST_RPMS = $(wildcard rpms/*.rpm)
|
|
DEBUGINFO_RPM = $(wildcard rpms/${PKG_NAME}-debuginfo-$(shell $(call queryspec,%{V}-%{R},${SPECFILE})).*.rpm)
|
|
RPMS ?= $(LATEST_RPMS)
|
|
|
|
WITH_SUDO = sudo
|
|
|
|
# MOCK_CONFIG_VAL is set in Makefile.shared
|
|
MOCK_SMP_FLAGS=$(patsubst -j%, -D_smp_mflags\ -j%,$(filter -j%, $(MAKEFLAGS)))
|
|
MOCK ?= $(WITH_SUDO) /usr/bin/mock -r $(MOCK_CONFIG_VAL) $(MOCK_SMP_FLAGS) $(MOCK_OPTS)
|
|
|
|
MOCK_CLEANUP_OPT := $(if $(CLEANUP),--cleanup-after,--no-cleanup-after)
|
|
AUTOSPEC_CLEANUP_OPT := $(if $(CLEANUP),-C)
|
|
|
|
ifneq ($(wildcard upstream),)
|
|
__allsources := $(notdir $(strip $(shell cat upstream)))
|
|
__missingsources := $(filter-out $(wildcard ${__allsources}), ${__allsources})
|
|
endif
|
|
|
|
$(SPECFILE):
|
|
@[[ -f "$@" ]] || (\
|
|
echo Error: $@ is missing. Please run \`make autospec\` to try and auto;\
|
|
echo Error: generate one for you.;\
|
|
exit 1 )
|
|
|
|
upstream:
|
|
@[[ -f "$@" ]] || (\
|
|
echo Error: The \"$@\" file is missing. Try running \`make autospec\` to;\
|
|
echo Error: auto generate one for you. If you are not using autospec to;\
|
|
echo Error: generate a spec file, specify the proper "Source*" entries in the;\
|
|
echo Error: spec header, and try running \`make generateupstream\`.;\
|
|
exit 1 )
|
|
|
|
#help spdxcheck: Checks that the package license is a valid SPDX license,
|
|
#help or that it is in the exceptions list.
|
|
spdxcheck: $(SPECFILE)
|
|
@for LICENSE in `$(call queryspec,%{LICENSE}\n,$(SPECFILE))`; do \
|
|
if ! grep -qx "$$LICENSE" $(TOPLVL)/projects/common/licenses-{spdx,exceptions,extra}; then FAIL=yes; echo "ERROR: License '$$LICENSE' is not an allowed SPDX license ID"; fi; \
|
|
done; test -z "$$FAIL"
|
|
|
|
#help clean: Cleans up the src.rpm file. but not the rpm files or log files.
|
|
clean:
|
|
rm -f $(SRPMFILE)
|
|
|
|
#help proper: Brings your copy of the package to a nearly clean git checkout state.
|
|
proper: repodel
|
|
rm -rf results rpms
|
|
rm -f build.log.round*
|
|
rm -f mock_build.log mock_srpm.log $(__allsources) report.html
|
|
|
|
#help mockclean: Clean all mock chroots and cache directories for all packages.
|
|
mockclean:
|
|
$(MOCK) --clean --scrub=all
|
|
|
|
#help mockproper: Clean mock chroot
|
|
mockproper:
|
|
$(MOCK) --clean --uniqueext=$(PKG_NAME)
|
|
|
|
configemail:
|
|
@test -d .git || git init -b main
|
|
@$(call subjectprefix,$(PKG_NAME))
|
|
@echo -n "Subject prefix email configured to: "
|
|
@git config --get format.subjectPrefix
|
|
|
|
#help checkblacklist: Verify rpms files to not include banned files for Clear Linux OS.
|
|
checkblacklist:
|
|
@$(TOPLVL)/projects/common/checkblacklist.sh $(TOPLVL)/projects/common/blacklist $(filter-out ${DEBUGINFO_RPM},${RPMS})
|
|
|
|
prebuild-checks:
|
|
|
|
#help build: Builds from current directory on your machine and puts log
|
|
#help files and rpms in the results directory of your package. If there
|
|
#help are mutlple tar.gz files for a package, make will do make sources,
|
|
#help which creates a src.rpm file from the spec file.
|
|
#help Use MOCK_OPTS environment varible to pass down arbitrary mock options.
|
|
build: prebuild-checks configemail $(SPECFILE) upstream $(SRPMFILE)
|
|
$(MOCK) $(SRPMFILE) --result=results/ $(MOCK_CLEANUP_OPT) --uniqueext=$(PKG_NAME)
|
|
$(MAKE) link-new-rpms PKG_REPO_DIR="."
|
|
@perl $(TOPLVL)/projects/common/logcheck.pl results/build.log
|
|
@perl $(TOPLVL)/projects/common/count.pl results/build.log &> testresults
|
|
@$(MAKE) checkblacklist
|
|
|
|
#help build-nocheck: Same as 'make build', but do not run the package's test suite.
|
|
build-nocheck: configemail $(SPECFILE) upstream $(SRPMFILE)
|
|
$(MOCK) $(SRPMFILE) --nocheck --result=results/ $(MOCK_CLEANUP_OPT) --uniqueext=$(PKG_NAME)
|
|
$(MAKE) link-new-rpms PKG_REPO_DIR="."
|
|
@perl $(TOPLVL)/projects/common/logcheck.pl results/build.log
|
|
@perl $(TOPLVL)/projects/common/count.pl results/build.log &> testresults
|
|
@$(MAKE) checkblacklist
|
|
|
|
fmvpatches: results/build.log
|
|
@perl $(TOPLVL)/projects/common/fmvpatches.pl $(PKG_NAME)
|
|
|
|
#help rootshell: Puts you in a root shell at the top of your build root.
|
|
rootshell:
|
|
$(MOCK) --result=results/ --no-cleanup-after --shell --uniqueext=$(PKG_NAME)
|
|
|
|
#help shell: Puts you in a user shell in the home directory in the build root.
|
|
shell:
|
|
$(MOCK) --result=results/ --no-cleanup-after --shell --uniqueext=$(PKG_NAME) --unpriv "cd && exec \$$SHELL -l -i"
|
|
|
|
# Always rebuild the source rpm
|
|
.PHONY: $(SRPMFILE)
|
|
$(SRPMFILE): $(SPECFILE) $(__allsources) localreponotice clean-old-content
|
|
@$(MAKE) spdxcheck
|
|
$(MOCK) --buildsrpm --source=./ --spec=$(SPECFILE) --result=results/ $(MOCK_CLEANUP_OPT) --uniqueext=$(PKG_NAME)
|
|
mv results/root.log results/srpm-root.log
|
|
mv results/build.log results/srpm-build.log
|
|
|
|
# Do a git fetch and a git rebase to apply local commits on top of latest
|
|
# commits from the remote. A git fetch/rebase is used rather than a git pull so
|
|
# aborting the git pull at a password prompt doesn't leave local changes
|
|
# stashed. Do the git status dance so we only apply a stash we create. Note
|
|
# that a fetch/rebase is not attempted if the remote 'origin' is not
|
|
# initialized locally, or if the remote contains no commits.
|
|
pullrebase:
|
|
@if [ -z "$$SKIP_GIT" ] && [ -e .git ]; then \
|
|
if ! git rev-parse --verify --quiet origin/main > /dev/null; then \
|
|
echo "Remote not yet initialized. Continuing."; \
|
|
exit 0; \
|
|
fi; \
|
|
echo "Fetching origin"; \
|
|
git fetch; \
|
|
if ! git rev-parse --verify --quiet FETCH_HEAD > /dev/null; then \
|
|
echo "No commits exist in remote. Continuing."; \
|
|
exit 0; \
|
|
fi; \
|
|
if [ "$$(git rev-list FETCH_HEAD | head -n 1)" = "$$(git rev-list HEAD | head -n 1)" ]; then \
|
|
echo "Current branch up-to-date. Continuing."; \
|
|
exit 0; \
|
|
fi; \
|
|
echo "Rebasing to origin/main"; \
|
|
if git status --porcelain | grep -q '^.[^?]'; \
|
|
then \
|
|
git stash save; \
|
|
git rebase FETCH_HEAD; \
|
|
git stash apply; \
|
|
else \
|
|
git rebase FETCH_HEAD; \
|
|
fi \
|
|
fi
|
|
|
|
preautospec-checks:
|
|
|
|
#help autospec: automatically generates a specfile. If there is
|
|
#help already a specfile, it will be overwritten. Several files used by
|
|
#help autospec will be created in the process.
|
|
#help Use MOCK_OPTS environment varible to pass down arbitrary mock options
|
|
#help to autospec.
|
|
#help For more information, see the project at https://github.com/clearlinux/autospec
|
|
autospec: preautospec-checks pullrebase localreponotice clean-old-content
|
|
git rm --ignore-unmatch pumpAutospec || rm -f pumpAutospec
|
|
@if [ -e $(SPECFILE) ] && ! grep -q "# Generated by: autospec.py" $(SPECFILE) ; then \
|
|
echo "Specfile already exists and was not created by autospec.py! Aborting."; \
|
|
exit 1; \
|
|
fi
|
|
$(eval ARCHIVES = $(shell $(TOPLVL)/projects/common/vendor.py '$(value ARCHIVES)' $(firstword $(NEWURL) $(URL)) $(PKG_NAME) $(VND_BASE_URL)))
|
|
@printf 'PKG_NAME := %s\nURL = %s\nARCHIVES = %s\n\ninclude ../common/Makefile.common\n' $(PKG_NAME) '$(firstword $(value NEWURL) $(value URL))' '$(value ARCHIVES)' > Makefile
|
|
python3 $(TOPLVL)/projects/autospec/autospec/autospec.py \
|
|
--target . \
|
|
--integrity \
|
|
--config "$(AUTOSPEC_CONF)" \
|
|
--name $(PKG_NAME) \
|
|
--archives $(ARCHIVES) \
|
|
--mock-config $(MOCK_CONFIG_VAL) \
|
|
--mock-opts="$(MOCK_SMP_FLAGS) $(MOCK_OPTS)" \
|
|
$${SETVERSION:+ --version $${SETVERSION}} \
|
|
$${NON_INTERACTIVE:+ --non_interactive} \
|
|
$${SKIP_GIT:+ --skip-git} \
|
|
$(AUTOSPEC_CLEANUP_OPT) \
|
|
$(firstword $(NEWURL) $(URL));
|
|
$(MAKE) link-new-rpms PKG_REPO_DIR="."
|
|
@$(MAKE) spdxcheck
|
|
@$(MAKE) checkblacklist
|
|
@if [ -e update_changelog.sh ] && [ -z "$$SKIP_GIT" ] ; then \
|
|
bash update_changelog.sh ; \
|
|
git commit --amend --no-edit Change* ; \
|
|
fi
|
|
@$(MAKE) -s for-review.txt
|
|
diffstat for-review.txt
|
|
@printf "\n**\n"
|
|
@printf "** NOTICE: A patch with changes is available in the file for-review.txt\n"
|
|
@printf "** To recreate (e.g., after git commit --amend), run make for-review.txt\n"
|
|
@printf "** To submit for review: git send-email --to <recipient> for-review.txt\n"
|
|
@printf "**\n\n"
|
|
|
|
#help for-review.txt: Creates the for-review.txt file, which is
|
|
#help a minimized version of the Git commit, suitable for code review.
|
|
for-review.txt:
|
|
git diff | grep -q index || python3 $(TOPLVL)/projects/common/patchfilter.py > for-review.txt
|
|
.PHONY: for-review.txt
|
|
|
|
#help autospecnogit: Runs autospec, but does not create a commit
|
|
autospecnogit:
|
|
$(MAKE) autospec SKIP_GIT=1
|
|
|
|
#help autospecnostate: Runs autospec, but cleans up mock chroots
|
|
#help and disables interactive mode.
|
|
autospecnostate:
|
|
$(MAKE) autospec CLEANUP=1 NON_INTERACTIVE=1
|
|
|
|
scanlicense:
|
|
python3 $(TOPLVL)/projects/autospec/autospec/autospec.py -t . --config $(AUTOSPEC_CONF) --license-only $(firstword $(NEWURL) $(URL)) --name $(PKG_NAME)
|
|
|
|
#help bump: Increments the package release number by one and commits the result. If
|
|
#help the variable BUMP_MSG is set, its value is used as the commit summary.
|
|
#help Otherwise a generic commit summary is used.
|
|
bump:
|
|
git stash
|
|
git pull --rebase
|
|
$(MAKE) bumpnogit
|
|
git add $(SPECFILE) release
|
|
fromver=$(shell $(call queryspec,%{VERSION}-%{RELEASE}\n,$(SPECFILE))); \
|
|
tover=`$(call queryspec,%{VERSION}-%{RELEASE}\n,$(SPECFILE))`; \
|
|
if [[ -n "$(BUMP_MSG)" ]]; then \
|
|
bumpmsg="$(BUMP_MSG)"; \
|
|
else \
|
|
bumpmsg="version bump from $$fromver to $$tover"; \
|
|
fi; \
|
|
git commit -a -m "$$bumpmsg"
|
|
|
|
#help bumpnogit: Increments the package release number by one and does not commit
|
|
#help changes.
|
|
bumpnogit:
|
|
@$(MAKE) spdxcheck
|
|
oldrel=$(shell $(call queryspec,%{RELEASE}\n,$(SPECFILE))); \
|
|
newrel=$$(($$oldrel + 1)); \
|
|
sed -i "s/^\(Release[[:blank:]]*:[[:blank:]]*\)$$oldrel$$/\1$$newrel/" $(SPECFILE); \
|
|
echo "$$newrel" > release;
|
|
|
|
$(__missingsources): sources
|
|
|
|
# First argument is a Clear Linux build number (e.g. 22000)
|
|
define fetch-from-srpm
|
|
tmp=$$(mktemp -d -p "."); \
|
|
srpm=$$($(call queryspec,%{NVR}.src.rpm\n,$(SPECFILE))); \
|
|
if cd "$$tmp" && ! curl -s -S -f -L -O $(MIRROR_CURL_OPTS) $(DOWNLOAD_MIRROR)/releases/$(1)/clear/source/SRPMS/$$srpm; then \
|
|
echo "Failed to download $$srpm from Clear Linux release $(1)." >&2; \
|
|
cd .. && rm -rf "$$tmp"; \
|
|
exit 1; \
|
|
fi; \
|
|
rpm2cpio $$srpm | cpio --quiet -id; \
|
|
cd ..; \
|
|
srclist=$$($(call queryspec,[%{SOURCE}\n],$(SPECFILE))); \
|
|
for s in $$srclist; do \
|
|
if ! mv --no-clobber "$$tmp"/$$s .; then \
|
|
echo "Missing source file \"$$s\" in $${srpm}." >&2; \
|
|
rm -rf "$$tmp"; \
|
|
exit 1; \
|
|
fi; \
|
|
echo "Retrieved source file $$s ..."; \
|
|
done; \
|
|
rm -rf "$$tmp"
|
|
endef
|
|
|
|
#help sources: If SOURCES_URL is defined, download required upstream source files
|
|
#help from that location. Otherwise, try to download source files according to the
|
|
#help URLs listed in the spec file. If any of the source files fail to download,
|
|
#help check for the relevant SRPM from published releases of Clear Linux OS, and
|
|
#help extract the files if found. Note that SRPMs are taken from the DOWNLOAD_MIRROR
|
|
#help location. This will run automatically, as a dependency. NOTE: A Koji server can
|
|
#help make use of this "make sources" command, since it lives in a repo named
|
|
#help "common". If you use this makefile in Koji, ensure "make sources" continues to
|
|
#help work for both remote and local builds, since it is a prerequisite of several
|
|
#help commands for building packages.
|
|
ifneq ($(strip $(SOURCES_URL)),)
|
|
sources: upstream
|
|
while read u; do \
|
|
case "$$u" in \
|
|
"") continue ;; \
|
|
*://*) n="$$u" ;; \
|
|
*) n="$(SOURCES_URL)/$$u" ;; \
|
|
esac; \
|
|
if ! curl --fail -L -o `basename "$$n"` $(SOURCES_CURL_OPTS) "$$n"; then \
|
|
echo "Failed to download $$n"; \
|
|
exit 1; \
|
|
fi; \
|
|
done < upstream
|
|
else
|
|
sources:
|
|
@$(MAKE) generateupstream; \
|
|
[ $$? -eq 0 ] && exit 0; \
|
|
nvr="$$($(call queryspec,%{NAME}\t%{VERSION}\t%{RELEASE}\n,$(SPECFILE)))"; \
|
|
git -C $(TOPLVL)/projects/common fetch --tags >/dev/null 2>&1; \
|
|
latest_builds=$$(git -C $(TOPLVL)/projects/common tag -l | sort -rn); \
|
|
for b in $$latest_builds; do \
|
|
url="$(DOWNLOAD_MIRROR)/releases/$$b/clear/source/package-sources"; \
|
|
echo "Checking for source files in build $$b ..."; \
|
|
if grep -q "$$nvr" <(curl -s -f -L $(MIRROR_CURL_OPTS) $$url); then \
|
|
$(call fetch-from-srpm,$$b); \
|
|
if [ $$? -eq 0 ]; then \
|
|
echo "Source files retrieved from build $$b"; \
|
|
exit 0; \
|
|
fi; \
|
|
fi; \
|
|
done; \
|
|
echo "Source files not found for package"; \
|
|
exit 1
|
|
endif
|
|
|
|
prekoji-checks:
|
|
|
|
#help koji: Creates a git tag on the latest local commit, then asks koji to
|
|
#help build from that tag on the server. If you have uncommitted local changes,
|
|
#help they will not be included.
|
|
koji: prekoji-checks kojidef
|
|
@$(MAKE) spdxcheck
|
|
@$(MAKE) checkblacklist
|
|
@if [ "$(CURRENT_BRANCH)" != "main" ]; then \
|
|
echo "Error: Must be on the \"main\" branch to submit to koji" >&2; \
|
|
exit 1; \
|
|
fi; \
|
|
if ! git diff --quiet HEAD -- ${SPECFILE}; then \
|
|
echo "Error: All changes to ${SPECFILE} must be committed first" >&2; \
|
|
exit 1; \
|
|
fi; \
|
|
git fetch; \
|
|
if git rev-parse --verify --quiet origin/main >/dev/null; then \
|
|
git pull --rebase; \
|
|
fi; \
|
|
if git ls-remote --tags --exit-code origin $(SRPMVERS) >/dev/null; then \
|
|
echo "Error: remote tag $(SRPMVERS) already exists" >&2; \
|
|
exit 1; \
|
|
fi
|
|
git tag $(SRPMVERS)
|
|
git push origin $(CURRENT_BRANCH):main refs/tags/$(SRPMVERS)
|
|
$(KOJI_CMD) build $$KOJI_NOWAIT $(KOJI_TAG) $(PKG_BASE_URL)/$(PKG_NAME)?#$(SRPMVERS)
|
|
@if [ -f bump.list ]; then \
|
|
$(MAKE) koji-waitrepo; \
|
|
msg="Bump for $(shell $(call queryspec,%{NAME} %{VERSION}\n,$(SPECFILE)))"; \
|
|
for bump_dep in $$(cat bump.list); do \
|
|
(cd ../"$$bump_dep" && $(MAKE) bump BUMP_MSG="$$msg" && $(MAKE) koji-nowait) \
|
|
done \
|
|
fi
|
|
|
|
#help rekoji: In case a previous 'make koji' failed, trigger a rebuild for the
|
|
#help same tag.
|
|
rekoji: kojidef
|
|
git pull --rebase
|
|
$(KOJI_CMD) build $$KOJI_NOWAIT $(KOJI_TAG) $(PKG_BASE_URL)/$(PKG_NAME)?#$(SRPMVERS)
|
|
|
|
#help scratch: Performs scratch-build on package in the background.
|
|
scratch: $(SPECFILE) upstream $(SRPMFILE) kojidef
|
|
$(KOJI_CMD) build --scratch --nowait --background $$KOJI_NOWAIT $(KOJI_TAG) $(SRPMFILE)
|
|
|
|
#help scratch-wait: Performs scratch-build on package.
|
|
scratch-wait: $(SPECFILE) upstream $(SRPMFILE) kojidef
|
|
$(KOJI_CMD) build --scratch --wait $(KOJI_TAG) $(SRPMFILE)
|
|
|
|
#help koji-nowait: Same as 'make koji', but do not block
|
|
koji-nowait:
|
|
$(MAKE) KOJI_NOWAIT="--nowait --background" koji &
|
|
|
|
#help rekoji-nowait: Same as 'make rekoji', but do not block
|
|
rekoji-nowait:
|
|
$(MAKE) KOJI_NOWAIT="--nowait --background" rekoji
|
|
|
|
#help koji-waitrepo: Wait for current package changes to become available in the
|
|
#help koji repo. If PKG_NAME is overridden on the command line, wait on changes for
|
|
#help that package instead. This capability allows the developer to "chain" builds
|
|
#help for submission to koji according to the state of the package repos on their
|
|
#help system. Additional options for `koji wait-repo` can be specified via the
|
|
#help WAIT_OPTS variable.
|
|
koji-waitrepo: kojidef
|
|
@if [[ ! "${PKG_NAME}" =~ ^[A-Za-z0-9._+-]+$$ ]]; then \
|
|
echo "[ERROR] Invalid package name \"${PKG_NAME}\""; \
|
|
exit 1; \
|
|
fi; \
|
|
if [[ "${PKG_NAME}" != "$(notdir ${CURDIR})" ]]; then \
|
|
$(MAKE) -s -C ../${PKG_NAME} koji-waitrepo; \
|
|
else \
|
|
koji wait-repo --build=${SRPMVERS} ${WAIT_OPTS} ${KOJI_TAG}-build; \
|
|
fi
|
|
|
|
.PHONY: koji-tag
|
|
#help koji-tag: runs koji tag-pkg on what's in the current specfile's nvr
|
|
koji-tag:
|
|
koji tag-pkg dist-clear $(SRPMVERS)
|
|
|
|
.PHONY: koji-untag
|
|
#help koji-untag: runs koji untag-pkg on what's in the current specfile's nvr
|
|
koji-untag:
|
|
koji untag-pkg dist-clear $(SRPMVERS)
|
|
|
|
|
|
update-versions:
|
|
|
|
.PHONY: update
|
|
#help update: Tries to run update.sh if it exists. update.sh is expected
|
|
#help to check for version updates, exit (successfully) if none are found
|
|
#help or update the package and push the update to koji.
|
|
#help If no update.sh exists, update the version, autospec and push the
|
|
#help update to koji (bumping the bump.list if found).
|
|
update: export AUTOSPEC_UPDATE=1
|
|
update:
|
|
@if [ -f update.first ]; then \
|
|
for pkg in $$(< update.first); do \
|
|
(cd "../$${pkg}" || exit 1; $(MAKE) update-versions || exit 0; $(MAKE) update) || exit; \
|
|
done; \
|
|
fi
|
|
@if [ -f update.sh ]; then \
|
|
./update.sh; \
|
|
else \
|
|
$(MAKE) -s update-versions && \
|
|
$(MAKE) autospec CLEANUP=1 && \
|
|
$(MAKE) -s koji && \
|
|
$(MAKE) koji-waitrepo; \
|
|
fi \
|
|
|
|
logcheck:
|
|
@perl $(TOPLVL)/projects/common/logcheck.pl results/build.log
|
|
|
|
#help repoadd: Adds locally-built RPMs for this package to the local RPM
|
|
#help repository. If this repository does not yet exist, it is created and
|
|
#help enabled.
|
|
repoadd: $(TOPLVL)/repo
|
|
@if [ -z "${LATEST_RPMS}" ]; then \
|
|
echo "No rpms found in rpms/ directory."; \
|
|
exit 1; \
|
|
fi
|
|
$(MAKE) -s repodel NO_CREATEREPO=1
|
|
@echo "Adding new rpms:"; \
|
|
for rpm in ${LATEST_RPMS}; do \
|
|
echo "+$${rpm#rpms/}"; \
|
|
echo "$${rpm#rpms/}" >> .repo-index; \
|
|
done; \
|
|
flock $</repo.lock ln -f -t $< ${LATEST_RPMS}
|
|
$(MAKE) -s localrepocreate
|
|
$(MAKE) -s localrepoenable
|
|
|
|
#help repodel: Removes RPMs from the local RPM repository that were
|
|
#help previously added by 'make repoadd' for this package.
|
|
repodel: $(TOPLVL)/repo
|
|
@if [ -f .repo-index ]; then \
|
|
echo "Cleaning old rpms:"; \
|
|
mapfile -t rpms < <(sed 's|.*|$</&|' .repo-index); \
|
|
for rpm in "$${rpms[@]}"; do \
|
|
echo "-$${rpm#$</}"; \
|
|
done < .repo-index; \
|
|
flock $</repo.lock rm -f "$${rpms[@]}"; \
|
|
rm .repo-index; \
|
|
if [ -z "$$NO_CREATEREPO" ]; then \
|
|
$(MAKE) -s localrepocreate; \
|
|
fi; \
|
|
fi
|
|
|
|
#help repoenable: Enables the local RPM repository for use with Yum/DNF and
|
|
#help Mock. If this repository does not yet exist, it is created.
|
|
repoenable: localrepoenable ;
|
|
|
|
#help repodisable: Disables the local RPM repository.
|
|
repodisable: localrepodisable ;
|
|
|
|
#help repostatus: Summarizes the local RPM repository status.
|
|
repostatus: localrepostatus ;
|
|
|
|
loop-up:
|
|
$(loopup)
|
|
|
|
loop-down:
|
|
$(loopdown)
|
|
|
|
#help install: Install locally built RPMs for this package into an image
|
|
#help located at ../../clear.img. Make sure the image is not being used before
|
|
#help running this rule! Note that debuginfo RPMs are installed to the cache
|
|
#help directory used by the automatic debuginfo system in Clear Linux.
|
|
install:
|
|
@$(MAKE) loop-up DEVICE=6 TARGET=$(TOPLVL)/clear.img
|
|
topdir=$(TOPLVL)/image; \
|
|
for r in $(RPMS); do rpm2cpio $$r | (cd $$topdir; sudo cpio -i -d -u); done; \
|
|
for dir in lib src; do \
|
|
if [ -d $$topdir/usr/$$dir/debug ]; then \
|
|
find $$topdir/usr/$$dir/debug -type f -o -type l | while read path; do \
|
|
newpath=`echo $$path | sed "s|\($$topdir\)/usr/$$dir/debug|\1/var/cache/debuginfo/$$dir|"`; \
|
|
sudo mkdir -p `dirname $$newpath`; \
|
|
sudo mv -f $$path $$newpath; \
|
|
done; \
|
|
fi; \
|
|
done
|
|
@$(MAKE) loop-down DEVICE=6
|
|
|
|
#help install-debuginfo-local: Install locally built debuginfo RPM to
|
|
#help the automatic debuginfo cache location (/var/cache/debuginfo)
|
|
install-debuginfo-local:
|
|
@if [ -z "${DEBUGINFO_RPM}" ]; then \
|
|
echo "No debuginfo to install... skipping"; \
|
|
exit 0; \
|
|
fi; \
|
|
echo -n "Installing ${DEBUGINFO_RPM}... "; \
|
|
tmpdir=$$(mktemp -d); \
|
|
rpm2cpio ${DEBUGINFO_RPM} | ( cd $$tmpdir; cpio -i -d -u 2> /dev/null); \
|
|
dest=/var/cache/debuginfo/lib; \
|
|
find $$tmpdir/usr/lib/debug/ -mindepth 1 -maxdepth 1 2> /dev/null | while read -r d; do \
|
|
sudo chown -R dbginfo:dbginfo "$$d"; \
|
|
sudo cp -a "$$d" $$dest/; \
|
|
done; \
|
|
find $$tmpdir/usr/share/debug/.build-id -type l 2> /dev/null | while read -r link; do \
|
|
new_target=$$(readlink $$link | sed 's|/usr/share/debug|/usr/lib/debug|'); \
|
|
sudo ln -sf "$$new_target" "$$link"; \
|
|
done; \
|
|
find $$tmpdir/usr/share/debug/ -mindepth 1 -maxdepth 1 -regextype awk -regex '.*/(.build-id|boot|lib|sbin|usr)$$' 2> /dev/null | while read -r d; do \
|
|
sudo chown -R dbginfo:dbginfo "$$d"; \
|
|
sudo cp -a "$$d" $$dest/; \
|
|
done; \
|
|
dest=/var/cache/debuginfo/src; \
|
|
find $$tmpdir/usr/src/debug/ -mindepth 1 -maxdepth 1 2> /dev/null | while read -r d; do \
|
|
sudo chown -R dbginfo:dbginfo "$$d"; \
|
|
sudo cp -a "$$d" $$dest/; \
|
|
done; \
|
|
find $$tmpdir/usr/share/debug/src/ -mindepth 1 -maxdepth 1 2> /dev/null | while read -r d; do \
|
|
sudo chown -R dbginfo:dbginfo "$$d"; \
|
|
sudo cp -a "$$d" $$dest/; \
|
|
done; \
|
|
sudo rm -rf $$tmpdir; \
|
|
echo "done"
|
|
|
|
#help install-local: Install locally built RPMs to the root filesystem. Note that the
|
|
#help debuginfo RPM installs to /var/cache/debuginfo
|
|
install-local:
|
|
@for r in $(filter-out ${DEBUGINFO_RPM},${RPMS}); do \
|
|
echo -n "Installing $$r... "; \
|
|
rpm2cpio $$r | (cd /; sudo cpio -i -d -u 2> /dev/null); \
|
|
echo "done"; \
|
|
done
|
|
@$(MAKE) -s install-debuginfo-local
|
|
|
|
#help install-mock: Install locally built RPMs to the mock rootcache
|
|
#help filesystem. This command is usually used with "make shell".
|
|
install-mock: repoadd
|
|
$(MOCK) --result=results/ --no-cleanup-after --uniqueext=$(PKG_NAME) -i $(filter-out ${DEBUGINFO_RPM},${RPMS})
|
|
|
|
#help generateupstream: Run this rule to create or update the 'upstream' file
|
|
#help by downloading the upstream source tarballs listed in the spec file and
|
|
#help calculating their hashes. Autospec performs this step automatically, so
|
|
#help ignore it for packages managed with autospec. Additional curl options
|
|
#help may be used for downloading the upstream source tarballs by defining the
|
|
#help CURL_OPTS variable for this rule.
|
|
generateupstream:
|
|
@[ -e upstream ] && mv upstream upstream.bak; \
|
|
urls=$$(rpmspec -D '_vendor clr' -P $(SPECFILE) | sed -n "s|^Source[0-9]*[[:blank:]]*:[[:blank:]]*\(..*://..*\)$$|\1|p"); \
|
|
for url in $$urls; do \
|
|
filename=$$(basename $$url); \
|
|
if [ ! -e $$filename ]; then \
|
|
if ! curl --fail -L -O $(CURL_OPTS) $$url; then \
|
|
echo "Failed to download $$url"; \
|
|
[ -e upstream.bak ] && mv --no-clobber upstream.bak upstream; \
|
|
exit 1; \
|
|
fi; \
|
|
fi; \
|
|
echo $$(sha1sum -- $$filename | cut -d\ -f1)/$$filename >> upstream; \
|
|
done
|
|
@rm -f upstream.bak
|
|
@cat upstream
|
|
|
|
#help drop-abandoned: Remove all unused patches from the git tree
|
|
drop-abandoned: $(SPECFILE)
|
|
python3 $(TOPLVL)/projects/common/drop-abandoned-patches.py $(SPECFILE)
|
|
|
|
#help cloc: Count lines of code with the `cloc` tool on the full sources of package
|
|
cloc: $(SRPMFILE)
|
|
@$(MOCK) -r $(TOPLVL)/repo/clear.cfg $(SRPMFILE) --result=results/ --no-cleanup-after
|
|
@$(MOCK) --chroot --copyin /usr/bin/cloc /usr/bin/cloc --result=results/ --no-cleanup-after
|
|
@$(MOCK) --result=results/ --no-cleanup-after --chroot '/usr/bin/cloc /builddir > /tmp/cloc.txt'
|
|
@$(MOCK) --copyout /tmp/cloc.txt results/ --result=results/
|
|
@$(MOCK) --clean --scrub=chroot --uniqueext=$(PKG_NAME)
|
|
cat results/cloc.txt
|
|
|
|
#help catchup: Backport the commits from the current version to the upstream HEAD (not release).
|
|
#help Only works if giturl is defined and the current package version can be mapped to a git tag.
|
|
catchup:
|
|
$(MAKE) catchup-HEAD
|
|
|
|
#help catchup-<commit|tag>: Backport the commits from the current version to the specified commit or tag.
|
|
#help Only works if giturl is defined and the current package version can be mapped to a git tag.
|
|
catchup-%:
|
|
@target=$*; \
|
|
giturl=$$(grep -E '^giturl\s*=\s*\S+' options.conf | sed 's/giturl\s*=\s*//' 2>/dev/null); \
|
|
if [[ -z "$${giturl}" ]]; then \
|
|
echo "Error: giturl not defined in options.conf"; \
|
|
exit 1; \
|
|
fi; \
|
|
mkdir -p results; \
|
|
if [[ -d results/$(PKG_NAME) ]]; then \
|
|
echo "Reusing existing repository..."; \
|
|
git -C results/$(PKG_NAME) fetch origin; \
|
|
else \
|
|
echo "Cloning upstream repository..."; \
|
|
git -C results clone "$${giturl}" $(PKG_NAME); \
|
|
fi; \
|
|
if ! git -C results/$(PKG_NAME) rev-parse --verify --quiet "$${target}" >/dev/null; then \
|
|
echo "Error: Target commit/tag $${target} not found"; \
|
|
exit 1; \
|
|
fi; \
|
|
version=$$(rpm -q --qf '%{VERSION}\n' --specfile $(SPECFILE) | head -1); \
|
|
echo "Version: $${version}"; \
|
|
current_tag=$$(git -C results/$(PKG_NAME) tag --list | grep -E "^($(PKG_NAME)-)?v?$${version}$$") || { \
|
|
echo "Error: No tag found for current package version"; \
|
|
exit 1; \
|
|
}; \
|
|
echo "Catching up from $${current_tag} to $${target}"; \
|
|
for commit in $$(git -C results/$(PKG_NAME) log --reverse --pretty=oneline $${current_tag}..$${target} | cut -d' ' -f1); do \
|
|
$(MAKE) backport-$${commit}; \
|
|
done;
|
|
|
|
|
|
#help backport-<commit>: Retrieve a commit from the upstream git repository and save it as a backport patch.
|
|
#help The giturl is read from options.conf.
|
|
backport-%:
|
|
@commit=$*; \
|
|
echo "Backporting commit: $${commit}"; \
|
|
giturl=$$(grep -E '^giturl\s*=\s*\S+' options.conf | sed 's/giturl\s*=\s*//' 2>/dev/null); \
|
|
if [[ -z "$${giturl}" ]]; then \
|
|
echo "Error: giturl not defined in options.conf"; \
|
|
exit 1; \
|
|
fi; \
|
|
mkdir -p results; \
|
|
if [[ -d results/$(PKG_NAME) ]]; then \
|
|
echo "Reusing existing repository..."; \
|
|
git -C results/$(PKG_NAME) fetch origin; \
|
|
else \
|
|
echo "Cloning upstream repository..."; \
|
|
git -C results clone "$${giturl}" $(PKG_NAME); \
|
|
fi; \
|
|
full_commit=$$(git -C results/$(PKG_NAME) show --pretty=oneline $${commit} 2>/dev/null | head -1 | cut -d' ' -f 1); \
|
|
if [[ -z "$${full_commit}" ]]; then \
|
|
echo "Error: Commit for $${commit} not found"; \
|
|
exit 1; \
|
|
fi; \
|
|
patch=backport-$${full_commit}.patch; \
|
|
git -C results/$(PKG_NAME) format-patch -1 --stdout $${full_commit} > $${patch}; \
|
|
if [[ -s $${patch} ]]; then \
|
|
echo "$${patch} created"; \
|
|
grep -qE "^$${patch}$$" series 2>/dev/null || echo "$${patch}" >> series; \
|
|
else \
|
|
rm -f $${patch}; \
|
|
echo "Error: Failed to create backport patch"; \
|
|
exit 1; \
|
|
fi \
|
|
|
|
.PHONY: whatrequires
|
|
#help whatrequires: Output a list of packages that directly depend on this one,
|
|
#help showing the subpackage-level breakdown. Each line of output has the format
|
|
#help "SUBPACKAGE(|SYMBOL)? <- PACKAGE (ARCH)". If ARCH is "src", the meaning is
|
|
#help "PACKAGE has a BuildRequires (build dependency) on SUBPACKAGE". And if ARCH
|
|
#help is "x86_64", the meaning is "PACKAGE has a Requires (runtime dependency) on
|
|
#help SUBPACKAGE". The optional "|SYMBOL" portion is printed when the symbol
|
|
#help required does not match the subpackage name. Note that the ability to query
|
|
#help version-qualified dependencies is not yet implemented... (For example, if
|
|
#help python3-core provides the version-qualified symbol "python(abi) = 3.9",
|
|
#help running `make whatrequires` for `python3` will detect packages that depend on
|
|
#help "python(abi)", but not "python(abi) = 3.9".)
|
|
whatrequires:
|
|
@Q="dnf --config=${PM_CONF} repoquery --quiet --releasever=clear"; \
|
|
TMP=$$(mktemp -d); trap "rm -rf $$TMP" EXIT; \
|
|
$${Q} --provides ${PKG_NAME} | awk '{ print $$1 }' > $$TMP/${PKG_NAME}; \
|
|
( \
|
|
while read -r provide; do \
|
|
$${Q} --qf="${PKG_NAME} <- %{NAME} (x86_64)" --arch=x86_64 --srpm --whatrequires $$provide; \
|
|
$${Q} --qf="${PKG_NAME} <- %{NAME} (src)" --arch=src --whatrequires $$provide; \
|
|
done < $$TMP/${PKG_NAME} \
|
|
) | awk '$$3 != "${PKG_NAME}"' | LC_COLLATE=C sort -u; \
|
|
sed -n 's/^%package *\(.*\)$$/\1/p' ${PKG_NAME}.spec | sort > $$TMP/subpkgs; \
|
|
while read -r val; do \
|
|
if grep -qE '^-n +' <<< $$val; then \
|
|
subpkg=$$(awk '{ print $$2 }' <<< $$val); \
|
|
else \
|
|
subpkg=${PKG_NAME}-$$val; \
|
|
fi; \
|
|
$${Q} --provides $$subpkg | awk '{ print $$1 }' > $$TMP/$$subpkg; \
|
|
( \
|
|
while read -r provide; do \
|
|
$${Q} --qf="$$subpkg|$$provide <- %{NAME} (x86_64)" --arch=x86_64 --srpm --whatrequires $$provide; \
|
|
$${Q} --qf="$$subpkg|$$provide <- %{NAME} (src)" --arch=src --whatrequires $$provide; \
|
|
done < $$TMP/$$subpkg \
|
|
) | awk '$$3 != "${PKG_NAME}"' | sed "s/^$$subpkg|\($$subpkg\)/\1/" | LC_COLLATE=C sort -u; \
|
|
done < $$TMP/subpkgs
|
|
|
|
# Define LTS-specific targets in a separate makefile
|
|
-include $(TOPLVL)/projects/common/Makefile.common.lts
|
|
|
|
# Define site local common targets in a separate makefile
|
|
-include $(TOPLVL)/projects/common/Makefile.common.site_local
|
|
|
|
# Include optional extended makefiles from individual package repos
|
|
-include Makefile.custom
|