os-test-framework/Makefile

186 lines
7.7 KiB
Makefile

####################################
# Makefile configuration variables #
OS_FILENAME = os.bat
BUILD_DIR = build
SCREENSHOTS_DIR = deploy-screenshots
COMMIT_TIMESTAMP_ISO_8601 = $$(git log -1 --pretty=format:%ad --date=iso8601-strict)
####################################
MAKEFLAGS = --warn-undefined-variables
SHELL = bash -euET -o pipefail -c
.SECONDEXPANSION:
Makefiles = Makefile Makefile.example-os Makefile.test-example-os
os_filename = ${OS_FILENAME}
bld = ${BUILD_DIR}
screenshots = ${SCREENSHOTS_DIR}
tests_emu = test/qemu-system-i386-floppy test/qemu-system-i386-cdrom test/qemu-system-arm test/virtualbox test/bochs test/gui-sh test/dosbox
tests_requiring_sudo = test/fat12_mount test/iso_mount
tests_noemu = test/zip test/os.reasm test/sizes test/fat12_contents test/reproducible_build
# We truncate the timezone, because the Darwin version of date seems to lack
# the %:z format (for ±HH:MM timezone).
define date_command
if test "$$(uname -s)" = Darwin; then \
date -j -f %Y-%m-%dT%H:%M:%S $$(echo ${1} | cut -c 1-19) ${2}; \
else \
date -d ${1} ${2}; \
fi
endef
commit_timestamp = "$$(${call date_command,"${COMMIT_TIMESTAMP_ISO_8601}",'+%Y%m%d%H%m.%S'})"
commit_timestamp_iso_8601 = ${COMMIT_TIMESTAMP_ISO_8601}
reproducible_os_filename="${bld}/reproduced_$$(basename "${os_filename}")"
built_files += ${bld}/check_makefile \
${bld}/check_makefile_targets \
${bld}/check_makefile_w_arnings \
${bld}/makefile_built_directories \
${bld}/makefile_built_files \
${bld}/makefile_database \
${bld}/makefile_database_files \
${bld}/makefile_file_targets \
${bld}/makefile_non_file_targets \
${bld}/makefile_phony \
${bld}/makefile_targets \
${bld}/makefile_w_arnings
include Makefile.example-os
include Makefile.test-example-os
more_built_directories = ${built_directories} ${bld}
.PHONY: all
# all: os.arm.disasm
all: .gitignore \
${bld}/check_makefile
${bld}/makefile_w_arnings: | $${@D}
${built_files}: | $${@D}
${bld}/makefile_w_arnings: ${Makefiles}
@unset MAKEFLAGS MAKELEVEL MAKE_TERMERR MFLAGS; \
make -n --warn-undefined-variables \
OS_FILENAME=${OS_FILENAME} \
BUILD_DIR=${BUILD_DIR} \
SCREENSHOTS_DIR=${SCREENSHOTS_DIR} \
COMMIT_TIMESTAMP_ISO_8601=${COMMIT_TIMESTAMP_ISO_8601} \
test 2>$@ 1>/dev/null \
|| cat $@
# Check that the file ${bld}/makefile_w_arnings is present, and that it does not contain the string "warn".
${bld}/check_makefile_w_arnings: ${bld}/makefile_w_arnings
@cat ${bld}/makefile_w_arnings > /dev/null && (! grep -i warn $<) && touch $@
# Check that the declared list of built files matches the list of targets extracted from the Makefile.
${bld}/check_makefile_targets: ${bld}/makefile_built_files ${bld}/makefile_file_targets ${bld}/check_makefile_w_arnings
@diff ${bld}/makefile_built_files ${bld}/makefile_file_targets && touch $@
${bld}/check_makefile: ${bld}/check_makefile_w_arnings ${bld}/check_makefile_targets
@touch $@
${bld}/makefile_database: ${Makefiles} ${bld}/check_makefile_w_arnings
@unset MAKEFLAGS MAKELEVEL MAKE_TERMERR MFLAGS; \
make -rpn \
OS_FILENAME=${OS_FILENAME} \
BUILD_DIR=${BUILD_DIR} \
SCREENSHOTS_DIR=${SCREENSHOTS_DIR} \
COMMIT_TIMESTAMP_ISO_8601=${COMMIT_TIMESTAMP_ISO_8601} \
| sed -n -e '/^# Make data base,/,$$p' > $@
${bld}/makefile_database_files: ${bld}/makefile_database ${bld}/check_makefile_w_arnings
@sed -n -e '/^# Files$$/,/^# files hash-table stats:$$/p' $< > $@
${bld}/makefile_built_directories: ${bld}/check_makefile_w_arnings
@echo ${more_built_directories} | tr ' ' '\n' | grep -v '^[[:space:]]*$$' | sort > $@
${bld}/makefile_built_files: ${bld}/check_makefile_w_arnings
@echo ${built_files} | tr ' ' '\n' | grep -v '^[[:space:]]*$$' | sort > $@
${bld}/makefile_phony: ${bld}/makefile_database_files ${bld}/check_makefile_w_arnings
@sed -n -e 's/^\.PHONY: \(.*\)$$/\1/p' $< | tr ' ' '\n' | grep -v '^[[:space:]]*$$' | sort > $@
${bld}/makefile_targets: ${bld}/makefile_database_files ${bld}/check_makefile_w_arnings
@grep -E -v '^([[:space:]]|#|\.|$$|^[^:]*:$$)' $< | grep '^[^ :]*:' | sed -e 's|^\([^:]*\):.*$$|\1|' | sort > $@
${bld}/makefile_non_file_targets: ${bld}/makefile_phony ${bld}/makefile_built_directories ${bld}/check_makefile_w_arnings
@cat ${bld}/makefile_phony ${bld}/makefile_built_directories | sort > $@
${bld}/makefile_file_targets: ${bld}/makefile_non_file_targets ${bld}/makefile_targets ${bld}/check_makefile_w_arnings
@comm -23 ${bld}/makefile_targets ${bld}/makefile_non_file_targets > $@
${built_directories}: ${bld}/check_makefile
${more_built_directories}: ${Makefiles}
mkdir -p $@ && touch $@
.PHONY: clean
clean: clean_reproducible ${bld}/check_makefile
rm -f ${built_files} ${temp_files}
for d in $$(echo ${more_built_directories} ${temp_directories} | tr ' ' '\n' | sort --reverse); do \
if test -e "$$d"; then \
rmdir "$$d"; \
fi; \
done
.PHONY: clean_reproducible
clean_reproducible: ${bld}/check_makefile
# Calling make unconditionally would cause infinite recursion, so we
# first check whether there is anything to remove.
if test -d ${bld}/reproducible -o -f ${bld}/${reproducible_os_filename}; then \
unset MAKEFLAGS MAKELEVEL MAKE_TERMERR MFLAGS; \
make OS_FILENAME=${reproducible_os_filename} \
BUILD_DIR=${bld}/reproducible \
SCREENSHOTS_DIR=${bld}/reproducible/screenshots \
COMMIT_TIMESTAMP_ISO_8601=${COMMIT_TIMESTAMP_ISO_8601} \
clean; \
fi
.gitignore: ${bld}/check_makefile
for f in ${built_files}; do echo "/$$f"; done | sort > $@
test: all \
${bld}/check_makefile
# DEBUG: ${bld}/os.hex_with_offsets ${bld}/os.offsets.hex
${bld}/test_pass/noemu_reproducible_build: ${os_filename} ${bld}/os.hex_with_offsets ${bld}/check_makefile
# Let some time pass so that any timestamp that may affect the result changes.
sleep 5
# TODO: try to see if we can re-enable some of these variables without
# causing problems on macos.
unset MAKEFLAGS MAKELEVEL MAKE_TERMERR MFLAGS; \
make OS_FILENAME=${reproducible_os_filename} \
BUILD_DIR=${bld}/reproducible \
SCREENSHOTS_DIR=${bld}/reproducible/screenshots \
COMMIT_TIMESTAMP_ISO_8601=${COMMIT_TIMESTAMP_ISO_8601} \
clean
unset MAKEFLAGS MAKELEVEL MAKE_TERMERR MFLAGS; \
make OS_FILENAME=${reproducible_os_filename} \
BUILD_DIR=${bld}/reproducible \
SCREENSHOTS_DIR=${bld}/reproducible/screenshots \
COMMIT_TIMESTAMP_ISO_8601=${COMMIT_TIMESTAMP_ISO_8601} \
${reproducible_os_filename} \
${bld}/reproducible/os.hex_with_offsets
# Check that the second build produced the same file.
if ! diff ${os_filename} ${reproducible_os_filename}; then \
diff ${bld}/os.hex_with_offsets ${bld}/reproducible/os.hex_with_offsets || true; \
if test "$$(uname -s)" = Darwin -o "$$(uname -o)" = "Cygwin"; then \
for i in `seq 5`; do \
printf '\033[1;31m########################################################\033[m'; \
done; \
echo "REPRODUCIBLE BUILDS ARE UNSUPPORTED ON MACOS AND WINDOWS"; \
for i in `seq 5`; do \
printf '\033[1;31m########################################################\033[m'; \
done; \
else \
exit 1; \
fi; \
fi
unset MAKEFLAGS MAKELEVEL MAKE_TERMERR MFLAGS; \
make OS_FILENAME=${reproducible_os_filename} \
BUILD_DIR=${bld}/reproducible \
SCREENSHOTS_DIR=${bld}/reproducible/screenshots \
COMMIT_TIMESTAMP_ISO_8601=${COMMIT_TIMESTAMP_ISO_8601} \
clean
touch $@