summaryrefslogtreecommitdiffstats
path: root/docs/BUILDING.md
blob: abf6185fd797eeaadc15b946e4a5b4e9fb77bf8f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
Building `bfs`
==============

Compiling
---------

`bfs` uses [GNU Make](https://www.gnu.org/software/make/) as its build system.
A simple invocation of

    $ make config
    $ make

should build `bfs` successfully.
As usual with `make`, you can run a [parallel build](https://www.gnu.org/software/make/manual/html_node/Parallel.html) with `-j`.
For example, to use all your cores, run `make -j$(nproc)`.

### Targets

| Command          | Description                                                   |
|------------------|---------------------------------------------------------------|
| `make config`    | Configures the build system                                   |
| `make`           | Builds just the `bfs` binary                                  |
| `make all`       | Builds everything, including the tests (but doesn't run them) |
| `make check`     | Builds everything, and runs the tests                         |
| `make install`   | Installs `bfs` (with man page, shell completions, etc.)       |
| `make uninstall` | Uninstalls `bfs`                                              |
| `make clean`     | Delete the build products                                     |
| `make mrclean`   | Delete all generated files, including the build configuration |

### Build profiles

The configuration system provides a few shorthand flags for handy configurations:

| Command                 | Description                                                 |
|-------------------------|-------------------------------------------------------------|
| `make config RELEASE=y` | Build `bfs` with optimizations, LTO, and without assertions |
| `make config ASAN=y`    | Enable [AddressSanitizer]                                   |
| `make config LSAN=y`    | Enable [LeakSanitizer]                                      |
| `make config MSAN=y`    | Enable [MemorySanitizer]                                    |
| `make config TSAN=y`    | Enable [ThreadSanitizer]                                    |
| `make config UBSAN=y`   | Enable [UndefinedBehaviorSanitizer]                         |
| `make config GCOV=y`    | Enable [code coverage]                                      |

[AddressSanitizer]: https://github.com/google/sanitizers/wiki/AddressSanitizer
[LeakSanitizer]: https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer#stand-alone-mode
[MemorySanitizer]: https://github.com/google/sanitizers/wiki/MemorySanitizer
[ThreadSanitizer]: https://github.com/google/sanitizers/wiki/ThreadSanitizerCppManual
[UndefinedBehaviorSanitizer]: https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html
[code coverage]: https://gcc.gnu.org/onlinedocs/gcc/Gcov.html

You can combine multiple profiles (e.g. `make config ASAN=y UBSAN=y`), but not all of them will work together.

### Flags

Other flags can be specified on the `make config` command line or in the environment.
Here are some of the common ones; check the [`Makefile`](/Makefile) for more.

| Flag                             | Description                                        |
|----------------------------------|----------------------------------------------------|
| `CC`                             | The C compiler to use, e.g. `make config CC=clang` |
| `CFLAGS`<br>`EXTRA_CFLAGS`       | Override/add to the default compiler flags         |
| `LDFLAGS`<br>`EXTRA_LDFLAGS`     | Override/add to the linker flags                   |
| `USE_ACL`<br>`USE_LIBCAP`<br>... | Enable/disable [optional dependencies]             |
| `TEST_FLAGS`                     | `tests.sh` flags for `make check`                  |
| `BUILDDIR`                       | The build output directory (default: `.`)          |
| `DESTDIR`                        | The root directory for `make install`              |
| `PREFIX`                         | The installation prefix (default: `/usr`)          |
| `MANDIR`                         | The man page installation directory                |

[optional dependencies]: #dependencies

### Dependencies

`bfs` depends on some system libraries for some of its features.
These dependencies are optional, and can be turned off in `make config` if necessary by setting the appropriate variable to `n` (e.g. `make config USE_ONIGURUMA=n`).

| Dependency  | Platforms  | `make config` flag |
|-------------|------------|--------------------|
| [acl]       | Linux only | `USE_ACL`          |
| [libcap]    | Linux only | `USE_LIBCAP`       |
| [liburing]  | Linux only | `USE_LIBURING`     |
| [Oniguruma] | All        | `USE_ONIGURUMA`    |

[acl]: https://savannah.nongnu.org/projects/acl
[libcap]: https://sites.google.com/site/fullycapable/
[liburing]: https://github.com/axboe/liburing
[Oniguruma]: https://github.com/kkos/oniguruma

### Dependency tracking

The build system automatically tracks header dependencies with the `-M` family of compiler options (see `DEPFLAGS` in the [`Makefile`](/Makefile)).
So if you edit a header file, `make` will rebuild the necessary object files ensuring they don't go out of sync.

We also add a dependency on the current configuration, so you can change configurations and rebuild without having to `make clean`.

We go one step further than most build systems by tracking the flags that were used for the previous compilation.
That means you can change configurations without having to `make clean`.
For example,

    $ make config
    $ make
    $ make config RELEASE=y
    $ make

will build the project in debug mode and then rebuild it in release mode.


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 --posix
    ...
    tests passed: 90
    tests skipped: 3
    tests failed: 6

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.