Building `bfs`
==============

A simple invocation of

    $ ./configure
    $ make

should build `bfs` successfully.


Configuration
-------------

```console
$ ./configure --help
Usage:

  $ ./configure [--enable-*|--disable-*] [--with-*|--without-*] [CC=...] [...]
  $ make

...
```

### Variables

Variables set in the environment or on the command line will be picked up:
These variables specify binaries to run during the configuration and build process:

MAKE=make
    make (https://en.wikipedia.org/wiki/Make_(software)) implementation
CC=cc
    C compiler
INSTALL=install
    Copy files during make install
MKDIR="mkdir -p"
    Create directories
PKG_CONFIG=pkg-config
    Detect external libraries and required build flags
RM="rm -f"
    Delete files

These flags will be used by the build process:

CPPFLAGS="-I... -D..."
CFLAGS="-W... -f..."
LDFLAGS="-L... -Wl,..."
    Preprocessor/compiler/linker flags

LDLIBS="-l... -l..."
    Dynamic libraries to link

EXTRA_{CPPFLAGS,CFLAGS,LDFLAGS,LDLIBS}="..."
    Adds to the default flags, instead of replacing them

### Build profiles

The default flags result in a plain debug build.
Other build profiles can be enabled:

--enable-release
    Enable optimizations, disable assertions

--enable-asan (https://github.com/google/sanitizers/wiki/AddressSanitizer)
--enable-lsan (https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer#stand-alone-mode)
--enable-msan (https://github.com/google/sanitizers/wiki/MemorySanitizer)
--enable-tsan (https://github.com/google/sanitizers/wiki/ThreadSanitizerCppManual)
--enable-ubsan (https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html)
    Enable sanitizers

--enable-gcov (https://gcc.gnu.org/onlinedocs/gcc/gcov/introduction-to-gcov.html)
    Enable code coverage instrumentation

You can combine multiple profiles (e.g. `./configure --enable-asan --enable-ubsan`), but not all of them will work together.

### Dependencies

`bfs` depends on some system libraries for some of its features.
External dependencies are auto-detected by default, but you can build `--with` or `--without` them explicitly:

--with-libacl (https://savannah.nongnu.org/projects/acl)      --without-libacl
--with-libcap (https://sites.google.com/site/fullycapable/)      --without-libcap
--with-libselinux (https://github.com/SELinuxProject/selinux)  --without-libselinux
--with-liburing (https://github.com/axboe/liburing)    --without-liburing
--with-oniguruma (https://github.com/kkos/oniguruma)   --without-oniguruma

[`pkg-config`] is used, if available, to detect these libraries and any additional build flags they may require.
If this is undesirable, disable it by setting `PKG_CONFIG` to the empty string (`./configure PKG_CONFIG=""`).

[`pkg-config`]: https://www.freedesktop.org/wiki/Software/pkg-config/

### Out-of-tree builds

You can set up an out-of-tree build by running the `configure` script from another directory, for example:

    $ mkdir out
    $ cd out
    $ ../configure
    $ make


Building
--------

### Targets

The [`Makefile`](/Makefile) supports several different build targets:

make
    The default target; builds just the bfs binary
make all
    Builds everything, including the tests (but doesn't run them)

make check
    Builds everything, and runs all tests
make unit-tests
    Builds and runs the unit tests
make integration-tests
    Builds and runs the integration tests
make distcheck
    Builds and runs the tests in multiple different configurations

make install
    Installs bfs globally
make uninstall
    Uninstalls bfs

make clean
    Deletes all built files
make distclean
    Also deletes files generated by ./configure

Troubleshooting
---------------

If the build fails or behaves unexpectedly, start by enabling verbose mode:

    $ ./configure V=1
    $ make V=1

This will print the generated configuration and the exact commands that are executed.

You can also check the file `gen/config.log`, which contains any errors from commands run during the configuration phase.


Testing
-------

`bfs` comes with an extensive test suite which can be run with

    $ make check

The test harness is implemented in the file [`tests/tests.sh`](/tests/tests.sh).
Individual test cases are found in `tests/*/*.sh`.
Most of them are *snapshot tests* which compare `bfs`'s output to a known-good copy saved under the matching `tests/*/*.out`.

You can pass the name of a particular test case (or a few) to run just those tests.
For example:

    $ ./tests/tests.sh posix/basic

If you need to update the reference snapshot, pass `--update`.
It can be handy to generate the snapshot with a different `find` implementation to ensure the output is correct, for example:

    $ ./tests/tests.sh posix/basic --bfs=find --update

But keep in mind, other `find` implementations may not be correct.
To my knowledge, no other implementation passes even the POSIX-compatible subset of the tests:

    $ ./tests/tests.sh --bfs=find --sudo --posix
    ...
    [PASS] 104 / 119
    [SKIP]   1 / 119
    [FAIL]  14 / 119

Run

    $ ./tests/tests.sh --help

for more details.

### Validation

A more thorough testsuite is run by the [CI](https://github.com/tavianator/bfs/actions) and to validate releases.
It builds `bfs` in multiple configurations to test for latent bugs, memory leaks, 32-bit compatibility, etc.
You can run it yourself with

    $ make distcheck

Some of these tests require `sudo`, and will prompt for your password if necessary.
