Something went wrong. Try again.
A breadth-first version of the UNIX find command tavianator.com/projects/bfs.html
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322# Copyright © Tavian Barnes <tavianator@tavianator.com># SPDX-License-Identifier: 0BSD
# To build bfs, run## $ ./configure# $ make
# Utilities and GNU/BSD portabilityinclude build/prelude.mk
# The default build targetdefault: bfs.PHONY: default
# Include the generated build config, if it exists-include gen/config.mk
## Configuration phase (`./configure`)
# bfs used to have flag-like targets (`make release`, `make asan ubsan`, etc.).# Direct users to the new configuration system.asan lsan msan tsan ubsan gcov lint release:: @printf 'error: `%s %s` is no longer supported. Use `./configure --enable-%s` instead.\n' \ "${MAKE}" $@ $@ >&2 @false
# Print an error if `make` is run before `./configure`gen/config.mk:: if ! [ -e $@ ]; then \ printf 'error: You must run `./configure` before `%s`.\n' "${MAKE}" >&2; \ false; \ fi.SILENT: gen/config.mk
## Build phase (`make`)
# The main binarybfs: bin/bfs.PHONY: bfs
# All binariesBINS := \ bin/bfs \ bin/tests/mksock \ bin/tests/ptyx \ bin/tests/units \ bin/tests/xspawnee \ bin/tests/xtouch \ bin/bench/ioq
# All librariesLIBS := \ lib/libbfs.a
all: ${BINS} ${LIBS}.PHONY: all
# All object files except the entry pointLIBBFS := \ obj/src/alloc.o \ obj/src/bar.o \ obj/src/bfstd.o \ obj/src/bftw.o \ obj/src/color.o \ obj/src/ctx.o \ obj/src/diag.o \ obj/src/dir.o \ obj/src/dstring.o \ obj/src/eval.o \ obj/src/exec.o \ obj/src/expr.o \ obj/src/fsade.o \ obj/src/ioq.o \ obj/src/mtab.o \ obj/src/opt.o \ obj/src/parse.o \ obj/src/printf.o \ obj/src/pwcache.o \ obj/src/sighook.o \ obj/src/stat.o \ obj/src/thread.o \ obj/src/trie.o \ obj/src/typo.o \ obj/src/version.o \ obj/src/xregex.o \ obj/src/xspawn.o \ obj/src/xtime.o
# All object filesOBJS := ${LIBBFS}
# The main librarylib/libbfs.a: ${LIBBFS}
${LIBS}: @${MKDIR} ${@D} +${MSG} "[ AR ] $@" ${AR} ${_ARFLAGS} $@ $^
# The main binarybin/bfs: obj/src/main.o lib/libbfs.aOBJS += obj/src/main.o
${BINS}: @${MKDIR} ${@D} +${MSG} "[ LD ] $@" ${CC} ${_CFLAGS} ${_LDFLAGS} $^ ${_LDLIBS} -o $@ ${POSTLINK}
# Get the .c file for a .o fileCSRC = ${@:obj/%.o=%.c}
# Save the version number to this file, but only update version.c if it changesgen/version.i.new:: ${MKDIR} ${@D} build/version.sh | tr -d '\n' | build/embed.sh >$@.SILENT: gen/version.i.new
gen/version.i: gen/version.i.new test -e $@ && cmp -s $@ $^ && ${RM} $^ || mv $^ $@.SILENT: gen/version.i
obj/src/version.o: gen/version.i
## Test phase (`make check`)
# Unit test binariesUTEST_BINS := \ bin/tests/units \ bin/tests/xspawnee
# Integration test binariesITEST_BINS := \ bin/tests/mksock \ bin/tests/ptyx \ bin/tests/xtouch
# Build (but don't run) test binariestests: ${UTEST_BINS} ${ITEST_BINS}.PHONY: tests
# Run all the testscheck: unit-tests integration-tests.PHONY: check
# Run the unit testsunit-tests: ${UTEST_BINS} ${MSG} "[TEST] tests/units" bin/tests/units.PHONY: unit-tests
# Unit test objectsUNIT_OBJS := \ obj/tests/alloc.o \ obj/tests/bfstd.o \ obj/tests/bit.o \ obj/tests/ioq.o \ obj/tests/list.o \ obj/tests/main.o \ obj/tests/sighook.o \ obj/tests/trie.o \ obj/tests/xspawn.o \ obj/tests/xtime.o
bin/tests/units: ${UNIT_OBJS} lib/libbfs.aOBJS += ${UNIT_OBJS}
bin/tests/xspawnee: obj/tests/xspawnee.oOBJS += obj/tests/xspawnee.o
# The different flag combinations we checkINTEGRATIONS := default dfs ids eds j1 j2 j3 sINTEGRATION_TESTS := ${INTEGRATIONS:%=check-%}
# Check just `bfs`check-default: bin/bfs ${ITEST_BINS} +${MSG} "[TEST] bfs" \ ./tests/tests.sh --make="${MAKE}" --bfs="bin/bfs" ${TEST_FLAGS}
# Check the different search strategiescheck-dfs check-ids check-eds: bin/bfs ${ITEST_BINS} +${MSG} "[TEST] bfs -S ${@:check-%=%}" \ ./tests/tests.sh --make="${MAKE}" --bfs="bin/bfs -S ${@:check-%=%}" ${TEST_FLAGS}
# Check various flagscheck-j1 check-j2 check-j3 check-s: bin/bfs ${ITEST_BINS} +${MSG} "[TEST] bfs -${@:check-%=%}" \ ./tests/tests.sh --make="${MAKE}" --bfs="bin/bfs -${@:check-%=%}" ${TEST_FLAGS}
# Run the integration testsintegration-tests: ${INTEGRATION_TESTS}.PHONY: integration-tests
bin/tests/mksock: obj/tests/mksock.o lib/libbfs.aOBJS += obj/tests/mksock.o
bin/tests/ptyx: obj/tests/ptyx.o lib/libbfs.aOBJS += obj/tests/ptyx.o
bin/tests/xtouch: obj/tests/xtouch.o lib/libbfs.aOBJS += obj/tests/xtouch.o
# `make distcheck` configurationsDISTCHECKS := \ distcheck-asan \ distcheck-msan \ distcheck-tsan \ distcheck-m32 \ distcheck-release
# Test multiple configurationsdistcheck: @+${MAKE} distcheck-asan @+test "$$(uname)" = Darwin || ${MAKE} distcheck-msan @+test "$$(uname)" = FreeBSD || ${MAKE} distcheck-tsan @+test "$$(uname)-$$(uname -m)" != Linux-x86_64 || ${MAKE} distcheck-m32 @+${MAKE} distcheck-release @+${MAKE} -C distcheck-release check-install @+test "$$(uname)" != Linux || ${MAKE} check-man.PHONY: distcheck
# Per-distcheck configurationDISTCHECK_CONFIG_asan := --enable-asan --enable-ubsan CC=clangDISTCHECK_CONFIG_msan := --enable-msan --enable-ubsan CC=clangDISTCHECK_CONFIG_tsan := --enable-tsan --enable-ubsan CC=clangDISTCHECK_CONFIG_m32 := EXTRA_CFLAGS="-m32" PKG_CONFIG_LIBDIR=/usr/lib32/pkgconfigDISTCHECK_CONFIG_release := --enable-release
${DISTCHECKS}:: @${MKDIR} $@ @test "$${GITHUB_ACTIONS-}" != true || printf '::group::%s\n' $@ @+cd $@ \ && ../configure MAKE="${MAKE}" ${DISTCHECK_CONFIG_${@:distcheck-%=%}} \ && ${MAKE} check TEST_FLAGS="--sudo --verbose=skipped" @test "$${GITHUB_ACTIONS-}" != true || printf '::endgroup::\n'
## Benchmarks (`make bench`)
bench: bin/bench/ioq.PHONY: bench
bin/bench/ioq: obj/bench/ioq.o lib/libbfs.aOBJS += obj/bench/ioq.o
## Automatic dependency tracking
# Rebuild when the configuration changes${OBJS}: gen/config.mk @${MKDIR} ${@D} ${MSG} "[ CC ] ${CSRC}" ${CC} ${_CPPFLAGS} ${_CFLAGS} -c ${CSRC} -o $@
# Include any generated dependency files-include ${OBJS:.o=.d}
## Packaging (`make dist`, `make install`)
TARBALL = bfs-$$(build/version.sh).tar.gz
dist: ${MSG} "[DIST] ${TARBALL}" git archive HEAD -o ${TARBALL}
distsign: dist ${MSG} "[SIGN] ${TARBALL}" ssh-keygen -Y sign -q -f $$(git config user.signingkey) -n file ${TARBALL}
.PHONY: dist distsign
DEST_PREFIX := ${DESTDIR}${PREFIX}DEST_MANDIR := ${DESTDIR}${MANDIR}
install:: ${Q}${MKDIR} ${DEST_PREFIX}/bin ${MSG} "[INST] bin/bfs" \ ${INSTALL} -m755 bin/bfs ${DEST_PREFIX}/bin/bfs ${Q}${MKDIR} ${DEST_MANDIR}/man1 ${MSG} "[INST] man/man1/bfs.1" \ ${INSTALL} -m644 docs/bfs.1 ${DEST_MANDIR}/man1/bfs.1 ${Q}${MKDIR} ${DEST_PREFIX}/share/bash-completion/completions ${MSG} "[INST] completions/bfs.bash" \ ${INSTALL} -m644 completions/bfs.bash ${DEST_PREFIX}/share/bash-completion/completions/bfs ${Q}${MKDIR} ${DEST_PREFIX}/share/zsh/site-functions ${MSG} "[INST] completions/bfs.zsh" \ ${INSTALL} -m644 completions/bfs.zsh ${DEST_PREFIX}/share/zsh/site-functions/_bfs ${Q}${MKDIR} ${DEST_PREFIX}/share/fish/vendor_completions.d ${MSG} "[INST] completions/bfs.fish" \ ${INSTALL} -m644 completions/bfs.fish ${DEST_PREFIX}/share/fish/vendor_completions.d/bfs.fish
uninstall:: ${MSG} "[ RM ] completions/bfs.bash" \ ${RM} ${DEST_PREFIX}/share/bash-completion/completions/bfs ${MSG} "[ RM ] completions/bfs.zsh" \ ${RM} ${DEST_PREFIX}/share/zsh/site-functions/_bfs ${MSG} "[ RM ] completions/bfs.fish" \ ${RM} ${DEST_PREFIX}/share/fish/vendor_completions.d/bfs.fish ${MSG} "[ RM ] man/man1/bfs.1" \ ${RM} ${DEST_MANDIR}/man1/bfs.1 ${MSG} "[ RM ] bin/bfs" \ ${RM} ${DEST_PREFIX}/bin/bfs
# Check that `make install` works and `make uninstall` removes everythingcheck-install:: +${MAKE} install DESTDIR=pkg +${MAKE} uninstall DESTDIR=pkg bin/bfs pkg -not -type d -print -exit 1 ${RM} -r pkg
# Check man page markupcheck-man:: ${MSG} "[LINT] docs/bfs.1" ${Q}groff -man -rCHECKSTYLE=3 -ww -b -z docs/bfs.1 ${Q}mandoc -Tlint -Wwarning docs/bfs.1
## Cleanup (`make clean`)
# Clean all build productsclean:: ${MSG} "[ RM ] bin lib obj" \ ${RM} -r bin lib obj
# Clean everything, including generated filesdistclean: clean ${MSG} "[ RM ] gen distcheck-*" \ ${RM} -r gen ${DISTCHECKS}.PHONY: distclean