1#!/usr/bin/make -f
2
3BUILDER_IMAGES=		\
4	centos-7 	\
5	fedora-33	\
6	debian-stretch	\
7	debian-buster	\
8	debian-bullseye	\
9	debian-testing	\
10	debian-sid	\
11	ubuntu-xenial	\
12	ubuntu-bionic	\
13	ubuntu-focal	\
14	ubuntu-impish \
15	kira		\
16	tarball
17
18IMAGES=${BUILDER_IMAGES} devshell
19DEFAULT_IMAGE ?= ubuntu-bionic
20TARBALL_IMAGE ?= tarball
21DEFAULT_DEB_IMAGE=ubuntu-bionic
22DEFAULT_RPM_IMAGE=centos-7
23DOCKER=docker
24CONTAINER_REGISTRY ?= ghcr.io/syslog-ng
25MODE ?= snapshot
26VERSION ?= $(shell MODE=${MODE} scripts/version.sh)
27DOCKER_RUN_ARGS=-e USER_NAME_ON_HOST=$(shell whoami)	\
28        --network=host --privileged \
29	--ulimit nofile=1024:1024 \
30	-v $(ROOT_DIR):/source \
31        -v $(DBLD_DIR):/dbld \
32	-v $(DBLD_DIR)/build:/build \
33	-v $(DBLD_DIR)/install:/install \
34	-e CONFIGURE_OPTS="$${CONFIGURE_OPTS:-$(CONFIGURE_OPTS)}" \
35	-e CCACHE_DIR=/build/ccache \
36	-e MODE=$(MODE) \
37	-e VERSION=$(VERSION) \
38	-e PATH=/usr/lib/ccache:/usr/lib64/ccache:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \
39	-e GRADLE_USER_HOME=/build/gradle-home \
40	-e GRADLE_PROJECT_CACHE_DIR=/build/gradle-cache \
41	-e GRADLE_FLAGS=--build-cache \
42	$(if $(wildcard ${HOME}/.gitconfig),-v ${HOME}/.gitconfig:/build/.gitconfig)
43DOCKER_BUILD_ARGS=
44ROOT_DIR=$(shell pwd)
45DBLD_DIR=$(ROOT_DIR)/dbld
46BUILD_DIR=$(DBLD_DIR)/build
47RELEASE_DIR=$(DBLD_DIR)/release
48TARBALL_BASENAME=syslog-ng-$(VERSION).tar.gz
49TARBALL=$(BUILD_DIR)/$(TARBALL_BASENAME)
50GIT=$(shell which git || echo false)
51GIT_RELEASE_TAG=syslog-ng-$(VERSION)
52CONFIGURE_OPTS=--enable-debug --enable-manpages --with-python=2 --prefix=/install $(CONFIGURE_ADD)
53DBLD_RULES=$(MAKE) --no-print-directory -f $(DBLD_DIR)/rules
54
55DOCKER_SHELL=$(DOCKER) run $(DOCKER_RUN_ARGS) --rm -ti ${CONTAINER_REGISTRY}/dbld-$* /dbld/shell
56
57-include dbld/rules.conf
58
59help:
60	@echo "This script allows you to build release/snapshot artifacts, such "
61	@echo "as rpm, deb packages and tarballs in controlled environments (e.g. "
62	@echo "within docker containers)."
63	@echo ""
64	@echo "Please create the required docker image first using the 'image' target"
65	@echo "then you can build syslog-ng binaries or do development using the "
66	@echo "targets described below."
67	@echo ""
68	@echo "Supported OSs are: $(IMAGES)"
69	@echo ""
70	@echo "Packaging targets:"
71	@echo "  deb: generate debs in dbld/build for $(DEFAULT_DEB_IMAGE)"
72	@echo "  rpm: generate RPMs in dbld/build for $(DEFAULT_RPM_IMAGE)"
73	@echo "  deb-<os>: generate debs in dbld/build for the specified OS"
74	@echo "  rpm-<os>: generate rpms in dbld/build for the specified OS"
75	@echo ""
76	@echo "Docker images:"
77	@echo "  image: generate the default docker image"
78	@echo "  image-<os>: generate docker image with a specific OS for building syslog-ng"
79	@echo "  images: generate all docker images"
80	@echo ""
81	@echo "Development:"
82	@echo "  bootstrap: bootstrap source from a git clone (e.g. autogen.sh and friends)"
83	@echo "  shell: start a shell in the specified OS"
84	@echo "  login: start a 2nd shell alongside an already running one"
85	@echo "  root-login: start a 2nd shell (as root) alongside an already running one"
86	@echo "  tarball: generate a tarball in a controlled environment (e.g. docker)"
87	@echo "  pkg-tarball: generate a tarball that includes deb/rpm packaging files"
88	@echo "  prepare-release VERSION=x.y.z: prepare the source tree for release, does not commit"
89	@echo "  release VERSION=x.y.z: generate a release tarball/deb package in a controlled environment (e.g. docker)"
90	@echo ""
91	@echo "Notable Make variables:"
92	@echo "  CONFIGURE_ADD -- add this to the configure command line in bootstrap"
93	@echo "  DEFAULT_IMAGE -- override the default image, currently $(DEFAULT_IMAGE)"
94	@echo "  TARBALL_IMAGE -- override the default image where the tarball is generated, currently $(TARBALL_IMAGE)"
95	@echo ""
96
97bootstrap: bootstrap-$(DEFAULT_IMAGE)
98bootstrap-%: setup
99	$(DOCKER) run $(DOCKER_RUN_ARGS) --rm  -i  ${CONTAINER_REGISTRY}/dbld-$* /dbld/bootstrap
100
101make-%: setup
102	$(DOCKER) run $(DOCKER_RUN_ARGS) --rm -i  ${CONTAINER_REGISTRY}/dbld-$(DEFAULT_IMAGE) /dbld/make $(MAKE_ARGS) $*
103
104tarball-from-root: setup
105	@if [ -f $(ROOT_DIR)/../$(TARBALL_BASENAME) ] && [ ! -f $(TARBALL) ]; then \
106		cp $(ROOT_DIR)/../$(TARBALL_BASENAME) $(TARBALL); \
107	fi
108
109tarball: tarball-$(TARBALL_IMAGE)
110tarball-%: tarball-from-root
111	@echo "Checking $(TARBALL) if it is up-to-date..."; \
112	if [ -f $(TARBALL) ]; then \
113		TARBALL_CHANGES=`find $(ROOT_DIR) -newer $(TARBALL) | sed -e 's,^$(ROOT_DIR),,' | grep -v -f $(DBLD_DIR)/tarball-changes.ignore | tee $(BUILD_DIR)/tarball-changed-files.txt | wc -l`; \
114	fi; \
115	if [ ! -f $(TARBALL) ] || [ "$${TARBALL_CHANGES}" -gt 0 ]; then \
116		if [ -f $(TARBALL) ]; then \
117			echo "Rebuilding, because these contents have changed since the tarball" && \
118			cat $(BUILD_DIR)/tarball-changed-files.txt; \
119		else \
120			echo "Rebuilding, because tarball $(TARBALL) not found"; \
121		fi; \
122		echo "Git status follows:" && \
123		( $(GIT) status || echo "Git not found..." ) && \
124		$(DOCKER) run $(DOCKER_RUN_ARGS) --rm -i ${CONTAINER_REGISTRY}/dbld-$* /dbld/tarball; \
125	else \
126		echo "Tarball $(TARBALL) is up to date (except files excluded by $(DBLD_DIR)/tarball-changes.ignore)"; \
127	fi
128
129
130
131pkg-tarball: pkg-tarball-$(TARBALL_IMAGE)
132
133#
134# pkg-tarball-%:
135#
136# NOTE: first check if the tarball is already a pkg-tarball (containing
137# packaging files).  This might happen if we try to reuse a cached tarball
138# and we can spare some time by avoiding the pulling of the tarball image as
139# well as not having to run the scripts that add the packaging files
140#
141pkg-tarball-%: tarball-%
142	@if ! tar --strip-components=1 --show-transformed-names  -tvf $(TARBALL) | grep  ' debian/rules$$' > /dev/null; then \
143		$(DOCKER) run $(DOCKER_RUN_ARGS) --rm -i ${CONTAINER_REGISTRY}/dbld-$* /dbld/pkg-tarball; \
144	fi
145
146package: package-$(DEFAULT_IMAGE)
147package-%: pkg-tarball
148	$(DOCKER) run $(DOCKER_RUN_ARGS) --rm -i  ${CONTAINER_REGISTRY}/dbld-$* /dbld/package
149
150deb: deb-$(DEFAULT_DEB_IMAGE)
151deb-%: pkg-tarball
152	$(DOCKER) run $(DOCKER_RUN_ARGS) --rm -i  ${CONTAINER_REGISTRY}/dbld-$* /dbld/deb
153
154rpm: rpm-$(DEFAULT_RPM_IMAGE)
155rpm-%: pkg-tarball
156	$(DOCKER) run $(DOCKER_RUN_ARGS) --rm -i  ${CONTAINER_REGISTRY}/dbld-$* /dbld/rpm
157
158validate-tree-clean:
159	@if ! $(GIT) diff-index --quiet HEAD; then \
160		echo "Your source tree has changed, this operation requires a clean git tree."; \
161		exit 1; \
162	fi
163
164validate-version-format:
165	@if [ "$$(echo $(VERSION) | sed -e 's/^[0-9]\+\.[0-9]\+.[0-9]\+//')" != "" ]; then \
166		echo "The version number you specified $(VERSION) is not a valid version for a RELEASE. Please supply one using VERSION= via the command line"; \
167		exit 1; \
168	fi
169
170prepare-release: setup validate-tree-clean validate-version-format
171	$(DOCKER) run $(DOCKER_RUN_ARGS) --rm -i  ${CONTAINER_REGISTRY}/dbld-$(TARBALL_IMAGE) /dbld/prepare-release $(VERSION)
172
173validate-release: validate-tree-clean validate-version-format
174	$(DOCKER) run $(DOCKER_RUN_ARGS) --rm -i  ${CONTAINER_REGISTRY}/dbld-$(TARBALL_IMAGE) /dbld/validate-release-version $(VERSION)
175
176	@if $(GIT) rev-parse --verify -q "$(GIT_RELEASE_TAG)" > /dev/null; then \
177		echo "Your git tree already has $(GIT_RELEASE_TAG), this might indicate a duplicate release, please remove that first."; \
178		exit 1; \
179	fi
180
181#
182# release:
183#
184# the order of these is important, so invoke ourselves recursively
185# instead of using make dependencies, which can be reordered in parallel builds
186#
187release: validate-release
188
189	ARTIFACT_DIR=$(RELEASE_DIR)/$(VERSION) && \
190	rm -rf "$$ARTIFACT_DIR" && mkdir -p "$$ARTIFACT_DIR" && rm -rf $(TARBALL) && \
191	$(DBLD_RULES) MODE=release VERSION=$(VERSION) pkg-tarball && \
192	echo "Building the release was successful, artifacts stored in $$ARTIFACT_DIR" && \
193	$(DBLD_RULES) MODE=release VERSION=$(VERSION) tag-release
194
195tag-release:
196	$(GIT) tag $(GIT_RELEASE_TAG)
197
198clean:
199	rm -rf $(BUILD_DIR)/*
200
201run: run-$(DEFAULT_IMAGE)
202run: RUN_COMMAND=echo Specify RUN_COMMAND to do something sensible here
203run-%: setup
204	$(DOCKER) run $(DOCKER_RUN_ARGS) --rm -ti ${CONTAINER_REGISTRY}/dbld-$* bash -c "$(RUN_COMMAND)"
205
206shell: shell-$(DEFAULT_IMAGE)
207shell-%: setup
208	$(DOCKER_SHELL)
209
210
211images: $(foreach image,$(IMAGES), image-$(image))
212image: image-$(DEFAULT_IMAGE)
213image-kira: image-ubuntu-focal
214image-devshell: image-tarball
215image-tarball: image-debian-testing
216image-%:
217	$(DBLD_DIR)/prepare-image-build $* && \
218        $(DOCKER) build $(DOCKER_BUILD_ARGS) --build-arg=ARG_IMAGE_PLATFORM=$* --build-arg=COMMIT=$$($(GIT) rev-parse --short HEAD || echo "") --build-arg=CONTAINER_REGISTRY=${CONTAINER_REGISTRY} --network=host -t ${CONTAINER_REGISTRY}/dbld-$* -f $(DBLD_DIR)/images/$*.dockerfile $(DBLD_DIR)
219
220pull-images: $(foreach image,$(BUILDER_IMAGES), pull-image-$(image))
221pull-image: pull-image-$(DEFAULT_IMAGE)
222pull-image-%:
223	$(DOCKER) pull ${CONTAINER_REGISTRY}/dbld-$*
224
225cache-image-%:
226	@IMAGE=${CONTAINER_REGISTRY}/dbld-$*:latest;										\
227	IMAGE_ID=$$(docker images -q $$IMAGE | head -1);								\
228	WATCHED_FILES="dbld packaging/rhel/syslog-ng.spec packaging/debian/control";					\
229	if [ "$$IMAGE_ID" = "" ]; then 											\
230		$(DBLD_RULES) pull-image-$*;										\
231	fi;														\
232	IMAGE_ID=$$(docker images -q $$IMAGE | head -1);								\
233	if [ "$$IMAGE_ID" != "" ]; then 										\
234		image_commit=$$(docker inspect  --format '{{ index .Config.Labels "COMMIT"}}' $$IMAGE_ID);		\
235		dbld_changes=$$( 											\
236			($(GIT) cat-file -e $${image_commit:-NO_COMMIT_LABEL_IN_DBLD_IMAGE}^{commit} 			\
237				&& $(GIT) diff $${image_commit} -- $${WATCHED_FILES} | wc -l				\
238				|| echo 1)										\
239		);													\
240	else														\
241		dbld_changes=1; 											\
242	fi;														\
243	if [ "$${dbld_changes}" -gt 0 ]; then										\
244		echo "Triggering rebuild of $$IMAGE, as dbld directory changed since the build of the image, or the "	\
245			"cached image has no COMMIT label, or couldn't fetch from dockerhub or couldn't find git" &&	\
246		$(DBLD_RULES) image-$*;											\
247	else 														\
248		echo "DBLD version in image matches, not initiating rebuild...";					\
249	fi
250
251exec: exec-$(DEFAULT_IMAGE)
252exec: EXEC_COMMAND=echo Specify EXEC_COMMAND to do something sensible here
253exec-%: setup
254	@container=`$(DOCKER) ps | grep dbld-$* | head -1 | cut -d ' ' -f1`; \
255	$(DOCKER) exec -ti  $$container $(EXEC_COMMAND)
256
257login: login-$(DEFAULT_IMAGE)
258login-%: EXEC_COMMAND=gosu $(shell whoami) /dbld/shell
259login-%: exec-%
260	@true
261
262root-login: root-login-$(DEFAULT_IMAGE)
263root-login-%: EXEC_COMMAND=bash
264root-login-%: exec-%
265	@true
266
267setup:
268	@mkdir -p dbld/build || true
269	@mkdir -p dbld/install || true
270	@mkdir -p dbld/release || true
271
272list-builder-images:
273	@echo ${BUILDER_IMAGES}
274