# Developer's guide ## Build To install from source, you'll need to install Rust and [Cargo][cargo]. Follow the instructions on the [Rust installation page][install-rust]. You'll also need the version of LLVM specified in the `llvm-ir` dependency in `Cargo.toml` (LLVM 14, at the time of writing).[^1] Follow the [instructions on building llvm-sys][llvm-sys] to make it available to Cargo. Then, get the source: ```bash git clone https://github.com/GaloisInc/yapall cd yapall ``` Finally, build everything: ```bash cargo build --release ``` You can find binaries in `target/release`. Run tests with `cargo test`. [^1]: When run from the repository root, this command will show you the exact version: `cargo read-manifest | jq '.dependencies|.[]|select(.name|contains("llvm"))|.features|.[0]'`. [cargo]: https://doc.rust-lang.org/cargo/ [install-rust]: https://www.rust-lang.org/tools/install [llvm-sys]: https://gitlab.com/taricorp/llvm-sys.rs#build-requirements ### Example: Debian "bookworm" Here's an end-to-end sequence of commands that installs the build and test dependencies of yapall on Debian bookworm: ```sh apt-get update UBUNTU_NAME="bookworm" LLVM_MAJOR_VERSION="14" wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add - echo "deb http://apt.llvm.org/${UBUNTU_NAME}/ llvm-toolchain-${UBUNTU_NAME}-${LLVM_MAJOR_VERSION} main" | tee /etc/apt/sources.list.d/llvm.list apt-get -y install --no-install-recommends llvm-${LLVM_MAJOR_VERSION} llvm-${LLVM_MAJOR_VERSION}-dev apt-get install libpolly-14-dev apt-get -y install clang-${LLVM_MAJOR_VERSION} apt-get -y install clang++-${LLVM_MAJOR_VERSION} ``` ### Features See `Cargo.toml` for various build features. `par` enables parallel Ascent. ### PGO First, build a benchmark program. You'll want this to be as large as possible, but still small enough to be handled context-sensitively. For example: ```sh clang++ -emit-llvm -O1 -c -fno-discard-value-names tests/medium/jackson.cpp ``` Then, build the instrumented binary: ```sh cargo install cargo-pgo rustup component add llvm-tools-preview cargo pgo build ``` Collect data: ```sh target/x86_64-unknown-linux-gnu/release/yapall --contexts 3 --quiet jackson.bc ``` Finally, build and install the optimized binary: ```sh cargo pgo optimize mv target/x86_64-unknown-linux-gnu/release/yapall /wherever ``` ## Docs HTML documentation can be built with [mdBook][mdbook]: ```sh cd doc mdbook build ``` [mdbook]: https://rust-lang.github.io/mdBook/ ## Format All code should be formatted with [rustfmt][rustfmt]. You can install rustfmt with [rustup][rustup] like so: ```sh rustup component add rustfmt ``` and then run it like this: ```sh cargo fmt ``` [rustfmt]: https://rust-lang.github.io/rustfmt [rustup]: https://rustup.rs/ ## Lint All code should pass [Clippy][clippy]. You can install Clippy with rustup like so: ```sh rustup component add clippy ``` and then run it like this: ```sh cargo clippy --workspace -- --deny warnings ``` [clippy]: https://doc.rust-lang.org/stable/clippy/ ## Profile ### Counts To see cumulative time taken by each rule: ```sh cargo install counts cargo run --quiet --release -- --quiet --tracing --signatures signatures.json irving.bc 2> /tmp/nanos counts -i -e /tmp/nanos ``` (You may also want to try with `cargo run --features par`.) To see cumulative tuples generated by each rule: ```sh cargo install counts cargo run --quiet --release --features count -- --quiet --signatures signatures.json irving.bc 2> /tmp/nanos counts -i -e /tmp/nanos ``` ### dhat ```sh cargo build -q --release --features dhat-heap ./target/release/yapall --quiet --signatures signatures.json jackson.bc ``` Then, go to to upload `dhat-heap.json`. ### perf ```sh cargo build -q --release perf record ./target/release/yapall --signatures signatures.json jackson.bc ``` ### Poor Man's Profiler ```sh cargo build -q --release ./target/release/yapall --signatures signatures.json jackson.bc & ./scripts/poor-mans-profiler.sh 10 > prof.txt ``` ### Samply ```sh cargo install samply cargo build --profile=profiling samply record ./target/release/yapall --signatures signatures.json jackson.bc ``` ## Test Running `cargo test` checks whether the pointer analysis correctly handles various LLVM features. Running `lit tests/pointer/soundness` checks whether the C test programs are compiling to the intended LLVM bitcode. ## Warnings Certain warnings are disallowed in the CI build. You can reproduce the behavior of the CI build by running `cargo check`, `cargo build`, or `cargo test` like so: ```sh env RUSTFLAGS="@$PWD/rustc-flags" cargo check ``` Using a flag file for this purpose achieves several objectives: - It frictionlessly allows code with warnings during local development - It makes it easy to reproduce the CI build process locally - It makes it easy to maintain the list of warnings - It [maintains forward-compatibility][anti-pat] with future rustc warnings - It ensures the flags are consistent across all crates in the project This flag file rejects all `rustc` warnings by default, as well as a subset of [allowed-by-default lints][allowed-by-default]. The goal is to balance high-quality, maintainable code with not annoying developers. To allow a lint in one spot, use: ```rust #[allow(name_of_lint)] ``` To enable these warnings on a semi-permanent basis, create a [Cargo configuration file][cargo-conf]: ```sh mkdir .cargo printf "[build]\nrustflags = [\"@${PWD}/rustc-flags\"]\n" > .cargo/config.toml ``` [allowed-by-default]: https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html [anti-pat]: https://rust-unofficial.github.io/patterns/anti_patterns/deny-warnings.html#denywarnings