-
Notifications
You must be signed in to change notification settings - Fork 23
/
Makefile.toplevel
274 lines (240 loc) · 10.8 KB
/
Makefile.toplevel
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
#-*-makefile-*-
all: clone
TOPLVL = .
include $(TOPLVL)/projects/common/Makefile.config
include $(TOPLVL)/projects/common/Makefile.shared
SHELL = /bin/bash
PKGS = $(shell cat $(PACKAGES_FILE))
PKGS_LOCAL = $(sort $(filter ${PKGS},$(subst packages/,,$(wildcard packages/*))))
PKGS_ORPHANED = $(sort $(filter-out common ${PKGS},$(subst packages/,,$(wildcard packages/*))))
proj_PKGS = $(addprefix proj_,$(PROJ_PKGS))
clone_PKGS = $(addprefix clone_,$(PKGS))
#help clone: Clones any new package/project in the git tree that you didn't
#help already check out. If you already have a package checked out,
#help it will not clone that package
clone: $(proj_PKGS) $(clone_PKGS)
#help clone-packages: Same action as 'make clone', but for package repos only.
clone-packages: $(clone_PKGS)
#help clone-projects: Same action as 'make clone', but for project repos only.
clone-projects: $(proj_PKGS)
$(proj_PKGS):
@proj=$(patsubst proj_%,%,$@); \
[ -d projects/$$proj ] || ( \
echo "Checking out: projects/$$proj"; \
if [ "$$proj" = "autospec" ] ; then \
git clone https://github.com/clearlinux/autospec.git projects/autospec; \
else \
git clone $(PRJ_BASE_URL)/$$proj projects/$$proj; \
fi; \
cd projects/$$proj; \
if [ "$$proj" != "autospec" ] ; then \
$(call gitoliteurl,projects/$$proj); \
fi; \
$(call subjectprefix,$$proj); \
)
packages/common/Makefile.common:
@mkdir -p $(dir $@)
@ln -s ../../projects/common/Makefile.common $@
$(clone_PKGS): $(PACKAGES_FILE) packages/common/Makefile.common
@pkg=$(patsubst clone_%,%,$@); \
remotepkg=$(call remotepkgname,$$pkg); \
[ -d packages/$$pkg ] || ( \
echo "Checking out: packages/$$pkg"; \
git clone -b main $(PKG_BASE_URL)/$$remotepkg packages/$$pkg; \
cd packages/$$pkg; \
$(call gitoliteurl,packages/$$pkg); \
$(call subjectprefix,$$pkg); \
)
#help pull: Performs a git pull --rebase for each package repo, avoiding the creation
#help of merge commits, while displaying any changes since your last pull. It is
#help silent if there are no changes.
.PHONY: pull ${PULL_PKGS}
PULL_PKGS:= $(addprefix PULL_projects/,$(PROJ_PKGS)) $(addprefix PULL_packages/,${PKGS_LOCAL})
${PULL_PKGS}:
@p=$(patsubst PULL_%,%,$@) ; \
if [ ! -d "$$p/.git" ]; then echo "Nothing to pull for $$p - $$p/.git missing"; exit 0; fi; \
cd "$$p" ; \
if git remote | grep origin >/dev/null 2>&1; then \
case "$$p" in \
("projects/"*) BRANCH=master ;; \
("packages/"*) BRANCH=main ;; \
(*) BRANCH=master ;; \
esac; \
O=$$(git rev-parse origin/"$$BRANCH" 2>/dev/null); \
git fetch --tags origin >/dev/null 2>&1; \
N=$$(git rev-parse origin/"$$BRANCH"); \
if [ "$$O" != "$$N" ]; then \
echo "Updating: $$p"; \
if ! git merge --ff-only origin/"$$BRANCH" 2>/dev/null; then \
echo "$$p: Cannot fast-forward $$(git rev-parse --abbrev-ref HEAD) to origin/$$BRANCH" ; \
fi ; \
git --no-pager log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit $$O..$$N; echo; \
fi ; \
if [ "$$p" != "projects/autospec" ] ; then \
$(call gitoliteurl,$$p); \
fi ; \
else \
echo "$$p: no such remote 'origin'"; \
fi ; \
case "$$p" in \
("projects/"*|"packages/"*) P=$${p#*/} ;; \
(*) P="$$p";; \
esac; \
$(call subjectprefix,$$P);
# If a user runs "make -j pull", set the job count to 4 to rate limit client
# requests to the server hosting package git repos. Finding the value that is
# passed to -j and changing it to limit it to 4 is even harder, see
# http://blog.jgc.org/2015/03/gnu-make-insanity-finding-value-of-j.html
# for a discussion, Simplified it comes to
### # Default target depends on parallel, and outputs the job count
### all: | compute_job_count
### @echo ${JOB_COUNT}
### # get the number of words in .parallel file and clean up.
### compute_job_count: .parallel
### @$(eval JOB_COUNT := $(words $(file < $<)))rm $<
### THIS_MAKEFILE := $(CURDIR)/$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
### # run a submake, sending the output (one word per job until failure) to the .parallel file
### .parallel: FORCE
### @$(MAKE) --no-print-directory -f ${THIS_MAKEFILE} par 2>/dev/null >$@ || true
### FORCE: ;
### # par depends on par-1 par-2 ... par-24
### par: $(addprefix par-,1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24)
### # Each job outputs a word, waits for a second and fails. So eventually
### # you have n tasks in sleep, then one fails and the job fails.
### # par-%: ; @echo $@ && sleep 1 && false
ifeq (pull,$(filter pull,${MAKECMDGOALS}))
ifeq (3,$(word 1,$(subst ., ,${MAKE_VERSION})))
$(warning *************** This version of make is too old to pull in parallel )
else
MAKEFLAGS += -j4 -Otarget
endif
endif
pull: ${PULL_PKGS}
#help clean-pkgs-dir: For packages that are no longer present in the distro,
#help removes the associated package repos from the ./packages tree and stores
#help it in packages_old. If it already exists in packages_old, skip it.
clean-pkgs-dir: $(PACKAGES_FILE)
@for p in ${PKGS_ORPHANED}; do \
mkdir -p packages_old; \
if [ -d "packages_old/$$p" ]; then \
echo "packages_old/$$p already exists, not touching it"; \
else \
echo "Moving $$p from packages to packages_old, as it is no longer in common/packages."; \
mv packages/$$p packages_old/$$p; \
fi; \
done
@echo "packages directory cleaned";
clean_PKGS = $(addprefix clean_,$(PKGS_LOCAL))
#help clean: Run 'make clean' for every package.
clean: $(clean_PKGS)
proper_PKGS = $(addprefix proper_,$(PKGS_LOCAL))
#help proper: Run 'make proper' for every package, and purge the local
#help repo and image.
proper: $(proper_PKGS)
rm -rf repo
rm -f clear.img
rm -f image-content.lst
rm -f report.html
.PHONY: $(clean_PKGS)
.PHONY: $(proper_PKGS)
$(clean_PKGS):
@echo "cleaning $(patsubst clean_%,%,$@)"
-@$(MAKE) -s -C $(addprefix packages/,$(patsubst clean_%,%,$@)) clean
$(proper_PKGS):
-@$(MAKE) -s -C $(addprefix packages/,$(patsubst proper_%,%,$@)) proper
#help status: Runs git status for all package repos, thus displaying untracked
#help and unstaged files in addition to staged files.
status: $(PACKAGES_FILE) $(addprefix packages/,$(PKGS_LOCAL))
@for p in projects/common $(addprefix packages/,$(PKGS_LOCAL)); do \
if [ -d "$$p/.git" ] && [ -n "$$(git -C $$p status -uno --porcelain)" ]; then echo "Uncommitted changes in $$p:"; git -C "$$p" status --short; fi ;\
done
#help diff: Runs git diff for all package repos and displays the diffstat using
#help the --stat flag.
diff: $(PACKAGES_FILE) $(addprefix packages/,$(PKGS_LOCAL))
@for p in projects/common $(addprefix packages/,$(PKGS_LOCAL)); do \
(cd $$p; git status --porcelain | grep -vq '^?? ' && (echo "Uncommitted changes in: $$p"; git --no-pager diff --stat); :) ;\
done
#help log: Run git log origin/main..HEAD for all package repos, thus
#help displaying any committed but unpushed changes.
log: $(PACKAGES_FILE) $(addprefix packages/,$(PKGS_LOCAL))
@for p in projects/common $(addprefix packages/,$(PKGS_LOCAL)); do \
( cd $$p; if [ -n "$$(git rev-list origin/main..HEAD)" ] ; then \
echo $$p ; git --no-pager log --pretty="format:%s" origin/main..HEAD ; echo ; echo;\
fi ; ) \
done
#help versions: Displays the version of each package in the ./packages tree.
versions: $(PACKAGES_FILE) $(addprefix packages/,$(PKGS_LOCAL))
@for p in $(addprefix packages/,$(PKGS_LOCAL)); do \
(cd $$p; if ls *.spec &> /dev/null; then $(call queryspec,%{NAME}-%{VERSION}\n,*.spec) | head -n1; fi) ;\
done
#help releases: Like 'make versions', but also displays the release number.
releases: $(PACKAGES_FILE) $(addprefix packages/,$(PKGS_LOCAL))
@for p in $(addprefix packages/,$(PKGS_LOCAL)); do \
(cd $$p; if ls *.spec &> /dev/null; then $(call queryspec,%{NVR}\n,*.spec) | head -n1; fi) ;\
done
#help provides: Is used to find out which RPM package provides some file.
#help Params: FP=<file_fullpath> RN=<release_number>, i.e. 'make provides FP=/usr/bin/ls'
provides:
@$(TOPLVL)/projects/common/provides.sh -f $(FP) -r $(RN)
preautospecnew-checks:
#help autospecnew: Creates a new autospec package with for a given URL=$(URL)
#help with NAME=$(NAME). Several files used by autospec will be created in the
#help process.
#help Use MOCK_OPTS environment varible to pass down arbitrary mock options
#help to autospec.
#help For more information about autospec, see the project page on Github https://github.com/clearlinux/autospec
autospecnew: preautospecnew-checks localreponotice
@if [ -z $(NAME) ] || [ -z $(URL) ]; then \
echo "Please specify NAME and URL. The ARCHIVES variable is optional."; \
exit 1; \
fi
$(call clone-if-available,$(NAME))
@if [ ! -d $(TOPLVL)/packages/$(NAME)/.git ]; then \
echo "no remote repository found, creating new package repository and running autospec"; \
mkdir -p $(TOPLVL)/packages/$(NAME); \
( \
cd $(TOPLVL)/packages/$(NAME); \
git init -b main; \
git remote add origin $(PKG_BASE_URL)/$(NAME); \
$(call gitoliteurl,packages/$(NAME)); \
$(call subjectprefix,$(NAME)); \
); \
printf 'PKG_NAME := %s\nURL = %s\nARCHIVES = %s\n\ninclude ../common/Makefile.common\n' $(NAME) '$(value URL)' '$(value ARCHIVES)' > $(TOPLVL)/packages/$(NAME)/Makefile; \
python3 $(TOPLVL)/projects/autospec/autospec/autospec.py \
--target packages/$(NAME) \
--integrity \
--config "$(AUTOSPEC_CONF)" \
--name $(NAME) \
--archives $(ARCHIVES) \
--mock-config $(MOCK_CONFIG_VAL) \
--mock-opts="$(MOCK_OPTS)" \
$${SETVERSION:+ --version $${SETVERSION}} \
${NON_INTERACTIVE} ${SKIP_GIT} $(if $(CLEANUP),-C) \
$(URL); \
if [ $$? -eq 0 ]; then \
$(MAKE) link-new-rpms PKG_REPO_DIR="${TOPLVL}/packages/${NAME}"; \
$(TOPLVL)/projects/common/checkblacklist.sh $(TOPLVL)/projects/common/blacklist $(TOPLVL)/packages/${NAME}/results/*.rpm; \
python3 $(TOPLVL)/projects/common/patchfilter.py <(git -C $(TOPLVL)/packages/$(NAME) format-patch -1 --stdout) > $(TOPLVL)/packages/$(NAME)/for-review.txt; \
printf "\n**\n"; \
printf "** NOTICE: A patch with changes is available in the file $(TOPLVL)/packages/$(NAME)/for-review.txt\n"; \
printf "** Please look through this file and if you are unsure, please submit for code review with git send-email\n"; \
printf "**\n\n"; \
else \
echo "Autospec of $(NAME) failed."; \
exit 1; \
fi; \
else \
echo "$(NAME) already exists at $(TOPLVL)/packages/$(NAME)"; \
exit 1; \
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 repoclean: Removes all RPMs from the local RPM repository.
repoclean: localrepoclean localrepocreate ;
#help repostatus: Summarizes the local RPM repository status.
repostatus: localrepostatus ;
# Define site local toplevel targets in a separate makefile
-include $(TOPLVL)/projects/common/Makefile.toplevel.site_local