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:

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

These flags will be used by the build process:

<pre>
<b>CPPFLAGS</b>="<i>-I... -D...</i>"
<b>CFLAGS</b>="<i>-W... -f...</i>"
<b>LDFLAGS</b>="<i>-L... -Wl,...</i>"
    Preprocessor/compiler/linker flags

<b>LDLIBS</b>="<i>-l... -l...</i>"
    Dynamic libraries to link

<b>EXTRA_</b>{<b>CPPFLAGS</b>,<b>CFLAGS</b>,<b>LDFLAGS</b>,<b>LDLIBS</b>}="<i>...</i>"
    Adds to the default flags, instead of replacing them
</pre>

### Build profiles

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

<pre>
--enable-release
    Enable optimizations, disable assertions

--enable-<a href="https://github.com/google/sanitizers/wiki/AddressSanitizer">asan</a>
--enable-<a href="https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer#stand-alone-mode">lsan</a>
--enable-<a href="https://github.com/google/sanitizers/wiki/MemorySanitizer">msan</a>
--enable-<a href="https://github.com/google/sanitizers/wiki/ThreadSanitizerCppManual">tsan</a>
--enable-<a href="https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html">ubsan</a>
    Enable sanitizers

--enable-<a href="https://gcc.gnu.org/onlinedocs/gcc/gcov/introduction-to-gcov.html">gcov</a>
    Enable code coverage instrumentation
</pre>

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:

<pre>
--with-<a href="https://savannah.nongnu.org/projects/acl">libacl</a>      --without-libacl
--with-<a href="https://sites.google.com/site/fullycapable/">libcap</a>      --without-libcap
--with-<a href="https://github.com/SELinuxProject/selinux">libselinux</a>  --without-libselinux
--with-<a href="https://github.com/axboe/liburing">liburing</a>    --without-liburing
--with-<a href="https://github.com/kkos/oniguruma">oniguruma</a>   --without-oniguruma
</pre>

[`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:

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

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

make <b>install</b>
    Installs bfs globally
make <b>uninstall</b>
    Uninstalls bfs

make <b>clean</b>
    Deletes all built files
make <b>distclean</b>
    Also deletes files generated by ./configure
</pre>


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.
