summaryrefslogtreecommitdiffstats
path: root/scripts/crossbuild/crossbuild.mk
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--scripts/crossbuild/crossbuild.mk236
1 files changed, 236 insertions, 0 deletions
diff --git a/scripts/crossbuild/crossbuild.mk b/scripts/crossbuild/crossbuild.mk
new file mode 100644
index 0000000..da96506
--- /dev/null
+++ b/scripts/crossbuild/crossbuild.mk
@@ -0,0 +1,236 @@
+#
+# Include crossbuild targets, to test building on lots of
+# different OSes. Uses Docker.
+#
+ifeq ($(shell which docker 2> /dev/null),)
+.PHONY: crossbuild crossbuild.help
+crossbuild crossbuild.help :
+ @echo crossbuild requires Docker to be installed
+else
+
+#
+# Short list of common builds
+#
+CB_COMMON:=centos7 debian10 ubuntu18
+
+# Where the docker directories are
+DT:=scripts/crossbuild/docker
+
+# Where to put stamp files (subdirectory of where this makefile is)
+DD:=$(dir $(realpath $(lastword $(MAKEFILE_LIST))))/build
+
+# List of all the docker images (sorted for "crossbuild.info")
+CB_IMAGES:=$(sort $(patsubst $(DT)/%,%,$(wildcard $(DT)/*)))
+
+# Location of the .git dir (may be different for e.g. submodules)
+GITDIR:=$(shell perl -MCwd -e 'print Cwd::abs_path shift' $$(git rev-parse --git-dir))
+
+CB_CPREFIX:=fr-crossbuild-
+CB_IPREFIX:=freeradius-build
+
+#
+# This Makefile is included in-line, and not via the "boilermake"
+# wrapper. But it's still useful to use the same process for
+# seeing commands that are run.
+#
+ifeq "${VERBOSE}" ""
+ Q=@
+else
+ Q=
+endif
+
+#
+# Enter here: This builds everything
+#
+.PHONY: crossbuild crossbuild.common
+crossbuild: crossbuild.info $(foreach IMG,${CB_IMAGES},crossbuild.${IMG})
+crossbuild.common: crossbuild.info $(foreach IMG,${CB_COMMON},crossbuild.${IMG})
+
+#
+# Dump out some useful information on what images we're going to test
+#
+.PHONY: crossbuild.info crossbuild.info_header crossbuild.help
+crossbuild.info: crossbuild.info_header $(foreach IMG,${CB_IMAGES},crossbuild.${IMG}.status)
+ @echo Common images: $(CB_COMMON)
+
+crossbuild.info_header:
+ @echo Images:
+
+crossbuild.help: crossbuild.info
+ @echo ""
+ @echo "Make targets:"
+ @echo " crossbuild - build and test all images"
+ @echo " crossbuild.common - build and test common images"
+ @echo " crossbuild.info - list images"
+ @echo " crossbuild.down - stop all containers"
+ @echo " crossbuild.reset - remove cache of docker state"
+ @echo " crossbuild.clean - down and reset all targets"
+ @echo " crossbuild.wipe - destroy all crossbuild Docker images"
+ @echo ""
+ @echo "Per-image targets:"
+ @echo " crossbuild.IMAGE - build and test image <IMAGE>"
+ @echo " crossbuild.IMAGE.log - show latest build log"
+ @echo " crossbuild.IMAGE.up - start container"
+ @echo " crossbuild.IMAGE.down - stop container"
+ @echo " crossbuild.IMAGE.sh - shell in container"
+ @echo " crossbuild.IMAGE.refresh - push latest commits into container"
+ @echo " crossbuild.IMAGE.reset - remove cache of docker state"
+ @echo " crossbuild.IMAGE.clean - stop container and tidy up"
+ @echo " crossbuild.IMAGE.wipe - remove Docker image"
+
+#
+# Remove stamp files, so that we try and create images again
+#
+crossbuild.reset: $(foreach IMG,${CB_IMAGES},crossbuild.${IMG}.reset)
+
+#
+# Stop all containers
+#
+crossbuild.down: $(foreach IMG,${CB_IMAGES},crossbuild.${IMG}.down)
+
+#
+# Clean up: stop all containers, do a reset
+#
+crossbuild.clean: $(foreach IMG,${CB_IMAGES},crossbuild.${IMG}.clean)
+
+#
+# Remove all images
+#
+crossbuild.wipe: $(foreach IMG,${CB_IMAGES},crossbuild.${IMG}.wipe)
+
+#
+# Define rules for building a particular image
+#
+define CROSSBUILD_IMAGE_RULE
+#
+# Show status (based on stamp files)
+#
+.PHONY: crossbuild.${1}.status
+crossbuild.${1}.status:
+ ${Q}printf "%s" "`echo \" ${1} \" | cut -c 1-20`"
+ ${Q}if [ -e "$(DD)/stamp-up.${1}" ]; then echo "running"; \
+ elif [ -e "$(DD)/stamp-image.${1}" ]; then echo "built"; \
+ else echo "-"; fi
+#
+# Build the docker image
+#
+$(DD)/stamp-image.${1}:
+ ${Q}echo "BUILD ${1} ($(CB_IPREFIX)/${1}) > $(DD)/build.${1}"
+ ${Q}docker build $(DOCKER_BUILD_OPTS) $(DT)/${1} -f $(DT)/${1}/Dockerfile -t $(CB_IPREFIX)/${1} >$(DD)/build.${1} 2>&1
+ ${Q}touch $(DD)/stamp-image.${1}
+
+#
+# Start up the docker container
+#
+.PHONY: $(DD)/docker.up.${1}
+$(DD)/docker.up.${1}: $(DD)/stamp-image.${1}
+ ${Q}echo "START ${1} ($(CB_CPREFIX)${1})"
+ ${Q}docker container inspect $(CB_CPREFIX)${1} >/dev/null 2>&1 || \
+ docker run -d --rm \
+ --privileged --cap-add=ALL \
+ --mount=type=bind,source="$(GITDIR)",destination=/srv/src,ro \
+ --name $(CB_CPREFIX)${1} $(CB_IPREFIX)/${1} \
+ /bin/sh -c 'while true; do sleep 60; done' >/dev/null
+
+$(DD)/stamp-up.${1}: $(DD)/docker.up.${1}
+ ${Q}touch $(DD)/stamp-up.${1}
+
+.PHONY: crossbuild.${1}.up
+crossbuild.${1}.up: $(DD)/stamp-up.${1}
+
+#
+# Run tests in the container
+#
+.PHONY: $(DD)/docker.refresh.${1}
+$(DD)/docker.refresh.${1}: $(DD)/stamp-up.${1}
+ ${Q}echo "REFRESH ${1}"
+ ${Q}docker container exec $(CB_CPREFIX)${1} sh -c 'rsync -a /srv/src/ /srv/local-src/'
+ ${Q}docker container exec $(CB_CPREFIX)${1} sh -c 'git config -f /srv/local-src/config core.bare true'
+ ${Q}docker container exec $(CB_CPREFIX)${1} sh -c 'git config -f /srv/local-src/config --unset core.worktree || true'
+ ${Q}docker container exec $(CB_CPREFIX)${1} sh -c '[ -d /srv/build ] || git clone /srv/local-src /srv/build'
+ ${Q}docker container exec $(CB_CPREFIX)${1} sh -c '(cd /srv/build && git pull --rebase)'
+ ${Q}docker container exec $(CB_CPREFIX)${1} sh -c '[ -e /srv/build/config.log ] || echo CONFIGURE ${1}'
+ ${Q}docker container exec $(CB_CPREFIX)${1} sh -c '[ -e /srv/build/config.log ] || (cd /srv/build && ./configure -C)' > $(DD)/configure.${1} 2>&1
+
+.PHONY: $(DD)/docker.run.${1}
+$(DD)/docker.run.${1}: $(DD)/docker.refresh.${1}
+ ${Q}echo "TEST ${1} > $(DD)/log.${1}"
+ ${Q}docker container exec $(CB_CPREFIX)${1} sh -c '(cd /srv/build && make && make test)' > $(DD)/log.${1} 2>&1 || echo FAIL ${1}
+
+#
+# Stop the docker container
+#
+.PHONY: crossbuild.${1}.down
+crossbuild.${1}.down:
+ @echo STOP ${1}
+ ${Q}docker container kill $(CB_CPREFIX)${1} || true
+ @rm -f $(DD)/stamp-up.${1}
+
+.PHONY: crossbuild.${1}.clean
+crossbuild.${1}.clean: crossbuild.${1}.down crossbuild.${1}.reset
+
+#
+# Shell into container. cd to root first (will always succeed),
+# then try to change to build dir, which might not exist, then
+# run bash. (Default cwd is the wrong freeradius source in
+# /usr/local, which would be confusing)
+#
+.PHONY: crossbuild.${1}.sh
+crossbuild.${1}.sh: crossbuild.${1}.up
+ ${Q}docker exec -it $(CB_CPREFIX)${1} sh -c 'cd / ; cd /srv/build 2>/dev/null; bash' || true
+
+#
+# Show last build logs. Try and use the most sensible pager.
+#
+.PHONY: crossbuild.${1}.log
+crossbuild.${1}.log:
+ @if which less >/dev/null; then \
+ less +G $(DD)/log.${1};\
+ elif which more >/dev/null; then \
+ more $(DD)/log.${1};\
+ else cat $(DD)/log.${1}; fi
+
+#
+# Tidy up stamp files. This means on next run we'll do
+# everything. Required if e.g. system has been rebooted, so
+# containers are stopped, but the stamp file still exists.
+#
+.PHONY: crossbuild.${1}.reset
+crossbuild.${1}.reset:
+ ${Q}echo RESET ${1}
+ ${Q}rm -f $(DD)/stamp-up.${1}
+ ${Q}rm -f $(DD)/stamp-image.${1}
+
+#
+# Clean down images. Means on next run we'll rebuild the
+# container (rather than just starting it).
+#
+.PHONY: crossbuild.${1}.wipe
+crossbuild.${1}.wipe:
+ ${Q}echo CLEAN ${1}
+ ${Q}docker image rm $(CB_IPREFIX)/${1} >/dev/null 2>&1 || true
+ ${Q}rm -f $(DD)/stamp-image.${1}
+
+#
+# Refresh git repository within the docker image
+#
+.PHONY: crossbuild.${1}.refresh
+crossbuild.${1}.refresh: $(DD)/docker.refresh.${1}
+
+#
+# Run the build test
+#
+.PHONY: crossbuild.${1}
+crossbuild.${1}: $(DD)/docker.run.${1}
+
+endef
+
+#
+# Add all the image building rules
+#
+$(foreach IMAGE,$(CB_IMAGES),\
+ $(eval $(call CROSSBUILD_IMAGE_RULE,$(IMAGE))))
+
+
+# if docker is defined
+endif