diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index db152280..220520a5 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -25,7 +25,26 @@ concurrency: cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} jobs: + seed-build-script: + runs-on: ubuntu-latest + name: Pre-seed static binaries' versions + steps: + - env: + GITHUB_TOKEN: ${{ github.token }} + run: >- + gh release download + -R cpp-linter/clang-tools-static-binaries + --pattern versions.json + --output versions.json + - name: Upload versions.json + uses: actions/upload-artifact@v7 + with: + name: static-binary-versions + path: versions.json + if-no-files-found: error + build-bin: + needs: [seed-build-script] name: Build ${{ matrix.name }} binary runs-on: ubuntu-latest strategy: @@ -60,6 +79,12 @@ jobs: fi - run: rustup update --no-self-update if: steps.cache.outputs.cache-hit != 'true' || steps.validate.outputs.cache-valid == 'false' + - name: Restore build script seed + if: steps.cache.outputs.cache-hit != 'true' || steps.validate.outputs.cache-valid == 'false' + uses: actions/download-artifact@v8 + with: + name: static-binary-versions + path: clang-installer - run: cargo build --bin cpp-linter --features bin --release if: steps.cache.outputs.cache-hit != 'true' || steps.validate.outputs.cache-valid == 'false' - name: Upload build artifact diff --git a/.github/workflows/binary-builds.yml b/.github/workflows/binary-builds.yml index e66c4287..b4b11637 100644 --- a/.github/workflows/binary-builds.yml +++ b/.github/workflows/binary-builds.yml @@ -34,7 +34,26 @@ concurrency: cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} jobs: + seed-build-script: + runs-on: ubuntu-latest + name: Pre-seed static binaries' versions + steps: + - env: + GITHUB_TOKEN: ${{ github.token }} + run: >- + gh release download + -R cpp-linter/clang-tools-static-binaries + --pattern versions.json + --output versions.json + - name: Upload versions.json + uses: actions/upload-artifact@v7 + with: + name: static-binary-versions + path: versions.json + if-no-files-found: error + create-assets: + needs: [seed-build-script] name: ${{ matrix.target }} strategy: fail-fast: false @@ -113,6 +132,12 @@ jobs: GITHUB_TOKEN: ${{ github.token }} run: cargo binstall -y cross + - name: Restore build script seed + uses: actions/download-artifact@v8 + with: + name: static-binary-versions + path: clang-installer + - name: Build run: >- ${{ matrix.cross && 'cross' || 'cargo '}} diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index 20960953..30f743aa 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -44,9 +44,27 @@ jobs: key: ${{ runner.os }}-docs-cargo-${{ hashFiles('Cargo.lock') }} - run: cargo fetch + seed-build-script: + runs-on: ubuntu-latest + name: Pre-seed static binaries' versions + steps: + - env: + GITHUB_TOKEN: ${{ github.token }} + run: >- + gh release download + -R cpp-linter/clang-tools-static-binaries + --pattern versions.json + --output versions.json + - name: Upload versions.json + uses: actions/upload-artifact@v7 + with: + name: static-binary-versions + path: versions.json + if-no-files-found: error + build-mkdocs: runs-on: ubuntu-latest - needs: [cache-deps] + needs: [cache-deps, seed-build-script] steps: - uses: actions/checkout@v6 with: @@ -66,6 +84,11 @@ jobs: run: cargo binstall -y nur env: GITHUB_TOKEN: ${{ github.token }} + - name: Restore build script seed + uses: actions/download-artifact@v8 + with: + name: static-binary-versions + path: clang-installer - name: Build docs run: nur docs --build - name: Upload docs build as artifact @@ -76,7 +99,7 @@ jobs: build-rustdoc: runs-on: ubuntu-latest - needs: [cache-deps] + needs: [cache-deps, seed-build-script] steps: - uses: actions/checkout@v6 with: @@ -97,6 +120,11 @@ jobs: run: cargo binstall -y nur env: GITHUB_TOKEN: ${{ github.token }} + - name: Restore build script seed + uses: actions/download-artifact@v8 + with: + name: static-binary-versions + path: clang-installer - run: nur docs rs - name: upload rustdoc build as artifact uses: actions/upload-artifact@v7 diff --git a/.github/workflows/bump-n-release.nu b/.github/workflows/bump-n-release.nu index b0378129..d9729159 100644 --- a/.github/workflows/bump-n-release.nu +++ b/.github/workflows/bump-n-release.nu @@ -168,6 +168,8 @@ export def bump-version [ run-cmd 'yarn' 'version' ($result | get 'new') print 'Updated version in bindings/node/package.json' cd '../..' + print "Regenerating index.js" + run-cmd yarn build:debug } $result | get new } diff --git a/.github/workflows/node-js-packaging.yml b/.github/workflows/node-js-packaging.yml index 948e0087..9d4a370d 100644 --- a/.github/workflows/node-js-packaging.yml +++ b/.github/workflows/node-js-packaging.yml @@ -38,7 +38,26 @@ concurrency: cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} jobs: + seed-build-script: + runs-on: ubuntu-latest + name: Pre-seed static binaries' versions + steps: + - env: + GITHUB_TOKEN: ${{ github.token }} + run: >- + gh release download + -R cpp-linter/clang-tools-static-binaries + --pattern versions.json + --output versions.json + - name: Upload versions.json + uses: actions/upload-artifact@v7 + with: + name: static-binary-versions + path: versions.json + if-no-files-found: error + build: + needs: [seed-build-script] strategy: fail-fast: false matrix: @@ -121,6 +140,11 @@ jobs: shell: bash - name: Install dependencies run: yarn install + - name: Restore build script seed + uses: actions/download-artifact@v8 + with: + name: static-binary-versions + path: clang-installer - name: Build run: ${{ matrix.settings.build }} shell: bash @@ -133,6 +157,7 @@ jobs: bindings/node/${{ env.APP_NAME }}.*.wasm if-no-files-found: error build-freebsd: + needs: [seed-build-script] runs-on: ubuntu-latest name: Build FreeBSD steps: @@ -150,6 +175,11 @@ jobs: memory: 8G cpu_count: 3 environment_variables: DEBUG RUSTUP_IO_THREADS + - name: Restore build script seed + uses: actions/download-artifact@v8 + with: + name: static-binary-versions + path: clang-installer - name: Build shell: cpa.sh {0} run: |- diff --git a/.github/workflows/python-packaging.yml b/.github/workflows/python-packaging.yml index db31e3b1..1eeb2545 100644 --- a/.github/workflows/python-packaging.yml +++ b/.github/workflows/python-packaging.yml @@ -43,9 +43,29 @@ concurrency: cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} jobs: + seed-build-script: + runs-on: ubuntu-latest + name: Pre-seed static binaries' versions + steps: + - env: + GITHUB_TOKEN: ${{ github.token }} + run: >- + gh release download + -R cpp-linter/clang-tools-static-binaries + --pattern versions.json + --output versions.json + - name: Upload versions.json + uses: actions/upload-artifact@v7 + with: + name: static-binary-versions + path: versions.json + if-no-files-found: error + linux: + needs: [seed-build-script] runs-on: ${{ matrix.platform.runner }} strategy: + fail-fast: false matrix: platform: - runner: ubuntu-latest @@ -56,10 +76,13 @@ jobs: target: aarch64 - runner: ubuntu-latest target: armv7 - - runner: ubuntu-latest - target: s390x - - runner: ubuntu-latest - target: ppc64le + # These targets currently fail because the docker containers used for building manylinux wheels + # use a known-bad C compiler version; aws-lc-sys refuses to build with the bad compiler: + # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95189 + # - runner: ubuntu-latest + # target: s390x + # - runner: ubuntu-latest + # target: ppc64le steps: - uses: actions/checkout@v6 with: @@ -67,7 +90,11 @@ jobs: - uses: actions/setup-python@v6 with: python-version: '3.x' - + - name: Restore build script seed + uses: actions/download-artifact@v8 + with: + name: static-binary-versions + path: clang-installer - name: Build wheels uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b # v1.51.0 with: @@ -75,28 +102,22 @@ jobs: # Use the zig toolchain for all targets except ppc64le. # Note, this is meant to avoid build errors in aws-lc-sys crate, which compiles C code. args: >- - --release --out dist --find-interpreter - ${{ matrix.platform.target != 'ppc64le' && '--zig' || ''}} + --release --out dist --find-interpreter --zig # avoid cache-poisoning potential for actually distributed builds sccache: ${{ startsWith(github.ref, 'refs/tags') && 'false' || 'true' }} - manylinux: auto - # here we either install the ppc64le compiler/toolchain or install zig on all others - before-script-linux: | - case "${{ matrix.platform.target }}" in - ppc64le) - apt-get update - apt-get install -y \ - pkg-config \ - gcc-powerpc64le-linux-gnu \ - g++-powerpc64le-linux-gnu \ - binutils-powerpc64le-linux-gnu \ - libc6-dev-ppc64el-cross - ;; - *) - # spell-checker: disable-next-line - pip install ziglang - ;; - esac + manylinux: 'auto' + # before-script-linux: | + # case "${{ matrix.platform.target }}" in + # ppc64le) + # apt-get update + # apt-get install -y \ + # pkg-config \ + # gcc-powerpc64le-linux-gnu \ + # g++-powerpc64le-linux-gnu \ + # binutils-powerpc64le-linux-gnu \ + # libc6-dev-ppc64el-cross + # ;; + # esac - name: Upload wheels uses: actions/upload-artifact@v7 with: @@ -104,6 +125,7 @@ jobs: path: dist/* windows: + needs: [seed-build-script] runs-on: ${{ matrix.platform.runner }} strategy: matrix: @@ -120,6 +142,11 @@ jobs: with: python-version: '3.x' architecture: ${{ matrix.platform.target }} + - name: Restore build script seed + uses: actions/download-artifact@v8 + with: + name: static-binary-versions + path: clang-installer - name: Build wheels uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b # v1.51.0 with: @@ -133,6 +160,7 @@ jobs: path: dist/* macos: + needs: [seed-build-script] runs-on: ${{ matrix.platform.runner }} strategy: fail-fast: false @@ -149,6 +177,11 @@ jobs: - uses: actions/setup-python@v6 with: python-version: '3.x' + - name: Restore build script seed + uses: actions/download-artifact@v8 + with: + name: static-binary-versions + path: clang-installer - name: Build wheels uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b # v1.51.0 with: diff --git a/.github/workflows/run-dev-tests.yml b/.github/workflows/run-dev-tests.yml index bc11211c..657f704b 100644 --- a/.github/workflows/run-dev-tests.yml +++ b/.github/workflows/run-dev-tests.yml @@ -29,7 +29,26 @@ concurrency: cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} jobs: + seed-build-script: + runs-on: ubuntu-latest + name: Pre-seed static binaries' versions + steps: + - env: + GITHUB_TOKEN: ${{ github.token }} + run: >- + gh release download + -R cpp-linter/clang-tools-static-binaries + --pattern versions.json + --output versions.json + - name: Upload versions.json + uses: actions/upload-artifact@v7 + with: + name: static-binary-versions + path: versions.json + if-no-files-found: error + test: + needs: [seed-build-script] strategy: fail-fast: false matrix: @@ -98,14 +117,28 @@ jobs: - name: Install nushell uses: hustcer/setup-nu@92c296ba1ba2ba04cc948ab64ddefe192dc13f0c # v3.23 + - name: Restore build script seed + uses: actions/download-artifact@v8 + with: + name: static-binary-versions + path: clang-installer + - name: Run test suite - env: - MIN_CLANG_TOOLS_VERSION: "11" - MAX_CLANG_TOOLS_VERSION: "22" shell: nu {0} run: |- - let max_ver = $env.MAX_CLANG_TOOLS_VERSION | into int - let min_ver = $env.MIN_CLANG_TOOLS_VERSION | into int + let version_info = open "clang-installer/versions.json" + mut max_ver = 0 + mut min_ver = 99 + for ver in ($version_info.llvm_versions | columns) { + let ver = $ver | into int + if ($ver < $min_ver) { + $min_ver = $ver + } + if ($ver > $max_ver) { + $max_ver = $ver + } + } + let min_ver = $min_ver # make immutable for $ver in ($min_ver..$max_ver) { print $"::group::Testing with clang v($ver)" with-env { CLANG_VERSION: $"($ver)" } { @@ -135,3 +168,4 @@ jobs: token: ${{secrets.CODECOV_TOKEN}} files: lcov.info fail_ci_if_error: true # optional (default = false) + use_pypi: true # workaround unexpected GPG key changes (temporarily) diff --git a/.gitignore b/.gitignore index 72e973fc..707c770c 100644 --- a/.gitignore +++ b/.gitignore @@ -347,3 +347,4 @@ cpp-linter-py/docs/cli_args.rst lcov.info coverage.json .config/ReleaseNotes.md +versions.json diff --git a/Cargo.lock b/Cargo.lock index 98cc1410..fbef1c3f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1687,7 +1687,9 @@ dependencies = [ "base64", "bytes", "encoding_rs", + "futures-channel", "futures-core", + "futures-util", "h2", "http", "http-body", diff --git a/bindings/node/index.js b/bindings/node/index.js index 70e40dfe..c5bf51fb 100644 --- a/bindings/node/index.js +++ b/bindings/node/index.js @@ -77,8 +77,8 @@ function requireNative() { try { const binding = require('@cpp-linter/cpp-linter-android-arm64') const bindingPackageVersion = require('@cpp-linter/cpp-linter-android-arm64/package.json').version - if (bindingPackageVersion !== '2.0.0-rc15' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.0-rc15 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.0-rc.16' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.0-rc.16 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -93,8 +93,8 @@ function requireNative() { try { const binding = require('@cpp-linter/cpp-linter-android-arm-eabi') const bindingPackageVersion = require('@cpp-linter/cpp-linter-android-arm-eabi/package.json').version - if (bindingPackageVersion !== '2.0.0-rc15' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.0-rc15 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.0-rc.16' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.0-rc.16 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -114,8 +114,8 @@ function requireNative() { try { const binding = require('@cpp-linter/cpp-linter-win32-x64-gnu') const bindingPackageVersion = require('@cpp-linter/cpp-linter-win32-x64-gnu/package.json').version - if (bindingPackageVersion !== '2.0.0-rc15' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.0-rc15 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.0-rc.16' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.0-rc.16 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -130,8 +130,8 @@ function requireNative() { try { const binding = require('@cpp-linter/cpp-linter-win32-x64-msvc') const bindingPackageVersion = require('@cpp-linter/cpp-linter-win32-x64-msvc/package.json').version - if (bindingPackageVersion !== '2.0.0-rc15' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.0-rc15 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.0-rc.16' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.0-rc.16 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -147,8 +147,8 @@ function requireNative() { try { const binding = require('@cpp-linter/cpp-linter-win32-ia32-msvc') const bindingPackageVersion = require('@cpp-linter/cpp-linter-win32-ia32-msvc/package.json').version - if (bindingPackageVersion !== '2.0.0-rc15' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.0-rc15 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.0-rc.16' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.0-rc.16 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -163,8 +163,8 @@ function requireNative() { try { const binding = require('@cpp-linter/cpp-linter-win32-arm64-msvc') const bindingPackageVersion = require('@cpp-linter/cpp-linter-win32-arm64-msvc/package.json').version - if (bindingPackageVersion !== '2.0.0-rc15' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.0-rc15 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.0-rc.16' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.0-rc.16 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -182,8 +182,8 @@ function requireNative() { try { const binding = require('@cpp-linter/cpp-linter-darwin-universal') const bindingPackageVersion = require('@cpp-linter/cpp-linter-darwin-universal/package.json').version - if (bindingPackageVersion !== '2.0.0-rc15' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.0-rc15 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.0-rc.16' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.0-rc.16 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -198,8 +198,8 @@ function requireNative() { try { const binding = require('@cpp-linter/cpp-linter-darwin-x64') const bindingPackageVersion = require('@cpp-linter/cpp-linter-darwin-x64/package.json').version - if (bindingPackageVersion !== '2.0.0-rc15' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.0-rc15 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.0-rc.16' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.0-rc.16 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -214,8 +214,8 @@ function requireNative() { try { const binding = require('@cpp-linter/cpp-linter-darwin-arm64') const bindingPackageVersion = require('@cpp-linter/cpp-linter-darwin-arm64/package.json').version - if (bindingPackageVersion !== '2.0.0-rc15' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.0-rc15 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.0-rc.16' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.0-rc.16 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -234,8 +234,8 @@ function requireNative() { try { const binding = require('@cpp-linter/cpp-linter-freebsd-x64') const bindingPackageVersion = require('@cpp-linter/cpp-linter-freebsd-x64/package.json').version - if (bindingPackageVersion !== '2.0.0-rc15' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.0-rc15 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.0-rc.16' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.0-rc.16 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -250,8 +250,8 @@ function requireNative() { try { const binding = require('@cpp-linter/cpp-linter-freebsd-arm64') const bindingPackageVersion = require('@cpp-linter/cpp-linter-freebsd-arm64/package.json').version - if (bindingPackageVersion !== '2.0.0-rc15' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.0-rc15 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.0-rc.16' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.0-rc.16 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -271,8 +271,8 @@ function requireNative() { try { const binding = require('@cpp-linter/cpp-linter-linux-x64-musl') const bindingPackageVersion = require('@cpp-linter/cpp-linter-linux-x64-musl/package.json').version - if (bindingPackageVersion !== '2.0.0-rc15' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.0-rc15 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.0-rc.16' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.0-rc.16 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -287,8 +287,8 @@ function requireNative() { try { const binding = require('@cpp-linter/cpp-linter-linux-x64-gnu') const bindingPackageVersion = require('@cpp-linter/cpp-linter-linux-x64-gnu/package.json').version - if (bindingPackageVersion !== '2.0.0-rc15' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.0-rc15 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.0-rc.16' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.0-rc.16 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -305,8 +305,8 @@ function requireNative() { try { const binding = require('@cpp-linter/cpp-linter-linux-arm64-musl') const bindingPackageVersion = require('@cpp-linter/cpp-linter-linux-arm64-musl/package.json').version - if (bindingPackageVersion !== '2.0.0-rc15' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.0-rc15 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.0-rc.16' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.0-rc.16 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -321,8 +321,8 @@ function requireNative() { try { const binding = require('@cpp-linter/cpp-linter-linux-arm64-gnu') const bindingPackageVersion = require('@cpp-linter/cpp-linter-linux-arm64-gnu/package.json').version - if (bindingPackageVersion !== '2.0.0-rc15' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.0-rc15 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.0-rc.16' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.0-rc.16 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -339,8 +339,8 @@ function requireNative() { try { const binding = require('@cpp-linter/cpp-linter-linux-arm-musleabihf') const bindingPackageVersion = require('@cpp-linter/cpp-linter-linux-arm-musleabihf/package.json').version - if (bindingPackageVersion !== '2.0.0-rc15' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.0-rc15 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.0-rc.16' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.0-rc.16 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -355,8 +355,8 @@ function requireNative() { try { const binding = require('@cpp-linter/cpp-linter-linux-arm-gnueabihf') const bindingPackageVersion = require('@cpp-linter/cpp-linter-linux-arm-gnueabihf/package.json').version - if (bindingPackageVersion !== '2.0.0-rc15' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.0-rc15 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.0-rc.16' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.0-rc.16 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -373,8 +373,8 @@ function requireNative() { try { const binding = require('@cpp-linter/cpp-linter-linux-loong64-musl') const bindingPackageVersion = require('@cpp-linter/cpp-linter-linux-loong64-musl/package.json').version - if (bindingPackageVersion !== '2.0.0-rc15' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.0-rc15 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.0-rc.16' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.0-rc.16 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -389,8 +389,8 @@ function requireNative() { try { const binding = require('@cpp-linter/cpp-linter-linux-loong64-gnu') const bindingPackageVersion = require('@cpp-linter/cpp-linter-linux-loong64-gnu/package.json').version - if (bindingPackageVersion !== '2.0.0-rc15' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.0-rc15 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.0-rc.16' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.0-rc.16 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -407,8 +407,8 @@ function requireNative() { try { const binding = require('@cpp-linter/cpp-linter-linux-riscv64-musl') const bindingPackageVersion = require('@cpp-linter/cpp-linter-linux-riscv64-musl/package.json').version - if (bindingPackageVersion !== '2.0.0-rc15' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.0-rc15 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.0-rc.16' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.0-rc.16 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -423,8 +423,8 @@ function requireNative() { try { const binding = require('@cpp-linter/cpp-linter-linux-riscv64-gnu') const bindingPackageVersion = require('@cpp-linter/cpp-linter-linux-riscv64-gnu/package.json').version - if (bindingPackageVersion !== '2.0.0-rc15' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.0-rc15 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.0-rc.16' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.0-rc.16 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -440,8 +440,8 @@ function requireNative() { try { const binding = require('@cpp-linter/cpp-linter-linux-ppc64-gnu') const bindingPackageVersion = require('@cpp-linter/cpp-linter-linux-ppc64-gnu/package.json').version - if (bindingPackageVersion !== '2.0.0-rc15' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.0-rc15 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.0-rc.16' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.0-rc.16 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -456,8 +456,8 @@ function requireNative() { try { const binding = require('@cpp-linter/cpp-linter-linux-s390x-gnu') const bindingPackageVersion = require('@cpp-linter/cpp-linter-linux-s390x-gnu/package.json').version - if (bindingPackageVersion !== '2.0.0-rc15' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.0-rc15 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.0-rc.16' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.0-rc.16 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -476,8 +476,8 @@ function requireNative() { try { const binding = require('@cpp-linter/cpp-linter-openharmony-arm64') const bindingPackageVersion = require('@cpp-linter/cpp-linter-openharmony-arm64/package.json').version - if (bindingPackageVersion !== '2.0.0-rc15' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.0-rc15 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.0-rc.16' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.0-rc.16 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -492,8 +492,8 @@ function requireNative() { try { const binding = require('@cpp-linter/cpp-linter-openharmony-x64') const bindingPackageVersion = require('@cpp-linter/cpp-linter-openharmony-x64/package.json').version - if (bindingPackageVersion !== '2.0.0-rc15' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.0-rc15 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.0-rc.16' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.0-rc.16 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { @@ -508,8 +508,8 @@ function requireNative() { try { const binding = require('@cpp-linter/cpp-linter-openharmony-arm') const bindingPackageVersion = require('@cpp-linter/cpp-linter-openharmony-arm/package.json').version - if (bindingPackageVersion !== '2.0.0-rc15' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { - throw new Error(`Native binding package version mismatch, expected 2.0.0-rc15 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + if (bindingPackageVersion !== '2.0.0-rc.16' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 2.0.0-rc.16 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { diff --git a/clang-installer/Cargo.toml b/clang-installer/Cargo.toml index 917c7f9a..075a1968 100644 --- a/clang-installer/Cargo.toml +++ b/clang-installer/Cargo.toml @@ -47,5 +47,10 @@ tokio = { workspace = true, features = ["macros", "rt-multi-thread"] } [features] bin = ["dep:clap", "dep:tokio", "dep:anyhow", "dep:colored"] +[build-dependencies] +serde = { workspace = true } +serde_json = { workspace = true } +reqwest = { workspace = true, features = ["default-tls", "blocking"] } + [package.metadata.binstall] pkg-url = "{ repo }/releases/download/clang-installer/v{ version }/{ name }-{ target }{ archive-suffix }" diff --git a/clang-installer/build.rs b/clang-installer/build.rs new file mode 100644 index 00000000..276cce4e --- /dev/null +++ b/clang-installer/build.rs @@ -0,0 +1,48 @@ +use std::{fs, path::PathBuf, time::Duration}; + +use reqwest::blocking::ClientBuilder; + +const URL: &str = "https://github.com/cpp-linter/clang-tools-static-binaries/releases/latest/download/versions.json"; + +#[derive(Debug, serde::Deserialize)] +struct VersionInfo { + release_tag: String, + llvm_versions: std::collections::HashMap, +} +fn main() { + let pre_seed = PathBuf::from("versions.json"); + let version_info_str = if pre_seed.exists() { + println!("cargo:warning=Using pre-seeded version info from {pre_seed:?}"); + fs::read_to_string(&pre_seed).unwrap() + } else { + ClientBuilder::new() + .user_agent("cpp-linter-rs/clang-installer") + .timeout(Duration::from_secs(30)) + .build() + .unwrap() + .get(URL) + .send() + .unwrap() + .text() + .unwrap() + }; + let version_info: VersionInfo = serde_json::from_str(&version_info_str).unwrap(); + let (min_ver, max_ver) = { + let (mut min_v, mut max_v) = (None, None); + for ver in version_info.llvm_versions.keys() { + if min_v.is_none_or(|v| v > ver) { + min_v = Some(ver); + } + if max_v.is_none_or(|v| v < ver) { + max_v = Some(ver); + } + } + (min_v.unwrap(), max_v.unwrap()) + }; + println!( + "cargo:rustc-env=CLANG_TOOLS_TAG={}", + version_info.release_tag + ); + println!("cargo:rustc-env=MIN_CLANG_TOOLS_VERSION={min_ver}"); + println!("cargo:rustc-env=MAX_CLANG_TOOLS_VERSION={max_ver}"); +} diff --git a/clang-installer/src/downloader/pypi.rs b/clang-installer/src/downloader/pypi.rs index bcc222f3..064af45f 100644 --- a/clang-installer/src/downloader/pypi.rs +++ b/clang-installer/src/downloader/pypi.rs @@ -353,11 +353,6 @@ impl FromStr for PlatformTag { /// ``` #[derive(Debug)] struct WheelTags { - /// The version of the package for which the wheel is built. - /// - /// For clang-format and clang-tidy wheels, this corresponds to the version of the clang tool. - version: Version, - /// The platform tag indicates the wheel's target platform. platform: PlatformTag, } @@ -377,12 +372,6 @@ impl FromStr for WheelTags { } iter.next(); // already know the package name - // The exact version (PEP 440 compatible) should comply with semver parsing. - let version = Version::parse( - iter.next() - .ok_or(PyPiDownloadError::InvalidWheelName(s.to_string()))?, - ) - .map_err(|_| PyPiDownloadError::InvalidVersion)?; let platform = PlatformTag::from_str(iter.next_back().unwrap())?; // The remaining tags are not used for compatibility checks. @@ -390,7 +379,7 @@ impl FromStr for WheelTags { // we don't need to validate python version nor abi tags here. // optional build tag is not used in clang_format or clang_tidy wheel deployments - Ok(Self { version, platform }) + Ok(Self { platform }) } } @@ -414,15 +403,47 @@ impl PyPiDownloader { clang_tool: &ClangTool, pypi_info: &PyPiProjectInfo, version: &VersionReq, - ) -> Result<(Version, PyPiReleaseInfo), PyPiDownloadError> { + ) -> Result<(Version, PyPiReleaseInfo, String), PyPiDownloadError> { let mut result = None; for (ver_str, releases) in &pypi_info.releases { let ver = match Version::parse(ver_str) { - Ok(v) => v, - Err(_) => continue, + Ok(v) => Version { + // append a pre-release number to weight it properly against a build number (translated to prerelease number below) + pre: semver::Prerelease::from_str("0").unwrap_or_default(), + ..v + }, + Err(_) => { + let mut components = ver_str.split('.'); + let count = components.clone().count(); + if count <= 3 { + // should've parsed this normally, log warning and skip this version + log::warn!("Skipping malformed version {ver_str} for {clang_tool} on PyPI"); + continue; + } else { + // take the first four components and treat them like a `major.minor.patch.build-number` + let major: u64 = components.next().unwrap_or("0").parse().unwrap_or(0); + let minor: u64 = components.next().unwrap_or("0").parse().unwrap_or(0); + let patch: u64 = components.next().unwrap_or("0").parse().unwrap_or(0); + let build: &str = components.next().unwrap_or("0"); + Version { + major, + minor, + patch, + pre: semver::Prerelease::from_str(build).unwrap_or_default(), + build: semver::BuildMetadata::EMPTY, + } + } + } }; - if version.matches(&ver) { + // do not compare pre-release numbers since these are actually build numbers + if version.matches(&Version { + major: ver.major, + minor: ver.minor, + patch: ver.patch, + pre: semver::Prerelease::default(), + build: semver::BuildMetadata::EMPTY, + }) { for release in releases { if !release.filename.ends_with(".whl") { continue; @@ -430,19 +451,19 @@ impl PyPiDownloader { let wheel_tags = WheelTags::from_str(&release.filename)?; if !release.yanked && wheel_tags.is_compatible_with_system() { log::debug!( - "Found {clang_tool} (size: {}, digest: {:?}); {wheel_tags:?}", + "Found {clang_tool} v{ver_str} (size: {}, digest: {:?}); {wheel_tags:?}", release.size, release.digests ); - if result.as_ref().is_none_or(|(v, _)| *v < ver) { - result = Some((wheel_tags.version.clone(), release)); + if result.as_ref().is_none_or(|(v, _, _)| *v < ver) { + result = Some((ver.clone(), release, ver_str.to_owned())); } } } } } result - .map(|(a, b)| (a, b.to_owned())) + .map(|(a, b, c)| (Version::new(a.major, a.minor, a.patch), b.to_owned(), c)) .ok_or(PyPiDownloadError::NoVersionFound) } @@ -484,18 +505,21 @@ impl PyPiDownloader { directory: Option<&PathBuf>, ) -> Result { let info = Self::get_pypi_release_info(clang_tool).await?; - let (ver, info) = Self::get_best_pypi_release(clang_tool, &info, version)?; - let cached_filename = format!("{clang_tool}_{ver}.whl"); + let (ver, info, ver_str) = Self::get_best_pypi_release(clang_tool, &info, version)?; + let cached_filename = format!("{clang_tool}_{ver_str}.whl",); let cached_dir = Self::get_cache_dir(); let cached_wheel = cached_dir.join("pypi").join(&cached_filename); let file_lock = lock_path(&cached_wheel)?; if Self::is_cache_valid(&cached_wheel, None) { log::info!( - "Using cached wheel for {clang_tool} version {ver} from {}", + "Using cached wheel for {clang_tool} version {ver_str} from {}", cached_wheel.to_string_lossy() ); } else { - log::info!("Downloading {clang_tool} version {ver} from {}", info.url); + log::info!( + "Downloading {clang_tool} version {ver_str} from {}", + info.url + ); download(&Url::parse(&info.url)?, &cached_wheel, 60).await?; } if let Some(digest) = info.digests.first() { diff --git a/clang-installer/src/downloader/static_dist.rs b/clang-installer/src/downloader/static_dist.rs index 39072da4..256aa627 100644 --- a/clang-installer/src/downloader/static_dist.rs +++ b/clang-installer/src/downloader/static_dist.rs @@ -1,7 +1,7 @@ //! A module to download static binaries from cpp-linter/clang-tools-static-binaries. use std::{ - env::consts, + env::consts::{ARCH, OS}, fs, ops::RangeInclusive, path::{Path, PathBuf}, @@ -27,8 +27,10 @@ pub enum StaticDistDownloadError { #[error("The requested version does not match any available versions")] UnsupportedVersion, - /// The static binaries are only built for x86_64 (amd64) architecture. - #[error("The static binaries are only built for x86_64 (amd64) architecture")] + /// The static binaries are only built for + /// x86_64 and aarch64 architecture on Linux MacOS, and + /// Windows (not aarch64 for Windows currently). + #[error("The static binaries are not built for {OS} {ARCH} architecture")] UnsupportedArchitecture, /// Failed to parse a URL. @@ -43,10 +45,10 @@ pub enum StaticDistDownloadError { #[error("Failed to parse the SHA512 sum file")] Sha512Corruption, } -const MIN_CLANG_TOOLS_VERSION: u8 = 11; -pub(crate) const MAX_CLANG_TOOLS_VERSION: u8 = 22; +const MIN_CLANG_TOOLS_VERSION: &str = env!("MIN_CLANG_TOOLS_VERSION"); +pub(crate) const MAX_CLANG_TOOLS_VERSION: &str = env!("MAX_CLANG_TOOLS_VERSION"); const CLANG_TOOLS_REPO: &str = "https://github.com/cpp-linter/clang-tools-static-binaries"; -const CLANG_TOOLS_TAG: &str = "master-6e612956"; +const CLANG_TOOLS_TAG: &str = env!("CLANG_TOOLS_TAG"); /// A downloader that uses statically linked binary distribution files /// provided by the cpp-linter team. @@ -56,25 +58,8 @@ impl Cacher for StaticDistDownloader {} impl StaticDistDownloader { pub fn get_major_version_range() -> RangeInclusive { - let min_clang_tools_version: u8 = option_env!("MIN_CLANG_TOOLS_VERSION") - .and_then(|v| match v.parse::() { - Ok(parsed) => Some(parsed), - Err(e) => { - log::error!("Invalid MIN_CLANG_TOOLS_VERSION env var value: {v}. Error: {e}"); - None - } - }) - .unwrap_or(MIN_CLANG_TOOLS_VERSION); - let max_clang_tools_version: u8 = option_env!("MAX_CLANG_TOOLS_VERSION") - .and_then(|v| match v.parse::() { - Ok(parsed) => Some(parsed), - Err(e) => { - log::error!("Invalid MAX_CLANG_TOOLS_VERSION env var value: {v}. Error: {e}"); - None - } - }) - .unwrap_or(MAX_CLANG_TOOLS_VERSION); - min_clang_tools_version..=max_clang_tools_version + MIN_CLANG_TOOLS_VERSION.parse().unwrap_or(11) + ..=MAX_CLANG_TOOLS_VERSION.parse().unwrap_or(22) } /// Finds a suitable version from `req_ver` within the range of available clang tools versions. @@ -83,18 +68,10 @@ impl StaticDistDownloader { /// `MAX_CLANG_TOOLS_VERSION` environment variables (inclusive) at compile time. fn find_suitable_version(req_ver: &VersionReq) -> Option { let clang_tools_versions: RangeInclusive = Self::get_major_version_range(); - let outlier = Version::new(12, 0, 1); - for ver in clang_tools_versions + clang_tools_versions .map(|v| Version::new(v as u64, 0, 0)) .rev() - { - if ver.major == 12 && req_ver.matches(&outlier) { - return Some(outlier); - } else if req_ver.matches(&ver) { - return Some(ver); - } - } - None + .find(|ver| req_ver.matches(ver)) } /// Verifies the SHA512 checksum of the downloaded file. @@ -121,34 +98,45 @@ impl StaticDistDownloader { requested_version: &VersionReq, directory: Option<&PathBuf>, ) -> Result { - if consts::ARCH != "x86_64" { - return Err(StaticDistDownloadError::UnsupportedArchitecture); - } + #[cfg(any( + // Windows support is only for x86_64 architecture (for now) + all(target_os = "windows", not(target_arch = "x86_64")), + // Linux and macOS support only x86_64 and aarch64 architectures + all( + any(target_os = "linux", target_os = "macos"), + not(any(target_arch = "x86_64", target_arch = "aarch64")) + ), + // Any OS other than Windows, Linux, or macOS is unsupported + not(any(target_os = "windows", target_os = "linux", target_os = "macos")), + ))] + return Err(StaticDistDownloadError::UnsupportedArchitecture); + let ver = Self::find_suitable_version(requested_version) .ok_or(StaticDistDownloadError::UnsupportedVersion)?; - let ver_str = if ver.minor == 0 && ver.patch == 0 { - ver.major.to_string() + let ver_str = ver.major.to_string(); + // we already gated unsupported architectures above, + // so we can assume it's either x86_64 or aarch64 here + let arch = if cfg!(target_arch = "aarch64") { + "arm64" } else { - ver.to_string() + "amd64" }; - let suffix = if cfg!(target_os = "windows") { - ".exe" + let platform = if cfg!(target_os = "windows") { + "windows" + } else if cfg!(target_os = "macos") { + "macos" } else { - "" + "linux" }; - let clang_tools_repo: &str = option_env!("CLANG_TOOLS_REPO").unwrap_or(CLANG_TOOLS_REPO); - let clang_tools_tag: &str = option_env!("CLANG_TOOLS_TAG").unwrap_or(CLANG_TOOLS_TAG); let base_url = format!( - "{clang_tools_repo}/releases/download/{clang_tools_tag}/{tool}-{ver_str}_{}-amd64", - if cfg!(target_os = "windows") { - "windows" - } else if cfg!(target_os = "macos") { - "macos" - } else { - "linux" - }, + "{CLANG_TOOLS_REPO}/releases/download/{CLANG_TOOLS_TAG}/{tool}-{ver_str}_{platform}-{arch}", ); + let suffix = if cfg!(target_os = "windows") { + ".exe" + } else { + "" + }; let url = Url::parse(format!("{base_url}{suffix}").as_str())?; let cache_path = Self::get_cache_dir(); let bin_name = format!("{tool}-{ver_str}{suffix}"); @@ -177,7 +165,7 @@ impl StaticDistDownloader { sha512_cache_path.to_string_lossy() ); } else { - let sha512_url = Url::parse(format!("{base_url}.sha512sum").as_str())?; + let sha512_url = Url::parse(format!("{base_url}{suffix}.sha512sum").as_str())?; log::info!( "Downloading SHA512 checksum for {tool} version {ver_str} from {sha512_url}" ); diff --git a/clang-installer/src/main.rs b/clang-installer/src/main.rs index c32abb8e..f8c3324b 100644 --- a/clang-installer/src/main.rs +++ b/clang-installer/src/main.rs @@ -99,15 +99,27 @@ mod logging { pub struct CliOptions { /// The desired version of clang to install. #[arg( - short, - long, - default_missing_value = "CPP-LINTER-VERSION", - num_args = 0..=1, - value_parser = RequestedVersion::from_str, - default_value = "", + short, + long, + default_missing_value = "CPP-LINTER-VERSION", + num_args = 0..=1, + value_parser = RequestedVersion::from_str, + default_value = "", )] pub version: Option, + /// Enable verbose logging for debugging purposes. + /// + /// This will include more DEBUG level log messages. + /// Without it, log level is set to INFO by default. + #[arg( + short = 'V', + long, + default_value_t = false, + action = clap::ArgAction::SetTrue, + )] + pub verbose: bool, + /// The clang tool to install. #[arg( short, @@ -132,7 +144,9 @@ pub struct CliOptions { async fn main() -> Result<()> { logging::initialize_logger(); let options = CliOptions::parse(); - + if options.verbose { + log::set_max_level(log::LevelFilter::Debug); + } let tool = options .tool .expect("--tool should have a default value: [clang-format, clang-tidy]"); diff --git a/clang-installer/src/version.rs b/clang-installer/src/version.rs index a603853e..58f631b9 100644 --- a/clang-installer/src/version.rs +++ b/clang-installer/src/version.rs @@ -326,7 +326,7 @@ mod tests { /// If successful, clang-tidy will be installed globally, which may be undesirable. #[tokio::test] async fn eval_version() { - let clang_version = option_env!("CLANG_VERSION").unwrap_or("12.0.1"); + let clang_version = option_env!("CLANG_VERSION").unwrap_or("16"); for tool in [ClangTool::ClangFormat, ClangTool::ClangTidy] { let version_req = VersionReq::parse(clang_version).unwrap(); println!("Installing {tool} with version requirement: {version_req}"); diff --git a/clang-installer/tests/static_dist.rs b/clang-installer/tests/static_dist.rs index 0bc28601..9bf8be50 100644 --- a/clang-installer/tests/static_dist.rs +++ b/clang-installer/tests/static_dist.rs @@ -45,8 +45,3 @@ async fn setup(ver_spec: &str) { async fn download_clang_format_17() { setup("17").await; } - -#[tokio::test] -async fn download_clang_format_12_0_1() { - setup("=12.0.1").await; -}