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[](./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