112a9d9c8Sopenharmony_ci# Contributing to `bindgen`
212a9d9c8Sopenharmony_ci
312a9d9c8Sopenharmony_ciHi! We'd love to have your contributions! If you want help or mentorship, reach
412a9d9c8Sopenharmony_ciout to us in a GitHub issue, or stop by
512a9d9c8Sopenharmony_ci[#rust on chat.mozilla.org](https://chat.mozilla.org/#/room/#rust:mozilla.org)
612a9d9c8Sopenharmony_ciand introduce yourself.
712a9d9c8Sopenharmony_ci
812a9d9c8Sopenharmony_ci<!-- START doctoc generated TOC please keep comment here to allow auto update -->
912a9d9c8Sopenharmony_ci<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
1012a9d9c8Sopenharmony_ci
1112a9d9c8Sopenharmony_ci- [Code of Conduct](#code-of-conduct)
1212a9d9c8Sopenharmony_ci- [Filing an Issue](#filing-an-issue)
1312a9d9c8Sopenharmony_ci- [Looking to Start Contributing to `bindgen`?](#looking-to-start-contributing-to-bindgen)
1412a9d9c8Sopenharmony_ci- [Building](#building)
1512a9d9c8Sopenharmony_ci- [Testing](#testing)
1612a9d9c8Sopenharmony_ci  - [Overview](#overview)
1712a9d9c8Sopenharmony_ci  - [Testing Bindings Generation](#testing-bindings-generation)
1812a9d9c8Sopenharmony_ci  - [Testing Generated Bindings](#testing-generated-bindings)
1912a9d9c8Sopenharmony_ci  - [Testing a Single Header's Bindings Generation and Compiling its Bindings](#testing-a-single-headers-bindings-generation-and-compiling-its-bindings)
2012a9d9c8Sopenharmony_ci  - [Authoring New Tests](#authoring-new-tests)
2112a9d9c8Sopenharmony_ci  - [Test Expectations and `libclang` Versions](#test-expectations-and-libclang-versions)
2212a9d9c8Sopenharmony_ci  - [Integration Tests](#integration-tests)
2312a9d9c8Sopenharmony_ci  - [Fuzzing `bindgen` with `csmith`](#fuzzing-bindgen-with-csmith)
2412a9d9c8Sopenharmony_ci  - [Property tests for `bindgen` with `quickchecking`](#property-tests-for-bindgen-with-quickchecking)
2512a9d9c8Sopenharmony_ci- [Code Overview](#code-overview)
2612a9d9c8Sopenharmony_ci  - [Implementing new options using `syn`](#implementing-new-options-using-syn)
2712a9d9c8Sopenharmony_ci- [Pull Requests and Code Reviews](#pull-requests-and-code-reviews)
2812a9d9c8Sopenharmony_ci- [Generating Graphviz Dot Files](#generating-graphviz-dot-files)
2912a9d9c8Sopenharmony_ci- [Debug Logging](#debug-logging)
3012a9d9c8Sopenharmony_ci- [Using `creduce` to Minimize Test Cases](#using-creduce-to-minimize-test-cases)
3112a9d9c8Sopenharmony_ci  - [Getting `creduce`](#getting-creduce)
3212a9d9c8Sopenharmony_ci  - [Isolating Your Test Case](#isolating-your-test-case)
3312a9d9c8Sopenharmony_ci  - [Writing a Predicate Script](#writing-a-predicate-script)
3412a9d9c8Sopenharmony_ci- [Cutting a new bindgen release](#cutting-a-new-bindgen-release)
3512a9d9c8Sopenharmony_ci  - [Updating the changelog](#updating-the-changelog)
3612a9d9c8Sopenharmony_ci  - [Bumping the version numbers.](#bumping-the-version-numbers)
3712a9d9c8Sopenharmony_ci  - [Merge to `main`](#merge-to-main)
3812a9d9c8Sopenharmony_ci  - [Publish and add a git tag for the right commit](#publish-and-add-a-git-tag-for-the-right-commit)
3912a9d9c8Sopenharmony_ci
4012a9d9c8Sopenharmony_ci<!-- END doctoc generated TOC please keep comment here to allow auto update -->
4112a9d9c8Sopenharmony_ci
4212a9d9c8Sopenharmony_ci## Code of Conduct
4312a9d9c8Sopenharmony_ci
4412a9d9c8Sopenharmony_ciWe abide by the [Rust Code of Conduct][coc] and ask that you do as well.
4512a9d9c8Sopenharmony_ci
4612a9d9c8Sopenharmony_ci[coc]: https://www.rust-lang.org/en-US/conduct.html
4712a9d9c8Sopenharmony_ci
4812a9d9c8Sopenharmony_ci## Filing an Issue
4912a9d9c8Sopenharmony_ci
5012a9d9c8Sopenharmony_ciThink you've found a bug? File an issue! To help us understand and reproduce the
5112a9d9c8Sopenharmony_ciissue, provide us with:
5212a9d9c8Sopenharmony_ci
5312a9d9c8Sopenharmony_ci* A (preferably reduced) C/C++ header file that reproduces the issue
5412a9d9c8Sopenharmony_ci* The `bindgen` flags used to reproduce the issue with the header file
5512a9d9c8Sopenharmony_ci* The expected `bindgen` output
5612a9d9c8Sopenharmony_ci* The actual `bindgen` output
5712a9d9c8Sopenharmony_ci* The [debugging logs](#logs) generated when running `bindgen` on this testcase
5812a9d9c8Sopenharmony_ci
5912a9d9c8Sopenharmony_ci## Looking to Start Contributing to `bindgen`?
6012a9d9c8Sopenharmony_ci
6112a9d9c8Sopenharmony_ci* [Issues labeled "easy"](https://github.com/rust-lang/rust-bindgen/issues?q=is%3Aopen+is%3Aissue+label%3AE-easy)
6212a9d9c8Sopenharmony_ci* [Issues labeled "less easy"](https://github.com/rust-lang/rust-bindgen/issues?q=is%3Aopen+is%3Aissue+label%3AE-less-easy)
6312a9d9c8Sopenharmony_ci* [Issues labeled "help wanted"](https://github.com/rust-lang/rust-bindgen/labels/help%20wanted)
6412a9d9c8Sopenharmony_ci* Still can't find something to work on? [Drop a comment here](https://github.com/rust-lang/rust-bindgen/issues/747)
6512a9d9c8Sopenharmony_ci
6612a9d9c8Sopenharmony_ci## Building
6712a9d9c8Sopenharmony_ci
6812a9d9c8Sopenharmony_ciTo build the `bindgen` library and the `bindgen` executable:
6912a9d9c8Sopenharmony_ci
7012a9d9c8Sopenharmony_ci```
7112a9d9c8Sopenharmony_ci$ cargo build
7212a9d9c8Sopenharmony_ci```
7312a9d9c8Sopenharmony_ci
7412a9d9c8Sopenharmony_ciIf you installed multiple versions of llvm, it may not be able to locate the
7512a9d9c8Sopenharmony_cilatest version of libclang. In that case, you may want to either uninstall other
7612a9d9c8Sopenharmony_civersions of llvm, or specify the path of the desired libclang explicitly:
7712a9d9c8Sopenharmony_ci
7812a9d9c8Sopenharmony_ci```
7912a9d9c8Sopenharmony_ci$ export LIBCLANG_PATH=path/to/clang-9.0/lib
8012a9d9c8Sopenharmony_ci```
8112a9d9c8Sopenharmony_ci
8212a9d9c8Sopenharmony_ciAdditionally, you may want to build and test with the `testing_only_docs`
8312a9d9c8Sopenharmony_cifeature to ensure that you aren't forgetting to document types and functions. CI
8412a9d9c8Sopenharmony_ciwill catch it if you forget, but the turn around will be a lot slower ;)
8512a9d9c8Sopenharmony_ci
8612a9d9c8Sopenharmony_ci```
8712a9d9c8Sopenharmony_ci$ cargo build --features testing_only_docs
8812a9d9c8Sopenharmony_ci```
8912a9d9c8Sopenharmony_ci
9012a9d9c8Sopenharmony_ci## Testing
9112a9d9c8Sopenharmony_ci
9212a9d9c8Sopenharmony_ci### Overview
9312a9d9c8Sopenharmony_ci
9412a9d9c8Sopenharmony_ciInput C/C++ test headers reside in the `bindgen-tests/tests/headers` directory. Expected
9512a9d9c8Sopenharmony_cioutput Rust bindings live in `bindgen-tests/tests/expectations/tests`. For example,
9612a9d9c8Sopenharmony_ci`bindgen-tests/tests/headers/my_header.h`'s expected generated Rust bindings would be
9712a9d9c8Sopenharmony_ci`bindgen-tests/tests/expectations/tests/my_header.rs`.
9812a9d9c8Sopenharmony_ci
9912a9d9c8Sopenharmony_ciThere are also some integration tests in the `./bindgen-integration` crate, which uses `bindgen` to
10012a9d9c8Sopenharmony_cigenerate bindings to some C++ code, and then uses the bindings, asserting that
10112a9d9c8Sopenharmony_civalues are what we expect them to be, both on the Rust and C++ side.
10212a9d9c8Sopenharmony_ci
10312a9d9c8Sopenharmony_ciThe generated and expected bindings are run through `rustfmt` before they are
10412a9d9c8Sopenharmony_cicompared. Make sure you have `rustfmt` up to date:
10512a9d9c8Sopenharmony_ci
10612a9d9c8Sopenharmony_ci```
10712a9d9c8Sopenharmony_ci$ rustup update nightly
10812a9d9c8Sopenharmony_ci$ rustup component add rustfmt --toolchain nightly
10912a9d9c8Sopenharmony_ci```
11012a9d9c8Sopenharmony_ci
11112a9d9c8Sopenharmony_ciNote: running `cargo test` from the root directory of `bindgen`'s repository does not
11212a9d9c8Sopenharmony_ciautomatically test the generated bindings or run the integration tests.
11312a9d9c8Sopenharmony_ciThese steps must be performed manually when needed.
11412a9d9c8Sopenharmony_ci
11512a9d9c8Sopenharmony_ci### Testing Bindings Generation
11612a9d9c8Sopenharmony_ci
11712a9d9c8Sopenharmony_ciTo regenerate bindings from the corpus of test headers in `bindgen-tests/tests/headers` and
11812a9d9c8Sopenharmony_cicompare them against the expected bindings in `bindgen-tests/tests/expectations/tests`, run:
11912a9d9c8Sopenharmony_ci
12012a9d9c8Sopenharmony_ci```
12112a9d9c8Sopenharmony_ci$ cargo test
12212a9d9c8Sopenharmony_ci```
12312a9d9c8Sopenharmony_ci
12412a9d9c8Sopenharmony_ciAs long as you aren't making any changes to `bindgen`'s output, running this
12512a9d9c8Sopenharmony_cishould be sufficient to test your local modifications.
12612a9d9c8Sopenharmony_ci
12712a9d9c8Sopenharmony_ciYou may set the `BINDGEN_OVERWRITE_EXPECTED` environment variable to overwrite
12812a9d9c8Sopenharmony_cithe expected bindings with `bindgen`'s current output:
12912a9d9c8Sopenharmony_ci
13012a9d9c8Sopenharmony_ci```
13112a9d9c8Sopenharmony_ci$ BINDGEN_OVERWRITE_EXPECTED=1 cargo test
13212a9d9c8Sopenharmony_ci```
13312a9d9c8Sopenharmony_ci
13412a9d9c8Sopenharmony_ciIf you set the BINDGEN_TESTS_DIFFTOOL environment variable, `cargo test` will
13512a9d9c8Sopenharmony_ciexecute $BINDGEN_TESTS_DIFFTOOL /path/of/expected/output /path/of/actual/output
13612a9d9c8Sopenharmony_ciwhen the expected output differs from the actual output. You can use this to
13712a9d9c8Sopenharmony_cihand check differences by setting it to e.g. "meld" (assuming you have meld
13812a9d9c8Sopenharmony_ciinstalled).
13912a9d9c8Sopenharmony_ci
14012a9d9c8Sopenharmony_ciIf you're not changing command line arguments, you may want to set
14112a9d9c8Sopenharmony_ci`BINDGEN_DISABLE_ROUNDTRIP_TEST` to avoid a lot of tests for round-tripping of
14212a9d9c8Sopenharmony_cithose.
14312a9d9c8Sopenharmony_ci
14412a9d9c8Sopenharmony_ci### Testing Generated Bindings
14512a9d9c8Sopenharmony_ci
14612a9d9c8Sopenharmony_ciIf your local changes are introducing expected modifications in the
14712a9d9c8Sopenharmony_ci`bindgen-tests/tests/expectations/tests/*` bindings files, then you should test that the
14812a9d9c8Sopenharmony_cigenerated bindings files still compile, and that their struct layout tests still
14912a9d9c8Sopenharmony_cipass. Also, run the integration tests (see below).
15012a9d9c8Sopenharmony_ci
15112a9d9c8Sopenharmony_ciYou can do this with these commands:
15212a9d9c8Sopenharmony_ci
15312a9d9c8Sopenharmony_ci```
15412a9d9c8Sopenharmony_ci$ cd bindgen-tests/tests/expectations
15512a9d9c8Sopenharmony_ci$ cargo test
15612a9d9c8Sopenharmony_ci```
15712a9d9c8Sopenharmony_ci
15812a9d9c8Sopenharmony_ci### Testing a Single Header's Bindings Generation and Compiling its Bindings
15912a9d9c8Sopenharmony_ci
16012a9d9c8Sopenharmony_ciNote: You will to need to install [Graphviz](https://graphviz.org/) since that
16112a9d9c8Sopenharmony_ciis a dependency for running `test-one.sh`.
16212a9d9c8Sopenharmony_ci
16312a9d9c8Sopenharmony_ciSometimes its useful to work with one test header from start (generating
16412a9d9c8Sopenharmony_cibindings for it) to finish (compiling the bindings and running their layout
16512a9d9c8Sopenharmony_citests). This can be done with the `bindgen-tests/tests/test-one.sh` script. It supports fuzzy
16612a9d9c8Sopenharmony_cisearching for test headers. For example, to test
16712a9d9c8Sopenharmony_ci`tests/headers/what_is_going_on.hpp`, execute this command:
16812a9d9c8Sopenharmony_ci
16912a9d9c8Sopenharmony_ci```
17012a9d9c8Sopenharmony_ci$ ./bindgen-tests/tests/test-one.sh going
17112a9d9c8Sopenharmony_ci```
17212a9d9c8Sopenharmony_ci
17312a9d9c8Sopenharmony_ciNote that `test-one.sh` does not recompile `bindgen`, so if you change the code,
17412a9d9c8Sopenharmony_ciyou'll need to rebuild it before running the script again.
17512a9d9c8Sopenharmony_ci
17612a9d9c8Sopenharmony_ci### Authoring New Tests
17712a9d9c8Sopenharmony_ci
17812a9d9c8Sopenharmony_ciTo add a new test header to the suite, simply put it in the `bindgen-tests/tests/headers`
17912a9d9c8Sopenharmony_cidirectory. Next, run `bindgen` to generate the initial expected output Rust
18012a9d9c8Sopenharmony_cibindings. Put those in `bindgen-tests/tests/expectations/tests`.
18112a9d9c8Sopenharmony_ci
18212a9d9c8Sopenharmony_ciIf your new test requires certain flags to be passed to `bindgen`, you can
18312a9d9c8Sopenharmony_cispecify them at the top of the test header, with a comment like this:
18412a9d9c8Sopenharmony_ci
18512a9d9c8Sopenharmony_ci`new_test_header.hpp`:
18612a9d9c8Sopenharmony_ci
18712a9d9c8Sopenharmony_ci```c
18812a9d9c8Sopenharmony_ci// bindgen-flags: --enable-cxx-namespaces -- -std=c++14
18912a9d9c8Sopenharmony_ci```
19012a9d9c8Sopenharmony_ci
19112a9d9c8Sopenharmony_ciThen verify the new Rust bindings compile and pass their layout tests:
19212a9d9c8Sopenharmony_ci
19312a9d9c8Sopenharmony_ci```
19412a9d9c8Sopenharmony_ci$ cd bindgen-tests/tests/expectations
19512a9d9c8Sopenharmony_ci$ cargo test new_test_header
19612a9d9c8Sopenharmony_ci```
19712a9d9c8Sopenharmony_ci
19812a9d9c8Sopenharmony_ci### Test Expectations and `libclang` Versions
19912a9d9c8Sopenharmony_ci
20012a9d9c8Sopenharmony_ciIf a test generates different bindings across different `libclang` versions (for
20112a9d9c8Sopenharmony_ciexample, because we take advantage of better/newer APIs when possible), then you
20212a9d9c8Sopenharmony_cican add multiple test expectations, one for each supported `libclang`
20312a9d9c8Sopenharmony_civersion. Instead of having a single `bindgen-tests/tests/expectations/tests/my_test.rs` file,
20412a9d9c8Sopenharmony_ciadd each of:
20512a9d9c8Sopenharmony_ci
20612a9d9c8Sopenharmony_ci* `bindgen-tests/tests/expectations/tests/libclang-9/my_test.rs`
20712a9d9c8Sopenharmony_ci* `bindgen-tests/tests/expectations/tests/libclang-5/my_test.rs`
20812a9d9c8Sopenharmony_ci
20912a9d9c8Sopenharmony_ciIf you need to update the test expectations for a test file that generates
21012a9d9c8Sopenharmony_cidifferent bindings for different `libclang` versions, you *don't* need to have
21112a9d9c8Sopenharmony_cimany version of `libclang` installed locally. Just make a work-in-progress pull
21212a9d9c8Sopenharmony_cirequest, and then when Travis CI fails, it will log a diff of the
21312a9d9c8Sopenharmony_ciexpectations. Use the diff to patch the appropriate expectation file locally and
21412a9d9c8Sopenharmony_cithen update your pull request.
21512a9d9c8Sopenharmony_ci
21612a9d9c8Sopenharmony_ciUsually, `bindgen`'s test runner can infer which version of `libclang` you
21712a9d9c8Sopenharmony_cihave. If for some reason it can't, you can force a specific `libclang` version
21812a9d9c8Sopenharmony_cito check the bindings against with a cargo feature:
21912a9d9c8Sopenharmony_ci
22012a9d9c8Sopenharmony_ci```
22112a9d9c8Sopenharmony_ci$ cargo test --features testing_only_libclang_$VERSION
22212a9d9c8Sopenharmony_ci```
22312a9d9c8Sopenharmony_ci
22412a9d9c8Sopenharmony_ciWhere `$VERSION` is one of:
22512a9d9c8Sopenharmony_ci
22612a9d9c8Sopenharmony_ci* `4`
22712a9d9c8Sopenharmony_ci* `3_9`
22812a9d9c8Sopenharmony_ci* `3_8`
22912a9d9c8Sopenharmony_ci
23012a9d9c8Sopenharmony_cidepending on which version of `libclang` you have installed.
23112a9d9c8Sopenharmony_ci
23212a9d9c8Sopenharmony_ci### Integration Tests
23312a9d9c8Sopenharmony_ci
23412a9d9c8Sopenharmony_ciThe `./bindgen-integration` crate uses `bindgen` to
23512a9d9c8Sopenharmony_cigenerate bindings to some C++ code, and then uses the bindings, asserting that
23612a9d9c8Sopenharmony_civalues are what we expect them to be, both on the Rust and C++ side.
23712a9d9c8Sopenharmony_ci
23812a9d9c8Sopenharmony_ciTo run the integration tests, issue the following:
23912a9d9c8Sopenharmony_ci
24012a9d9c8Sopenharmony_ci```
24112a9d9c8Sopenharmony_ci$ cd bindgen-integration
24212a9d9c8Sopenharmony_ci$ cargo test
24312a9d9c8Sopenharmony_ci```
24412a9d9c8Sopenharmony_ci
24512a9d9c8Sopenharmony_ci### Fuzzing `bindgen` with `csmith`
24612a9d9c8Sopenharmony_ci
24712a9d9c8Sopenharmony_ciWe <3 finding hidden bugs and the people who help us find them! One way to help
24812a9d9c8Sopenharmony_ciuncover hidden bugs is by running `csmith` to generate random headers to test
24912a9d9c8Sopenharmony_ci`bindgen` against.
25012a9d9c8Sopenharmony_ci
25112a9d9c8Sopenharmony_ciSee [./csmith-fuzzing/README.md](./csmith-fuzzing/README.md) for details.
25212a9d9c8Sopenharmony_ci
25312a9d9c8Sopenharmony_ci### Property tests for `bindgen` with `quickchecking`
25412a9d9c8Sopenharmony_ci
25512a9d9c8Sopenharmony_ciThe `tests/quickchecking` crate generates property tests for `bindgen`.
25612a9d9c8Sopenharmony_ciFrom the crate's directory you can run the tests with `cargo run`. For details
25712a9d9c8Sopenharmony_cion additional configuration including how to preserve / inspect the generated
25812a9d9c8Sopenharmony_ciproperty tests, see
25912a9d9c8Sopenharmony_ci[./tests/quickchecking/README.md](./tests/quickchecking/README.md).
26012a9d9c8Sopenharmony_ci
26112a9d9c8Sopenharmony_ci## Code Overview
26212a9d9c8Sopenharmony_ci
26312a9d9c8Sopenharmony_ci`bindgen` takes C and C++ header files as input and generates corresponding Rust
26412a9d9c8Sopenharmony_ci`#[repr(C)]` type definitions and `extern` foreign function declarations.
26512a9d9c8Sopenharmony_ci
26612a9d9c8Sopenharmony_ciFirst, we use `libclang` to parse the input headers. See `src/clang.rs` for our
26712a9d9c8Sopenharmony_ciRust-y wrappers over the raw C `libclang` API that the `clang-sys` crate
26812a9d9c8Sopenharmony_ciexposes. We walk over `libclang`'s AST and construct our own internal
26912a9d9c8Sopenharmony_cirepresentation (IR).  The `ir` module and submodules (`src/ir/*`) contain the IR
27012a9d9c8Sopenharmony_citype definitions and `libclang` AST into IR parsing code.
27112a9d9c8Sopenharmony_ci
27212a9d9c8Sopenharmony_ciThe umbrella IR type is the `Item`. It contains various nested `enum`s that let
27312a9d9c8Sopenharmony_cius drill down and get more specific about the kind of construct that we're
27412a9d9c8Sopenharmony_cilooking at. Here is a summary of the IR types and their relationships:
27512a9d9c8Sopenharmony_ci
27612a9d9c8Sopenharmony_ci* `Item` contains:
27712a9d9c8Sopenharmony_ci    * An `ItemId` to uniquely identify it.
27812a9d9c8Sopenharmony_ci    * An `ItemKind`, which is one of:
27912a9d9c8Sopenharmony_ci        * A `Module`, which is originally a C++ namespace and becomes a Rust
28012a9d9c8Sopenharmony_ci          module. It contains the set of `ItemId`s of `Item`s that are defined
28112a9d9c8Sopenharmony_ci          within it.
28212a9d9c8Sopenharmony_ci        * A `Type`, which contains:
28312a9d9c8Sopenharmony_ci            * A `Layout`, describing the type's size and alignment.
28412a9d9c8Sopenharmony_ci            * A `TypeKind`, which is one of:
28512a9d9c8Sopenharmony_ci                * Some integer type.
28612a9d9c8Sopenharmony_ci                * Some float type.
28712a9d9c8Sopenharmony_ci                * A `Pointer` to another type.
28812a9d9c8Sopenharmony_ci                * A function pointer type, with `ItemId`s of its parameter types
28912a9d9c8Sopenharmony_ci                  and return type.
29012a9d9c8Sopenharmony_ci                * An `Alias` to another type (`typedef` or `using X = ...`).
29112a9d9c8Sopenharmony_ci                * A fixed size `Array` of `n` elements of another type.
29212a9d9c8Sopenharmony_ci                * A `Comp` compound type, which is either a `struct`, `class`,
29312a9d9c8Sopenharmony_ci                  or `union`. This is potentially a template definition.
29412a9d9c8Sopenharmony_ci                * A `TemplateInstantiation` referencing some template definition
29512a9d9c8Sopenharmony_ci                  and a set of template argument types.
29612a9d9c8Sopenharmony_ci                * Etc...
29712a9d9c8Sopenharmony_ci        * A `Function`, which contains:
29812a9d9c8Sopenharmony_ci            * An ABI
29912a9d9c8Sopenharmony_ci            * A mangled name
30012a9d9c8Sopenharmony_ci            * a `FunctionKind`, which describes whether this function is a plain
30112a9d9c8Sopenharmony_ci              function, method, static method, constructor, destructor, etc.
30212a9d9c8Sopenharmony_ci            * The `ItemId` of its function pointer type.
30312a9d9c8Sopenharmony_ci        * A `Var` representing a static variable or `#define` constant, which
30412a9d9c8Sopenharmony_ci          contains:
30512a9d9c8Sopenharmony_ci            * Its type's `ItemId`
30612a9d9c8Sopenharmony_ci            * Optionally, a mangled name
30712a9d9c8Sopenharmony_ci            * Optionally, a value
30812a9d9c8Sopenharmony_ci    * An optional `clang::SourceLocation` that holds the first source code
30912a9d9c8Sopenharmony_ci      location where the `Item` was encountered.
31012a9d9c8Sopenharmony_ci
31112a9d9c8Sopenharmony_ciThe IR forms a graph of interconnected and inter-referencing types and
31212a9d9c8Sopenharmony_cifunctions. The `ir::traversal` module provides IR graph traversal
31312a9d9c8Sopenharmony_ciinfrastructure: edge kind definitions (base member vs field type vs function
31412a9d9c8Sopenharmony_ciparameter, etc...), the `Trace` trait to enumerate an IR thing's outgoing edges,
31512a9d9c8Sopenharmony_civarious traversal types.
31612a9d9c8Sopenharmony_ci
31712a9d9c8Sopenharmony_ciAfter constructing the IR, we run a series of analyses on it. These analyses do
31812a9d9c8Sopenharmony_cieverything from allocate logical bitfields into physical units, compute for
31912a9d9c8Sopenharmony_ciwhich types we can `#[derive(Debug)]`, to determining which implicit template
32012a9d9c8Sopenharmony_ciparameters a given type uses. The analyses are defined in
32112a9d9c8Sopenharmony_ci`src/ir/analysis/*`. They are implemented as fixed-point algorithms, using the
32212a9d9c8Sopenharmony_ci`ir::analysis::MonotoneFramework` trait.
32312a9d9c8Sopenharmony_ci
32412a9d9c8Sopenharmony_ciThe final phase is generating Rust source text from the analyzed IR, and it is
32512a9d9c8Sopenharmony_cidefined in `src/codegen/*`. We use the `quote` crate, which provides the `quote!
32612a9d9c8Sopenharmony_ci{ ... }` macro for quasi-quoting Rust forms. Some options that affect the
32712a9d9c8Sopenharmony_cigenerated Rust code are implemented using the [`syn`](https://docs.rs/syn) crate.
32812a9d9c8Sopenharmony_ci
32912a9d9c8Sopenharmony_ci### Implementing new options using `syn`
33012a9d9c8Sopenharmony_ci
33112a9d9c8Sopenharmony_ciIf a new option can be implemented using the `syn` crate it should be added to
33212a9d9c8Sopenharmony_cithe `codegen::postprocessing` module by following these steps:
33312a9d9c8Sopenharmony_ci
33412a9d9c8Sopenharmony_ci- Introduce a new field to `BindgenOptions` for the option.
33512a9d9c8Sopenharmony_ci- Write a free function inside `codegen::postprocessing` implementing the
33612a9d9c8Sopenharmony_ci  option. This function with the same name of the `BindgenOptions` field.
33712a9d9c8Sopenharmony_ci- Add a new value to the `codegen::postprocessing::PASSES` for the option using
33812a9d9c8Sopenharmony_ci  the `pass!` macro.
33912a9d9c8Sopenharmony_ci
34012a9d9c8Sopenharmony_ci## Pull Requests and Code Reviews
34112a9d9c8Sopenharmony_ci
34212a9d9c8Sopenharmony_ciEnsure that each commit stands alone, and passes tests. This enables better `git
34312a9d9c8Sopenharmony_cibisect`ing when needed. If your commits do not stand on their own, then rebase
34412a9d9c8Sopenharmony_cithem on top of the latest main and squash them into a single commit.
34512a9d9c8Sopenharmony_ci
34612a9d9c8Sopenharmony_ciAll pull requests undergo code review before merging. To request review, comment
34712a9d9c8Sopenharmony_ci`r? @github_username_of_reviewer`. They we will respond with `r+` to approve the
34812a9d9c8Sopenharmony_cipull request, or may leave feedback and request changes to the pull request. Any
34912a9d9c8Sopenharmony_cichanges should be squashed into the original commit.
35012a9d9c8Sopenharmony_ci
35112a9d9c8Sopenharmony_ciUnsure who to ask for review? Ask any of:
35212a9d9c8Sopenharmony_ci
35312a9d9c8Sopenharmony_ci* `@emilio`
35412a9d9c8Sopenharmony_ci* `@fitzgen`
35512a9d9c8Sopenharmony_ci
35612a9d9c8Sopenharmony_ciMore resources:
35712a9d9c8Sopenharmony_ci
35812a9d9c8Sopenharmony_ci* [Servo's GitHub Workflow](https://github.com/servo/servo/wiki/Github-workflow)
35912a9d9c8Sopenharmony_ci* [Beginner's Guide to Rebasing and Squashing](https://github.com/servo/servo/wiki/Beginner's-guide-to-rebasing-and-squashing)
36012a9d9c8Sopenharmony_ci
36112a9d9c8Sopenharmony_ci## Generating Graphviz Dot Files
36212a9d9c8Sopenharmony_ci
36312a9d9c8Sopenharmony_ciWe can generate [Graphviz](http://graphviz.org/pdf/dotguide.pdf) dot files from
36412a9d9c8Sopenharmony_ciour internal representation of a C/C++ input header, and then you can create a
36512a9d9c8Sopenharmony_ciPNG or PDF from it with Graphviz's `dot` program. This is very useful when
36612a9d9c8Sopenharmony_cidebugging bindgen!
36712a9d9c8Sopenharmony_ci
36812a9d9c8Sopenharmony_ciFirst, make sure you have Graphviz and `dot` installed:
36912a9d9c8Sopenharmony_ci
37012a9d9c8Sopenharmony_ci```
37112a9d9c8Sopenharmony_ci$ brew install graphviz         # OS X
37212a9d9c8Sopenharmony_ci$ sudo dnf install graphviz     # Fedora
37312a9d9c8Sopenharmony_ci$ # Etc...
37412a9d9c8Sopenharmony_ci```
37512a9d9c8Sopenharmony_ci
37612a9d9c8Sopenharmony_ciThen, use the `--emit-ir-graphviz` flag to generate a `dot` file from our IR:
37712a9d9c8Sopenharmony_ci
37812a9d9c8Sopenharmony_ci```
37912a9d9c8Sopenharmony_ci$ cargo run -- example.hpp --emit-ir-graphviz output.dot
38012a9d9c8Sopenharmony_ci```
38112a9d9c8Sopenharmony_ci
38212a9d9c8Sopenharmony_ciFinally, convert the `dot` file to an image:
38312a9d9c8Sopenharmony_ci
38412a9d9c8Sopenharmony_ci```
38512a9d9c8Sopenharmony_ci$ dot -Tpng output.dot -o output.png
38612a9d9c8Sopenharmony_ci```
38712a9d9c8Sopenharmony_ci
38812a9d9c8Sopenharmony_ciThe final result will look something like this:
38912a9d9c8Sopenharmony_ci
39012a9d9c8Sopenharmony_ci[![An example graphviz rendering of our IR](./example-graphviz-ir.png)](./example-graphviz-ir.png)
39112a9d9c8Sopenharmony_ci
39212a9d9c8Sopenharmony_ci## Debug Logging
39312a9d9c8Sopenharmony_ci
39412a9d9c8Sopenharmony_ciTo help debug what `bindgen` is doing, you can define the environment variable
39512a9d9c8Sopenharmony_ci`RUST_LOG=bindgen` to get a bunch of debugging log spew.
39612a9d9c8Sopenharmony_ci
39712a9d9c8Sopenharmony_ci```
39812a9d9c8Sopenharmony_ci$ RUST_LOG=bindgen ./target/debug/bindgen [flags...] ~/path/to/some/header.h
39912a9d9c8Sopenharmony_ci```
40012a9d9c8Sopenharmony_ci
40112a9d9c8Sopenharmony_ciThis logging can also be used when debugging failing tests:
40212a9d9c8Sopenharmony_ci
40312a9d9c8Sopenharmony_ci```
40412a9d9c8Sopenharmony_ci$ RUST_LOG=bindgen cargo test
40512a9d9c8Sopenharmony_ci```
40612a9d9c8Sopenharmony_ci
40712a9d9c8Sopenharmony_ci## Using `creduce` to Minimize Test Cases
40812a9d9c8Sopenharmony_ci
40912a9d9c8Sopenharmony_ciIf you find a test case that triggers an unexpected panic in `bindgen`, causes
41012a9d9c8Sopenharmony_ci`bindgen` to emit bindings that won't compile, define structs with the wrong
41112a9d9c8Sopenharmony_cisize/alignment, or results in any other kind of incorrectness, then using
41212a9d9c8Sopenharmony_ci`creduce` can help reduce the test case to a minimal one that still exhibits
41312a9d9c8Sopenharmony_cithat same bad behavior.
41412a9d9c8Sopenharmony_ci
41512a9d9c8Sopenharmony_ci***Reduced test cases are SUPER helpful when filing bug reports!***
41612a9d9c8Sopenharmony_ci
41712a9d9c8Sopenharmony_ci### Getting `creduce`
41812a9d9c8Sopenharmony_ci
41912a9d9c8Sopenharmony_ciOften, you can install `creduce` from your OS's package manager:
42012a9d9c8Sopenharmony_ci
42112a9d9c8Sopenharmony_ci```
42212a9d9c8Sopenharmony_ci$ sudo apt install creduce
42312a9d9c8Sopenharmony_ci$ brew install creduce
42412a9d9c8Sopenharmony_ci$ # Etc...
42512a9d9c8Sopenharmony_ci```
42612a9d9c8Sopenharmony_ci
42712a9d9c8Sopenharmony_ciOtherwise, follow [these instructions](https://github.com/csmith-project/creduce/blob/main/INSTALL.md) for building and/or installing `creduce`.
42812a9d9c8Sopenharmony_ci
42912a9d9c8Sopenharmony_ciRunning `creduce` requires two things:
43012a9d9c8Sopenharmony_ci
43112a9d9c8Sopenharmony_ci1. Your isolated test case, and
43212a9d9c8Sopenharmony_ci
43312a9d9c8Sopenharmony_ci2. A script to act as a predicate script describing whether the behavior you're
43412a9d9c8Sopenharmony_ci   trying to isolate occurred.
43512a9d9c8Sopenharmony_ci
43612a9d9c8Sopenharmony_ciWith those two things in hand, running `creduce` looks like this:
43712a9d9c8Sopenharmony_ci
43812a9d9c8Sopenharmony_ci    $ creduce ./predicate.sh ./isolated-test-case.h
43912a9d9c8Sopenharmony_ci
44012a9d9c8Sopenharmony_ci### Isolating Your Test Case
44112a9d9c8Sopenharmony_ci
44212a9d9c8Sopenharmony_ciIf you're using `bindgen` as a command line tool, pass
44312a9d9c8Sopenharmony_ci`--dump-preprocessed-input` flag.
44412a9d9c8Sopenharmony_ci
44512a9d9c8Sopenharmony_ciIf you're using `bindgen` as a Rust library, invoke the
44612a9d9c8Sopenharmony_ci`bindgen::Builder::dump_preprocessed_input` method where you call
44712a9d9c8Sopenharmony_ci`bindgen::Builder::generate`.
44812a9d9c8Sopenharmony_ci
44912a9d9c8Sopenharmony_ciAfterwards, there should be a `__bindgen.i` or `__bindgen.ii` file containing
45012a9d9c8Sopenharmony_cithe combined and preprocessed input headers, which is usable as an isolated,
45112a9d9c8Sopenharmony_cistandalone test case.
45212a9d9c8Sopenharmony_ci
45312a9d9c8Sopenharmony_ci### Writing a Predicate Script
45412a9d9c8Sopenharmony_ci
45512a9d9c8Sopenharmony_ciWriting a `predicate.sh` script for a `bindgen` test case is straightforward. We
45612a9d9c8Sopenharmony_cialready have a general purpose predicate script that you can use, you just have
45712a9d9c8Sopenharmony_cito wrap and configure it.
45812a9d9c8Sopenharmony_ci
45912a9d9c8Sopenharmony_ci```bash
46012a9d9c8Sopenharmony_ci#!/usr/bin/env bash
46112a9d9c8Sopenharmony_ci
46212a9d9c8Sopenharmony_ci# Exit the script with a nonzero exit code if:
46312a9d9c8Sopenharmony_ci# * any individual command finishes with a nonzero exit code, or
46412a9d9c8Sopenharmony_ci# * we access any undefined variable.
46512a9d9c8Sopenharmony_ciset -eu
46612a9d9c8Sopenharmony_ci
46712a9d9c8Sopenharmony_ci# Invoke the general purpose predicate script that comes in the
46812a9d9c8Sopenharmony_ci# `bindgen` repository.
46912a9d9c8Sopenharmony_ci#
47012a9d9c8Sopenharmony_ci# You'll need to replace `--whatever-flags` with things that are specific to the
47112a9d9c8Sopenharmony_ci# incorrectness you're trying to pin down. See below for details.
47212a9d9c8Sopenharmony_cipath/to/rust-bindgen/csmith-fuzzing/predicate.py \
47312a9d9c8Sopenharmony_ci    --whatever-flags \
47412a9d9c8Sopenharmony_ci    ./isolated-test-case.h
47512a9d9c8Sopenharmony_ci```
47612a9d9c8Sopenharmony_ci
47712a9d9c8Sopenharmony_ciWhen hunting down a particular panic emanating from inside `bindgen`, you can
47812a9d9c8Sopenharmony_ciinvoke `predicate.py` like this:
47912a9d9c8Sopenharmony_ci
48012a9d9c8Sopenharmony_ci```bash
48112a9d9c8Sopenharmony_cipath/to/rust-bindgen/csmith-fuzzing/predicate.py \
48212a9d9c8Sopenharmony_ci    --expect-bindgen-fail \
48312a9d9c8Sopenharmony_ci    --bindgen-grep "thread main panicked at '<insert panic message here>'" \
48412a9d9c8Sopenharmony_ci    ./isolated-test-case.h
48512a9d9c8Sopenharmony_ci```
48612a9d9c8Sopenharmony_ci
48712a9d9c8Sopenharmony_ciAlternatively, when hunting down a bad `#[derive(Eq)]` that is causing `rustc`
48812a9d9c8Sopenharmony_cito fail to compile `bindgen`'s emitted bindings, you can invoke `predicate.py`
48912a9d9c8Sopenharmony_cilike this:
49012a9d9c8Sopenharmony_ci
49112a9d9c8Sopenharmony_ci```bash
49212a9d9c8Sopenharmony_cipath/to/rust-bindgen/csmith-fuzzing/predicate.py \
49312a9d9c8Sopenharmony_ci    --bindings-grep NameOfTheStructThatIsErroneouslyDerivingEq \
49412a9d9c8Sopenharmony_ci    --expect-compile-fail \
49512a9d9c8Sopenharmony_ci    --rustc-grep 'error[E0277]: the trait bound `f64: std::cmp::Eq` is not satisfied' \
49612a9d9c8Sopenharmony_ci    ./isolated-test-case.h
49712a9d9c8Sopenharmony_ci```
49812a9d9c8Sopenharmony_ci
49912a9d9c8Sopenharmony_ciOr, when minimizing a failing layout test in the compiled bindings, you can
50012a9d9c8Sopenharmony_ciinvoke `predicate.py` like this:
50112a9d9c8Sopenharmony_ci
50212a9d9c8Sopenharmony_ci```bash
50312a9d9c8Sopenharmony_cipath/to/rust-bindgen/csmith-fuzzing/predicate.py \
50412a9d9c8Sopenharmony_ci    --bindings-grep MyStruct \
50512a9d9c8Sopenharmony_ci    --expect-layout-tests-fail \
50612a9d9c8Sopenharmony_ci    --layout-tests-grep "thread 'bindgen_test_layout_MyStruct' panicked" \
50712a9d9c8Sopenharmony_ci    ./isolated-test-case.h
50812a9d9c8Sopenharmony_ci```
50912a9d9c8Sopenharmony_ci
51012a9d9c8Sopenharmony_ciFor details on all the flags that you can pass to `predicate.py`, run:
51112a9d9c8Sopenharmony_ci
51212a9d9c8Sopenharmony_ci```
51312a9d9c8Sopenharmony_ci$ path/to/rust-bindgen/csmith-fuzzing/predicate.py --help
51412a9d9c8Sopenharmony_ci```
51512a9d9c8Sopenharmony_ci
51612a9d9c8Sopenharmony_ciAnd you can always write your own, arbitrary predicate script if you prefer.
51712a9d9c8Sopenharmony_ci(Although, maybe we should add extra functionality to `predicate.py` -- file an
51812a9d9c8Sopenharmony_ciissue if you think so!)
51912a9d9c8Sopenharmony_ci
52012a9d9c8Sopenharmony_ci`creduce` is *really* helpful and can cut hundreds of thousands of lines of test
52112a9d9c8Sopenharmony_cicase down to 5 lines.
52212a9d9c8Sopenharmony_ci
52312a9d9c8Sopenharmony_ciHappy bug hunting and test case reducing!
52412a9d9c8Sopenharmony_ci
52512a9d9c8Sopenharmony_ci[More information on using `creduce`.](https://embed.cs.utah.edu/creduce/using/)
52612a9d9c8Sopenharmony_ci
52712a9d9c8Sopenharmony_ci## Cutting a new bindgen release
52812a9d9c8Sopenharmony_ci
52912a9d9c8Sopenharmony_ciTo cut a release, the following needs to happen:
53012a9d9c8Sopenharmony_ci
53112a9d9c8Sopenharmony_ci### Updating the changelog
53212a9d9c8Sopenharmony_ci
53312a9d9c8Sopenharmony_ciUpdate the CHANGELOG.md file with the changes from the last release. Something
53412a9d9c8Sopenharmony_cilike the following is a useful way to check what has landed:
53512a9d9c8Sopenharmony_ci
53612a9d9c8Sopenharmony_ci ```
53712a9d9c8Sopenharmony_ci $ git log --oneline v0.62.0..HEAD
53812a9d9c8Sopenharmony_ci ```
53912a9d9c8Sopenharmony_ci
54012a9d9c8Sopenharmony_ciAlso worth checking the [next-release tag](https://github.com/rust-lang/rust-bindgen/pulls?q=is%3Apr+label%3Anext-release).
54112a9d9c8Sopenharmony_ci
54212a9d9c8Sopenharmony_ciOnce that's done and the changelog is up-to-date, run `doctoc` on it.
54312a9d9c8Sopenharmony_ci
54412a9d9c8Sopenharmony_ciIf needed, install it locally by running:
54512a9d9c8Sopenharmony_ci
54612a9d9c8Sopenharmony_ci```
54712a9d9c8Sopenharmony_ci$ npm install doctoc
54812a9d9c8Sopenharmony_ci$ ./node_modules/doctoc/doctoc.js CHANGELOG.md
54912a9d9c8Sopenharmony_ci```
55012a9d9c8Sopenharmony_ci
55112a9d9c8Sopenharmony_ci### Bumping the version numbers.
55212a9d9c8Sopenharmony_ci
55312a9d9c8Sopenharmony_ciBump version numbers as needed. Run tests just to ensure everything is working
55412a9d9c8Sopenharmony_cias expected.
55512a9d9c8Sopenharmony_ci
55612a9d9c8Sopenharmony_ci### Merge to `main`
55712a9d9c8Sopenharmony_ci
55812a9d9c8Sopenharmony_ciFor regular releases, the changes above should end up in `main` before
55912a9d9c8Sopenharmony_cipublishing. For dot-releases of an old version (e.g., cherry-picking an
56012a9d9c8Sopenharmony_ciimportant fix) you can skip this.
56112a9d9c8Sopenharmony_ci
56212a9d9c8Sopenharmony_ci### Publish and add a git tag for the right commit
56312a9d9c8Sopenharmony_ci
56412a9d9c8Sopenharmony_ciOnce you're in the right commit, do:
56512a9d9c8Sopenharmony_ci
56612a9d9c8Sopenharmony_ci```
56712a9d9c8Sopenharmony_ci$ git tag -a v0.62.1 # With the right version of course
56812a9d9c8Sopenharmony_ci$ pushd bindgen && cargo publish && popd
56912a9d9c8Sopenharmony_ci$ pushd bindgen-cli && cargo publish && popd
57012a9d9c8Sopenharmony_ci$ git push --tags upstream # To publish the tag
57112a9d9c8Sopenharmony_ci```
572