diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..394368ad --- /dev/null +++ b/.dockerignore @@ -0,0 +1,7 @@ +emsdk +llvm*/ +target-llvm/ +target/ +node_modules/ +utils/ +build/ diff --git a/.github/trigger-wasm-llvm-build b/.github/trigger-wasm-llvm-build new file mode 100644 index 00000000..56a6051c --- /dev/null +++ b/.github/trigger-wasm-llvm-build @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/.github/workflows/build-revive-debian.yml b/.github/workflows/build-revive-debian.yml deleted file mode 100644 index 57c1d0f4..00000000 --- a/.github/workflows/build-revive-debian.yml +++ /dev/null @@ -1,38 +0,0 @@ -name: Build revive-debian -on: - workflow_dispatch: - -env: - REVIVE_DEBIAN_PACKAGE: revive-debian-x86 - DEBIAN_CONTAINER: revive-builder-debian-x86 - DEBIAN_CONTAINER_BUILDER: build-debian-builder.sh - DEBIAN_CONTAINER_RUNNER: run-debian-builder.sh - REVIVE_DEBIAN_INSTALL: ${{ github.workspace }}/target/release - REVIVE_DEBIAN_BINARY: resolc - RUST_VERSION: "1.81" - -jobs: - build-revive-debian-x86: - name: debian-container-x86 - runs-on: ubuntu-22.04 - steps: - - uses: actions/checkout@v4 - - - name: build-container - run: | - (cd utils && ./${{ env.DEBIAN_CONTAINER_BUILDER}} --build-arg RUST_VERSION=${{ env.RUST_VERSION}} . ) - - - name: build-revive-debian - run: | - rustup show - cargo --version - rustup +nightly show - cargo +nightly --version - bash --version - utils/${{ env.DEBIAN_CONTAINER_RUNNER }} utils/build-revive.sh -o ${{ env.REVIVE_DEBIAN_INSTALL}} - - - uses: actions/upload-artifact@v4 - with: - name: ${{ env.REVIVE_DEBIAN_PACKAGE }} - path: ${{ env.REVIVE_DEBIAN_INSTALL }}/${{ env.REVIVE_DEBIAN_BINARY }} - retention-days: 1 diff --git a/.github/workflows/build-revive-wasm.yml b/.github/workflows/build-revive-wasm.yml index dd1db44a..15676761 100644 --- a/.github/workflows/build-revive-wasm.yml +++ b/.github/workflows/build-revive-wasm.yml @@ -14,7 +14,7 @@ env: jobs: build-revive-wasm: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 defaults: run: shell: bash @@ -26,24 +26,30 @@ jobs: uses: actions/cache@v3 with: path: | - llvm18.0-emscripten + target-llvm # Use a unique key based on LLVM version or configuration files to avoid cache invalidation - key: llvm-build-${{ runner.os }}-${{ hashFiles('clone-llvm.sh', 'emscripten-build-llvm.sh') }} + key: llvm-build-${{ runner.os }}-${{ hashFiles('LLVM.lock', '.github/trigger-wasm-llvm-build') }} - name: Install Dependencies run: | - sudo apt-get update && sudo apt-get install -y cmake ninja-build libncurses5 + # system dependencies + sudo apt-get update && sudo apt-get install -y cmake ninja-build curl git libssl-dev pkg-config clang lld rustup target add wasm32-unknown-emscripten - # Install LLVM required for the compiler runtime, runtime-api and stdlib - curl -sSL --output llvm.tar.xz https://github.com/llvm/llvm-project/releases/download/llvmorg-18.1.4/clang+llvm-18.1.4-x86_64-linux-gnu-ubuntu-18.04.tar.xz - tar Jxf llvm.tar.xz - mv clang+llvm-18.1.4-x86_64-linux-gnu-ubuntu-18.04 llvm18/ - echo "$(pwd)/llvm18/bin" >> $GITHUB_PATH - # Install Emscripten - git clone https://github.com/emscripten-core/emsdk.git - cd emsdk - ./emsdk install ${{ env.EMSCRIPTEN_VERSION }} - ./emsdk activate ${{ env.EMSCRIPTEN_VERSION }} + # host LLVM + curl -sSL --output llvm.tar.xz https://github.com/paritytech/revive/releases/download/v0.1.0-dev.7/clang+llvm-18.1.8-x86_64-linux-gnu-ubuntu-24.04.tar.xz + mkdir llvm18 + tar Jxf llvm.tar.xz -C llvm18/ + echo "LLVM_SYS_181_PREFIX=$(pwd)/llvm18" >> $GITHUB_ENV + # Clone LLVM and install the Emscripten SDK + make install-llvm-builder + revive-llvm --target-env emscripten clone + + - name: Build target LLVM + if: steps.cache-llvm.outputs.cache-hit != 'true' + run: | + source emsdk/emsdk_env.sh + revive-llvm --target-env emscripten build + echo "REVIVE_LLVM_TARGET_PREFIX=${PWD}/target-llvm/emscripten/target-final" >> $GITHUB_ENV - run: | rustup show @@ -52,13 +58,6 @@ jobs: cargo +nightly --version cmake --version bash --version - llvm-config --version - - - name: Build LLVM - if: steps.cache-llvm.outputs.cache-hit != 'true' - run: | - export EMSDK_ROOT=${PWD}/emsdk - ./emscripten-build-llvm.sh - name: Use Cached LLVM if: steps.cache-llvm.outputs.cache-hit == 'true' @@ -67,8 +66,7 @@ jobs: - name: Build revive run: | - export LLVM_LINK_PREFIX=${PWD}/llvm18.0-emscripten - source ./emsdk/emsdk_env.sh + source emsdk/emsdk_env.sh make install-wasm - uses: actions/upload-artifact@v4 @@ -83,7 +81,7 @@ jobs: needs: build-revive-wasm strategy: matrix: - os: ['ubuntu-24.04', 'macos-14', 'windows-2022'] + os: ["ubuntu-24.04", "macos-14", "windows-2022"] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 @@ -100,7 +98,7 @@ jobs: - name: Set Up Node.js uses: actions/setup-node@v3 with: - node-version: '20' + node-version: "20" - name: Install Bun on Windows if: runner.os == 'Windows' diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 3b1c56d7..c92b886f 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -11,7 +11,7 @@ env: jobs: build-ubuntu-x86: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 @@ -25,16 +25,16 @@ jobs: - name: Install LLVM run: | - curl -sSL --output llvm.tar.xz https://github.com/llvm/llvm-project/releases/download/llvmorg-18.1.4/clang+llvm-18.1.4-x86_64-linux-gnu-ubuntu-18.04.tar.xz - tar Jxf llvm.tar.xz - mv clang+llvm-18.1.4-x86_64-linux-gnu-ubuntu-18.04 llvm18/ - echo "$(pwd)/llvm18/bin" >> $GITHUB_PATH + curl -sSL --output llvm.tar.xz https://github.com/paritytech/revive/releases/download/v0.1.0-dev.7/clang+llvm-18.1.8-x86_64-linux-gnu-ubuntu-24.04.tar.xz + mkdir llvm18 + tar Jxf llvm.tar.xz -C llvm18/ + echo "LLVM_SYS_181_PREFIX=$(pwd)/llvm18" >> $GITHUB_ENV - name: Install apt dependencies run: | sudo add-apt-repository -y ppa:ethereum/ethereum sudo apt update - sudo apt install -y libtinfo5 ethereum + sudo apt install -y ethereum - name: Format run: make format diff --git a/.gitignore b/.gitignore index a8a0c39c..87ea5207 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /target +target-llvm *.dot .vscode/ .DS_Store @@ -6,9 +7,7 @@ /*.yul /*.ll /*.s -/llvm-project -/llvm18.0 -/llvm18.0-emscripten +/llvm* node_modules artifacts tmp @@ -16,3 +15,4 @@ package-lock.json /*.html /build soljson.js +emsdk diff --git a/CHANGELOG.md b/CHANGELOG.md index 347078b8..2a9009a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,17 @@ ## Unreleased +This is a development pre-release. + +### Added +- The `revive-llvm-builder` crate with the `revive-llvm` helper utility for streamlined management of the LLVM framework dependency. + +### Changed +- The minimum supported Rust version is `1.81.0`. + +### Fixed +- Decouple the LLVM target dependency from the LLVM host dependency. + ## v0.1.0-dev.7 This is a development pre-release. diff --git a/Cargo.lock b/Cargo.lock index b5c48762..6bdd9c1f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -101,9 +101,9 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "alloy-core" -version = "0.8.15" +version = "0.8.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c618bd382f0bc2ac26a7e4bfae01c9b015ca8f21b37ca40059ae35a7e62b3dc6" +checksum = "d0713007d14d88a6edb8e248cddab783b698dbb954a28b8eee4bab21cfb7e578" dependencies = [ "alloy-dyn-abi", "alloy-json-abi", @@ -114,9 +114,9 @@ dependencies = [ [[package]] name = "alloy-dyn-abi" -version = "0.8.15" +version = "0.8.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41056bde53ae10ffbbf11618efbe1e0290859e5eab0fe9ef82ebdb62f12a866f" +checksum = "44e3b98c37b3218924cd1d2a8570666b89662be54e5b182643855f783ea68b33" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -142,9 +142,9 @@ dependencies = [ [[package]] name = "alloy-json-abi" -version = "0.8.15" +version = "0.8.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c357da577dfb56998d01f574d81ad7a1958d248740a7981b205d69d65a7da404" +checksum = "731ea743b3d843bc657e120fb1d1e9cc94f5dab8107e35a82125a63e6420a102" dependencies = [ "alloy-primitives", "alloy-sol-type-parser", @@ -154,9 +154,9 @@ dependencies = [ [[package]] name = "alloy-primitives" -version = "0.8.15" +version = "0.8.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6259a506ab13e1d658796c31e6e39d2e2ee89243bcc505ddc613b35732e0a430" +checksum = "788bb18e8f61d5d9340b52143f27771daf7e1dccbaf2741621d2493f9debf52e" dependencies = [ "alloy-rlp", "bytes", @@ -165,7 +165,6 @@ dependencies = [ "derive_more 1.0.0", "foldhash", "hashbrown 0.15.2", - "hex-literal", "indexmap 2.7.0", "itoa", "k256", @@ -203,23 +202,23 @@ dependencies = [ [[package]] name = "alloy-sol-macro" -version = "0.8.15" +version = "0.8.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9d64f851d95619233f74b310f12bcf16e0cbc27ee3762b6115c14a84809280a" +checksum = "a07b74d48661ab2e4b50bb5950d74dbff5e61dd8ed03bb822281b706d54ebacb" dependencies = [ "alloy-sol-macro-expander", "alloy-sol-macro-input", "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] name = "alloy-sol-macro-expander" -version = "0.8.15" +version = "0.8.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bf7ed1574b699f48bf17caab4e6e54c6d12bc3c006ab33d58b1e227c1c3559f" +checksum = "19cc9c7f20b90f9be1a8f71a3d8e283a43745137b0837b1a1cb13159d37cad72" dependencies = [ "alloy-sol-macro-input", "const-hex", @@ -228,31 +227,31 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", "syn-solidity", "tiny-keccak", ] [[package]] name = "alloy-sol-macro-input" -version = "0.8.15" +version = "0.8.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c02997ccef5f34f9c099277d4145f183b422938ed5322dc57a089fe9b9ad9ee" +checksum = "713b7e6dfe1cb2f55c80fb05fd22ed085a1b4e48217611365ed0ae598a74c6ac" dependencies = [ "const-hex", "dunce", "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", "syn-solidity", ] [[package]] name = "alloy-sol-type-parser" -version = "0.8.15" +version = "0.8.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce13ff37285b0870d0a0746992a4ae48efaf34b766ae4c2640fa15e5305f8e73" +checksum = "1eda2711ab2e1fb517fc6e2ffa9728c9a232e296d16810810e6957b781a1b8bc" dependencies = [ "serde", "winnow", @@ -260,9 +259,9 @@ dependencies = [ [[package]] name = "alloy-sol-types" -version = "0.8.15" +version = "0.8.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1174cafd6c6d810711b4e00383037bdb458efc4fe3dbafafa16567e0320c54d8" +checksum = "e3b478bc9c0c4737a04cd976accde4df7eba0bdc0d90ad6ff43d58bc93cf79c1" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -328,9 +327,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.94" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7" +checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" [[package]] name = "approx" @@ -352,7 +351,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -603,7 +602,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62945a2f7e6de02a31fe400aa489f0e0f5b2502e69f95f853adb82a96c7a6b60" dependencies = [ "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -641,7 +640,7 @@ dependencies = [ "num-traits", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -768,7 +767,7 @@ checksum = "213888f660fddcca0d257e88e54ac05bca01885f258ccdf695bafd77031bb69d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -833,6 +832,37 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +[[package]] +name = "assert_cmd" +version = "2.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc1835b7f27878de8525dc71410b5a31cdcc5f230aed5ba5df968e09c201b23d" +dependencies = [ + "anstyle", + "bstr", + "doc-comment", + "libc", + "predicates", + "predicates-core", + "predicates-tree", + "wait-timeout", +] + +[[package]] +name = "assert_fs" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7efdb1fdb47602827a342857666feb372712cbc64b414172bd6b167a02927674" +dependencies = [ + "anstyle", + "doc-comment", + "globwalk", + "predicates", + "predicates-core", + "predicates-tree", + "tempfile", +] + [[package]] name = "assert_matches" version = "1.5.0" @@ -895,13 +925,13 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.83" +version = "0.1.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" +checksum = "3f934833b4b7233644e5848f235df3f57ed8c80f1528a26c3dfa13d2147fa056" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -912,7 +942,7 @@ checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -931,7 +961,7 @@ dependencies = [ "cfg-if", "libc", "miniz_oxide", - "object 0.36.5", + "object 0.36.7", "rustc-demangle", "windows-targets 0.52.6", ] @@ -1094,9 +1124,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +checksum = "1be3f42a67d6d345ecd59f675f3f012d6974981560836e938c22b424b85ce1be" [[package]] name = "bitvec" @@ -1433,6 +1463,17 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "bstr" +version = "1.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "531a9155a481e2ee699d4f98f43c0ca4ff8ee1bfd55c31e9e98fb29d2b176fe0" +dependencies = [ + "memchr", + "regex-automata 0.4.9", + "serde", +] + [[package]] name = "build-helper" version = "0.1.1" @@ -1456,9 +1497,9 @@ checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" [[package]] name = "bytemuck" -version = "1.20.0" +version = "1.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b37c88a63ffd85d15b406896cc343916d7cf57838a847b3a6f2ca5d39a5695a" +checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3" [[package]] name = "byteorder" @@ -1515,9 +1556,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.5" +version = "1.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31a0499c1dc64f458ad13872de75c0eb7e3fdb0e67964610c914b034fc5956e" +checksum = "c8293772165d9345bdaaa39b45b2109591e63fe5e6fbc23c6ff930a048aa310b" dependencies = [ "jobserver", "libc", @@ -1579,9 +1620,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.23" +version = "4.5.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84" +checksum = "a8eb5e908ef3a6efbe1ed62520fb7287959888c88485abe072543190ecc66783" dependencies = [ "clap_builder", "clap_derive", @@ -1589,9 +1630,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.23" +version = "4.5.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" +checksum = "96b01801b5fc6a0a232407abc821660c9c6d25a1cafc0d4f85f29fb8d9afc121" dependencies = [ "anstream", "anstyle", @@ -1601,14 +1642,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.18" +version = "4.5.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" +checksum = "54b755194d6389280185988721fffba69495eed5ee9feeee9a599b53db80318c" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -1735,6 +1776,22 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + [[package]] name = "cpp_demangle" version = "0.3.5" @@ -2061,7 +2118,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -2277,14 +2334,14 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] name = "cxx" -version = "1.0.135" +version = "1.0.136" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d44ff199ff93242c3afe480ab588d544dd08d72e92885e152ffebc670f076ad" +checksum = "ad7c7515609502d316ab9a24f67dc045132d93bfd3f00713389e90d9898bf30d" dependencies = [ "cc", "cxxbridge-cmd", @@ -2296,47 +2353,47 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.135" +version = "1.0.136" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66fd8f17ad454fc1e4f4ab83abffcc88a532e90350d3ffddcb73030220fcbd52" +checksum = "8bfd16fca6fd420aebbd80d643c201ee4692114a0de208b790b9cd02ceae65fb" dependencies = [ "cc", "codespan-reporting", "proc-macro2", "quote", "scratch", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] name = "cxxbridge-cmd" -version = "1.0.135" +version = "1.0.136" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4717c9c806a9e07fdcb34c84965a414ea40fafe57667187052cf1eb7f5e8a8a9" +checksum = "6c33fd49f5d956a1b7ee5f7a9768d58580c6752838d92e39d0d56439efdedc35" dependencies = [ "clap", "codespan-reporting", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] name = "cxxbridge-flags" -version = "1.0.135" +version = "1.0.136" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f6515329bf3d98f4073101c7866ff2bec4e635a13acb82e3f3753fff0bf43cb" +checksum = "be0f1077278fac36299cce8446effd19fe93a95eedb10d39265f3bf67b3036c9" [[package]] name = "cxxbridge-macro" -version = "1.0.135" +version = "1.0.136" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb93e6a7ce8ec985c02bbb758237a31598b340acbbc3c19c5a4fa6adaaac92ab" +checksum = "3da7e4d6e74af6b79031d264b2f13c3ea70af1978083741c41ffce9308f1f24f" dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -2360,7 +2417,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -2371,7 +2428,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -2412,7 +2469,7 @@ checksum = "d65d7ce8132b7c0e54497a4d9a55a1c2a0912a0d786cf894472ba818fba45762" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -2423,7 +2480,7 @@ checksum = "62d671cc41a825ebabc75757b62d3d168c577f9149b2d49ece1dad1f72119d25" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -2436,7 +2493,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version 0.4.1", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -2456,10 +2513,16 @@ checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", "unicode-xid", ] +[[package]] +name = "difflib" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" + [[package]] name = "digest" version = "0.9.0" @@ -2531,7 +2594,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -2550,6 +2613,12 @@ dependencies = [ "zeroize", ] +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + [[package]] name = "docify" version = "0.2.9" @@ -2571,7 +2640,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.90", + "syn 2.0.96", "termcolor", "toml 0.8.19", "walkdir", @@ -2583,6 +2652,19 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" +[[package]] +name = "downloader" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ac1e888d6830712d565b2f3a974be3200be9296bc1b03db8251a4cbf18a4a34" +dependencies = [ + "futures", + "rand", + "reqwest", + "thiserror 1.0.69", + "tokio", +] + [[package]] name = "dunce" version = "1.0.5" @@ -2679,7 +2761,7 @@ dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -2731,7 +2813,7 @@ checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -2751,7 +2833,7 @@ checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -2762,7 +2844,7 @@ checksum = "2f9ed6b3789237c8a0c1c505af1c7eb2c560df6186f01b098c3a1064ea532f38" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -2853,7 +2935,7 @@ dependencies = [ "prettyplease", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -2985,6 +3067,16 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "flate2" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + [[package]] name = "fnv" version = "1.0.7" @@ -2997,6 +3089,21 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + [[package]] name = "form_urlencoded" version = "1.2.1" @@ -3066,7 +3173,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -3202,7 +3309,7 @@ dependencies = [ "proc-macro2", "quote", "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk?rev=243b751abbb94369bbd92c83d8ab159ddfc3c556)", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -3214,7 +3321,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -3224,7 +3331,7 @@ source = "git+https://github.com/paritytech/polkadot-sdk?rev=243b751abbb94369bbd dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -3291,6 +3398,12 @@ dependencies = [ "autocfg", ] +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + [[package]] name = "funty" version = "2.0.0" @@ -3354,7 +3467,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -3471,15 +3584,37 @@ version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b903b73e45dc0c6c596f2d37eccece7c1c8bb6e4407b001096387c63d0d93724" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.7.0", "libc", "libgit2-sys", "log", - "openssl-probe", - "openssl-sys", "url", ] +[[package]] +name = "globset" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15f1ce686646e7f1e19bf7d5533fe443a45dbfb990e00629110797578b42fb19" +dependencies = [ + "aho-corasick", + "bstr", + "log", + "regex-automata 0.4.9", + "regex-syntax 0.8.5", +] + +[[package]] +name = "globwalk" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf760ebf69878d9fd8f110c89703d90ce35095324d1f1edcb595c63945ee757" +dependencies = [ + "bitflags 2.7.0", + "ignore", + "walkdir", +] + [[package]] name = "group" version = "0.13.0" @@ -3654,12 +3789,106 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "http" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +dependencies = [ + "bytes", + "futures-util", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" + [[package]] name = "humantime" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +[[package]] +name = "hyper" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "256fb8d4bd6413123cc9d91832d78325c48ff41677595be797d90f42969beae0" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + [[package]] name = "iced-x86" version = "1.21.0" @@ -3784,7 +4013,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -3814,6 +4043,22 @@ dependencies = [ "icu_properties", ] +[[package]] +name = "ignore" +version = "0.4.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d89fd380afde86567dfba715db065673989d6253f42b88179abd3eae47bda4b" +dependencies = [ + "crossbeam-deque", + "globset", + "log", + "memchr", + "regex-automata 0.4.9", + "same-file", + "walkdir", + "winapi-util", +] + [[package]] name = "impl-codec" version = "0.6.0" @@ -3869,7 +4114,7 @@ checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -3940,7 +4185,7 @@ source = "git+https://github.com/TheDan64/inkwell.git?rev=7b410298b6a93450adaa90 dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -3972,6 +4217,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "ipnet" +version = "2.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" + [[package]] name = "is-terminal" version = "0.4.13" @@ -4113,9 +4364,7 @@ checksum = "10472326a8a6477c3c20a64547b0059e4b0d086869eee31e6d7da728a8eb7224" dependencies = [ "cc", "libc", - "libssh2-sys", "libz-sys", - "openssl-sys", "pkg-config", ] @@ -4141,7 +4390,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.7.0", "libc", "redox_syscall", ] @@ -4194,25 +4443,11 @@ dependencies = [ "libsecp256k1-core", ] -[[package]] -name = "libssh2-sys" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dc8a030b787e2119a731f1951d6a773e2280c660f8ec4b0f5e1505a386e71ee" -dependencies = [ - "cc", - "libc", - "libz-sys", - "openssl-sys", - "pkg-config", - "vcpkg", -] - [[package]] name = "libz-sys" -version = "1.1.20" +version = "1.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2d16453e800a8cf6dd2fc3eb4bc99b786a9b90c663b8559a5b1a041bf89e472" +checksum = "df9b68e50e6e0b26f672573834882eb57759f6db9b3be2ea3c35c91188bb4eaa" dependencies = [ "cc", "libc", @@ -4246,9 +4481,9 @@ checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" [[package]] name = "linux-raw-sys" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "litemap" @@ -4262,6 +4497,7 @@ version = "0.1.0-dev.7" dependencies = [ "cc", "libc", + "revive-build-utils", ] [[package]] @@ -4312,7 +4548,7 @@ dependencies = [ "macro_magic_core", "macro_magic_macros", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -4326,7 +4562,7 @@ dependencies = [ "macro_magic_core_macros", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -4337,7 +4573,7 @@ checksum = "b02abfe41815b5bd98dbd4260173db2c116dda171dc0fe7838cb206333b83308" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -4348,7 +4584,7 @@ checksum = "73ea28ee64b88876bf45277ed9a5817c1817df061a74f2b988971a12570e5869" dependencies = [ "macro_magic_core", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -4388,7 +4624,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2cffa4ad52c6f791f4f8b15f0c05f9824b2ced1160e88cc393d64fff9a8ac64" dependencies = [ - "rustix 0.38.42", + "rustix 0.38.43", ] [[package]] @@ -4430,6 +4666,12 @@ dependencies = [ "libmimalloc-sys", ] +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + [[package]] name = "miniz_oxide" version = "0.8.2" @@ -4439,6 +4681,17 @@ dependencies = [ "adler2", ] +[[package]] +name = "mio" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.52.0", +] + [[package]] name = "multi-stash" version = "0.2.0" @@ -4460,6 +4713,23 @@ dependencies = [ "typenum", ] +[[package]] +name = "native-tls" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + [[package]] name = "nohash-hasher" version = "0.2.0" @@ -4523,7 +4793,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -4601,9 +4871,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.5" +version = "0.36.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" dependencies = [ "memchr", ] @@ -4626,6 +4896,32 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" +[[package]] +name = "openssl" +version = "0.10.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" +dependencies = [ + "bitflags 2.7.0", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + [[package]] name = "openssl-probe" version = "0.1.5" @@ -5208,7 +5504,7 @@ source = "git+https://github.com/paritytech/polkadot-sdk?rev=243b751abbb94369bbd dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -5959,7 +6255,7 @@ source = "git+https://github.com/paritytech/polkadot-sdk?rev=243b751abbb94369bbd dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -6683,15 +6979,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b7cafe60d6cf8e62e1b9b2ea516a089c008945bb5a275416789e7db0bc199dc" dependencies = [ "memchr", - "thiserror 2.0.8", + "thiserror 2.0.11", "ucd-trie", ] [[package]] name = "pin-project-lite" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "pin-utils" @@ -7240,14 +7536,14 @@ dependencies = [ [[package]] name = "polkavm-derive-impl" -version = "0.18.0" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12d2840cc62a0550156b1676fed8392271ddf2fab4a00661db56231424674624" +checksum = "2f2116a92e6e96220a398930f4c8a6cda1264206f3e2034fc9982bfd93f261f7" dependencies = [ "polkavm-common", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -7257,7 +7553,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c16669ddc7433e34c1007d31080b80901e3e8e523cb9d4b441c3910cf9294b" dependencies = [ "polkavm-derive-impl", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -7283,7 +7579,7 @@ dependencies = [ "gimli 0.31.1", "hashbrown 0.14.5", "log", - "object 0.36.5", + "object 0.36.7", "polkavm-common", "regalloc2 0.9.3", "rustc-demangle", @@ -7333,14 +7629,41 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "predicates" +version = "3.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5d19ee57562043d37e82899fade9a22ebab7be9cef5026b07fda9cdd4293573" +dependencies = [ + "anstyle", + "difflib", + "predicates-core", +] + +[[package]] +name = "predicates-core" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "727e462b119fe9c93fd0eb1429a5f7647394014cf3c04ab2c0350eeb09095ffa" + +[[package]] +name = "predicates-tree" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72dd2d6d381dfb73a193c7fca536518d7caee39fc8503f74e7dc0be0531b425c" +dependencies = [ + "predicates-core", + "termtree", +] + [[package]] name = "prettyplease" -version = "0.2.25" +version = "0.2.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" +checksum = "924b9a625d6df5b74b0b3cfbb5669b3f62ddf3d46a677ce12b1945471b4ae5c3" dependencies = [ "proc-macro2", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -7421,7 +7744,7 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -7432,14 +7755,14 @@ checksum = "834da187cfe638ae8abb0203f0b33e5ccdb02a28e7199f2f47b3e2754f50edca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] name = "proc-macro2" -version = "1.0.92" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" dependencies = [ "unicode-ident", ] @@ -7452,7 +7775,7 @@ checksum = "b4c2511913b88df1637da85cc8d96ec8e43a3f8bb8ccb71ee1ac240d6f3df58d" dependencies = [ "bit-set", "bit-vec", - "bitflags 2.6.0", + "bitflags 2.7.0", "lazy_static", "num-traits", "rand", @@ -7481,9 +7804,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" dependencies = [ "proc-macro2", ] @@ -7566,7 +7889,7 @@ version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.7.0", ] [[package]] @@ -7597,7 +7920,7 @@ checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -7675,6 +7998,46 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +[[package]] +name = "reqwest" +version = "0.12.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43e734407157c3c2034e0258f5e4473ddb361b1e85f95a66690d67264d7cd1da" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-core", + "futures-util", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-tls", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-native-tls", + "tower", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows-registry", +] + [[package]] name = "revive-benchmarks" version = "0.1.0-dev.7" @@ -7687,9 +8050,16 @@ dependencies = [ "revive-runner", ] +[[package]] +name = "revive-build-utils" +version = "0.1.0-dev.7" + [[package]] name = "revive-builtins" version = "0.1.0-dev.7" +dependencies = [ + "revive-build-utils", +] [[package]] name = "revive-common" @@ -7749,6 +8119,29 @@ dependencies = [ "tempfile", ] +[[package]] +name = "revive-llvm-builder" +version = "0.1.0-dev.7" +dependencies = [ + "anyhow", + "assert_cmd", + "assert_fs", + "clap", + "downloader", + "env_logger", + "flate2", + "fs_extra", + "http", + "log", + "num_cpus", + "once_cell", + "path-slash", + "regex", + "serde", + "tar", + "toml 0.8.19", +] + [[package]] name = "revive-llvm-context" version = "0.1.0-dev.7" @@ -7795,6 +8188,7 @@ version = "0.1.0-dev.7" dependencies = [ "anyhow", "inkwell", + "revive-build-utils", "revive-common", ] @@ -7832,6 +8226,7 @@ name = "revive-stdlib" version = "0.1.0-dev.7" dependencies = [ "inkwell", + "revive-build-utils", ] [[package]] @@ -8005,22 +8400,37 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.42" +version = "0.38.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" +checksum = "a78891ee6bf2340288408954ac787aa063d8e8817e9f53abb37c695c6d834ef6" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.7.0", "errno", "libc", - "linux-raw-sys 0.4.14", + "linux-raw-sys 0.4.15", "windows-sys 0.59.0", ] +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2bf47e6ff922db3825eb750c4e2ff784c6ff8fb9e13046ef6a1d1c5401b0b37" + [[package]] name = "rustversion" -version = "1.0.18" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" +checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" [[package]] name = "rusty-fork" @@ -8051,9 +8461,9 @@ dependencies = [ [[package]] name = "safe_arch" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3460605018fdc9612bce72735cba0d27efbcd9904780d44c7e3a9948f96148a" +checksum = "96b02de82ddbe1b636e6170c21be622223aea188ef2e139be0a5b219ec215323" dependencies = [ "bytemuck", ] @@ -8188,7 +8598,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -8216,7 +8626,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -8242,7 +8652,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -8271,11 +8681,20 @@ dependencies = [ "scale-type-resolver", ] +[[package]] +name = "schannel" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" +dependencies = [ + "windows-sys 0.59.0", +] + [[package]] name = "schnellru" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9a8ef13a93c54d20580de1e5c413e624e53121d42fc7e2c11d10ef7f8b02367" +checksum = "356285bbf17bea63d9e52e96bd18f039672ac92b55b8cb997d6162a2a37d1649" dependencies = [ "ahash", "cfg-if", @@ -8396,6 +8815,29 @@ dependencies = [ "zeroize", ] +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags 2.7.0", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "semver" version = "0.6.0" @@ -8449,9 +8891,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.216" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" dependencies = [ "serde_derive", ] @@ -8476,20 +8918,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.216" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] name = "serde_json" -version = "1.0.133" +version = "1.0.135" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" +checksum = "2b0d7ba2887406110130a978386c4e1befb98c674b4fba677954e4db976630d9" dependencies = [ "itoa", "memchr", @@ -8516,6 +8958,18 @@ dependencies = [ "stacker", ] +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + [[package]] name = "serdect" version = "0.2.0" @@ -8965,6 +9419,16 @@ dependencies = [ "staging-xcm", ] +[[package]] +name = "socket2" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + [[package]] name = "sp-api" version = "26.0.0" @@ -8998,7 +9462,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -9238,7 +9702,7 @@ dependencies = [ [[package]] name = "sp-crypto-ec-utils" version = "0.10.0" -source = "git+https://github.com/paritytech/polkadot-sdk#4e805ca05067f6ed970f33f9be51483185b0cc0b" +source = "git+https://github.com/paritytech/polkadot-sdk#738282a2c4127f5e6a1c8d50235ba126b9f05025" dependencies = [ "ark-bls12-377", "ark-bls12-377-ext", @@ -9289,7 +9753,7 @@ source = "git+https://github.com/paritytech/polkadot-sdk?rev=243b751abbb94369bbd dependencies = [ "quote", "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk?rev=243b751abbb94369bbd92c83d8ab159ddfc3c556)", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -9299,17 +9763,17 @@ source = "git+https://github.com/paritytech/polkadot-sdk?rev=243b751abbb94369bbd dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] name = "sp-debug-derive" version = "14.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#4e805ca05067f6ed970f33f9be51483185b0cc0b" +source = "git+https://github.com/paritytech/polkadot-sdk#738282a2c4127f5e6a1c8d50235ba126b9f05025" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -9325,7 +9789,7 @@ dependencies = [ [[package]] name = "sp-externalities" version = "0.25.0" -source = "git+https://github.com/paritytech/polkadot-sdk#4e805ca05067f6ed970f33f9be51483185b0cc0b" +source = "git+https://github.com/paritytech/polkadot-sdk#738282a2c4127f5e6a1c8d50235ba126b9f05025" dependencies = [ "environmental", "parity-scale-codec", @@ -9534,7 +9998,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface" version = "24.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#4e805ca05067f6ed970f33f9be51483185b0cc0b" +source = "git+https://github.com/paritytech/polkadot-sdk#738282a2c4127f5e6a1c8d50235ba126b9f05025" dependencies = [ "bytes", "impl-trait-for-tuples", @@ -9560,20 +10024,20 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] name = "sp-runtime-interface-proc-macro" version = "17.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#4e805ca05067f6ed970f33f9be51483185b0cc0b" +source = "git+https://github.com/paritytech/polkadot-sdk#738282a2c4127f5e6a1c8d50235ba126b9f05025" dependencies = [ "Inflector", "expander", "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -9655,7 +10119,7 @@ source = "git+https://github.com/paritytech/polkadot-sdk?rev=243b751abbb94369bbd [[package]] name = "sp-std" version = "14.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#4e805ca05067f6ed970f33f9be51483185b0cc0b" +source = "git+https://github.com/paritytech/polkadot-sdk#738282a2c4127f5e6a1c8d50235ba126b9f05025" [[package]] name = "sp-storage" @@ -9672,7 +10136,7 @@ dependencies = [ [[package]] name = "sp-storage" version = "19.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#4e805ca05067f6ed970f33f9be51483185b0cc0b" +source = "git+https://github.com/paritytech/polkadot-sdk#738282a2c4127f5e6a1c8d50235ba126b9f05025" dependencies = [ "impl-serde", "parity-scale-codec", @@ -9707,7 +10171,7 @@ dependencies = [ [[package]] name = "sp-tracing" version = "16.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#4e805ca05067f6ed970f33f9be51483185b0cc0b" +source = "git+https://github.com/paritytech/polkadot-sdk#738282a2c4127f5e6a1c8d50235ba126b9f05025" dependencies = [ "parity-scale-codec", "tracing", @@ -9786,7 +10250,7 @@ dependencies = [ "proc-macro-warning", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -9804,7 +10268,7 @@ dependencies = [ [[package]] name = "sp-wasm-interface" version = "20.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#4e805ca05067f6ed970f33f9be51483185b0cc0b" +source = "git+https://github.com/paritytech/polkadot-sdk#738282a2c4127f5e6a1c8d50235ba126b9f05025" dependencies = [ "anyhow", "impl-trait-for-tuples", @@ -10036,7 +10500,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -10163,9 +10627,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.90" +version = "2.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" +checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" dependencies = [ "proc-macro2", "quote", @@ -10174,14 +10638,23 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "0.8.15" +version = "0.8.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "219389c1ebe89f8333df8bdfb871f6631c552ff399c23cac02480b6088aad8f0" +checksum = "31e89d8bf2768d277f40573c83a02a099e96d96dd3104e13ea676194e61ac4b0" dependencies = [ "paste", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", ] [[package]] @@ -10192,7 +10665,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -10201,6 +10674,17 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" +[[package]] +name = "tar" +version = "0.4.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c65998313f8e17d0d553d28f91a0df93e4dbbbf770279c7bc21ca0f09ea1a1f6" +dependencies = [ + "filetime", + "libc", + "xattr", +] + [[package]] name = "target-lexicon" version = "0.12.16" @@ -10209,14 +10693,15 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "tempfile" -version = "3.14.0" +version = "3.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" +checksum = "9a8a559c81686f576e8cd0290cd2a24a2a9ad80c98b3478856500fcbd7acd704" dependencies = [ "cfg-if", "fastrand", + "getrandom", "once_cell", - "rustix 0.38.42", + "rustix 0.38.43", "windows-sys 0.59.0", ] @@ -10229,6 +10714,12 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "termtree" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683" + [[package]] name = "testnet-parachains-constants" version = "1.0.0" @@ -10255,11 +10746,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.8" +version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f5383f3e0071702bf93ab5ee99b52d26936be9dedd9413067cbdcddcb6141a" +checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc" dependencies = [ - "thiserror-impl 2.0.8", + "thiserror-impl 2.0.11", ] [[package]] @@ -10270,18 +10761,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] name = "thiserror-impl" -version = "2.0.8" +version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f357fcec90b3caef6623a099691be676d033b40a058ac95d2a6ade6fa0c943" +checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -10356,9 +10847,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.8.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +checksum = "022db8904dfa342efe721985167e9fcd16c29b226db4397ed752a761cfce81e8" dependencies = [ "tinyvec_macros", ] @@ -10369,6 +10860,31 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" +[[package]] +name = "tokio" +version = "1.43.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2", + "windows-sys 0.52.0", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + [[package]] name = "toml" version = "0.5.11" @@ -10412,6 +10928,33 @@ dependencies = [ "winnow", ] +[[package]] +name = "tower" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + [[package]] name = "tracing" version = "0.1.41" @@ -10432,7 +10975,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -10496,6 +11039,12 @@ dependencies = [ "hash-db", ] +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + [[package]] name = "tt-call" version = "1.0.9" @@ -10695,6 +11244,15 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -10722,10 +11280,23 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", "wasm-bindgen-shared", ] +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38176d9b44ea84e9184eff0bc34cc167ed044f816accfe5922e54d84cf48eca2" +dependencies = [ + "cfg-if", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "wasm-bindgen-macro" version = "0.2.99" @@ -10744,7 +11315,7 @@ checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -11093,15 +11664,15 @@ dependencies = [ "either", "home", "once_cell", - "rustix 0.38.42", + "rustix 0.38.43", "windows-sys 0.48.0", ] [[package]] name = "wide" -version = "0.7.30" +version = "0.7.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58e6db2670d2be78525979e9a5f9c69d296fd7d670549fe9ebf70f8708cb5019" +checksum = "41b5576b9a81633f3e8df296ce0063042a73507636cbe956c61133dd7034ab22" dependencies = [ "bytemuck", "safe_arch", @@ -11138,6 +11709,36 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result", + "windows-strings", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets 0.52.6", +] + [[package]] name = "windows-sys" version = "0.45.0" @@ -11354,9 +11955,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.20" +version = "0.6.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +checksum = "c8d71a593cc5c42ad7876e2c1fda56f314f3754c084128833e64f1345ff8a03a" dependencies = [ "memchr", ] @@ -11394,6 +11995,17 @@ dependencies = [ "zeroize", ] +[[package]] +name = "xattr" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e105d177a3871454f754b33bb0ee637ecaaac997446375fd3e5d43a2ed00c909" +dependencies = [ + "libc", + "linux-raw-sys 0.4.15", + "rustix 0.38.43", +] + [[package]] name = "xcm-procedural" version = "7.0.0" @@ -11402,7 +12014,7 @@ dependencies = [ "Inflector", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -11461,7 +12073,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", "synstructure", ] @@ -11483,7 +12095,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -11503,7 +12115,7 @@ checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", "synstructure", ] @@ -11524,7 +12136,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -11546,7 +12158,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 0db12d0d..6a2d9894 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,7 @@ revive-runtime-api = { version = "0.1.0-dev.7", path = "crates/runtime-api" } revive-runner = { version = "0.1.0-dev.7", path = "crates/runner" } revive-solidity = { version = "0.1.0-dev.7", path = "crates/solidity" } revive-stdlib = { version = "0.1.0-dev.7", path = "crates/stdlib" } +revive-build-utils = { version = "0.1.0-dev.7", path = "crates/build-utils" } hex = "0.4" petgraph = "0.6" @@ -63,7 +64,16 @@ env_logger = { version = "0.10.0", default-features = false } serde_stacker = "0.1" criterion = { version = "0.5", features = ["html_reports"] } log = { version = "0.4" } -git2 = "0.19.0" +git2 = { version = "0.19.0", default-features = false } +downloader = "0.2.8" +flate2 = "1.0.35" +http = "1.2.0" +fs_extra = "1.3.0" +num_cpus = "1" +tar = "0.4.4" +toml = "0.8" +assert_cmd = "2.0.16" +assert_fs = "1.1.2" # polkadot-sdk and friends codec = { version = "3.6.12", default-features = false, package = "parity-scale-codec" } diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..23d1c9b2 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,32 @@ +FROM rust:1.84.0 AS llvm-builder +WORKDIR /opt/revive + +RUN apt update && \ + apt upgrade -y && \ + apt install -y cmake ninja-build curl git libssl-dev pkg-config clang lld musl + +COPY . . + +RUN make install-llvm-builder +RUN revive-llvm --target-env musl clone +RUN revive-llvm --target-env musl build + +FROM messense/rust-musl-cross:x86_64-musl AS resolc-builder +WORKDIR /opt/revive + +RUN apt update && \ + apt upgrade -y && \ + apt install -y pkg-config + +COPY . . +COPY --from=llvm-builder /opt/revive/target-llvm /opt/revive/target-llvm + +ENV LLVM_SYS_181_PREFIX=/opt/revive/target-llvm/musl/target-final +RUN make install-bin + +FROM alpine:latest +ADD https://github.com/ethereum/solidity/releases/download/v0.8.28/solc-static-linux /usr/bin/solc +COPY --from=resolc-builder /root/.cargo/bin/resolc /usr/bin/resolc + +RUN apk add --no-cache libc6-compat +RUN chmod +x /usr/bin/solc diff --git a/LLVM.lock b/LLVM.lock new file mode 100644 index 00000000..4e375734 --- /dev/null +++ b/LLVM.lock @@ -0,0 +1,2 @@ +url = "https://github.com/llvm/llvm-project.git" +branch = "release/18.x" \ No newline at end of file diff --git a/Makefile b/Makefile index df875de3..d1085a17 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: install format test test-solidity test-cli test-integration test-workspace test-wasm clean docs docs-build +.PHONY: install format test test-solidity test-cli test-integration test-workspace test-wasm clean install-llvm install-llvm-builder RUSTFLAGS_EMSCRIPTEN := \ -C link-arg=-sEXPORTED_FUNCTIONS=_main,_free,_malloc \ @@ -28,16 +28,16 @@ install-npm: install-wasm: install-npm RUSTFLAGS='$(RUSTFLAGS_EMSCRIPTEN)' cargo build --target wasm32-unknown-emscripten -p revive-solidity --release --no-default-features +install-llvm-builder: + cargo install --path crates/llvm-builder + +install-llvm: install-llvm-builder + revive-llvm clone + revive-llvm build + test-wasm: install-wasm npm run test:wasm -# install-revive: Build and install to the directory specified in REVIVE_INSTALL_DIR -ifeq ($(origin REVIVE_INSTALL_DIR), undefined) -REVIVE_INSTALL_DIR=`pwd`/release/revive-debian -endif -install-revive: - cargo install --path crates/solidity --root $(REVIVE_INSTALL_DIR) - format: cargo fmt --all --check @@ -53,11 +53,15 @@ test-solidity: install cargo test --package revive-solidity test-workspace: install - cargo test --workspace + cargo test --workspace --exclude revive-llvm-builder test-cli: install npm run test:cli +test-llvm-builder: + @echo "warning: the llvm-builder tests will take many hours" + cargo test --package revive-llvm-builder -- --test-threads=1 + bench-pvm: install-bin cargo criterion --bench execute --features bench-pvm-interpreter --message-format=json \ | criterion-table > crates/benchmarks/PVM.md @@ -72,9 +76,11 @@ bench: install-bin clean: cargo clean ; \ + revive-llvm clean ; \ rm -rf node_modules ; \ rm -rf crates/solidity/src/tests/cli-tests/artifacts ; \ cargo uninstall revive-solidity ; \ + cargo uninstall revive-llvm-builder ; \ rm -f package-lock.json ; \ rm -rf js/dist ; \ rm -f js/src/resolc.{wasm,js} diff --git a/README.md b/README.md index 745afd4a..940538b8 100644 --- a/README.md +++ b/README.md @@ -21,34 +21,40 @@ Building from source requires a compatible LLVM build. ### LLVM -`revive` requires a build of LLVM 18.1.4 or later with the RISC-V _embedded_ target, including `compiler-rt`. Use the provided [build-llvm.sh](build-llvm.sh) build script to compile a compatible LLVM build locally in `$PWD/llvm18.0` (don't forget to add that to `$PATH` afterwards). +`revive` requires a build of LLVM v18.1.8 with the RISC-V _embedded_ target, including `compiler-rt`. Use the provided [revive-llvm](crates/llvm-builder/README.md) utility to compile a compatible LLVM build locally and point `$LLVM_SYS_181_PREFIX` to the installation directory afterwards. ### The `resolc` Solidity frontend To install the `resolc` Solidity frontend executable: ```bash -bash build-llvm.sh -export PATH=${PWD}/llvm18.0/bin:$PATH +# Build the host LLVM dependency with PolkaVM target support +make install-llvm +export LLVM_SYS_181_PREFIX=${PWD}/target-llvm/gnu/target-final + +# Build the resolc frontend executable make install-bin resolc --version ``` -### Cross-compilation to WASM -Cross-compiles the Revive compiler to WASM for running it in a Node.js or browser environment. +### Cross-compilation to WASM -Install [emscripten](https://emscripten.org/docs/getting_started/downloads.html). Tested on version 3.1.64. -To build resolc.js execute: +Cross-compile resolc.js frontend executable to Wasm for running it in a Node.js or browser environment. The `REVIVE_LLVM_TARGET_PREFIX` environment variable is used to control the target environment LLVM dependency. ```bash -bash build-llvm.sh -export PATH=${PWD}/llvm18.0/bin:$PATH -export EMSDK_ROOT= -bash emscripten-build-llvm.sh -source $EMSDK_ROOT/emsdk_env.sh -export LLVM_LINK_PREFIX=${PWD}/llvm18.0-emscripten -export PATH=$PATH:$PWD/llvm18.0-emscripten/bin/ +# Build the host LLVM dependency with PolkaVM target support +make install-llvm +export LLVM_SYS_181_PREFIX=${PWD}/target-llvm/gnu/target-final + +# Build the target LLVM dependency with PolkaVM target support +revive-llvm --target-env emscripten clone +source emsdk/emsdk_env.sh +revive-llvm --target-env emscripten build +export REVIVE_LLVM_TARGET_PREFIX=${PWD}/target-llvm/emscripten/target-final + +# Build the resolc frontend executable make install-wasm +make test-wasm ``` ### Development diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000..50de6ef8 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1 @@ +https://github.com/paritytech/polkadot-sdk/blob/master/docs/contributor/SECURITY.md \ No newline at end of file diff --git a/build-llvm.sh b/build-llvm.sh deleted file mode 100755 index 26ba75a2..00000000 --- a/build-llvm.sh +++ /dev/null @@ -1,88 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -INSTALL_DIR="${PWD}/llvm18.0" -mkdir -p ${INSTALL_DIR} - -# Build LLVM, clang -LLVM_SRC_PREFIX=${PWD}/llvm-project -LLVM_SRC_DIR=${LLVM_SRC_PREFIX}/llvm -LLVM_BUILD_DIR=${PWD}/build/llvm - -./clone-llvm.sh "${LLVM_SRC_PREFIX}" - -if [ ! -d ${LLVM_BUILD_DIR} ] ; then - mkdir -p ${LLVM_BUILD_DIR} -fi - -cmake -G Ninja \ - -S ${LLVM_SRC_DIR} \ - -B ${LLVM_BUILD_DIR} \ - -DLLVM_ENABLE_ASSERTIONS=On \ - -DLLVM_ENABLE_TERMINFO=Off \ - -DLLVM_ENABLE_LIBXML2=Off \ - -DLLVM_ENABLE_ZLIB=Off \ - -DLLVM_ENABLE_PROJECTS='clang;lld' \ - -DLLVM_TARGETS_TO_BUILD='RISCV' \ - -DLLVM_ENABLE_ZSTD=Off \ - -DCMAKE_BUILD_TYPE=MinSizeRel \ - -DCMAKE_INSTALL_PREFIX=${INSTALL_DIR} - -cmake --build ${LLVM_BUILD_DIR} -cmake --install ${LLVM_BUILD_DIR} - -# Build compiler builtins -COMPILER_RT_SRC_DIR=${LLVM_SRC_PREFIX}/compiler-rt -COMPILER_RT_BUILD_DIR=${PWD}/build/compiler-rt -if [ ! -d ${COMPILER_RT_BUILD_DIR} ] ; then - mkdir -p ${COMPILER_RT_BUILD_DIR} -fi - -build_compiler_rt() { - case "$1" in - 64) TARGET_ABI=lp64e ;; - 32) TARGET_ABI=ilp32e ;; - *) exit -1 - esac - CFLAGS="--target=riscv${1} -march=rv${1}em -mabi=${TARGET_ABI} -mcpu=generic-rv${1} -nostdlib -nodefaultlibs" - - cmake -G Ninja \ - -S ${COMPILER_RT_SRC_DIR} \ - -B ${COMPILER_RT_BUILD_DIR} \ - -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_INSTALL_PREFIX=${INSTALL_DIR} \ - -DCOMPILER_RT_BUILD_BUILTINS=ON \ - -DCOMPILER_RT_BUILD_LIBFUZZER=OFF \ - -DCOMPILER_RT_BUILD_MEMPROF=OFF \ - -DCOMPILER_RT_BUILD_PROFILE=OFF \ - -DCOMPILER_RT_BUILD_SANITIZERS=OFF \ - -DCOMPILER_RT_BUILD_XRAY=OFF \ - -DCMAKE_C_COMPILER=${INSTALL_DIR}/bin/clang \ - -DCMAKE_C_COMPILER_TARGET=riscv${1} \ - -DCMAKE_ASM_COMPILER_TARGET=riscv${1} \ - -DCMAKE_CXX_COMPILER_TARGET=riscv${1} \ - -DCMAKE_C_TARGET_BITS=riscv${1} \ - -DCMAKE_ASM_TARGET_BITS=riscv${1} \ - -DCMAKE_AR=${INSTALL_DIR}/bin/llvm-ar \ - -DCMAKE_NM=${INSTALL_DIR}/bin/llvm-nm \ - -DCMAKE_RANLIB=${INSTALL_DIR}/bin/llvm-ranlib \ - -DCOMPILER_RT_BAREMETAL_BUILD=ON \ - -DLLVM_CONFIG_PATH=${INSTALL_DIR}/bin/llvm-config \ - -DCMAKE_C_FLAGS="${CFLAGS}" \ - -DCMAKE_ASM_FLAGS="${CFLAGS}" \ - -DCOMPILER_RT_TEST_COMPILER=${INSTALL_DIR}/bin/clang \ - -DCMAKE_CXX_FLAGS="${CFLAGS}" \ - -DCMAKE_SYSTEM_NAME=unknown \ - -DCOMPILER_RT_DEFAULT_TARGET_ONLY=ON - - cmake --build ${COMPILER_RT_BUILD_DIR} - cmake --install ${COMPILER_RT_BUILD_DIR} -} - -build_compiler_rt 32 -build_compiler_rt 64 - -echo "" -echo "success" -echo "add this directory to your PATH: ${INSTALL_DIR}/bin/" diff --git a/crates/build-utils/.gitignore b/crates/build-utils/.gitignore new file mode 100644 index 00000000..6ee06a19 --- /dev/null +++ b/crates/build-utils/.gitignore @@ -0,0 +1,14 @@ +# Generated by Cargo +# will have compiled files and executables +/target/ + +# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries +# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html +Cargo.lock + +# These are backup files generated by rustfmt +**/*.rs.bk + +# IDE +/.idea/ +/.vscode/ diff --git a/crates/build-utils/Cargo.toml b/crates/build-utils/Cargo.toml new file mode 100644 index 00000000..edcf97a3 --- /dev/null +++ b/crates/build-utils/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "revive-build-utils" +version.workspace = true +license.workspace = true +edition.workspace = true +repository.workspace = true +authors = [ + "Cyrill Leutwiler ", +] +description = "Shared build utilities of the revive compiler" + +[lib] +doctest = false + +[dependencies] diff --git a/crates/build-utils/README.md b/crates/build-utils/README.md new file mode 100644 index 00000000..6eb27ae8 --- /dev/null +++ b/crates/build-utils/README.md @@ -0,0 +1,10 @@ +# revive: Compiler Common + +## License + +This library is distributed under the terms of either + +- Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or ) +- MIT license ([LICENSE-MIT](LICENSE-MIT) or ) + +at your option. diff --git a/crates/build-utils/src/lib.rs b/crates/build-utils/src/lib.rs new file mode 100644 index 00000000..16a58433 --- /dev/null +++ b/crates/build-utils/src/lib.rs @@ -0,0 +1,48 @@ +//! The compiler build utilities library. + +/// The revive LLVM host dependency directory prefix environment variable. +pub const REVIVE_LLVM_HOST_PREFIX: &str = "LLVM_SYS_181_PREFIX"; + +/// The revive LLVM target dependency directory prefix environment variable. +pub const REVIVE_LLVM_TARGET_PREFIX: &str = "REVIVE_LLVM_TARGET_PREFIX"; + +/// Constructs a path to the LLVM tool `name`. +/// +/// Respects the [`REVIVE_LLVM_HOST_PREFIX`] environment variable. +pub fn llvm_host_tool(name: &str) -> std::path::PathBuf { + std::env::var_os(REVIVE_LLVM_HOST_PREFIX) + .map(Into::::into) + .unwrap_or_else(|| { + panic!( + "install LLVM using the revive-llvm builder and export {REVIVE_LLVM_HOST_PREFIX}", + ) + }) + .join("bin") + .join(name) +} + +/// Returns the LLVM lib dir. +/// +/// Respects the [`REVIVE_LLVM_HOST_PREFIX`] environment variable. +pub fn llvm_lib_dir() -> std::path::PathBuf { + std::path::PathBuf::from(llvm_config("--libdir").trim()) +} + +/// Returns the LLVM CXX compiler flags. +/// +/// Respects the [`REVIVE_LLVM_HOST_PREFIX`] environment variable. +pub fn llvm_cxx_flags() -> String { + llvm_config("--cxxflags") +} + +/// Execute the `llvm-config` utility respecting the [`REVIVE_LLVM_HOST_PREFIX`] environment variable. +fn llvm_config(arg: &str) -> String { + let llvm_config = llvm_host_tool("llvm-config"); + let output = std::process::Command::new(&llvm_config) + .arg(arg) + .output() + .unwrap_or_else(|error| panic!("`{} {arg}` failed: {error}", llvm_config.display())); + + String::from_utf8(output.stdout) + .unwrap_or_else(|_| panic!("output of `{} {arg}` should be utf8", llvm_config.display())) +} diff --git a/crates/builtins/Cargo.toml b/crates/builtins/Cargo.toml index dfb79bc3..f0ce56ca 100644 --- a/crates/builtins/Cargo.toml +++ b/crates/builtins/Cargo.toml @@ -8,4 +8,5 @@ authors.workspace = true build = "build.rs" description = "compiler builtins for the revive compiler" -[dependencies] +[build-dependencies] +revive-build-utils = { workspace = true } diff --git a/crates/builtins/build.rs b/crates/builtins/build.rs index 6078ffd3..b2a54f53 100644 --- a/crates/builtins/build.rs +++ b/crates/builtins/build.rs @@ -3,25 +3,32 @@ use std::{env, fs, io::Read, path::Path, process::Command}; pub const BUILTINS_ARCHIVE_FILE: &str = "libclang_rt.builtins-riscv64.a"; fn main() { - let mut llvm_lib_dir = String::new(); + println!( + "cargo:rerun-if-env-changed={}", + revive_build_utils::REVIVE_LLVM_HOST_PREFIX + ); - Command::new("llvm-config") - .args(["--libdir"]) + let llvm_config = revive_build_utils::llvm_host_tool("llvm-config"); + let mut llvm_lib_dir = String::new(); + Command::new(&llvm_config) + .arg("--libdir") .output() - .expect("llvm-config should be able to provide LD path") + .unwrap_or_else(|_| { + panic!( + "{} should be able to provide LD path", + llvm_config.display() + ) + }) .stdout .as_slice() .read_to_string(&mut llvm_lib_dir) .expect("llvm-config output should be utf8"); - let mut lib_path = std::path::PathBuf::from(llvm_lib_dir.trim()) - .join("linux") + let lib_path = revive_build_utils::llvm_lib_dir() + .join("unknown") .join(BUILTINS_ARCHIVE_FILE); - if !lib_path.exists() { - lib_path = std::path::PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap()) - .join(BUILTINS_ARCHIVE_FILE); - } - let archive = fs::read(lib_path).expect("clang builtins not found"); + let archive = fs::read(&lib_path).expect("clang builtins not found"); + println!("cargo:rerun-if-env-changed={}", lib_path.display()); let out_dir = env::var_os("OUT_DIR").expect("has OUT_DIR"); let archive_path = Path::new(&out_dir).join(BUILTINS_ARCHIVE_FILE); diff --git a/crates/builtins/libclang_rt.builtins-riscv32.a b/crates/builtins/libclang_rt.builtins-riscv32.a deleted file mode 100644 index f13a8848..00000000 Binary files a/crates/builtins/libclang_rt.builtins-riscv32.a and /dev/null differ diff --git a/crates/builtins/libclang_rt.builtins-riscv64.a b/crates/builtins/libclang_rt.builtins-riscv64.a deleted file mode 100644 index 57a7d970..00000000 Binary files a/crates/builtins/libclang_rt.builtins-riscv64.a and /dev/null differ diff --git a/crates/lld-sys/Cargo.toml b/crates/lld-sys/Cargo.toml index abefef76..93e0444e 100644 --- a/crates/lld-sys/Cargo.toml +++ b/crates/lld-sys/Cargo.toml @@ -13,3 +13,4 @@ libc = { workspace = true } [build-dependencies] cc = { workspace = true } +revive-build-utils = { workspace = true } diff --git a/crates/lld-sys/build.rs b/crates/lld-sys/build.rs index 27a1a988..c8d82523 100644 --- a/crates/lld-sys/build.rs +++ b/crates/lld-sys/build.rs @@ -1,34 +1,16 @@ -use std::{ - env, - path::{Path, PathBuf}, -}; +fn set_rustc_link_flags() { + let llvm_lib_path = match std::env::var(revive_build_utils::REVIVE_LLVM_TARGET_PREFIX) { + Ok(path) => std::path::PathBuf::from(path).join("lib"), + _ => revive_build_utils::llvm_lib_dir(), + }; -const LLVM_LINK_PREFIX: &str = "LLVM_LINK_PREFIX"; - -fn locate_llvm_config() -> PathBuf { - let prefix = env::var_os(LLVM_LINK_PREFIX) - .map(|p| PathBuf::from(p).join("bin")) - .unwrap_or_default(); - prefix.join("llvm-config") -} - -fn llvm_config(llvm_config_path: &Path, arg: &str) -> String { - let output = std::process::Command::new(llvm_config_path) - .args([arg]) - .output() - .unwrap_or_else(|_| panic!("`llvm-config {arg}` failed")); - - String::from_utf8(output.stdout) - .unwrap_or_else(|_| panic!("output of `llvm-config {arg}` should be utf8")) -} - -fn set_rustc_link_flags(llvm_config_path: &Path) { println!( "cargo:rustc-link-search=native={}", - llvm_config(llvm_config_path, "--libdir") + llvm_lib_path.to_string_lossy() ); for lib in [ + // These are required by ld.lld "lldELF", "lldCommon", "lldMachO", @@ -91,18 +73,27 @@ fn set_rustc_link_flags(llvm_config_path: &Path) { } let target_os = std::env::var("CARGO_CFG_TARGET_OS").unwrap_or_default(); + let target_env = std::env::var("CARGO_CFG_TARGET_ENV").unwrap_or_default(); if target_os == "linux" { - println!("cargo:rustc-link-lib=dylib=stdc++"); - println!("cargo:rustc-link-lib=tinfo"); + if target_env == "musl" { + println!("cargo:rustc-link-lib=static=c++"); + } else { + println!("cargo:rustc-link-lib=dylib=stdc++"); + } } } fn main() { - println!("cargo:rerun-if-env-changed={}", LLVM_LINK_PREFIX); - - let llvm_config_path = locate_llvm_config(); + println!( + "cargo:rerun-if-env-changed={}", + revive_build_utils::REVIVE_LLVM_HOST_PREFIX + ); + println!( + "cargo:rerun-if-env-changed={}", + revive_build_utils::REVIVE_LLVM_TARGET_PREFIX + ); - llvm_config(&llvm_config_path, "--cxxflags") + revive_build_utils::llvm_cxx_flags() .split_whitespace() .fold(&mut cc::Build::new(), |builder, flag| builder.flag(flag)) .flag("-Wno-unused-parameter") @@ -110,7 +101,7 @@ fn main() { .file("src/linker.cpp") .compile("liblinker.a"); - set_rustc_link_flags(&llvm_config_path); + set_rustc_link_flags(); println!("cargo:rerun-if-changed=build.rs"); } diff --git a/crates/llvm-builder/Cargo.toml b/crates/llvm-builder/Cargo.toml new file mode 100644 index 00000000..7491fb06 --- /dev/null +++ b/crates/llvm-builder/Cargo.toml @@ -0,0 +1,40 @@ +[package] +name = "revive-llvm-builder" +description = "revive LLVM compiler framework builder" +authors = [ + "Oleksandr Zarudnyi ", + "Anton Baliasnikov ", + "Cyrill Leutwiler ", +] +version.workspace = true +license.workspace = true +edition.workspace = true +repository.workspace = true + +[[bin]] +name = "revive-llvm" +path = "src/revive_llvm/main.rs" + +[lib] +doctest = false + +[dependencies] +clap = { workspace = true, features = ["std", "derive"] } +anyhow = { workspace = true } +serde = { workspace = true, features = [ "derive" ] } +toml = { workspace = true } +num_cpus = { workspace = true } +fs_extra = { workspace = true } +path-slash = { workspace = true } +regex = { workspace = true } +downloader = { workspace = true } +tar = { workspace = true } +flate2 = { workspace = true } +http = { workspace = true } +env_logger = { workspace = true } +log = { workspace = true } +once_cell = { workspace = true } + +[dev-dependencies] +assert_cmd = { workspace = true } +assert_fs = { workspace = true } diff --git a/crates/llvm-builder/README.md b/crates/llvm-builder/README.md new file mode 100644 index 00000000..40be01ce --- /dev/null +++ b/crates/llvm-builder/README.md @@ -0,0 +1,132 @@ +# revive LLVM builder + +Parity fork of the [Matter Labs zksync LLVM builder](https://github.com/matter-labs/era-compiler-llvm-builder) helper utility for compiling [revive](https://github.com/paritytech/revive) compatible LLVM builds. + +## Installation and usage + +The LLVM compiler framework for revive must be built with our tool called `revive-llvm`. +This is because the revive compiler has requirements not fullfilled in upstream builds: +- Special builds for compiling the frontend into statically linked ELF binaries and also Wasm executables +- The RISC-V target (the PolkaVM target) +- The compiler-rt builtins for the PolkaVM target +- We want to leave the assertions always on +- Various other specific configurations and optimization may be applied + +Obtain a compatible build for your host platform from the release section of this repository (TODO). Alternatively follow below steps to get a custom build: + +
+1. Install the system prerequisites. + + * Linux (Debian): + + Install the following packages: + ```shell + apt install cmake ninja-build curl git libssl-dev pkg-config clang lld + ``` + * Linux (Arch): + + Install the following packages: + ```shell + pacman -Syu which cmake ninja curl git pkg-config clang lld + ``` + + * MacOS: + + * Install the [HomeBrew](https://brew.sh) package manager. + * Install the following packages: + + ```shell + brew install cmake ninja coreutils + ``` + + * Install your choice of a recent LLVM/[Clang](https://clang.llvm.org) compiler, e.g. via [Xcode](https://developer.apple.com/xcode/), [Apple’s Command Line Tools](https://developer.apple.com/library/archive/technotes/tn2339/_index.html), or your preferred package manager. +
+ +
+2. Install Rust. + + * Follow the latest [official instructions](https://www.rust-lang.org/tools/install: + ```shell + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh + . ${HOME}/.cargo/env + ``` + + > Currently we are not pinned to any specific version of Rust, so just install the latest stable build for your platform. +
+ +
+3. Install the revive LLVM framework builder. + + * Install the builder using `cargo`: + ```shell + cargo install --git https://github.com/paritytech/revive-llvm-builder --force --locked + ``` + + > The builder is not the LLVM framework itself, but a tool that clones its repository and runs a sequence of build commands. By default it is installed in `~/.cargo/bin/`, which is recommended to be added to your `$PATH`. + +
+ +
+4. (Optional) Create the `LLVM.lock` file. + + * The `LLVM.lock` dictates the LLVM source tree being used. + A default `./LLVM.lock` pointing to the release used for development is already provided. + +
+ +
+5. Build LLVM. + + * Clone and build the LLVM framework using the `revive-llvm` tool. + + The clang and lld projects are required for the `resolc` Solidity frontend executable; they are enabled by default. LLVM assertions are also enabled by default. + + ```shell + revive-llvm clone + revive-llvm build + ``` + + Build artifacts end up in the `./target-llvm/gnu/target-final/` directory by default. + The `gnu` directory depends on the supported archticture and will either be `gnu`, `musl` or `emscripten`. + You now need to export the final target directory `$LLVM_SYS_181_PREFIX`: `export LLVM_SYS_181_PREFIX=${PWD}/target-llvm/gnu/target-final` + If built with the `--enable-tests` option, test tools will be in the `./target-llvm/gnu/build-final/` directory, along with copies of the build artifacts. For all supported build options, run `revive-llvm build --help`. + +
+ +## Supported target architectures + +The following target platforms are supported: +- Linux GNU (x86) +- Linux MUSL (x86) +- MacOS (aarch64) +- Windows GNU (x86) +- Emscripten (wasm32) + +
+Building for MUSL + + * Via a musl build we can build revive into fully static ELF binaries. + Which is desirable for reproducible Solidity contracts builds. + The resulting binary is also very portable, akin to the`solc` frontend binary distribution. + + Clone and build the LLVM framework using the `revive-llvm` tool: + ```shell + revive-llvm --target-env musl clone + revive-llvm --target-env musl build --enable-assertions --llvm-projects clang --llvm-projects lld + ``` + +
+ +
+Building for Emscripten + + * Via an emsdk build we can run revive in the browser and on node.js. + + Clone and build the LLVM framework using the `revive-llvm` tool: + ```shell + revive-llvm --target-env emscripten clone + revive-llvm --target-env emscripten build --enable-assertions --llvm-projects clang --llvm-projects lld + ``` + +
+ diff --git a/crates/llvm-builder/src/build_type.rs b/crates/llvm-builder/src/build_type.rs new file mode 100644 index 00000000..0c4b5089 --- /dev/null +++ b/crates/llvm-builder/src/build_type.rs @@ -0,0 +1,39 @@ +//! The revive LLVM build type. + +/// The revive LLVM build type. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum BuildType { + /// The debug build. + Debug, + /// The release build. + Release, + /// The release with debug info build. + RelWithDebInfo, + /// The minimal size release build. + MinSizeRel, +} + +impl std::str::FromStr for BuildType { + type Err = String; + + fn from_str(value: &str) -> Result { + match value { + "Debug" => Ok(Self::Debug), + "Release" => Ok(Self::Release), + "RelWithDebInfo" => Ok(Self::RelWithDebInfo), + "MinSizeRel" => Ok(Self::MinSizeRel), + value => Err(format!("Unsupported build type: `{}`", value)), + } + } +} + +impl std::fmt::Display for BuildType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Debug => write!(f, "Debug"), + Self::Release => write!(f, "Release"), + Self::RelWithDebInfo => write!(f, "RelWithDebInfo"), + Self::MinSizeRel => write!(f, "MinSizeRel"), + } + } +} diff --git a/crates/llvm-builder/src/builtins.rs b/crates/llvm-builder/src/builtins.rs new file mode 100644 index 00000000..1f6231cd --- /dev/null +++ b/crates/llvm-builder/src/builtins.rs @@ -0,0 +1,137 @@ +//! Utilities for compiling the LLVM compiler-rt builtins. + +/// Static CFLAGS variable passed to the compiler building the compiler-rt builtins. +const C_FLAGS: [&str; 6] = [ + "--target=riscv64", + "-march=rv64emac", + "-mabi=lp64e", + "-mcpu=generic-rv64", + "-nostdlib", + "-nodefaultlibs", +]; + +/// Static CMAKE arguments for building the compiler-rt builtins. +const CMAKE_STATIC_ARGS: [&str; 14] = [ + "-DCOMPILER_RT_BUILD_BUILTINS='On'", + "-DCOMPILER_RT_BUILD_LIBFUZZER='Off'", + "-DCOMPILER_RT_BUILD_MEMPROF='Off'", + "-DCOMPILER_RT_BUILD_PROFILE='Off'", + "-DCOMPILER_RT_BUILD_SANITIZERS='Off'", + "-DCOMPILER_RT_BUILD_XRAY='Off'", + "-DCOMPILER_RT_DEFAULT_TARGET_ONLY='On'", + "-DCOMPILER_RT_BAREMETAL_BUILD='On'", + "-DCMAKE_BUILD_WITH_INSTALL_RPATH=1", + "-DCMAKE_EXPORT_COMPILE_COMMANDS='On'", + "-DCMAKE_SYSTEM_NAME='unknown'", + "-DCMAKE_C_COMPILER_TARGET='riscv64'", + "-DCMAKE_ASM_COMPILER_TARGET='riscv64'", + "-DCMAKE_CXX_COMPILER_TARGET='riscv64'", +]; + +/// Dynamic cmake arguments for building the compiler-rt builtins. +fn cmake_dynamic_args( + build_type: crate::BuildType, + target_env: crate::target_env::TargetEnv, +) -> anyhow::Result<[String; 13]> { + let llvm_compiler_rt_target = crate::LLVMPath::llvm_target_compiler_rt()?; + + // The Emscripten target needs to use the host LLVM tools. + let llvm_target_host = if target_env == crate::target_env::TargetEnv::Emscripten { + crate::LLVMPath::llvm_build_host()? + } else { + crate::LLVMPath::llvm_target_final()? + }; + + let mut clang_path = llvm_target_host.to_path_buf(); + clang_path.push("bin/clang"); + + let mut clangxx_path = llvm_target_host.to_path_buf(); + clangxx_path.push("bin/clang++"); + + let mut llvm_config_path = llvm_target_host.to_path_buf(); + llvm_config_path.push("bin/llvm-config"); + + let mut ar_path = llvm_target_host.to_path_buf(); + ar_path.push("bin/llvm-ar"); + + let mut nm_path = llvm_target_host.to_path_buf(); + nm_path.push("bin/llvm-nm"); + + let mut ranlib_path = llvm_target_host.to_path_buf(); + ranlib_path.push("bin/llvm-ranlib"); + + let mut linker_path = llvm_target_host.to_path_buf(); + linker_path.push("bin/ld.lld"); + + Ok([ + format!( + "-DCMAKE_INSTALL_PREFIX='{}'", + llvm_compiler_rt_target.to_string_lossy().as_ref(), + ), + format!("-DCMAKE_BUILD_TYPE='{build_type}'"), + format!( + "-DCOMPILER_RT_TEST_COMPILER='{}'", + clang_path.to_string_lossy() + ), + format!("-DCMAKE_C_FLAGS='{}'", C_FLAGS.join(" ")), + format!("-DCMAKE_ASM_FLAGS='{}'", C_FLAGS.join(" ")), + format!("-DCMAKE_CXX_FLAGS='{}'", C_FLAGS.join(" ")), + format!("-DCMAKE_C_COMPILER='{}'", clang_path.to_string_lossy()), + format!("-DCMAKE_ASM_COMPILER='{}'", clang_path.to_string_lossy()), + format!("-DCMAKE_CXX_COMPILER='{}'", clangxx_path.to_string_lossy()), + format!("-DCMAKE_AR='{}'", ar_path.to_string_lossy()), + format!("-DCMAKE_NM='{}'", nm_path.to_string_lossy()), + format!("-DCMAKE_RANLIB='{}'", ranlib_path.to_string_lossy()), + format!( + "-DLLVM_CONFIG_PATH='{}'", + llvm_config_path.to_string_lossy() + ), + ]) +} + +/// Build the compiler-rt builtins library. +pub fn build( + build_type: crate::BuildType, + target_env: crate::target_env::TargetEnv, + default_target: Option, + extra_args: &[String], + ccache_variant: Option, + sanitizer: Option, +) -> anyhow::Result<()> { + log::info!("building compiler-rt for rv64emac"); + + crate::utils::check_presence("cmake")?; + crate::utils::check_presence("ninja")?; + + let llvm_module_compiler_rt = crate::LLVMPath::llvm_module_compiler_rt()?; + let llvm_compiler_rt_build = crate::LLVMPath::llvm_build_compiler_rt()?; + + crate::utils::command( + std::process::Command::new("cmake") + .args([ + "-S", + llvm_module_compiler_rt.to_string_lossy().as_ref(), + "-B", + llvm_compiler_rt_build.to_string_lossy().as_ref(), + "-G", + "Ninja", + ]) + .args(CMAKE_STATIC_ARGS) + .args(cmake_dynamic_args(build_type, target_env)?) + .args(extra_args) + .args(crate::platforms::shared::shared_build_opts_ccache( + ccache_variant, + )) + .args(crate::platforms::shared::shared_build_opts_default_target( + default_target, + )) + .args(crate::platforms::shared::shared_build_opts_sanitizers( + sanitizer, + )), + "LLVM compiler-rt building cmake", + )?; + + crate::utils::ninja(&llvm_compiler_rt_build)?; + + Ok(()) +} diff --git a/crates/llvm-builder/src/ccache_variant.rs b/crates/llvm-builder/src/ccache_variant.rs new file mode 100644 index 00000000..3dc10912 --- /dev/null +++ b/crates/llvm-builder/src/ccache_variant.rs @@ -0,0 +1,31 @@ +//! Compiler cache variants. + +/// The list compiler cache variants to be used as constants. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum CcacheVariant { + /// Standard ccache. + Ccache, + /// Mozilla's sccache. + Sccache, +} + +impl std::str::FromStr for CcacheVariant { + type Err = String; + + fn from_str(value: &str) -> Result { + match value { + "ccache" => Ok(Self::Ccache), + "sccache" => Ok(Self::Sccache), + value => Err(format!("Unsupported ccache variant: `{}`", value)), + } + } +} + +impl std::fmt::Display for CcacheVariant { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + Self::Ccache => write!(f, "ccache"), + Self::Sccache => write!(f, "sccache"), + } + } +} diff --git a/crates/llvm-builder/src/lib.rs b/crates/llvm-builder/src/lib.rs new file mode 100644 index 00000000..75369c89 --- /dev/null +++ b/crates/llvm-builder/src/lib.rs @@ -0,0 +1,340 @@ +//! The revive LLVM builder library. + +pub mod build_type; +pub mod builtins; +pub mod ccache_variant; +pub mod llvm_path; +pub mod llvm_project; +pub mod lock; +pub mod platforms; +pub mod sanitizer; +pub mod target_env; +pub mod target_triple; +pub mod utils; + +pub use self::build_type::BuildType; +pub use self::llvm_path::LLVMPath; +pub use self::lock::Lock; +pub use self::platforms::Platform; + +use std::collections::HashSet; +use std::path::{Path, PathBuf}; +use std::process::Command; +pub use target_env::TargetEnv; +pub use target_triple::TargetTriple; + +/// Executes the LLVM repository cloning. +pub fn clone(lock: Lock, deep: bool, target_env: TargetEnv) -> anyhow::Result<()> { + utils::check_presence("git")?; + + if target_env == TargetEnv::Emscripten { + utils::install_emsdk()?; + } + + let destination_path = PathBuf::from(LLVMPath::DIRECTORY_LLVM_SOURCE); + if destination_path.exists() { + log::warn!( + "LLVM repository directory {} already exists, falling back to checkout", + destination_path.display() + ); + return checkout(lock, false); + } + + let mut clone_args = vec!["clone", "--branch", lock.branch.as_str()]; + if !deep { + clone_args.push("--depth"); + clone_args.push("1"); + } + + utils::command( + Command::new("git") + .args(clone_args) + .arg(lock.url.as_str()) + .arg(destination_path.to_string_lossy().as_ref()), + "LLVM repository cloning", + )?; + + if let Some(r#ref) = lock.r#ref { + utils::command( + Command::new("git") + .args(["checkout", r#ref.as_str()]) + .current_dir(destination_path.to_string_lossy().as_ref()), + "LLVM repository commit checking out", + )?; + } + + Ok(()) +} + +/// Executes the checkout of the specified branch. +pub fn checkout(lock: Lock, force: bool) -> anyhow::Result<()> { + let destination_path = PathBuf::from(LLVMPath::DIRECTORY_LLVM_SOURCE); + + utils::command( + Command::new("git") + .current_dir(destination_path.as_path()) + .args(["fetch", "--all", "--tags"]), + "LLVM repository data fetching", + )?; + + if force { + utils::command( + Command::new("git") + .current_dir(destination_path.as_path()) + .args(["clean", "-d", "-x", "--force"]), + "LLVM repository cleaning", + )?; + } + + utils::command( + Command::new("git") + .current_dir(destination_path.as_path()) + .args(["checkout", "--force", lock.branch.as_str()]), + "LLVM repository data pulling", + )?; + + if let Some(r#ref) = lock.r#ref { + let mut checkout_command = Command::new("git"); + checkout_command.current_dir(destination_path.as_path()); + checkout_command.arg("checkout"); + if force { + checkout_command.arg("--force"); + } + checkout_command.arg(r#ref); + utils::command(&mut checkout_command, "LLVM repository checking out")?; + } + + Ok(()) +} + +/// Executes the building of the LLVM framework for the platform determined by the cfg macro. +/// Since cfg is evaluated at compile time, overriding the platform with a command-line +/// argument is not possible. So for cross-platform testing, comment out all but the +/// line to be tested, and perhaps also checks in the platform-specific build method. +#[allow(clippy::too_many_arguments)] +pub fn build( + build_type: BuildType, + target_env: TargetEnv, + targets: HashSet, + llvm_projects: HashSet, + enable_rtti: bool, + default_target: Option, + enable_tests: bool, + enable_coverage: bool, + extra_args: &[String], + ccache_variant: Option, + enable_assertions: bool, + sanitizer: Option, + enable_valgrind: bool, +) -> anyhow::Result<()> { + log::trace!("build type: {:?}", build_type); + log::trace!("target env: {:?}", target_env); + log::trace!("targets: {:?}", targets); + log::trace!("llvm projects: {:?}", llvm_projects); + log::trace!("enable rtti: {:?}", enable_rtti); + log::trace!("default target: {:?}", default_target); + log::trace!("eneable tests: {:?}", enable_tests); + log::trace!("enable_coverage: {:?}", enable_coverage); + log::trace!("extra args: {:?}", extra_args); + log::trace!("sanitzer: {:?}", sanitizer); + log::trace!("enable valgrind: {:?}", enable_valgrind); + + if !PathBuf::from(LLVMPath::DIRECTORY_LLVM_SOURCE).exists() { + log::error!( + "LLVM project source directory {} does not exist (run `revive-llvm --target-env {} clone`)", + LLVMPath::DIRECTORY_LLVM_SOURCE, + target_env + ) + } + + std::fs::create_dir_all(llvm_path::DIRECTORY_LLVM_TARGET.get().unwrap())?; + + if cfg!(target_arch = "x86_64") { + if cfg!(target_os = "linux") { + if target_env == TargetEnv::MUSL { + platforms::x86_64_linux_musl::build( + build_type, + targets, + llvm_projects, + enable_rtti, + default_target, + enable_tests, + enable_coverage, + extra_args, + ccache_variant, + enable_assertions, + sanitizer, + enable_valgrind, + )?; + } else if target_env == TargetEnv::GNU { + platforms::x86_64_linux_gnu::build( + build_type, + targets, + llvm_projects, + enable_rtti, + default_target, + enable_tests, + enable_coverage, + extra_args, + ccache_variant, + enable_assertions, + sanitizer, + enable_valgrind, + )?; + } else if target_env == TargetEnv::Emscripten { + platforms::wasm32_emscripten::build( + build_type, + targets, + llvm_projects, + enable_rtti, + default_target, + enable_tests, + enable_coverage, + extra_args, + ccache_variant, + enable_assertions, + sanitizer, + enable_valgrind, + )?; + } else { + anyhow::bail!("Unsupported target environment for x86_64 and Linux"); + } + } else if cfg!(target_os = "macos") { + platforms::x86_64_macos::build( + build_type, + targets, + llvm_projects, + enable_rtti, + default_target, + enable_tests, + enable_coverage, + extra_args, + ccache_variant, + enable_assertions, + sanitizer, + )?; + } else if cfg!(target_os = "windows") { + platforms::x86_64_windows_gnu::build( + build_type, + targets, + llvm_projects, + enable_rtti, + default_target, + enable_tests, + enable_coverage, + extra_args, + ccache_variant, + enable_assertions, + sanitizer, + )?; + } else { + anyhow::bail!("Unsupported target OS for x86_64"); + } + } else if cfg!(target_arch = "aarch64") { + if cfg!(target_os = "linux") { + if target_env == TargetEnv::MUSL { + platforms::aarch64_linux_musl::build( + build_type, + targets, + llvm_projects, + enable_rtti, + default_target, + enable_tests, + enable_coverage, + extra_args, + ccache_variant, + enable_assertions, + sanitizer, + enable_valgrind, + )?; + } else if target_env == TargetEnv::GNU { + platforms::aarch64_linux_gnu::build( + build_type, + targets, + llvm_projects, + enable_rtti, + default_target, + enable_tests, + enable_coverage, + extra_args, + ccache_variant, + enable_assertions, + sanitizer, + enable_valgrind, + )?; + } else { + anyhow::bail!("Unsupported target environment for aarch64 and Linux"); + } + } else if cfg!(target_os = "macos") { + if target_env == TargetEnv::Emscripten { + platforms::wasm32_emscripten::build( + build_type, + targets, + llvm_projects, + enable_rtti, + default_target, + enable_tests, + enable_coverage, + extra_args, + ccache_variant, + enable_assertions, + sanitizer, + enable_valgrind, + )?; + } else { + platforms::aarch64_macos::build( + build_type, + targets, + llvm_projects, + enable_rtti, + default_target, + enable_tests, + enable_coverage, + extra_args, + ccache_variant, + enable_assertions, + sanitizer, + )?; + } + } else { + anyhow::bail!("Unsupported target OS for aarch64"); + } + } else { + anyhow::bail!("Unsupported target architecture"); + } + + crate::builtins::build( + build_type, + target_env, + default_target, + extra_args, + ccache_variant, + sanitizer, + )?; + + Ok(()) +} + +/// Executes the build artifacts cleaning. +pub fn clean() -> anyhow::Result<()> { + let remove_if_exists = |path: &Path| { + if !path.exists() { + return Ok(()); + } + log::info!("deleting {}", path.display()); + std::fs::remove_dir_all(path) + }; + + remove_if_exists( + llvm_path::DIRECTORY_LLVM_TARGET + .get() + .expect("target_env is always set because of the default value") + .parent() + .expect("target_env parent directory is target-llvm"), + )?; + remove_if_exists(&PathBuf::from(LLVMPath::DIRECTORY_EMSDK_SOURCE))?; + remove_if_exists(&PathBuf::from(LLVMPath::DIRECTORY_LLVM_SOURCE))?; + remove_if_exists(&PathBuf::from(LLVMPath::DIRECTORY_LLVM_HOST_SOURCE))?; + + Ok(()) +} diff --git a/crates/llvm-builder/src/llvm_path.rs b/crates/llvm-builder/src/llvm_path.rs new file mode 100644 index 00000000..4b70d097 --- /dev/null +++ b/crates/llvm-builder/src/llvm_path.rs @@ -0,0 +1,151 @@ +//! The revive LLVM builder constants. + +use std::path::PathBuf; +use std::sync::OnceLock; + +pub static DIRECTORY_LLVM_TARGET: OnceLock = OnceLock::new(); + +/// The LLVM path resolver. +pub struct LLVMPath {} + +impl LLVMPath { + /// The LLVM source directory. + pub const DIRECTORY_LLVM_SOURCE: &'static str = "./llvm/"; + + /// The LLVM host source directory for stage 1 of multistage MUSL and Emscripten builds. + /// + /// We use upstream LLVM anyways; re-use the same tree for host and target builds. + pub const DIRECTORY_LLVM_HOST_SOURCE: &'static str = Self::DIRECTORY_LLVM_SOURCE; + + /// The Emscripten SDK source directory. + pub const DIRECTORY_EMSDK_SOURCE: &'static str = "./emsdk/"; + + /// Returns the path to the `llvm` stage 1 host LLVM source module directory. + pub fn llvm_host_module_llvm() -> anyhow::Result { + let mut path = PathBuf::from(Self::DIRECTORY_LLVM_HOST_SOURCE); + path.push("llvm"); + crate::utils::absolute_path(path).inspect(|absolute_path| { + log::debug!( + "llvm stage 1 host llvm source module: {}", + absolute_path.display() + ) + }) + } + + /// Returns the path to the `llvm` LLVM source module directory. + pub fn llvm_module_llvm() -> anyhow::Result { + let mut path = PathBuf::from(Self::DIRECTORY_LLVM_SOURCE); + path.push("llvm"); + crate::utils::absolute_path(path) + .inspect(|absolute_path| log::debug!("llvm source module: {}", absolute_path.display())) + } + + /// Returns the path to the MUSL source. + pub fn musl_source(name: &str) -> anyhow::Result { + let mut path = PathBuf::from(DIRECTORY_LLVM_TARGET.get().unwrap()); + path.push(name); + crate::utils::absolute_path(path) + .inspect(|absolute_path| log::debug!("musl source: {}", absolute_path.display())) + } + + /// Returns the path to the MUSL build directory. + pub fn musl_build(source_directory: &str) -> anyhow::Result { + let mut path = PathBuf::from(DIRECTORY_LLVM_TARGET.get().unwrap()); + path.push(source_directory); + path.push("build"); + crate::utils::absolute_path(path) + .inspect(|absolute_path| log::debug!("musl build: '{}'", absolute_path.display())) + } + + /// Returns the path to the LLVM CRT build directory. + pub fn llvm_build_crt() -> anyhow::Result { + let mut path = PathBuf::from(DIRECTORY_LLVM_TARGET.get().unwrap()); + path.push("build-crt"); + crate::utils::absolute_path(path) + .inspect(|absolute_path| log::debug!("llvm build crt: {}", absolute_path.display())) + } + + /// Returns the path to the LLVM host build directory. + pub fn llvm_build_host() -> anyhow::Result { + let mut path = PathBuf::from(DIRECTORY_LLVM_TARGET.get().unwrap()); + path.push("build-host"); + crate::utils::absolute_path(path) + .inspect(|absolute_path| log::debug!("llvm build host: {}", absolute_path.display())) + } + + /// Returns the path to the LLVM final build directory. + pub fn llvm_build_final() -> anyhow::Result { + let mut path = PathBuf::from(DIRECTORY_LLVM_TARGET.get().unwrap()); + path.push("build-final"); + crate::utils::absolute_path(path) + .inspect(|absolute_path| log::debug!("llvm build final: {}", absolute_path.display())) + } + + /// Returns the path to the MUSL target directory. + pub fn musl_target() -> anyhow::Result { + let mut path = PathBuf::from(DIRECTORY_LLVM_TARGET.get().unwrap()); + path.push("target-musl"); + crate::utils::absolute_path(path) + .inspect(|absolute_path| log::debug!("musl target: {}", absolute_path.display())) + } + + /// Returns the path to the LLVM CRT target directory. + pub fn llvm_target_crt() -> anyhow::Result { + let mut path = PathBuf::from(DIRECTORY_LLVM_TARGET.get().unwrap()); + path.push("target-crt"); + crate::utils::absolute_path(path) + .inspect(|absolute_path| log::debug!("llvm crt target: {}", absolute_path.display())) + } + + /// Returns the path to the LLVM host target directory. + pub fn llvm_target_host() -> anyhow::Result { + let mut path = PathBuf::from(DIRECTORY_LLVM_TARGET.get().unwrap()); + path.push("target-host"); + crate::utils::absolute_path(path) + .inspect(|absolute_path| log::debug!("llvm host target: {}", absolute_path.display())) + } + + /// Returns the path to the LLVM final target directory. + pub fn llvm_target_final() -> anyhow::Result { + let mut path = PathBuf::from(DIRECTORY_LLVM_TARGET.get().unwrap()); + path.push("target-final"); + crate::utils::absolute_path(path) + .inspect(|absolute_path| log::debug!("llvm final target: {}", absolute_path.display())) + } + + /// Returns the path to the LLVM compiler builtin target directory. + pub fn llvm_module_compiler_rt() -> anyhow::Result { + let mut path = PathBuf::from(Self::DIRECTORY_LLVM_SOURCE); + path.push("compiler-rt"); + crate::utils::absolute_path(path).inspect(|absolute_path| { + log::debug!("compiler-rt source dir: {}", absolute_path.display()) + }) + } + + /// Returns the path to the LLVM compiler-rt target directory. + pub fn llvm_target_compiler_rt() -> anyhow::Result { + Self::llvm_target_final() + } + + /// Returns the path to the LLVM compiler-rt build directory. + pub fn llvm_build_compiler_rt() -> anyhow::Result { + let mut path = PathBuf::from(DIRECTORY_LLVM_TARGET.get().unwrap()); + path.push("build-compiler-rt"); + crate::utils::absolute_path(path).inspect(|absolute_path| { + log::debug!("llvm compiler-rt build: {}", absolute_path.display()) + }) + } + + /// Returns the path to the LLVM target final bin path. + /// + pub fn llvm_target_final_bin( + target_env: crate::target_env::TargetEnv, + ) -> anyhow::Result { + let mut path = Self::llvm_target_final()?; + path.push("bin"); + path.push(format!("{target_env}")); + crate::utils::absolute_path(path).inspect(|absolute_path| { + log::debug!("llvm target final bin: {}", absolute_path.display()) + }) + } +} diff --git a/crates/llvm-builder/src/llvm_project.rs b/crates/llvm-builder/src/llvm_project.rs new file mode 100644 index 00000000..0a6a35ac --- /dev/null +++ b/crates/llvm-builder/src/llvm_project.rs @@ -0,0 +1,39 @@ +//! The LLVM projects to enable during the build. + +/// The list of LLVM projects used as constants. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum LLVMProject { + /// The Clang compiler. + CLANG, + /// LLD, the LLVM linker. + LLD, + /// The LLVM debugger. + LLDB, + /// The MLIR compiler. + MLIR, +} + +impl std::str::FromStr for LLVMProject { + type Err = String; + + fn from_str(value: &str) -> Result { + match value.to_lowercase().as_str() { + "clang" => Ok(Self::CLANG), + "lld" => Ok(Self::LLD), + "lldb" => Ok(Self::LLDB), + "mlir" => Ok(Self::MLIR), + value => Err(format!("Unsupported LLVM project to enable: `{}`", value)), + } + } +} + +impl std::fmt::Display for LLVMProject { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + Self::CLANG => write!(f, "clang"), + Self::LLD => write!(f, "lld"), + Self::LLDB => write!(f, "lldb"), + Self::MLIR => write!(f, "mlir"), + } + } +} diff --git a/crates/llvm-builder/src/lock.rs b/crates/llvm-builder/src/lock.rs new file mode 100644 index 00000000..b04004c2 --- /dev/null +++ b/crates/llvm-builder/src/lock.rs @@ -0,0 +1,37 @@ +//! The revive LLVM builder lock file. + +use anyhow::Context; +use std::fs::File; +use std::io::Read; +use std::path::PathBuf; + +use serde::Deserialize; +use serde::Serialize; + +/// The default lock file location. +pub const LLVM_LOCK_DEFAULT_PATH: &str = "LLVM.lock"; + +/// The lock file data. +/// +/// This file describes the exact reference of the LLVM framework. +#[derive(Debug, Deserialize, Serialize)] +pub struct Lock { + /// The LLVM repository URL. + pub url: String, + /// The LLVM repository branch. + pub branch: String, + /// The LLVM repository commit reference. + pub r#ref: Option, +} + +impl TryFrom<&PathBuf> for Lock { + type Error = anyhow::Error; + + fn try_from(path: &PathBuf) -> Result { + let mut config_str = String::new(); + let mut config_file = + File::open(path).with_context(|| format!("Error opening {:?} file", path))?; + config_file.read_to_string(&mut config_str)?; + Ok(toml::from_str(&config_str)?) + } +} diff --git a/crates/llvm-builder/src/platforms/aarch64_linux_gnu.rs b/crates/llvm-builder/src/platforms/aarch64_linux_gnu.rs new file mode 100644 index 00000000..4bda3b71 --- /dev/null +++ b/crates/llvm-builder/src/platforms/aarch64_linux_gnu.rs @@ -0,0 +1,111 @@ +//! The revive LLVM arm64 `linux-gnu` builder. + +use std::collections::HashSet; +use std::process::Command; + +use crate::build_type::BuildType; +use crate::ccache_variant::CcacheVariant; +use crate::llvm_path::LLVMPath; +use crate::llvm_project::LLVMProject; +use crate::platforms::Platform; +use crate::sanitizer::Sanitizer; +use crate::target_triple::TargetTriple; + +/// The building sequence. +#[allow(clippy::too_many_arguments)] +pub fn build( + build_type: BuildType, + targets: HashSet, + llvm_projects: HashSet, + enable_rtti: bool, + default_target: Option, + enable_tests: bool, + enable_coverage: bool, + extra_args: &[String], + ccache_variant: Option, + enable_assertions: bool, + sanitizer: Option, + enable_valgrind: bool, +) -> anyhow::Result<()> { + crate::utils::check_presence("cmake")?; + crate::utils::check_presence("clang")?; + crate::utils::check_presence("clang++")?; + crate::utils::check_presence("lld")?; + crate::utils::check_presence("ninja")?; + + let llvm_module_llvm = LLVMPath::llvm_module_llvm()?; + let llvm_build_final = LLVMPath::llvm_build_final()?; + let llvm_target_final = LLVMPath::llvm_target_final()?; + + crate::utils::command( + Command::new("cmake") + .args([ + "-S", + llvm_module_llvm.to_string_lossy().as_ref(), + "-B", + llvm_build_final.to_string_lossy().as_ref(), + "-G", + "Ninja", + format!( + "-DCMAKE_INSTALL_PREFIX='{}'", + llvm_target_final.to_string_lossy().as_ref(), + ) + .as_str(), + format!("-DCMAKE_BUILD_TYPE='{build_type}'").as_str(), + "-DCMAKE_C_COMPILER='clang'", + "-DCMAKE_CXX_COMPILER='clang++'", + format!( + "-DLLVM_TARGETS_TO_BUILD='{}'", + targets + .into_iter() + .map(|platform| platform.to_string()) + .collect::>() + .join(";") + ) + .as_str(), + format!( + "-DLLVM_ENABLE_PROJECTS='{}'", + llvm_projects + .into_iter() + .map(|project| project.to_string()) + .collect::>() + .join(";") + ) + .as_str(), + "-DLLVM_USE_LINKER='lld'", + ]) + .args(crate::platforms::shared::shared_build_opts_default_target( + default_target, + )) + .args(crate::platforms::shared::shared_build_opts_tests( + enable_tests, + )) + .args(crate::platforms::shared::shared_build_opts_coverage( + enable_coverage, + )) + .args(crate::platforms::shared::SHARED_BUILD_OPTS) + .args(crate::platforms::shared::SHARED_BUILD_OPTS_NOT_MUSL) + .args(crate::platforms::shared::shared_build_opts_werror( + crate::target_env::TargetEnv::GNU, + )) + .args(extra_args) + .args(crate::platforms::shared::shared_build_opts_ccache( + ccache_variant, + )) + .args(crate::platforms::shared::shared_build_opts_assertions( + enable_assertions, + )) + .args(crate::platforms::shared::shared_build_opts_rtti( + enable_rtti, + )) + .args(crate::platforms::shared::shared_build_opts_sanitizers( + sanitizer, + )) + .args(crate::platforms::shared::shared_build_opts_valgrind( + enable_valgrind, + )), + "LLVM building cmake", + )?; + crate::utils::ninja(llvm_build_final.as_ref())?; + Ok(()) +} diff --git a/crates/llvm-builder/src/platforms/aarch64_linux_musl.rs b/crates/llvm-builder/src/platforms/aarch64_linux_musl.rs new file mode 100644 index 00000000..dd33a12d --- /dev/null +++ b/crates/llvm-builder/src/platforms/aarch64_linux_musl.rs @@ -0,0 +1,394 @@ +//! The revive LLVM arm64 `linux-musl` builder. + +use crate::build_type::BuildType; +use crate::ccache_variant::CcacheVariant; +use crate::llvm_path::LLVMPath; +use crate::llvm_project::LLVMProject; +use crate::platforms::Platform; +use crate::sanitizer::Sanitizer; +use crate::target_triple::TargetTriple; +use std::collections::HashSet; +use std::path::Path; +use std::process::Command; + +/// The building sequence. +#[allow(clippy::too_many_arguments)] +pub fn build( + build_type: BuildType, + targets: HashSet, + llvm_projects: HashSet, + enable_rtti: bool, + default_target: Option, + enable_tests: bool, + enable_coverage: bool, + extra_args: &[String], + ccache_variant: Option, + enable_assertions: bool, + sanitizer: Option, + enable_valgrind: bool, +) -> anyhow::Result<()> { + crate::utils::check_presence("cmake")?; + crate::utils::check_presence("clang")?; + crate::utils::check_presence("clang++")?; + crate::utils::check_presence("lld")?; + crate::utils::check_presence("ninja")?; + + let musl_name = "musl-1.2.3"; + let musl_build = LLVMPath::musl_build(musl_name)?; + let musl_target = LLVMPath::musl_target()?; + + let llvm_module_llvm = LLVMPath::llvm_module_llvm()?; + let llvm_host_module_llvm = LLVMPath::llvm_host_module_llvm()?; + + let llvm_build_crt = LLVMPath::llvm_build_crt()?; + let llvm_target_crt = LLVMPath::llvm_target_crt()?; + + let llvm_build_host = LLVMPath::llvm_build_host()?; + let llvm_target_host = LLVMPath::llvm_target_host()?; + + let llvm_build_final = LLVMPath::llvm_build_final()?; + let llvm_target_final = LLVMPath::llvm_target_final()?; + + if !LLVMPath::musl_source(musl_name)?.exists() { + crate::utils::download_musl(musl_name)?; + } + crate::platforms::shared::build_musl(musl_build.as_path(), musl_target.as_path())?; + build_crt( + targets.clone(), + llvm_host_module_llvm.as_path(), + llvm_build_crt.as_path(), + llvm_target_crt.as_path(), + ccache_variant, + )?; + build_host( + llvm_host_module_llvm.as_path(), + llvm_build_host.as_path(), + llvm_target_host.as_path(), + musl_target.as_path(), + llvm_target_crt.as_path(), + ccache_variant, + )?; + build_target( + build_type, + targets, + llvm_projects, + enable_rtti, + default_target, + llvm_module_llvm.as_path(), + llvm_build_final.as_path(), + llvm_target_final.as_path(), + musl_target.as_path(), + llvm_target_host.as_path(), + enable_tests, + enable_coverage, + extra_args, + ccache_variant, + enable_assertions, + sanitizer, + enable_valgrind, + )?; + + Ok(()) +} + +/// +/// The `crt` building sequence. +/// +fn build_crt( + mut targets: HashSet, + source_directory: &Path, + build_directory: &Path, + target_directory: &Path, + ccache_variant: Option, +) -> anyhow::Result<()> { + targets.insert(Platform::AArch64); + + crate::utils::command( + Command::new("cmake") + .args([ + "-S", + source_directory.to_string_lossy().as_ref(), + "-B", + build_directory.to_string_lossy().as_ref(), + "-G", + "Ninja", + format!( + "-DCMAKE_INSTALL_PREFIX='{}'", + target_directory.to_string_lossy() + ) + .as_str(), + "-DCMAKE_BUILD_TYPE='Release'", + "-DCMAKE_C_COMPILER='clang'", + "-DCMAKE_CXX_COMPILER='clang++'", + "-DLLVM_ENABLE_PROJECTS='compiler-rt'", + format!("-DLLVM_TARGETS_TO_BUILD='{}'", Platform::AArch64).as_str(), + "-DLLVM_DEFAULT_TARGET_TRIPLE='aarch64-unknown-linux-musl'", + "-DLLVM_BUILD_TESTS='Off'", + "-DLLVM_BUILD_RUNTIMES='Off'", + "-DLLVM_BUILD_UTILS='Off'", + "-DLLVM_INCLUDE_TESTS='Off'", + "-DLLVM_INCLUDE_RUNTIMES='Off'", + "-DLLVM_INCLUDE_UTILS='Off'", + "-DCOMPILER_RT_DEFAULT_TARGET_ARCH='aarch64'", + "-DCOMPILER_RT_BUILD_CRT='On'", + "-DCOMPILER_RT_BUILD_BUILTINS='On'", + "-DCOMPILER_RT_BUILD_SANITIZERS='Off'", + "-DCOMPILER_RT_BUILD_XRAY='Off'", + "-DCOMPILER_RT_BUILD_LIBFUZZER='Off'", + "-DCOMPILER_RT_BUILD_PROFILE='Off'", + "-DCOMPILER_RT_BUILD_MEMPROF='Off'", + "-DCOMPILER_RT_BUILD_ORC='Off'", + ]) + .args(crate::platforms::shared::SHARED_BUILD_OPTS) + .args(crate::platforms::shared::shared_build_opts_ccache( + ccache_variant, + )), + "CRT building cmake", + )?; + + crate::utils::command( + Command::new("ninja") + .arg("-C") + .arg(build_directory) + .arg("install-crt"), + "CRT building ninja", + )?; + + Ok(()) +} + +/// +/// The host toolchain building sequence. +/// +fn build_host( + source_directory: &Path, + build_directory: &Path, + target_directory: &Path, + musl_target_directory: &Path, + crt_target_directory: &Path, + ccache_variant: Option, +) -> anyhow::Result<()> { + crate::utils::command( + Command::new("cmake") + .args([ + "-S", + source_directory.to_string_lossy().as_ref(), + "-B", + build_directory.to_string_lossy().as_ref(), + "-G", + "Ninja", + format!( + "-DDEFAULT_SYSROOT='{}'", + musl_target_directory.to_string_lossy() + ) + .as_str(), + "-DLINKER_SUPPORTS_COLOR_DIAGNOSTICS=0", + format!( + "-DCMAKE_INSTALL_PREFIX='{}'", + target_directory.to_string_lossy() + ) + .as_str(), + "-DCMAKE_BUILD_TYPE='Release'", + "-DCMAKE_C_COMPILER='clang'", + "-DCMAKE_CXX_COMPILER='clang++'", + "-DCLANG_DEFAULT_CXX_STDLIB='libc++'", + "-DCLANG_DEFAULT_RTLIB='compiler-rt'", + "-DLLVM_DEFAULT_TARGET_TRIPLE='aarch64-unknown-linux-musl'", + "-DLLVM_TARGETS_TO_BUILD='AArch64'", + "-DLLVM_BUILD_TESTS='Off'", + "-DLLVM_BUILD_UTILS='Off'", + "-DLLVM_INCLUDE_TESTS='Off'", + "-DLLVM_INCLUDE_UTILS='Off'", + "-DLLVM_ENABLE_PROJECTS='clang;lld'", + "-DLLVM_ENABLE_RUNTIMES='compiler-rt;libcxx;libcxxabi;libunwind'", + "-DLIBCXX_CXX_ABI='libcxxabi'", + "-DLIBCXX_HAS_MUSL_LIBC='On'", + "-DLIBCXX_ENABLE_SHARED='Off'", + "-DLIBCXX_ENABLE_STATIC='On'", + "-DLIBCXX_ENABLE_STATIC_ABI_LIBRARY='On'", + "-DLIBCXXABI_ENABLE_SHARED='Off'", + "-DLIBCXXABI_ENABLE_STATIC='On'", + "-DLIBCXXABI_ENABLE_STATIC_UNWINDER='On'", + "-DLIBCXXABI_USE_LLVM_UNWINDER='On'", + "-DLIBCXXABI_USE_COMPILER_RT='On'", + "-DLIBUNWIND_ENABLE_STATIC='On'", + "-DLIBUNWIND_ENABLE_SHARED='Off'", + "-DCOMPILER_RT_BUILD_CRT='On'", + "-DCOMPILER_RT_BUILD_SANITIZERS='Off'", + "-DCOMPILER_RT_BUILD_XRAY='Off'", + "-DCOMPILER_RT_BUILD_LIBFUZZER='Off'", + "-DCOMPILER_RT_BUILD_PROFILE='On'", + "-DCOMPILER_RT_BUILD_MEMPROF='Off'", + "-DCOMPILER_RT_BUILD_ORC='Off'", + "-DCOMPILER_RT_DEFAULT_TARGET_ARCH='aarch64'", + "-DCOMPILER_RT_DEFAULT_TARGET_ONLY='On'", + ]) + .args(crate::platforms::shared::SHARED_BUILD_OPTS) + .args(crate::platforms::shared::shared_build_opts_ccache( + ccache_variant, + )), + "LLVM host building cmake", + )?; + + let mut crt_lib_directory = crt_target_directory.to_path_buf(); + crt_lib_directory.push("lib/"); + + let mut build_lib_directory = build_directory.to_path_buf(); + build_lib_directory.push("lib/"); + + let copy_options = fs_extra::dir::CopyOptions { + overwrite: true, + copy_inside: true, + content_only: true, + ..Default::default() + }; + fs_extra::dir::copy(crt_lib_directory, build_lib_directory, ©_options)?; + + crate::utils::command( + Command::new("ninja") + .arg("-C") + .arg(build_directory) + .arg("install"), + "LLVM host building ninja", + )?; + + Ok(()) +} + +/// +/// The target toolchain building sequence. +/// +#[allow(clippy::too_many_arguments)] +fn build_target( + build_type: BuildType, + targets: HashSet, + llvm_projects: HashSet, + enable_rtti: bool, + default_target: Option, + source_directory: &Path, + build_directory: &Path, + target_directory: &Path, + musl_target_directory: &Path, + host_target_directory: &Path, + enable_tests: bool, + enable_coverage: bool, + extra_args: &[String], + ccache_variant: Option, + enable_assertions: bool, + sanitizer: Option, + enable_valgrind: bool, +) -> anyhow::Result<()> { + let mut clang_path = host_target_directory.to_path_buf(); + clang_path.push("bin/clang"); + + let mut clang_cxx_path = host_target_directory.to_path_buf(); + clang_cxx_path.push("bin/clang++"); + + crate::utils::command( + Command::new("cmake") + .args([ + "-S", + source_directory.to_string_lossy().as_ref(), + "-B", + build_directory.to_string_lossy().as_ref(), + "-G", + "Ninja", + "-DBUILD_SHARED_LIBS='Off'", + "-DLINKER_SUPPORTS_COLOR_DIAGNOSTICS=0", + format!( + "-DCMAKE_INSTALL_PREFIX='{}'", + target_directory.to_string_lossy() + ) + .as_str(), + format!("-DCMAKE_BUILD_TYPE='{build_type}'").as_str(), + format!("-DCMAKE_C_COMPILER='{}'", clang_path.to_string_lossy()).as_str(), + format!( + "-DCMAKE_CXX_COMPILER='{}'", + clang_cxx_path.to_string_lossy() + ) + .as_str(), + "-DCMAKE_FIND_LIBRARY_SUFFIXES='.a'", + "-DCMAKE_BUILD_WITH_INSTALL_RPATH=1", + "-DCMAKE_EXE_LINKER_FLAGS='-fuse-ld=lld -static'", + format!( + "-DLLVM_TARGETS_TO_BUILD='{}'", + targets + .into_iter() + .map(|platform| platform.to_string()) + .collect::>() + .join(";") + ) + .as_str(), + format!( + "-DLLVM_ENABLE_PROJECTS='{}'", + llvm_projects + .into_iter() + .map(|project| project.to_string()) + .collect::>() + .join(";") + ) + .as_str(), + ]) + .args(crate::platforms::shared::shared_build_opts_default_target( + default_target, + )) + .args(crate::platforms::shared::SHARED_BUILD_OPTS) + .args(crate::platforms::shared::SHARED_BUILD_OPTS_NOT_MUSL) + .args(crate::platforms::shared::shared_build_opts_werror( + crate::target_env::TargetEnv::MUSL, + )) + .args(crate::platforms::shared::shared_build_opts_tests( + enable_tests, + )) + .args(crate::platforms::shared::shared_build_opts_coverage( + enable_coverage, + )) + .args(extra_args) + .args(crate::platforms::shared::shared_build_opts_ccache( + ccache_variant, + )) + .args(crate::platforms::shared::shared_build_opts_assertions( + enable_assertions, + )) + .args(crate::platforms::shared::shared_build_opts_rtti( + enable_rtti, + )) + .args(crate::platforms::shared::shared_build_opts_sanitizers( + sanitizer, + )) + .args(crate::platforms::shared::shared_build_opts_valgrind( + enable_valgrind, + )), + "LLVM target building cmake", + )?; + + crate::utils::ninja(build_directory)?; + + let mut musl_lib_directory = musl_target_directory.to_path_buf(); + musl_lib_directory.push("lib/"); + + let mut host_lib_directory = host_target_directory.to_path_buf(); + host_lib_directory.push("lib/aarch64-unknown-linux-musl/"); + + let mut target_lib_directory = target_directory.to_path_buf(); + target_lib_directory.push("lib/"); + + let copy_options = fs_extra::dir::CopyOptions { + overwrite: true, + copy_inside: true, + content_only: true, + ..Default::default() + }; + fs_extra::dir::copy( + musl_lib_directory, + target_lib_directory.as_path(), + ©_options, + )?; + fs_extra::dir::copy( + host_lib_directory, + target_lib_directory.as_path(), + ©_options, + )?; + + Ok(()) +} diff --git a/crates/llvm-builder/src/platforms/aarch64_macos.rs b/crates/llvm-builder/src/platforms/aarch64_macos.rs new file mode 100644 index 00000000..a33b827d --- /dev/null +++ b/crates/llvm-builder/src/platforms/aarch64_macos.rs @@ -0,0 +1,105 @@ +//! The revive LLVM arm64 `macos-aarch64` builder. + +use std::collections::HashSet; +use std::process::Command; + +use crate::build_type::BuildType; +use crate::ccache_variant::CcacheVariant; +use crate::llvm_path::LLVMPath; +use crate::llvm_project::LLVMProject; +use crate::platforms::Platform; +use crate::sanitizer::Sanitizer; +use crate::target_triple::TargetTriple; + +/// The building sequence. +#[allow(clippy::too_many_arguments)] +pub fn build( + build_type: BuildType, + targets: HashSet, + llvm_projects: HashSet, + enable_rtti: bool, + default_target: Option, + enable_tests: bool, + enable_coverage: bool, + extra_args: &[String], + ccache_variant: Option, + enable_assertions: bool, + sanitizer: Option, +) -> anyhow::Result<()> { + crate::utils::check_presence("cmake")?; + crate::utils::check_presence("ninja")?; + + let llvm_module_llvm = LLVMPath::llvm_module_llvm()?; + let llvm_build_final = LLVMPath::llvm_build_final()?; + let llvm_target_final = LLVMPath::llvm_target_final()?; + + crate::utils::command( + Command::new("cmake") + .args([ + "-S", + llvm_module_llvm.to_string_lossy().as_ref(), + "-B", + llvm_build_final.to_string_lossy().as_ref(), + "-G", + "Ninja", + format!( + "-DCMAKE_INSTALL_PREFIX='{}'", + llvm_target_final.to_string_lossy().as_ref(), + ) + .as_str(), + format!("-DCMAKE_BUILD_TYPE='{build_type}'").as_str(), + format!( + "-DLLVM_TARGETS_TO_BUILD='{}'", + targets + .into_iter() + .map(|platform| platform.to_string()) + .collect::>() + .join(";") + ) + .as_str(), + format!( + "-DLLVM_ENABLE_PROJECTS='{}'", + llvm_projects + .into_iter() + .map(|project| project.to_string()) + .collect::>() + .join(";") + ) + .as_str(), + "-DCMAKE_OSX_DEPLOYMENT_TARGET='11.0'", + ]) + .args(crate::platforms::shared::shared_build_opts_default_target( + default_target, + )) + .args(crate::platforms::shared::shared_build_opts_tests( + enable_tests, + )) + .args(crate::platforms::shared::shared_build_opts_coverage( + enable_coverage, + )) + .args(crate::platforms::shared::SHARED_BUILD_OPTS) + .args(crate::platforms::shared::SHARED_BUILD_OPTS_NOT_MUSL) + .args(crate::platforms::shared::shared_build_opts_werror( + crate::target_env::TargetEnv::GNU, + )) + .args(extra_args) + .args(crate::platforms::shared::shared_build_opts_ccache( + ccache_variant, + )) + .args(crate::platforms::shared::shared_build_opts_assertions( + enable_assertions, + )) + .args(crate::platforms::shared::shared_build_opts_rtti( + enable_rtti, + )) + .args(crate::platforms::shared::macos_build_opts_ignore_dupicate_libs_warnings()) + .args(crate::platforms::shared::shared_build_opts_sanitizers( + sanitizer, + )), + "LLVM building cmake", + )?; + + crate::utils::ninja(llvm_build_final.as_ref())?; + + Ok(()) +} diff --git a/crates/llvm-builder/src/platforms/mod.rs b/crates/llvm-builder/src/platforms/mod.rs new file mode 100644 index 00000000..4164c5a6 --- /dev/null +++ b/crates/llvm-builder/src/platforms/mod.rs @@ -0,0 +1,45 @@ +//! The revive LLVM builder platforms. + +pub mod aarch64_linux_gnu; +pub mod aarch64_linux_musl; +pub mod aarch64_macos; +pub mod shared; +pub mod wasm32_emscripten; +pub mod x86_64_linux_gnu; +pub mod x86_64_linux_musl; +pub mod x86_64_macos; +pub mod x86_64_windows_gnu; + +use std::str::FromStr; + +/// The list of platforms used as constants. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum Platform { + /// The native X86 platform. + X86, + /// The native AArch64 platform. + AArch64, + /// The PolkaVM RISC-V platform. + PolkaVM, +} + +impl FromStr for Platform { + type Err = String; + + fn from_str(value: &str) -> Result { + match value { + "PolkaVM" => Ok(Self::PolkaVM), + value => Err(format!("Unsupported platform: `{}`", value)), + } + } +} + +impl std::fmt::Display for Platform { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + Self::X86 => write!(f, "X86"), + Self::AArch64 => write!(f, "AArch64"), + Self::PolkaVM => write!(f, "RISCV"), + } + } +} diff --git a/crates/llvm-builder/src/platforms/shared.rs b/crates/llvm-builder/src/platforms/shared.rs new file mode 100644 index 00000000..71e2e036 --- /dev/null +++ b/crates/llvm-builder/src/platforms/shared.rs @@ -0,0 +1,232 @@ +//! The shared options for building various platforms. + +use crate::ccache_variant::CcacheVariant; +use crate::sanitizer::Sanitizer; +use crate::target_env::TargetEnv; +use crate::target_triple::TargetTriple; +use std::path::Path; +use std::process::Command; + +/// The build options shared by all platforms. +pub const SHARED_BUILD_OPTS: [&str; 19] = [ + "-DPACKAGE_VENDOR='Parity Technologies'", + "-DCMAKE_BUILD_WITH_INSTALL_RPATH=1", + "-DLLVM_BUILD_DOCS='Off'", + "-DLLVM_INCLUDE_DOCS='Off'", + "-DLLVM_INCLUDE_BENCHMARKS='Off'", + "-DLLVM_INCLUDE_EXAMPLES='Off'", + "-DLLVM_ENABLE_DOXYGEN='Off'", + "-DLLVM_ENABLE_SPHINX='Off'", + "-DLLVM_ENABLE_OCAMLDOC='Off'", + "-DLLVM_ENABLE_ZLIB='Off'", + "-DLLVM_ENABLE_ZSTD='Off'", + "-DLLVM_ENABLE_LIBXML2='Off'", + "-DLLVM_ENABLE_BINDINGS='Off'", + "-DLLVM_ENABLE_TERMINFO='Off'", + "-DLLVM_ENABLE_LIBEDIT='Off'", + "-DLLVM_ENABLE_LIBPFM='Off'", + "-DCMAKE_EXPORT_COMPILE_COMMANDS='On'", + "-DPython3_FIND_REGISTRY='LAST'", // Use Python version from $PATH, not from registry + "-DBUG_REPORT_URL='https://github.com/paritytech/contract-issues/issues/'", +]; + +/// The build options shared by all platforms except MUSL. +pub const SHARED_BUILD_OPTS_NOT_MUSL: [&str; 4] = [ + "-DLLVM_OPTIMIZED_TABLEGEN='On'", + "-DLLVM_BUILD_RUNTIME='Off'", + "-DLLVM_BUILD_RUNTIMES='Off'", + "-DLLVM_INCLUDE_RUNTIMES='Off'", +]; + +/// The shared build options to treat warnings as errors. +/// +/// Disabled on Windows due to the following upstream issue with MSYS2 with mingw-w64: +/// ProgramTest.cpp:23:15: error: '__p__environ' redeclared without 'dllimport' attribute +pub fn shared_build_opts_werror(target_env: TargetEnv) -> Vec { + vec![format!( + "-DLLVM_ENABLE_WERROR='{}'", + if cfg!(target_os = "windows") || target_env == TargetEnv::Emscripten { + "Off" + } else { + "On" + }, + )] +} + +/// The build options to set the default target. +pub fn shared_build_opts_default_target(target: Option) -> Vec { + match target { + Some(target) => vec![format!( + "-DLLVM_DEFAULT_TARGET_TRIPLE='{}'", + target.to_string() + )], + None => vec![format!( + "-DLLVM_DEFAULT_TARGET_TRIPLE='{}'", + TargetTriple::PolkaVM + )], + } +} + +/// The `musl` building sequence. +pub fn build_musl(build_directory: &Path, target_directory: &Path) -> anyhow::Result<()> { + std::fs::create_dir_all(build_directory)?; + std::fs::create_dir_all(target_directory)?; + + crate::utils::command( + Command::new("../configure") + .current_dir(build_directory) + .arg(format!("--prefix={}", target_directory.to_string_lossy())) + .arg(format!( + "--syslibdir={}/lib/", + target_directory.to_string_lossy() + )) + .arg("--enable-wrapper='clang'"), + "MUSL configuring", + )?; + crate::utils::command( + Command::new("make") + .current_dir(build_directory) + .arg("-j") + .arg(num_cpus::get().to_string()), + "MUSL building", + )?; + crate::utils::command( + Command::new("make") + .current_dir(build_directory) + .arg("install"), + "MUSL installing", + )?; + + let mut include_directory = target_directory.to_path_buf(); + include_directory.push("include/"); + + let mut asm_include_directory = include_directory.clone(); + asm_include_directory.push("asm/"); + std::fs::create_dir_all(asm_include_directory.as_path())?; + + let mut types_header_path = asm_include_directory.clone(); + types_header_path.push("types.h"); + + let copy_options = fs_extra::dir::CopyOptions { + overwrite: true, + copy_inside: true, + ..Default::default() + }; + fs_extra::dir::copy("/usr/include/linux", include_directory, ©_options)?; + + let copy_options = fs_extra::dir::CopyOptions { + overwrite: true, + copy_inside: true, + content_only: true, + ..Default::default() + }; + fs_extra::dir::copy( + "/usr/include/asm-generic", + asm_include_directory, + ©_options, + )?; + + crate::utils::command( + Command::new("sed") + .arg("-i") + .arg("s/asm-generic/asm/") + .arg(types_header_path), + "types_header asm signature replacement", + )?; + + Ok(()) +} + +/// The build options to enable assertions. +pub fn shared_build_opts_assertions(enabled: bool) -> Vec { + vec![format!( + "-DLLVM_ENABLE_ASSERTIONS='{}'", + if enabled { "On" } else { "Off" }, + )] +} + +/// The build options to build with RTTI support. +pub fn shared_build_opts_rtti(enabled: bool) -> Vec { + vec![format!( + "-DLLVM_ENABLE_RTTI='{}'", + if enabled { "On" } else { "Off" }, + )] +} + +/// The build options to enable sanitizers. +pub fn shared_build_opts_sanitizers(sanitizer: Option) -> Vec { + match sanitizer { + Some(sanitizer) => vec![format!("-DLLVM_USE_SANITIZER='{}'", sanitizer)], + None => vec![], + } +} + +/// The build options to enable Valgrind for LLVM regression tests. +pub fn shared_build_opts_valgrind(enabled: bool) -> Vec { + if enabled { + vec!["-DLLVM_LIT_ARGS='-sv --vg --vg-leak'".to_owned()] + } else { + vec![] + } +} + +/// The LLVM tests build options shared by all platforms. +pub fn shared_build_opts_tests(enabled: bool) -> Vec { + vec![ + format!( + "-DLLVM_BUILD_UTILS='{}'", + if enabled { "On" } else { "Off" }, + ), + format!( + "-DLLVM_BUILD_TESTS='{}'", + if enabled { "On" } else { "Off" }, + ), + format!( + "-DLLVM_INCLUDE_UTILS='{}'", + if enabled { "On" } else { "Off" }, + ), + format!( + "-DLLVM_INCLUDE_TESTS='{}'", + if enabled { "On" } else { "Off" }, + ), + ] +} + +/// The code coverage build options shared by all platforms. +pub fn shared_build_opts_coverage(enabled: bool) -> Vec { + vec![format!( + "-DLLVM_BUILD_INSTRUMENTED_COVERAGE='{}'", + if enabled { "On" } else { "Off" }, + )] +} + +/// Use of compiler cache (ccache) to speed up the build process. +pub fn shared_build_opts_ccache(ccache_variant: Option) -> Vec { + match ccache_variant { + Some(ccache_variant) => vec![ + format!( + "-DCMAKE_C_COMPILER_LAUNCHER='{}'", + ccache_variant.to_string() + ), + format!( + "-DCMAKE_CXX_COMPILER_LAUNCHER='{}'", + ccache_variant.to_string() + ), + ], + None => vec![], + } +} + +/// Ignore duplicate libraries warnings for MacOS with XCode>=15. +pub fn macos_build_opts_ignore_dupicate_libs_warnings() -> Vec { + let xcode_version = + crate::utils::get_xcode_version().unwrap_or(crate::utils::XCODE_MIN_VERSION); + if xcode_version >= crate::utils::XCODE_VERSION_15 { + vec![ + "-DCMAKE_EXE_LINKER_FLAGS='-Wl,-no_warn_duplicate_libraries'".to_owned(), + "-DCMAKE_SHARED_LINKER_FLAGS='-Wl,-no_warn_duplicate_libraries'".to_owned(), + ] + } else { + vec![] + } +} diff --git a/crates/llvm-builder/src/platforms/wasm32_emscripten.rs b/crates/llvm-builder/src/platforms/wasm32_emscripten.rs new file mode 100644 index 00000000..5b209c2c --- /dev/null +++ b/crates/llvm-builder/src/platforms/wasm32_emscripten.rs @@ -0,0 +1,224 @@ +//! The revive LLVM `wasm32_unknown_emscripten` builder. +//! +//! Cross-compiling LLVM for Emscripten requires llvm-tblgen, clang-tblgen and llvm-config. + +use std::{collections::HashSet, path::Path, process::Command}; + +/// The building sequence. +#[allow(clippy::too_many_arguments)] +pub fn build( + build_type: crate::BuildType, + targets: HashSet, + llvm_projects: HashSet, + enable_rtti: bool, + default_target: Option, + enable_tests: bool, + enable_coverage: bool, + extra_args: &[String], + ccache_variant: Option, + enable_assertions: bool, + sanitizer: Option, + enable_valgrind: bool, +) -> anyhow::Result<()> { + crate::utils::check_presence("cmake")?; + crate::utils::check_presence("ninja")?; + crate::utils::check_presence("emsdk")?; + crate::utils::check_presence("clang")?; + crate::utils::check_presence("clang++")?; + if cfg!(target_os = "linux") { + crate::utils::check_presence("lld")?; + } + + let llvm_module_llvm = crate::LLVMPath::llvm_module_llvm()?; + let llvm_host_module_llvm = crate::LLVMPath::llvm_host_module_llvm()?; + + let llvm_build_host = crate::LLVMPath::llvm_build_host()?; + let llvm_target_host = crate::LLVMPath::llvm_target_host()?; + + let llvm_build_final = crate::LLVMPath::llvm_build_final()?; + let llvm_target_final = crate::LLVMPath::llvm_target_final()?; + + build_host( + llvm_host_module_llvm.as_path(), + llvm_build_host.as_path(), + llvm_target_host.as_path(), + ccache_variant, + )?; + + build_target( + build_type, + targets, + llvm_projects, + enable_rtti, + default_target, + llvm_module_llvm.as_path(), + llvm_build_final.as_path(), + llvm_target_final.as_path(), + llvm_target_host.as_path(), + enable_tests, + enable_coverage, + extra_args, + ccache_variant, + enable_assertions, + sanitizer, + enable_valgrind, + )?; + + Ok(()) +} + +/// The host toolchain building sequence. +fn build_host( + source_directory: &Path, + build_directory: &Path, + target_directory: &Path, + ccache_variant: Option, +) -> anyhow::Result<()> { + log::info!("building the LLVM Emscripten host utilities"); + + crate::utils::command( + Command::new("cmake") + .args([ + "-S", + source_directory.to_string_lossy().as_ref(), + "-B", + build_directory.to_string_lossy().as_ref(), + "-G", + "Ninja", + "-DLINKER_SUPPORTS_COLOR_DIAGNOSTICS=0", + &format!( + "-DCMAKE_INSTALL_PREFIX='{}'", + target_directory.to_string_lossy() + ), + "-DLLVM_BUILD_SHARED_LIBS='Off'", + "-DCMAKE_BUILD_TYPE='Release'", + &format!( + "-DLLVM_TARGETS_TO_BUILD='WebAssembly;{}'", + crate::Platform::PolkaVM + ), + "-DLLVM_ENABLE_PROJECTS='clang;lld'", + ]) + .args(crate::platforms::shared::SHARED_BUILD_OPTS) + .args(crate::platforms::shared::SHARED_BUILD_OPTS_NOT_MUSL) + .args(crate::platforms::shared::shared_build_opts_ccache( + ccache_variant, + )), + "LLVM host building cmake config", + )?; + + crate::utils::ninja(build_directory)?; + + Ok(()) +} + +/// The target toolchain building sequence. +#[allow(clippy::too_many_arguments)] +fn build_target( + build_type: crate::BuildType, + targets: HashSet, + llvm_projects: HashSet, + enable_rtti: bool, + default_target: Option, + source_directory: &Path, + build_directory: &Path, + target_directory: &Path, + host_target_directory: &Path, + enable_tests: bool, + enable_coverage: bool, + extra_args: &[String], + ccache_variant: Option, + enable_assertions: bool, + sanitizer: Option, + enable_valgrind: bool, +) -> anyhow::Result<()> { + let mut llvm_tblgen_path = host_target_directory.to_path_buf(); + llvm_tblgen_path.push("bin/llvm-tblgen"); + + let mut clang_tblgen_path = host_target_directory.to_path_buf(); + clang_tblgen_path.push("bin/clang-tblgen"); + + crate::utils::command( + Command::new("emcmake") + .env("EMCC_DEBUG", "2") + .env("CXXFLAGS", "-Dwait4=__syscall_wait4") + .env("LDFLAGS", "-lnodefs.js -s NO_INVOKE_RUN -s EXIT_RUNTIME -s INITIAL_MEMORY=64MB -s ALLOW_MEMORY_GROWTH -s EXPORTED_RUNTIME_METHODS=FS,callMain,NODEFS -s MODULARIZE -s EXPORT_ES6 -s WASM_BIGINT") + .arg("cmake") + .args([ + "-S", + source_directory.to_string_lossy().as_ref(), + "-B", + build_directory.to_string_lossy().as_ref(), + "-G", + "Ninja", + "-DLINKER_SUPPORTS_COLOR_DIAGNOSTICS=0", + "-DCMAKE_BUILD_WITH_INSTALL_RPATH=1", + // Enable thin LTO but emscripten has various issues with it. + // FIXME: https://github.com/paritytech/revive/issues/148 + //"-DLLVM_ENABLE_LTO='Thin'", + //"-DCMAKE_EXE_LINKER_FLAGS='-Wl,-u,htons -Wl,-u,htonl -Wl,-u,fileno -Wl,-u,ntohs'", + &format!( + "-DCMAKE_INSTALL_PREFIX='{}'", + target_directory.to_string_lossy() + ), + &format!("-DCMAKE_BUILD_TYPE='{build_type}'"), + &format!( + "-DLLVM_TARGETS_TO_BUILD='{}'", + targets + .into_iter() + .map(|platform| platform.to_string()) + .collect::>() + .join(";") + ), + &format!( + "-DLLVM_ENABLE_PROJECTS='{}'", + llvm_projects + .into_iter() + .map(|project| project.to_string()) + .collect::>() + .join(";") + ), + "-DLLVM_BUILD_SHARED_LIBS='Off'", + "-DLLVM_ENABLE_DUMP='Off'", + "-DLLVM_ENABLE_EXPENSIVE_CHECKS='Off'", + "-DLLVM_ENABLE_BACKTRACES='Off'", + "-DLLVM_ENABLE_BACKTRACES='Off'", + "-DLLVM_ENABLE_THREADS='Off'", + "-DLLVM_BUILD_TOOLS='Off'", + &format!("-DLLVM_TABLEGEN='{}'", llvm_tblgen_path.to_string_lossy()), + &format!("-DCLANG_TABLEGEN='{}'", clang_tblgen_path.to_string_lossy()), + ]) + .args(crate::platforms::shared::shared_build_opts_default_target( + default_target, + )) + .args(crate::platforms::shared::SHARED_BUILD_OPTS) + .args(crate::platforms::shared::SHARED_BUILD_OPTS_NOT_MUSL) + .args(crate::platforms::shared::shared_build_opts_werror(crate::target_env::TargetEnv::Emscripten)) + .args(crate::platforms::shared::shared_build_opts_tests( + enable_tests, + )) + .args(crate::platforms::shared::shared_build_opts_coverage( + enable_coverage, + )) + .args(extra_args) + .args(crate::platforms::shared::shared_build_opts_ccache( + ccache_variant, + )) + .args(crate::platforms::shared::shared_build_opts_assertions( + enable_assertions, + )) + .args(crate::platforms::shared::shared_build_opts_rtti( + enable_rtti, + )) + .args(crate::platforms::shared::shared_build_opts_sanitizers( + sanitizer, + )) + .args(crate::platforms::shared::shared_build_opts_valgrind( + enable_valgrind, + )), + "LLVM target building cmake", + )?; + + crate::utils::ninja(build_directory)?; + + Ok(()) +} diff --git a/crates/llvm-builder/src/platforms/x86_64_linux_gnu.rs b/crates/llvm-builder/src/platforms/x86_64_linux_gnu.rs new file mode 100644 index 00000000..c3aa7333 --- /dev/null +++ b/crates/llvm-builder/src/platforms/x86_64_linux_gnu.rs @@ -0,0 +1,111 @@ +//! The revive LLVM amd64 `linux-gnu` builder. + +use std::collections::HashSet; +use std::process::Command; + +use crate::build_type::BuildType; +use crate::ccache_variant::CcacheVariant; +use crate::llvm_path::LLVMPath; +use crate::llvm_project::LLVMProject; +use crate::platforms::Platform; +use crate::sanitizer::Sanitizer; +use crate::target_triple::TargetTriple; + +/// The building sequence. +#[allow(clippy::too_many_arguments)] +pub fn build( + build_type: BuildType, + targets: HashSet, + llvm_projects: HashSet, + enable_rtti: bool, + default_target: Option, + enable_tests: bool, + enable_coverage: bool, + extra_args: &[String], + ccache_variant: Option, + enable_assertions: bool, + sanitizer: Option, + enable_valgrind: bool, +) -> anyhow::Result<()> { + crate::utils::check_presence("cmake")?; + crate::utils::check_presence("clang")?; + crate::utils::check_presence("clang++")?; + crate::utils::check_presence("lld")?; + crate::utils::check_presence("ninja")?; + + let llvm_module_llvm = LLVMPath::llvm_module_llvm()?; + let llvm_build_final = LLVMPath::llvm_build_final()?; + let llvm_target_final = LLVMPath::llvm_target_final()?; + + crate::utils::command( + Command::new("cmake") + .args([ + "-S", + llvm_module_llvm.to_string_lossy().as_ref(), + "-B", + llvm_build_final.to_string_lossy().as_ref(), + "-G", + "Ninja", + format!( + "-DCMAKE_INSTALL_PREFIX='{}'", + llvm_target_final.to_string_lossy().as_ref(), + ) + .as_str(), + format!("-DCMAKE_BUILD_TYPE='{build_type}'").as_str(), + "-DCMAKE_C_COMPILER='clang'", + "-DCMAKE_CXX_COMPILER='clang++'", + format!( + "-DLLVM_TARGETS_TO_BUILD='{}'", + targets + .into_iter() + .map(|platform| platform.to_string()) + .collect::>() + .join(";") + ) + .as_str(), + format!( + "-DLLVM_ENABLE_PROJECTS='{}'", + llvm_projects + .into_iter() + .map(|project| project.to_string()) + .collect::>() + .join(";") + ) + .as_str(), + "-DLLVM_USE_LINKER='lld'", + ]) + .args(crate::platforms::shared::shared_build_opts_default_target( + default_target, + )) + .args(crate::platforms::shared::shared_build_opts_tests( + enable_tests, + )) + .args(crate::platforms::shared::shared_build_opts_coverage( + enable_coverage, + )) + .args(crate::platforms::shared::shared_build_opts_ccache( + ccache_variant, + )) + .args(crate::platforms::shared::SHARED_BUILD_OPTS) + .args(crate::platforms::shared::SHARED_BUILD_OPTS_NOT_MUSL) + .args(crate::platforms::shared::shared_build_opts_werror( + crate::target_env::TargetEnv::GNU, + )) + .args(extra_args) + .args(crate::platforms::shared::shared_build_opts_assertions( + enable_assertions, + )) + .args(crate::platforms::shared::shared_build_opts_rtti( + enable_rtti, + )) + .args(crate::platforms::shared::shared_build_opts_sanitizers( + sanitizer, + )) + .args(crate::platforms::shared::shared_build_opts_valgrind( + enable_valgrind, + )), + "LLVM building cmake", + )?; + crate::utils::ninja(llvm_build_final.as_ref())?; + Ok(()) +} diff --git a/crates/llvm-builder/src/platforms/x86_64_linux_musl.rs b/crates/llvm-builder/src/platforms/x86_64_linux_musl.rs new file mode 100644 index 00000000..74228bc2 --- /dev/null +++ b/crates/llvm-builder/src/platforms/x86_64_linux_musl.rs @@ -0,0 +1,394 @@ +//! The revive LLVM amd64 `linux-musl` builder. + +use std::collections::HashSet; +use std::path::Path; +use std::process::Command; + +use crate::build_type::BuildType; +use crate::ccache_variant::CcacheVariant; +use crate::llvm_path::LLVMPath; +use crate::llvm_project::LLVMProject; +use crate::platforms::Platform; +use crate::sanitizer::Sanitizer; +use crate::target_triple::TargetTriple; + +/// The building sequence. +#[allow(clippy::too_many_arguments)] +pub fn build( + build_type: BuildType, + targets: HashSet, + llvm_projects: HashSet, + enable_rtti: bool, + default_target: Option, + enable_tests: bool, + enable_coverage: bool, + extra_args: &[String], + ccache_variant: Option, + enable_assertions: bool, + sanitizer: Option, + enable_valgrind: bool, +) -> anyhow::Result<()> { + log::info!("building for target x86_64_linux_musl"); + + crate::utils::check_presence("cmake")?; + crate::utils::check_presence("clang")?; + crate::utils::check_presence("clang++")?; + crate::utils::check_presence("lld")?; + crate::utils::check_presence("ninja")?; + + let musl_name = "musl-1.2.3"; + let musl_build = LLVMPath::musl_build(musl_name)?; + let musl_target = LLVMPath::musl_target()?; + + let llvm_module_llvm = LLVMPath::llvm_module_llvm()?; + let llvm_host_module_llvm = LLVMPath::llvm_host_module_llvm()?; + + let llvm_build_crt = LLVMPath::llvm_build_crt()?; + let llvm_target_crt = LLVMPath::llvm_target_crt()?; + + let llvm_build_host = LLVMPath::llvm_build_host()?; + let llvm_target_host = LLVMPath::llvm_target_host()?; + + let llvm_build_final = LLVMPath::llvm_build_final()?; + let llvm_target_final = LLVMPath::llvm_target_final()?; + + if !LLVMPath::musl_source(musl_name)?.exists() { + crate::utils::download_musl(musl_name)?; + } + crate::platforms::shared::build_musl(musl_build.as_path(), musl_target.as_path())?; + build_crt( + targets.clone(), + llvm_host_module_llvm.as_path(), + llvm_build_crt.as_path(), + llvm_target_crt.as_path(), + ccache_variant, + )?; + build_host( + llvm_host_module_llvm.as_path(), + llvm_build_host.as_path(), + llvm_target_host.as_path(), + musl_target.as_path(), + llvm_target_crt.as_path(), + ccache_variant, + )?; + build_target( + build_type, + targets, + llvm_projects, + enable_rtti, + default_target, + llvm_module_llvm.as_path(), + llvm_build_final.as_path(), + llvm_target_final.as_path(), + musl_target.as_path(), + llvm_target_host.as_path(), + enable_tests, + enable_coverage, + extra_args, + ccache_variant, + enable_assertions, + sanitizer, + enable_valgrind, + )?; + + Ok(()) +} + +/// The `crt` building sequence. +fn build_crt( + mut targets: HashSet, + source_directory: &Path, + build_directory: &Path, + target_directory: &Path, + ccache_variant: Option, +) -> anyhow::Result<()> { + targets.insert(Platform::X86); + + crate::utils::command( + Command::new("cmake") + .args([ + "-S", + source_directory.to_string_lossy().as_ref(), + "-B", + build_directory.to_string_lossy().as_ref(), + "-G", + "Ninja", + format!( + "-DCMAKE_INSTALL_PREFIX='{}'", + target_directory.to_string_lossy() + ) + .as_str(), + "-DCMAKE_BUILD_TYPE='Release'", + "-DCMAKE_C_COMPILER='clang'", + "-DCMAKE_CXX_COMPILER='clang++'", + "-DLLVM_ENABLE_PROJECTS='compiler-rt'", + format!("-DLLVM_TARGETS_TO_BUILD='{}'", Platform::X86).as_str(), + "-DLLVM_DEFAULT_TARGET_TRIPLE='x86_64-pc-linux-musl'", + "-DLLVM_BUILD_TESTS='Off'", + "-DLLVM_BUILD_RUNTIMES='Off'", + "-DLLVM_BUILD_UTILS='Off'", + "-DLLVM_INCLUDE_TESTS='Off'", + "-DLLVM_INCLUDE_RUNTIMES='Off'", + "-DLLVM_INCLUDE_UTILS='Off'", + "-DCOMPILER_RT_DEFAULT_TARGET_ARCH='x86_64'", + "-DCOMPILER_RT_BUILD_CRT='On'", + "-DCOMPILER_RT_BUILD_SANITIZERS='Off'", + "-DCOMPILER_RT_BUILD_XRAY='Off'", + "-DCOMPILER_RT_BUILD_LIBFUZZER='Off'", + "-DCOMPILER_RT_BUILD_PROFILE='Off'", + "-DCOMPILER_RT_BUILD_MEMPROF='Off'", + "-DCOMPILER_RT_BUILD_ORC='Off'", + ]) + .args(crate::platforms::shared::SHARED_BUILD_OPTS) + .args(crate::platforms::shared::shared_build_opts_ccache( + ccache_variant, + )), + "CRT building cmake", + )?; + + crate::utils::command( + Command::new("ninja") + .arg("-C") + .arg(build_directory) + .arg("install-crt"), + "CRT building ninja", + )?; + + Ok(()) +} + +/// The host toolchain building sequence. +fn build_host( + source_directory: &Path, + build_directory: &Path, + target_directory: &Path, + musl_target_directory: &Path, + crt_target_directory: &Path, + ccache_variant: Option, +) -> anyhow::Result<()> { + crate::utils::command( + Command::new("cmake") + .args([ + "-S", + source_directory.to_string_lossy().as_ref(), + "-B", + build_directory.to_string_lossy().as_ref(), + "-G", + "Ninja", + format!( + "-DDEFAULT_SYSROOT='{}'", + musl_target_directory.to_string_lossy() + ) + .as_str(), + "-DLINKER_SUPPORTS_COLOR_DIAGNOSTICS=0", + format!( + "-DCMAKE_INSTALL_PREFIX='{}'", + target_directory.to_string_lossy() + ) + .as_str(), + "-DCMAKE_BUILD_TYPE='Release'", + "-DCMAKE_C_COMPILER='clang'", + "-DCMAKE_CXX_COMPILER='clang++'", + "-DCLANG_DEFAULT_CXX_STDLIB='libc++'", + "-DCLANG_DEFAULT_RTLIB='compiler-rt'", + "-DLLVM_DEFAULT_TARGET_TRIPLE='x86_64-pc-linux-musl'", + "-DLLVM_TARGETS_TO_BUILD='X86'", + "-DLLVM_BUILD_TESTS='Off'", + "-DLLVM_BUILD_UTILS='Off'", + "-DLLVM_INCLUDE_TESTS='Off'", + "-DLLVM_INCLUDE_UTILS='Off'", + "-DLLVM_ENABLE_PROJECTS='clang;lld'", + "-DLLVM_ENABLE_RUNTIMES='compiler-rt;libcxx;libcxxabi;libunwind'", + "-DLIBCXX_CXX_ABI='libcxxabi'", + "-DLIBCXX_HAS_MUSL_LIBC='On'", + "-DLIBCXX_ENABLE_SHARED='Off'", + "-DLIBCXX_ENABLE_STATIC='On'", + "-DLIBCXX_ENABLE_STATIC_ABI_LIBRARY='On'", + "-DLIBCXXABI_ENABLE_SHARED='Off'", + "-DLIBCXXABI_ENABLE_STATIC='On'", + "-DLIBCXXABI_ENABLE_STATIC_UNWINDER='On'", + "-DLIBCXXABI_USE_LLVM_UNWINDER='On'", + "-DLIBCXXABI_USE_COMPILER_RT='On'", + "-DLIBUNWIND_ENABLE_STATIC='On'", + "-DLIBUNWIND_ENABLE_SHARED='Off'", + "-DCOMPILER_RT_BUILD_CRT='On'", + "-DCOMPILER_RT_BUILD_SANITIZERS='Off'", + "-DCOMPILER_RT_BUILD_XRAY='Off'", + "-DCOMPILER_RT_BUILD_LIBFUZZER='Off'", + "-DCOMPILER_RT_BUILD_PROFILE='On'", + "-DCOMPILER_RT_BUILD_MEMPROF='Off'", + "-DCOMPILER_RT_BUILD_ORC='Off'", + "-DCOMPILER_RT_DEFAULT_TARGET_ARCH='x86_64'", + "-DCOMPILER_RT_DEFAULT_TARGET_ONLY='On'", + "-DLIBCLANG_BUILD_STATIC='On'", + "-DBUILD_SHARED_LIBS='Off'", + ]) + .args(crate::platforms::shared::SHARED_BUILD_OPTS) + .args(crate::platforms::shared::shared_build_opts_ccache( + ccache_variant, + )), + "LLVM host building cmake", + )?; + + let mut crt_lib_directory = crt_target_directory.to_path_buf(); + crt_lib_directory.push("lib/"); + + let mut build_lib_directory = build_directory.to_path_buf(); + build_lib_directory.push("lib/"); + + let copy_options = fs_extra::dir::CopyOptions { + overwrite: true, + copy_inside: true, + content_only: true, + ..Default::default() + }; + fs_extra::dir::copy(crt_lib_directory, build_lib_directory, ©_options)?; + + crate::utils::command( + Command::new("ninja") + .arg("-C") + .arg(build_directory) + .arg("install"), + "LLVM host building ninja", + )?; + + Ok(()) +} + +/// The target toolchain building sequence. +#[allow(clippy::too_many_arguments)] +fn build_target( + build_type: BuildType, + targets: HashSet, + llvm_projects: HashSet, + enable_rtti: bool, + default_target: Option, + source_directory: &Path, + build_directory: &Path, + target_directory: &Path, + musl_target_directory: &Path, + host_target_directory: &Path, + enable_tests: bool, + enable_coverage: bool, + extra_args: &[String], + ccache_variant: Option, + enable_assertions: bool, + sanitizer: Option, + enable_valgrind: bool, +) -> anyhow::Result<()> { + let mut clang_path = host_target_directory.to_path_buf(); + clang_path.push("bin/clang"); + + let mut clang_cxx_path = host_target_directory.to_path_buf(); + clang_cxx_path.push("bin/clang++"); + + crate::utils::command( + Command::new("cmake") + .args([ + "-S", + source_directory.to_string_lossy().as_ref(), + "-B", + build_directory.to_string_lossy().as_ref(), + "-G", + "Ninja", + "-DBUILD_SHARED_LIBS='Off'", + "-DLIBCLANG_BUILD_STATIC='On'", + "-DLLVM_BUILD_STATIC='On'", + "-DLINKER_SUPPORTS_COLOR_DIAGNOSTICS=0", + format!( + "-DCMAKE_INSTALL_PREFIX='{}'", + target_directory.to_string_lossy() + ) + .as_str(), + format!("-DCMAKE_BUILD_TYPE='{build_type}'").as_str(), + format!("-DCMAKE_C_COMPILER='{}'", clang_path.to_string_lossy()).as_str(), + format!( + "-DCMAKE_CXX_COMPILER='{}'", + clang_cxx_path.to_string_lossy() + ) + .as_str(), + "-DCMAKE_FIND_LIBRARY_SUFFIXES='.a'", + "-DCMAKE_BUILD_WITH_INSTALL_RPATH=1", + "-DCMAKE_EXE_LINKER_FLAGS='-fuse-ld=lld -static'", + format!( + "-DLLVM_TARGETS_TO_BUILD='{}'", + targets + .into_iter() + .map(|platform| platform.to_string()) + .collect::>() + .join(";") + ) + .as_str(), + format!( + "-DLLVM_ENABLE_PROJECTS='{}'", + llvm_projects + .into_iter() + .map(|project| project.to_string()) + .collect::>() + .join(";") + ) + .as_str(), + ]) + .args(crate::platforms::shared::shared_build_opts_default_target( + default_target, + )) + .args(crate::platforms::shared::SHARED_BUILD_OPTS) + .args(crate::platforms::shared::SHARED_BUILD_OPTS_NOT_MUSL) + .args(crate::platforms::shared::shared_build_opts_werror( + crate::target_env::TargetEnv::MUSL, + )) + .args(crate::platforms::shared::shared_build_opts_tests( + enable_tests, + )) + .args(crate::platforms::shared::shared_build_opts_coverage( + enable_coverage, + )) + .args(extra_args) + .args(crate::platforms::shared::shared_build_opts_ccache( + ccache_variant, + )) + .args(crate::platforms::shared::shared_build_opts_assertions( + enable_assertions, + )) + .args(crate::platforms::shared::shared_build_opts_rtti( + enable_rtti, + )) + .args(crate::platforms::shared::shared_build_opts_sanitizers( + sanitizer, + )) + .args(crate::platforms::shared::shared_build_opts_valgrind( + enable_valgrind, + )), + "LLVM target building cmake", + )?; + + crate::utils::ninja(build_directory)?; + + let mut musl_lib_directory = musl_target_directory.to_path_buf(); + musl_lib_directory.push("lib/"); + + let mut host_lib_directory = host_target_directory.to_path_buf(); + host_lib_directory.push("lib/x86_64-pc-linux-musl/"); + + let mut target_lib_directory = target_directory.to_path_buf(); + target_lib_directory.push("lib/"); + + let copy_options = fs_extra::dir::CopyOptions { + overwrite: true, + copy_inside: true, + content_only: true, + ..Default::default() + }; + fs_extra::dir::copy( + musl_lib_directory, + target_lib_directory.as_path(), + ©_options, + )?; + fs_extra::dir::copy( + host_lib_directory, + target_lib_directory.as_path(), + ©_options, + )?; + + Ok(()) +} diff --git a/crates/llvm-builder/src/platforms/x86_64_macos.rs b/crates/llvm-builder/src/platforms/x86_64_macos.rs new file mode 100644 index 00000000..4a037511 --- /dev/null +++ b/crates/llvm-builder/src/platforms/x86_64_macos.rs @@ -0,0 +1,105 @@ +//! The revive LLVM amd64 `macos` builder. + +use std::collections::HashSet; +use std::process::Command; + +use crate::build_type::BuildType; +use crate::ccache_variant::CcacheVariant; +use crate::llvm_path::LLVMPath; +use crate::llvm_project::LLVMProject; +use crate::platforms::Platform; +use crate::sanitizer::Sanitizer; +use crate::target_triple::TargetTriple; + +/// The building sequence. +#[allow(clippy::too_many_arguments)] +pub fn build( + build_type: BuildType, + targets: HashSet, + llvm_projects: HashSet, + enable_rtti: bool, + default_target: Option, + enable_tests: bool, + enable_coverage: bool, + extra_args: &[String], + ccache_variant: Option, + enable_assertions: bool, + sanitizer: Option, +) -> anyhow::Result<()> { + crate::utils::check_presence("cmake")?; + crate::utils::check_presence("ninja")?; + + let llvm_module_llvm = LLVMPath::llvm_module_llvm()?; + let llvm_build_final = LLVMPath::llvm_build_final()?; + let llvm_target_final = LLVMPath::llvm_target_final()?; + + crate::utils::command( + Command::new("cmake") + .args([ + "-S", + llvm_module_llvm.to_string_lossy().as_ref(), + "-B", + llvm_build_final.to_string_lossy().as_ref(), + "-G", + "Ninja", + format!( + "-DCMAKE_INSTALL_PREFIX='{}'", + llvm_target_final.to_string_lossy().as_ref(), + ) + .as_str(), + format!("-DCMAKE_BUILD_TYPE='{build_type}'").as_str(), + format!( + "-DLLVM_TARGETS_TO_BUILD='{}'", + targets + .into_iter() + .map(|platform| platform.to_string()) + .collect::>() + .join(";") + ) + .as_str(), + format!( + "-DLLVM_ENABLE_PROJECTS='{}'", + llvm_projects + .into_iter() + .map(|project| project.to_string()) + .collect::>() + .join(";") + ) + .as_str(), + "-DCMAKE_OSX_DEPLOYMENT_TARGET='11.0'", + ]) + .args(crate::platforms::shared::shared_build_opts_default_target( + default_target, + )) + .args(crate::platforms::shared::shared_build_opts_tests( + enable_tests, + )) + .args(crate::platforms::shared::shared_build_opts_coverage( + enable_coverage, + )) + .args(crate::platforms::shared::SHARED_BUILD_OPTS) + .args(crate::platforms::shared::SHARED_BUILD_OPTS_NOT_MUSL) + .args(crate::platforms::shared::shared_build_opts_werror( + crate::target_env::TargetEnv::GNU, + )) + .args(extra_args) + .args(crate::platforms::shared::shared_build_opts_ccache( + ccache_variant, + )) + .args(crate::platforms::shared::shared_build_opts_assertions( + enable_assertions, + )) + .args(crate::platforms::shared::shared_build_opts_rtti( + enable_rtti, + )) + .args(crate::platforms::shared::macos_build_opts_ignore_dupicate_libs_warnings()) + .args(crate::platforms::shared::shared_build_opts_sanitizers( + sanitizer, + )), + "LLVM building cmake", + )?; + + crate::utils::ninja(llvm_build_final.as_ref())?; + + Ok(()) +} diff --git a/crates/llvm-builder/src/platforms/x86_64_windows_gnu.rs b/crates/llvm-builder/src/platforms/x86_64_windows_gnu.rs new file mode 100644 index 00000000..0e80d9df --- /dev/null +++ b/crates/llvm-builder/src/platforms/x86_64_windows_gnu.rs @@ -0,0 +1,127 @@ +//! The revive LLVM amd64 `windows-gnu` builder. + +use std::collections::HashSet; +use std::path::PathBuf; +use std::process::Command; + +use crate::build_type::BuildType; +use crate::ccache_variant::CcacheVariant; +use crate::llvm_path::LLVMPath; +use crate::llvm_project::LLVMProject; +use crate::platforms::Platform; +use crate::sanitizer::Sanitizer; +use crate::target_triple::TargetTriple; + +/// The building sequence. +#[allow(clippy::too_many_arguments)] +pub fn build( + build_type: BuildType, + targets: HashSet, + llvm_projects: HashSet, + enable_rtti: bool, + default_target: Option, + enable_tests: bool, + enable_coverage: bool, + extra_args: &[String], + ccache_variant: Option, + enable_assertions: bool, + sanitizer: Option, +) -> anyhow::Result<()> { + crate::utils::check_presence("cmake")?; + crate::utils::check_presence("clang")?; + crate::utils::check_presence("clang++")?; + crate::utils::check_presence("lld")?; + crate::utils::check_presence("ninja")?; + + let llvm_module_llvm = + LLVMPath::llvm_module_llvm().and_then(crate::utils::path_windows_to_unix)?; + let llvm_build_final = + LLVMPath::llvm_build_final().and_then(crate::utils::path_windows_to_unix)?; + let llvm_target_final = + LLVMPath::llvm_target_final().and_then(crate::utils::path_windows_to_unix)?; + + crate::utils::command( + Command::new("cmake") + .args([ + "-S", + llvm_module_llvm.to_string_lossy().as_ref(), + "-B", + llvm_build_final.to_string_lossy().as_ref(), + "-G", + "Ninja", + format!( + "-DCMAKE_INSTALL_PREFIX='{}'", + llvm_target_final.to_string_lossy().as_ref(), + ) + .as_str(), + format!("-DCMAKE_BUILD_TYPE='{build_type}'").as_str(), + "-DCMAKE_C_COMPILER='clang'", + "-DCMAKE_CXX_COMPILER='clang++'", + format!( + "-DLLVM_TARGETS_TO_BUILD='{}'", + targets + .into_iter() + .map(|platform| platform.to_string()) + .collect::>() + .join(";") + ) + .as_str(), + format!( + "-DLLVM_ENABLE_PROJECTS='{}'", + llvm_projects + .into_iter() + .map(|project| project.to_string()) + .collect::>() + .join(";") + ) + .as_str(), + "-DLLVM_USE_LINKER='lld'", + ]) + .args(crate::platforms::shared::shared_build_opts_default_target( + default_target, + )) + .args(crate::platforms::shared::shared_build_opts_tests( + enable_tests, + )) + .args(crate::platforms::shared::shared_build_opts_coverage( + enable_coverage, + )) + .args(crate::platforms::shared::SHARED_BUILD_OPTS) + .args(crate::platforms::shared::SHARED_BUILD_OPTS_NOT_MUSL) + .args(crate::platforms::shared::shared_build_opts_werror( + crate::target_env::TargetEnv::GNU, + )) + .args(extra_args) + .args(crate::platforms::shared::shared_build_opts_ccache( + ccache_variant, + )) + .args(crate::platforms::shared::shared_build_opts_assertions( + enable_assertions, + )) + .args(crate::platforms::shared::shared_build_opts_rtti( + enable_rtti, + )) + .args(crate::platforms::shared::shared_build_opts_sanitizers( + sanitizer, + )), + "LLVM building cmake", + )?; + + crate::utils::ninja(llvm_build_final.as_ref())?; + + let libstdcpp_source_path = match std::env::var("LIBSTDCPP_SOURCE_PATH") { + Ok(libstdcpp_source_path) => PathBuf::from(libstdcpp_source_path), + Err(error) => anyhow::bail!( + "The `LIBSTDCPP_SOURCE_PATH` must be set to the path to the libstdc++.a static library: {}", error + ), + }; + let mut libstdcpp_destination_path = llvm_target_final; + libstdcpp_destination_path.push("./lib/libstdc++.a"); + fs_extra::file::copy( + crate::utils::path_windows_to_unix(libstdcpp_source_path)?, + crate::utils::path_windows_to_unix(libstdcpp_destination_path)?, + &fs_extra::file::CopyOptions::default(), + )?; + + Ok(()) +} diff --git a/crates/llvm-builder/src/revive_llvm/arguments.rs b/crates/llvm-builder/src/revive_llvm/arguments.rs new file mode 100644 index 00000000..0c585906 --- /dev/null +++ b/crates/llvm-builder/src/revive_llvm/arguments.rs @@ -0,0 +1,119 @@ +//! The revive LLVM builder arguments. + +use clap::Parser; +use revive_llvm_builder::ccache_variant::CcacheVariant; + +/// The revive LLVM builder arguments. +#[derive(Debug, Parser)] +#[command(version, about)] +pub struct Arguments { + /// Target environment to build LLVM (gnu, musl, emscripten). + #[arg(long, default_value_t = revive_llvm_builder::target_env::TargetEnv::GNU)] + pub target_env: revive_llvm_builder::target_env::TargetEnv, + + #[command(subcommand)] + pub subcommand: Subcommand, +} + +/// The revive LLVM builder arguments. +#[derive(Debug, clap::Subcommand)] +pub enum Subcommand { + /// Clone the branch specified in `LLVM.lock`. + Clone { + /// Clone with full commits history. + #[arg(long)] + deep: bool, + }, + + /// Build the LLVM framework. + Build { + /// LLVM build type (`Debug`, `Release`, `RelWithDebInfo`, or `MinSizeRel`). + #[arg(long, default_value_t = revive_llvm_builder::BuildType::Release)] + build_type: revive_llvm_builder::BuildType, + + /// Additional targets to build LLVM with. + #[arg(long)] + targets: Vec, + + /// LLVM projects to build LLVM with. + #[arg( + long, + default_values_t = vec![ + revive_llvm_builder::llvm_project::LLVMProject::CLANG, + revive_llvm_builder::llvm_project::LLVMProject::LLD + ] + )] + llvm_projects: Vec, + + /// Whether to build LLVM with run-time type information (RTTI) enabled. + #[arg(long)] + enable_rtti: bool, + + /// The default target to build LLVM with. + #[arg(long)] + default_target: Option, + + /// Whether to build the LLVM tests. + #[arg(long)] + enable_tests: bool, + + /// Whether to build LLVM for source-based code coverage. + #[arg(long)] + enable_coverage: bool, + + /// Extra arguments to pass to CMake. + /// A leading backslash will be unescaped. + #[arg(long)] + extra_args: Vec, + + /// Whether to use compiler cache (ccache) to speed-up builds. + #[arg(long)] + ccache_variant: Option, + + /// Whether to build with assertions enabled or not. + #[arg(long, default_value_t = true)] + enable_assertions: bool, + + /// Build LLVM with sanitizer enabled (`Address`, `Memory`, `MemoryWithOrigins`, `Undefined`, `Thread`, `DataFlow`, or `Address;Undefined`). + #[arg(long)] + sanitizer: Option, + + /// Whether to run LLVM unit tests under valgrind or not. + #[arg(long)] + enable_valgrind: bool, + }, + + /// Checkout the branch specified in `LLVM.lock`. + Checkout { + /// Remove all artifacts preventing the checkout (removes all local changes!). + #[arg(long)] + force: bool, + }, + + /// Clean the build artifacts. + Clean, + + /// Build the LLVM compiler-rt builtins for the PolkaVM target. + Builtins { + /// LLVM build type (`Debug`, `Release`, `RelWithDebInfo`, or `MinSizeRel`). + #[arg(long, default_value_t = revive_llvm_builder::BuildType::Release)] + build_type: revive_llvm_builder::BuildType, + + /// The default target to build LLVM with. + #[arg(long)] + default_target: Option, + + /// Extra arguments to pass to CMake. + /// A leading backslash will be unescaped. + #[arg(long)] + extra_args: Vec, + + /// Whether to use compiler cache (ccache) to speed-up builds. + #[arg(long)] + ccache_variant: Option, + + /// Build LLVM with sanitizer enabled (`Address`, `Memory`, `MemoryWithOrigins`, `Undefined`, `Thread`, `DataFlow`, or `Address;Undefined`). + #[arg(long)] + sanitizer: Option, + }, +} diff --git a/crates/llvm-builder/src/revive_llvm/main.rs b/crates/llvm-builder/src/revive_llvm/main.rs new file mode 100644 index 00000000..6e3b510b --- /dev/null +++ b/crates/llvm-builder/src/revive_llvm/main.rs @@ -0,0 +1,141 @@ +//! The revive LLVM builder. + +pub(crate) mod arguments; + +use std::collections::HashSet; +use std::path::PathBuf; +use std::str::FromStr; + +use anyhow::Context; +use clap::Parser; + +use self::arguments::{Arguments, Subcommand}; + +fn main() { + env_logger::init(); + + match main_inner() { + Ok(()) => std::process::exit(0), + Err(error) => { + log::error!("{error:?}"); + std::process::exit(1) + } + } +} + +fn main_inner() -> anyhow::Result<()> { + let arguments = Arguments::parse(); + + revive_llvm_builder::utils::directory_target_llvm(arguments.target_env); + + match arguments.subcommand { + Subcommand::Clone { deep } => { + let lock = revive_llvm_builder::Lock::try_from(&PathBuf::from( + revive_llvm_builder::lock::LLVM_LOCK_DEFAULT_PATH, + ))?; + revive_llvm_builder::clone(lock, deep, arguments.target_env)?; + } + + Subcommand::Build { + build_type, + targets, + llvm_projects, + enable_rtti, + default_target, + enable_tests, + enable_coverage, + extra_args, + ccache_variant, + enable_assertions, + sanitizer, + enable_valgrind, + } => { + let mut targets = targets + .into_iter() + .map(|target| revive_llvm_builder::Platform::from_str(target.as_str())) + .collect::, String>>() + .map_err(|platform| anyhow::anyhow!("Unknown platform `{}`", platform))?; + targets.insert(revive_llvm_builder::Platform::PolkaVM); + + log::info!("build targets: {:?}", &targets); + + let extra_args_unescaped: Vec = extra_args + .iter() + .map(|argument| { + argument + .strip_prefix('\\') + .unwrap_or(argument.as_str()) + .to_owned() + }) + .collect(); + + log::debug!("extra_args: {:#?}", extra_args); + log::debug!("extra_args_unescaped: {:#?}", extra_args_unescaped); + + if let Some(ccache_variant) = ccache_variant { + revive_llvm_builder::utils::check_presence(ccache_variant.to_string().as_str())?; + } + + let mut projects = llvm_projects + .into_iter() + .map(|project| { + revive_llvm_builder::llvm_project::LLVMProject::from_str( + project.to_string().as_str(), + ) + }) + .collect::, String>>( + ) + .map_err(|project| anyhow::anyhow!("Unknown LLVM project `{}`", project))?; + projects.insert(revive_llvm_builder::llvm_project::LLVMProject::LLD); + + log::info!("build projects: {:?}", &projects); + + revive_llvm_builder::build( + build_type, + arguments.target_env, + targets, + projects, + enable_rtti, + default_target, + enable_tests, + enable_coverage, + &extra_args_unescaped, + ccache_variant, + enable_assertions, + sanitizer, + enable_valgrind, + )?; + } + + Subcommand::Checkout { force } => { + let lock = revive_llvm_builder::Lock::try_from(&PathBuf::from( + revive_llvm_builder::lock::LLVM_LOCK_DEFAULT_PATH, + ))?; + revive_llvm_builder::checkout(lock, force)?; + } + + Subcommand::Clean => { + revive_llvm_builder::clean() + .with_context(|| "Unable to remove target LLVM directory")?; + } + + Subcommand::Builtins { + build_type, + default_target, + extra_args, + ccache_variant, + sanitizer, + } => { + revive_llvm_builder::builtins::build( + build_type, + arguments.target_env, + default_target, + &extra_args, + ccache_variant, + sanitizer, + )?; + } + } + + Ok(()) +} diff --git a/crates/llvm-builder/src/sanitizer.rs b/crates/llvm-builder/src/sanitizer.rs new file mode 100644 index 00000000..5b982e7b --- /dev/null +++ b/crates/llvm-builder/src/sanitizer.rs @@ -0,0 +1,50 @@ +//! LLVM sanitizers. + +/// LLVM sanitizers. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum Sanitizer { + /// The address sanitizer. + Address, + /// The memory sanitizer. + Memory, + /// The memory with origins sanitizer. + MemoryWithOrigins, + /// The undefined behavior sanitizer + Undefined, + /// The thread sanitizer. + Thread, + /// The data flow sanitizer. + DataFlow, + /// Combine address and undefined behavior sanitizer. + AddressUndefined, +} + +impl std::str::FromStr for Sanitizer { + type Err = String; + fn from_str(value: &str) -> Result { + match value.to_lowercase().as_str() { + "address" => Ok(Self::Address), + "memory" => Ok(Self::Memory), + "memorywithorigins" => Ok(Self::MemoryWithOrigins), + "undefined" => Ok(Self::Undefined), + "thread" => Ok(Self::Thread), + "dataflow" => Ok(Self::DataFlow), + "address;undefined" => Ok(Self::AddressUndefined), + value => Err(format!("Unsupported sanitizer: `{}`", value)), + } + } +} + +impl std::fmt::Display for Sanitizer { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + Self::Address => write!(f, "Address"), + Self::Memory => write!(f, "Memory"), + Self::MemoryWithOrigins => write!(f, "MemoryWithOrigins"), + Self::Undefined => write!(f, "Undefined"), + Self::Thread => write!(f, "Thread"), + Self::DataFlow => write!(f, "DataFlow"), + Self::AddressUndefined => write!(f, "Address;Undefined"), + } + } +} diff --git a/crates/llvm-builder/src/target_env.rs b/crates/llvm-builder/src/target_env.rs new file mode 100644 index 00000000..2ddbb1b4 --- /dev/null +++ b/crates/llvm-builder/src/target_env.rs @@ -0,0 +1,36 @@ +//! The target environments to build LLVM. + +/// The list of target environments used as constants. +#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum TargetEnv { + /// The GNU target environment. + #[default] + GNU, + /// The MUSL target environment. + MUSL, + /// The wasm32 Emscripten environment. + Emscripten, +} + +impl std::str::FromStr for TargetEnv { + type Err = String; + + fn from_str(value: &str) -> Result { + match value { + "gnu" => Ok(Self::GNU), + "musl" => Ok(Self::MUSL), + "emscripten" => Ok(Self::Emscripten), + value => Err(format!("Unsupported target environment: `{}`", value)), + } + } +} + +impl std::fmt::Display for TargetEnv { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::GNU => write!(f, "gnu"), + Self::MUSL => write!(f, "musl"), + Self::Emscripten => write!(f, "emscripten"), + } + } +} diff --git a/crates/llvm-builder/src/target_triple.rs b/crates/llvm-builder/src/target_triple.rs new file mode 100644 index 00000000..45a55126 --- /dev/null +++ b/crates/llvm-builder/src/target_triple.rs @@ -0,0 +1,29 @@ +//! The PolkaVM LLVM target triples. + +/// The list of target triples used as constants. +/// +/// It must be in the lowercase. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum TargetTriple { + /// The PolkaVM RISC-V target triple. + PolkaVM, +} + +impl std::str::FromStr for TargetTriple { + type Err = String; + + fn from_str(value: &str) -> Result { + match value { + "polkavm" => Ok(Self::PolkaVM), + value => Err(format!("Unsupported target triple: `{}`", value)), + } + } +} + +impl std::fmt::Display for TargetTriple { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + Self::PolkaVM => write!(f, "riscv64-unknown-elf"), + } + } +} diff --git a/crates/llvm-builder/src/utils.rs b/crates/llvm-builder/src/utils.rs new file mode 100644 index 00000000..5d5dc18e --- /dev/null +++ b/crates/llvm-builder/src/utils.rs @@ -0,0 +1,230 @@ +//! The LLVM builder utilities. + +use std::fs::File; +use std::path::Path; +use std::path::PathBuf; +use std::process::Command; +use std::process::Stdio; +use std::time::Duration; + +use path_slash::PathBufExt; + +/// The LLVM host repository URL. +pub const LLVM_HOST_SOURCE_URL: &str = "https://github.com/llvm/llvm-project"; + +/// The LLVM host repository tag. +pub const LLVM_HOST_SOURCE_TAG: &str = "llvmorg-18.1.8"; + +/// The minimum required XCode version. +pub const XCODE_MIN_VERSION: u32 = 11; + +/// The XCode version 15. +pub const XCODE_VERSION_15: u32 = 15; + +/// The number of download retries if failed. +pub const DOWNLOAD_RETRIES: u16 = 16; + +/// The number of parallel download requests. +pub const DOWNLOAD_PARALLEL_REQUESTS: u16 = 1; + +/// The download timeout in seconds. +pub const DOWNLOAD_TIMEOUT_SECONDS: u64 = 300; + +/// The musl snapshots URL. +pub const MUSL_SNAPSHOTS_URL: &str = "https://git.musl-libc.org/cgit/musl/snapshot"; + +/// The emscripten SDK git URL. +pub const EMSDK_SOURCE_URL: &str = "https://github.com/emscripten-core/emsdk.git"; + +/// The emscripten SDK version. +pub const EMSDK_VERSION: &str = "3.1.64"; + +/// The subprocess runner. +/// +/// Checks the status and prints `stderr`. +pub fn command(command: &mut Command, description: &str) -> anyhow::Result<()> { + log::debug!("executing '{command:?}' ({description})"); + + if std::env::var("DRY_RUN").is_ok() { + log::warn!("Only a dry run; not executing the command."); + return Ok(()); + } + + let status = command + .status() + .map_err(|error| anyhow::anyhow!("{} process: {}", description, error))?; + + if !status.success() { + log::error!("the command '{command:?}' failed!"); + anyhow::bail!("{} failed", description); + } + + Ok(()) +} + +/// Download a file from the URL to the path. +pub fn download(url: &str, path: &str) -> anyhow::Result<()> { + log::trace!("downloading '{url}' into '{path}'"); + + let mut downloader = downloader::Downloader::builder() + .download_folder(Path::new(path)) + .parallel_requests(DOWNLOAD_PARALLEL_REQUESTS) + .retries(DOWNLOAD_RETRIES) + .timeout(Duration::from_secs(DOWNLOAD_TIMEOUT_SECONDS)) + .build()?; + while let Err(error) = downloader.download(&[downloader::Download::new(url)]) { + log::error!("MUSL download from `{url}` failed: {error}"); + } + Ok(()) +} + +/// Unpack a tarball. +pub fn unpack_tar(filename: PathBuf, path: &str) -> anyhow::Result<()> { + let tar_gz = File::open(filename)?; + let tar = flate2::read::GzDecoder::new(tar_gz); + let mut archive = tar::Archive::new(tar); + archive.unpack(path)?; + Ok(()) +} + +/// The `musl` downloading sequence. +pub fn download_musl(name: &str) -> anyhow::Result<()> { + log::info!("downloading musl {name}"); + let tar_file_name = format!("{name}.tar.gz"); + let url = format!("{}/{tar_file_name}", MUSL_SNAPSHOTS_URL); + let target_path = crate::llvm_path::DIRECTORY_LLVM_TARGET + .get() + .unwrap() + .to_string_lossy(); + download(url.as_str(), &target_path)?; + let musl_tarball = crate::LLVMPath::musl_source(tar_file_name.as_str())?; + unpack_tar(musl_tarball, &target_path)?; + Ok(()) +} + +/// Call ninja to build the LLVM. +pub fn ninja(build_dir: &Path) -> anyhow::Result<()> { + let mut ninja = Command::new("ninja"); + ninja.args(["-C", build_dir.to_string_lossy().as_ref()]); + if std::env::var("DRY_RUN").is_ok() { + ninja.arg("-n"); + } + command(ninja.arg("install"), "Running ninja install")?; + Ok(()) +} + +/// Create an absolute path, appending it to the current working directory. +pub fn absolute_path>(path: P) -> anyhow::Result { + let mut full_path = std::env::current_dir()?; + full_path.push(path); + Ok(full_path) +} + +/// +/// Converts a Windows path into a Unix path. +/// +pub fn path_windows_to_unix + PathBufExt>(path: P) -> anyhow::Result { + path.to_slash() + .map(|pathbuf| PathBuf::from(pathbuf.to_string())) + .ok_or_else(|| anyhow::anyhow!("Windows-to-Unix path conversion error")) +} + +/// Checks if the tool exists in the system. +pub fn check_presence(name: &str) -> anyhow::Result<()> { + let description = &format!("checking the `{name}` executable"); + log::info!("{description}"); + + command(Command::new("which").arg(name), description) + .map_err(|_| anyhow::anyhow!("Tool `{}` is missing. Please install", name)) +} + +/// Identify XCode version using `pkgutil`. +pub fn get_xcode_version() -> anyhow::Result { + let pkgutil = Command::new("pkgutil") + .args(["--pkg-info", "com.apple.pkg.CLTools_Executables"]) + .stdout(Stdio::piped()) + .spawn() + .map_err(|error| anyhow::anyhow!("`pkgutil` process: {}", error))?; + let grep_version = Command::new("grep") + .arg("version") + .stdin(Stdio::from(pkgutil.stdout.expect( + "Failed to identify XCode version - XCode or CLI tools are not installed", + ))) + .output() + .map_err(|error| anyhow::anyhow!("`grep` process: {}", error))?; + let version_string = String::from_utf8(grep_version.stdout)?; + let version_regex = regex::Regex::new(r"version: (\d+)\..*")?; + let captures = version_regex + .captures(version_string.as_str()) + .ok_or(anyhow::anyhow!( + "Failed to parse XCode version: {version_string}" + ))?; + let xcode_version: u32 = captures + .get(1) + .expect("Always has a major version") + .as_str() + .parse() + .map_err(|error| anyhow::anyhow!("Failed to parse XCode version: {error}"))?; + Ok(xcode_version) +} + +/// Install the Emscripten SDK. +pub fn install_emsdk() -> anyhow::Result<()> { + log::info!("installing emsdk v{EMSDK_VERSION}"); + + let emsdk_source_path = PathBuf::from(crate::LLVMPath::DIRECTORY_EMSDK_SOURCE); + + if emsdk_source_path.exists() { + log::warn!( + "emsdk source path {emsdk_source_path:?} already exists. + Skipping the emsdk installation, delete the source path for re-installation" + ); + return Ok(()); + } + + crate::utils::command( + Command::new("git") + .arg("clone") + .arg(crate::utils::EMSDK_SOURCE_URL) + .arg(emsdk_source_path.to_string_lossy().as_ref()), + "Emscripten SDK repository cloning", + )?; + + crate::utils::command( + Command::new("git") + .arg("checkout") + .arg(format!("tags/{}", crate::utils::EMSDK_VERSION)) + .current_dir(&emsdk_source_path), + "Emscripten SDK repository version checkout", + )?; + + crate::utils::command( + Command::new("./emsdk") + .arg("install") + .arg(EMSDK_VERSION) + .current_dir(&emsdk_source_path), + "Emscripten SDK installation", + )?; + + crate::utils::command( + Command::new("./emsdk") + .arg("activate") + .arg(EMSDK_VERSION) + .current_dir(&emsdk_source_path), + "Emscripten SDK activation", + )?; + + log::warn!( + "run 'source {}emsdk_env.sh' to finish the emsdk installation", + emsdk_source_path.display() + ); + + Ok(()) +} + +/// The LLVM target directory default path. +pub fn directory_target_llvm(target_env: crate::target_env::TargetEnv) -> PathBuf { + crate::llvm_path::DIRECTORY_LLVM_TARGET + .get_or_init(|| PathBuf::from(format!("./target-llvm/{}/", target_env))) + .clone() +} diff --git a/crates/llvm-builder/tests/build.rs b/crates/llvm-builder/tests/build.rs new file mode 100644 index 00000000..e465885a --- /dev/null +++ b/crates/llvm-builder/tests/build.rs @@ -0,0 +1,158 @@ +pub mod common; + +use std::process::Command; + +use assert_cmd::prelude::*; + +/// This test verifies that the LLVM repository can be successfully cloned, built, and cleaned. +#[test] +fn clone_build_and_clean() -> anyhow::Result<()> { + let test_dir = common::TestDir::with_lockfile(None)?; + + Command::cargo_bin(common::REVIVE_LLVM)? + .current_dir(test_dir.path()) + .arg("clone") + .assert() + .success(); + + Command::cargo_bin(common::REVIVE_LLVM)? + .current_dir(test_dir.path()) + .arg("build") + .arg("--llvm-projects") + .arg("clang") + .arg("--llvm-projects") + .arg("lld") + .assert() + .success(); + + Command::cargo_bin(common::REVIVE_LLVM)? + .current_dir(test_dir.path()) + .arg("builtins") + .assert() + .success(); + + Command::cargo_bin(common::REVIVE_LLVM)? + .current_dir(test_dir.path()) + .arg("clean") + .assert() + .success(); + + Ok(()) +} + +/// This test verifies that the LLVM repository can be successfully cloned, built, and cleaned +/// with 2-staged build using MUSL as sysroot. +#[test] +#[cfg(target_os = "linux")] +fn clone_build_and_clean_musl() -> anyhow::Result<()> { + let test_dir = common::TestDir::with_lockfile(None)?; + + Command::cargo_bin(common::REVIVE_LLVM)? + .arg("clone") + .current_dir(test_dir.path()) + .assert() + .success(); + + Command::cargo_bin(common::REVIVE_LLVM)? + .arg("--target-env") + .arg("musl") + .arg("build") + .arg("--llvm-projects") + .arg("clang") + .arg("--llvm-projects") + .arg("lld") + .current_dir(test_dir.path()) + .assert() + .success(); + + Command::cargo_bin(common::REVIVE_LLVM)? + .current_dir(test_dir.path()) + .arg("builtins") + .assert() + .success(); + + Command::cargo_bin(common::REVIVE_LLVM)? + .current_dir(test_dir.path()) + .arg("clean") + .assert() + .success(); + + Ok(()) +} + +/// This test verifies that the LLVM repository can be successfully cloned and built in debug mode +/// with tests and coverage enabled. +#[test] +fn debug_build_with_tests_coverage() -> anyhow::Result<()> { + let test_dir = common::TestDir::with_lockfile(None)?; + + Command::cargo_bin(common::REVIVE_LLVM)? + .current_dir(test_dir.path()) + .arg("clone") + .assert() + .success(); + + Command::cargo_bin(common::REVIVE_LLVM)? + .current_dir(test_dir.path()) + .arg("build") + .arg("--enable-coverage") + .arg("--enable-tests") + .arg("--build-type") + .arg("Debug") + .assert() + .success(); + + Ok(()) +} + +/// This test verifies that the LLVM repository can be successfully built with address sanitizer. +#[test] +fn build_with_sanitizers() -> anyhow::Result<()> { + let test_dir = common::TestDir::with_lockfile(None)?; + + Command::cargo_bin(common::REVIVE_LLVM)? + .current_dir(test_dir.path()) + .arg("clone") + .assert() + .success(); + + Command::cargo_bin(common::REVIVE_LLVM)? + .current_dir(test_dir.path()) + .arg("build") + .arg("--sanitizer") + .arg("Address") + .assert() + .success(); + + Ok(()) +} + +/// Tests the clone, build, and clean process of the LLVM repository for the emscripten target. +#[test] +#[cfg(any(target_os = "linux", target_os = "macos"))] +fn clone_build_and_clean_emscripten() -> anyhow::Result<()> { + let test_dir = common::TestDir::with_lockfile(None)?; + let command = Command::cargo_bin(common::REVIVE_LLVM)?; + let program = command.get_program().to_string_lossy(); + let emsdk_wrapped_build_command = format!( + "{program} --target-env emscripten clone && \ + source {}emsdk_env.sh && \ + {program} --target-env emscripten build --llvm-projects clang --llvm-projects lld", + revive_llvm_builder::LLVMPath::DIRECTORY_EMSDK_SOURCE, + ); + + Command::new("sh") + .arg("-c") + .arg(emsdk_wrapped_build_command) + .current_dir(test_dir.path()) + .assert() + .success(); + + Command::cargo_bin(common::REVIVE_LLVM)? + .arg("clean") + .current_dir(test_dir.path()) + .assert() + .success(); + + Ok(()) +} diff --git a/crates/llvm-builder/tests/checkout.rs b/crates/llvm-builder/tests/checkout.rs new file mode 100644 index 00000000..2fd8d1c5 --- /dev/null +++ b/crates/llvm-builder/tests/checkout.rs @@ -0,0 +1,48 @@ +pub mod common; + +use std::process::Command; + +use assert_cmd::prelude::*; + +/// This test verifies that after cloning the LLVM repository, checking out a specific branch +/// or reference works as expected. +#[test] +fn checkout_after_clone() -> anyhow::Result<()> { + let test_dir = common::TestDir::with_lockfile(None)?; + + Command::cargo_bin(common::REVIVE_LLVM)? + .current_dir(test_dir.path()) + .arg("clone") + .assert() + .success(); + + Command::cargo_bin(common::REVIVE_LLVM)? + .current_dir(test_dir.path()) + .arg("checkout") + .assert() + .success(); + + Ok(()) +} + +/// This test verifies that after cloning the LLVM repository, checking out a specific branch +/// or reference with the `--force` option works as expected. +#[test] +fn force_checkout() -> anyhow::Result<()> { + let test_dir = common::TestDir::with_lockfile(None)?; + + Command::cargo_bin(common::REVIVE_LLVM)? + .current_dir(test_dir.path()) + .arg("clone") + .assert() + .success(); + + Command::cargo_bin(common::REVIVE_LLVM)? + .current_dir(test_dir.path()) + .arg("checkout") + .arg("--force") + .assert() + .success(); + + Ok(()) +} diff --git a/crates/llvm-builder/tests/clone.rs b/crates/llvm-builder/tests/clone.rs new file mode 100644 index 00000000..8c2dede5 --- /dev/null +++ b/crates/llvm-builder/tests/clone.rs @@ -0,0 +1,36 @@ +pub mod common; + +use std::process::Command; + +use assert_cmd::prelude::*; + +/// This test verifies that the LLVM repository can be successfully cloned using a specific branch +/// and reference. +#[test] +fn clone() -> anyhow::Result<()> { + let test_dir = common::TestDir::with_lockfile(None)?; + + Command::cargo_bin(common::REVIVE_LLVM)? + .current_dir(test_dir.path()) + .arg("clone") + .assert() + .success(); + + Ok(()) +} + +/// This test verifies that the LLVM repository can be successfully cloned using a specific branch +/// and reference with --deep option. +#[test] +fn clone_deep() -> anyhow::Result<()> { + let test_dir = common::TestDir::with_lockfile(None)?; + + Command::cargo_bin(common::REVIVE_LLVM)? + .current_dir(test_dir.path()) + .arg("clone") + .arg("--deep") + .assert() + .success(); + + Ok(()) +} diff --git a/crates/llvm-builder/tests/common.rs b/crates/llvm-builder/tests/common.rs new file mode 100644 index 00000000..78465fc0 --- /dev/null +++ b/crates/llvm-builder/tests/common.rs @@ -0,0 +1,36 @@ +use assert_fs::fixture::FileWriteStr; + +pub const REVIVE_LLVM: &str = "revive-llvm"; +pub const REVIVE_LLVM_REPO_URL: &str = "https://github.com/llvm/llvm-project"; +pub const REVIVE_LLVM_REPO_TEST_BRANCH: &str = "release/18.x"; + +pub struct TestDir { + _lockfile: assert_fs::NamedTempFile, + path: std::path::PathBuf, +} + +/// Creates a temporary lock file for testing. +impl TestDir { + pub fn with_lockfile(reference: Option) -> anyhow::Result { + let file = + assert_fs::NamedTempFile::new(revive_llvm_builder::lock::LLVM_LOCK_DEFAULT_PATH)?; + let lock = revive_llvm_builder::Lock { + url: REVIVE_LLVM_REPO_URL.to_string(), + branch: REVIVE_LLVM_REPO_TEST_BRANCH.to_string(), + r#ref: reference, + }; + file.write_str(toml::to_string(&lock)?.as_str())?; + + Ok(Self { + path: file + .parent() + .expect("lockfile parent dir always exists") + .into(), + _lockfile: file, + }) + } + + pub fn path(&self) -> &std::path::Path { + &self.path + } +} diff --git a/crates/runner/Cargo.toml b/crates/runner/Cargo.toml index c4efd9c5..81a914fd 100644 --- a/crates/runner/Cargo.toml +++ b/crates/runner/Cargo.toml @@ -8,6 +8,7 @@ authors.workspace = true description = "Execute revive contracts in a simulated blockchain runtime" [features] +std = ["polkadot-sdk/std"] default = ["solidity"] solidity = ["revive-solidity", "revive-differential"] diff --git a/crates/runtime-api/Cargo.toml b/crates/runtime-api/Cargo.toml index ccc3cd75..11d35508 100644 --- a/crates/runtime-api/Cargo.toml +++ b/crates/runtime-api/Cargo.toml @@ -12,3 +12,6 @@ anyhow = { workspace = true } inkwell = { workspace = true, features = ["target-riscv", "no-libffi-linking", "llvm18-0"] } revive-common = { workspace = true } + +[build-dependencies] +revive-build-utils = { workspace = true } diff --git a/crates/runtime-api/build.rs b/crates/runtime-api/build.rs index a9225846..2e54fc4d 100644 --- a/crates/runtime-api/build.rs +++ b/crates/runtime-api/build.rs @@ -14,7 +14,7 @@ const EXPORTS_BC: &str = "polkavm_exports.bc"; const EXPORTS_RUST: &str = "polkavm_exports.rs"; fn compile(source_path: &str, bitcode_path: &str) { - let output = Command::new("clang") + let output = Command::new(revive_build_utils::llvm_host_tool("clang")) .args([ TARGET_FLAG, "-Xclang", @@ -37,7 +37,7 @@ fn compile(source_path: &str, bitcode_path: &str) { source_path, ]) .output() - .expect("should be able to invoke C clang"); + .unwrap_or_else(|error| panic!("failed to execute clang: {}", error)); assert!( output.status.success(), @@ -59,6 +59,11 @@ fn build_module(source_path: &str, bitcode_path: &str, rust_file: &str) { } fn main() { + println!( + "cargo:rerun-if-env-changed={}", + revive_build_utils::REVIVE_LLVM_HOST_PREFIX + ); + build_module(IMPORTS_SOUCE, IMPORTS_BC, IMPORTS_RUST); build_module(EXPORTS_SOUCE, EXPORTS_BC, EXPORTS_RUST); diff --git a/crates/stdlib/Cargo.toml b/crates/stdlib/Cargo.toml index 33055e67..c474760e 100644 --- a/crates/stdlib/Cargo.toml +++ b/crates/stdlib/Cargo.toml @@ -8,3 +8,6 @@ description = "revive compiler stdlib components" [dependencies] inkwell = { workspace = true, features = ["target-riscv", "no-libffi-linking", "llvm18-0"] } + +[build-dependencies] +revive-build-utils = { workspace = true } diff --git a/crates/stdlib/build.rs b/crates/stdlib/build.rs index 10f7513a..89553819 100644 --- a/crates/stdlib/build.rs +++ b/crates/stdlib/build.rs @@ -1,18 +1,23 @@ use std::{env, fs, path::Path, process::Command}; fn main() { + println!( + "cargo:rerun-if-env-changed={}", + revive_build_utils::REVIVE_LLVM_HOST_PREFIX + ); + let lib = "stdlib.bc"; let out_dir = env::var_os("OUT_DIR").expect("env should have $OUT_DIR"); let bitcode_path = Path::new(&out_dir).join(lib); - - let output = Command::new("llvm-as") + let llvm_as = revive_build_utils::llvm_host_tool("llvm-as"); + let output = Command::new(llvm_as) .args([ "-o", bitcode_path.to_str().expect("$OUT_DIR should be UTF-8"), "stdlib.ll", ]) .output() - .expect("should be able to invoke llvm-as"); + .unwrap_or_else(|error| panic!("failed to execute llvm-as: {}", error)); assert!( output.status.success(), diff --git a/deny.toml b/deny.toml new file mode 100644 index 00000000..74cac153 --- /dev/null +++ b/deny.toml @@ -0,0 +1,65 @@ +[advisories] +yanked = "warn" +ignore = [ + #"RUSTSEC-0000-0000", +] + +[licenses] +allow = [ + #"Apache-2.0 WITH LLVM-exception", + "MIT", + "Apache-2.0", + "ISC", + "Unlicense", + "MPL-2.0", + "Unicode-DFS-2016", + "Unicode-3.0", + "CC0-1.0", + "BSD-2-Clause", + "BSD-3-Clause", + "Zlib", + "LGPL-3.0", +] +confidence-threshold = 0.8 +exceptions = [ + # Each entry is the crate and version constraint, and its specific allow + # list + #{ allow = ["Zlib"], name = "adler32", version = "*" }, +] + +unused-allowed-license = "allow" + +[licenses.private] +ignore = false +registries = [ + #"https://sekretz.com/registry +] + +[bans] +multiple-versions = "warn" +wildcards = "allow" +highlight = "all" +workspace-default-features = "allow" +external-default-features = "allow" +allow = [ + #{ name = "ansi_term", version = "=0.11.0" }, +] +# List of crates to deny +deny = [ + # Each entry the name of a crate and a version range. If version is + # not specified, all versions will be matched. + #{ name = "ansi_term", version = "=0.11.0" }, +] + +skip = [ + #{ name = "ansi_term", version = "=0.11.0" }, +] +skip-tree = [ + #{ name = "ansi_term", version = "=0.11.0", depth = 20 }, +] + +[sources] +unknown-registry = "deny" +unknown-git = "allow" +allow-registry = ["https://github.com/rust-lang/crates.io-index"] +allow-git = [] diff --git a/emscripten-build-llvm.sh b/emscripten-build-llvm.sh deleted file mode 100755 index c7c7a29d..00000000 --- a/emscripten-build-llvm.sh +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -INSTALL_DIR="${PWD}/llvm18.0-emscripten" -mkdir -p "${INSTALL_DIR}" - -# Check if EMSDK_ROOT is defined -if [ -z "${EMSDK_ROOT:-}" ]; then - echo "Error: EMSDK_ROOT is not defined." - echo "Please set the EMSDK_ROOT environment variable to the root directory of your Emscripten SDK." - exit 1 -fi - -source "${EMSDK_ROOT}/emsdk_env.sh" - -LLVM_SRC="${PWD}/llvm-project" -LLVM_NATIVE="${PWD}/build/llvm-tools" -LLVM_WASM="${PWD}/build/llvm-wasm" - -./clone-llvm.sh "${LLVM_SRC}" - -# Cross-compiling LLVM requires a native build of "llvm-tblgen", "clang-tblgen" and "llvm-config" -if [ ! -d "${LLVM_NATIVE}" ]; then - cmake -G Ninja \ - -S "${LLVM_SRC}/llvm" \ - -B "${LLVM_NATIVE}" \ - -DCMAKE_BUILD_TYPE=Release \ - -DLLVM_TARGETS_TO_BUILD=WebAssembly \ - -DLLVM_ENABLE_PROJECTS="clang" -fi - -cmake --build "${LLVM_NATIVE}" -- llvm-tblgen clang-tblgen llvm-config - -if [ ! -d "${LLVM_WASM}" ]; then - EMCC_DEBUG=2 \ - CXXFLAGS="-Dwait4=__syscall_wait4" \ - LDFLAGS="-lnodefs.js -s NO_INVOKE_RUN -s EXIT_RUNTIME -s INITIAL_MEMORY=64MB -s ALLOW_MEMORY_GROWTH -s \ - EXPORTED_RUNTIME_METHODS=FS,callMain,NODEFS -s MODULARIZE -s EXPORT_ES6 -s WASM_BIGINT" \ - emcmake cmake -G Ninja \ - -S "${LLVM_SRC}/llvm" \ - -B "${LLVM_WASM}" \ - -DCMAKE_BUILD_TYPE=Release \ - -DLLVM_TARGETS_TO_BUILD='RISCV' \ - -DLLVM_ENABLE_PROJECTS="clang;lld" \ - -DLLVM_ENABLE_DUMP=OFF \ - -DLLVM_ENABLE_ASSERTIONS=OFF \ - -DLLVM_ENABLE_EXPENSIVE_CHECKS=OFF \ - -DLLVM_ENABLE_BACKTRACES=OFF \ - -DLLVM_BUILD_TOOLS=OFF \ - -DLLVM_ENABLE_THREADS=OFF \ - -DLLVM_BUILD_LLVM_DYLIB=OFF \ - -DLLVM_INCLUDE_TESTS=OFF \ - -DLLVM_ENABLE_TERMINFO=Off \ - -DLLVM_ENABLE_LIBXML2=Off \ - -DLLVM_ENABLE_ZLIB=Off \ - -DLLVM_ENABLE_ZSTD=Off \ - -DLLVM_TABLEGEN="${LLVM_NATIVE}/bin/llvm-tblgen" \ - -DCLANG_TABLEGEN="${LLVM_NATIVE}/bin/clang-tblgen" \ - -DCMAKE_INSTALL_PREFIX="${INSTALL_DIR}" -fi - -cmake --build "${LLVM_WASM}" -cmake --install "${LLVM_WASM}" - -cp "${LLVM_NATIVE}/bin/llvm-config" "${INSTALL_DIR}/bin" - -echo "" -echo "LLVM cross-compilation for WebAssembly completed successfully." diff --git a/utils/build-debian-builder.sh b/utils/build-debian-builder.sh deleted file mode 100755 index 87c81e0c..00000000 --- a/utils/build-debian-builder.sh +++ /dev/null @@ -1,7 +0,0 @@ -#! /usr/bin/env bash - -CONTAINER=revive-builder-debian-x86 -VERSION=latest -DOCKERFILE=revive-builder-debian.dockerfile - -docker build --rm -t ${CONTAINER}:${VERSION} -f ${DOCKERFILE} $@ diff --git a/utils/build-revive.sh b/utils/build-revive.sh deleted file mode 100755 index a1b1dde0..00000000 --- a/utils/build-revive.sh +++ /dev/null @@ -1,20 +0,0 @@ -#! /usr/bin/env bash - -set -euo pipefail - -REVIVE_INSTALL_DIR=$(pwd)/target/release -while getopts "o:" option ; do - case $option in - o) # Output directory - REVIVE_INSTALL_DIR=$OPTARG - ;; - \?) echo "Error: Invalid option" - exit 1;; - esac -done -echo "Installing to ${REVIVE_INSTALL_DIR}" - -$(pwd)/build-llvm.sh -export PATH=$(pwd)/llvm18.0/bin:$PATH - -make install-revive REVIVE_INSTALL_DIR=${REVIVE_INSTALL_DIR} diff --git a/utils/revive-builder-debian.dockerfile b/utils/revive-builder-debian.dockerfile deleted file mode 100644 index 2631aed7..00000000 --- a/utils/revive-builder-debian.dockerfile +++ /dev/null @@ -1,14 +0,0 @@ -# syntax=docker/dockerfile:1 -# Dockerfile for building revive in a Debian container. -FROM debian:12 -RUN <