diff --git a/.github/workflows/ci-clang-tidy.yml b/.github/workflows/ci-clang-tidy.yml new file mode 100644 index 00000000..284803a7 --- /dev/null +++ b/.github/workflows/ci-clang-tidy.yml @@ -0,0 +1,144 @@ +# The MIT License (MIT) +# +# Copyright (c) 2018 Mateusz Pusz +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +name: clang-tidy + +on: + push: + paths-ignore: + - "docs/**" + pull_request: + paths-ignore: + - "docs/**" + +env: + CHANNEL: ${{ fromJSON('["testing", "stable"]')[github.ref_type == 'tag' && startsWith(github.ref_name, 'v')] }} + +jobs: + build: + name: "${{ matrix.formatting }} ${{ matrix.contracts }} C++${{ matrix.std }} ${{ matrix.config.name }} ${{ matrix.build_type }}" + runs-on: ${{ matrix.config.os }} + strategy: + fail-fast: false + matrix: + formatting: ["std::format", "fmtlib"] + contracts: ["none", "gsl-lite", "ms-gsl"] + std: [20, 23] + config: + - { + name: "Clang-18", + os: ubuntu-24.04, + compiler: + { + type: CLANG, + version: 18, + cc: "clang-18", + cxx: "clang++-18", + }, + lib: "libc++", + cxx_modules: "False", + std_format_support: "True", + conan-config: "", + } + build_type: ["Release", "Debug"] + exclude: + - formatting: "std::format" + config: { std_format_support: "False" } + + env: + CC: ${{ matrix.config.compiler.cc }} + CXX: ${{ matrix.config.compiler.cxx }} + + steps: + - uses: actions/checkout@v4 + - run: echo "cache_id=$(/bin/date -u "+%Y%m%d")" >> $GITHUB_ENV + - name: Cache Conan data + uses: actions/cache@v4 + if: always() + env: + cache-name: cache-conan-data + with: + path: ~/.conan2/p + key: clang-tidy-${{ matrix.config.os }}-${{ matrix.formatting }}-${{ matrix.contracts }}-${{ matrix.config.compiler.type }}-${{ matrix.config.lib }}-${{ matrix.build_type }}-${{ matrix.config.compiler.version }}-${{ matrix.std }}-${{ env.cache_id }} + restore-keys: | + clang-tidy-${{ matrix.config.os }}-${{ matrix.formatting }}-${{ matrix.contracts }}-${{ matrix.config.compiler.type }}-${{ matrix.config.lib }}-${{ matrix.build_type }}-${{ matrix.config.compiler.version }}-${{ matrix.std }}- + clang-tidy-${{ matrix.config.os }}-${{ matrix.formatting }}-${{ matrix.contracts }}-${{ matrix.config.compiler.type }}-${{ matrix.config.lib }}-${{ matrix.build_type }}-${{ matrix.config.compiler.version }}- + clang-tidy-${{ matrix.config.os }}-${{ matrix.formatting }}-${{ matrix.contracts }}-${{ matrix.config.compiler.type }}-${{ matrix.config.lib }}-${{ matrix.build_type }}- + clang-tidy-${{ matrix.config.os }}-${{ matrix.formatting }}-${{ matrix.contracts }}-${{ matrix.config.compiler.type }}-${{ matrix.config.lib }}- + clang-tidy-${{ matrix.config.os }}-${{ matrix.formatting }}-${{ matrix.contracts }}-${{ matrix.config.compiler.type }}- + clang-tidy-${{ matrix.config.os }}-${{ matrix.formatting }}-${{ matrix.contracts }}- + clang-tidy-${{ matrix.config.os }}-${{ matrix.formatting }}- + clang-tidy-${{ matrix.config.os }}- + - uses: hendrikmuhs/ccache-action@v1.2 + if: runner.os == 'Linux' + with: + key: ${{ matrix.config.os }}-${{ matrix.formatting }}-${{ matrix.contracts }}-${{ matrix.config.compiler.type }}-${{ matrix.config.lib }}-${{ matrix.build_type }}-${{ matrix.config.compiler.version }}-${{ matrix.std }} + max-size: 50M + - name: Install Clang + if: matrix.config.compiler.type == 'CLANG' + shell: bash + working-directory: ${{ env.HOME }} + run: | + wget https://apt.llvm.org/llvm.sh + chmod +x llvm.sh + sudo ./llvm.sh ${{ matrix.config.compiler.version }} + sudo apt install -y clang-tools-${{ matrix.config.compiler.version }} + - name: Install Libc++ + if: matrix.config.compiler.type == 'CLANG' && matrix.config.lib == 'libc++' + shell: bash + run: | + sudo apt install -y libc++-${{ matrix.config.compiler.version }}-dev libc++abi-${{ matrix.config.compiler.version }}-dev libunwind-${{ matrix.config.compiler.version }}-dev + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: 3.x + - name: Install Ninja + shell: bash + run: | + pip install -U ninja + - name: Install Conan + shell: bash + run: | + pip install -U conan + - name: Configure Conan + shell: bash + run: | + conan profile detect --force + if [[ "${{ matrix.config.compiler.type }}" == "CLANG" ]]; then + sed -i.backup '/^\[settings\]$/,/^\[/ s/^compiler.libcxx=.*/compiler.libcxx=${{ matrix.config.lib }}/' ~/.conan2/profiles/default + fi + sed -i.backup '/^\[settings\]$/,/^\[/ s/^compiler.cppstd=.*/compiler.cppstd=${{ matrix.std }}/' ~/.conan2/profiles/default + sed -i.backup '/^\[settings\]$/,/^\[/ s/^build_type=.*/build_type=${{ matrix.build_type }}/' ~/.conan2/profiles/default + conan profile show -pr default + - run: echo "std_format=$([ "${{ matrix.formatting }}" == "std::format" ] && echo "True" || echo "False")" >> $GITHUB_ENV + - name: Run clang-tidy + shell: bash + run: | + conan build . -b missing -c tools.cmake.cmaketoolchain:generator="Ninja Multi-Config" \ + -c user.mp-units.build:all=True -c user.mp-units.analyze:clang-tidy=True \ + -o cxx_modules=${{ matrix.config.cxx_modules }} -o std_format=${{ env.std_format }} -o contracts=${{ matrix.contracts }} ${{ matrix.config.conan-config }} + - name: Clean Conan cache before backup + shell: bash + run: | + conan remove *#~latest --confirm + conan remove *:*#~latest --confirm + conan cache clean "*" -s -b -d diff --git a/README.md b/README.md index dd6ea350..3b334e98 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ [![Conan CI](https://img.shields.io/github/actions/workflow/status/mpusz/mp-units/ci-conan.yml?branch=master&label=Conan%20CI)](https://github.com/mpusz/mp-units/actions?query=workflow%3A%22Conan%20CI%22+branch%3Amaster) [![CMake CI](https://img.shields.io/github/actions/workflow/status/mpusz/mp-units/ci-test-package-cmake.yml?branch=master&label=CMake%20CI)](https://github.com/mpusz/mp-units/actions?query=workflow%3A%22CMake+Test+Package+CI%22+branch%3Amaster) +[![clang-tidy](https://img.shields.io/github/actions/workflow/status/mpusz/mp-units/ci-clang-tidy.yml?branch=master&label=clang-tidy)](https://github.com/mpusz/mp-units/actions?query=workflow%3A%22clang-tidy%20CI%22+branch%3Amaster) [![Formatting CI](https://img.shields.io/github/actions/workflow/status/mpusz/mp-units/ci-formatting.yml?branch=master&label=Formatting%20CI)](https://github.com/mpusz/mp-units/actions?query=workflow%3A%22Formatting%20CI%22+branch%3Amaster) [![GitHub Workflow Documentation](https://img.shields.io/github/actions/workflow/status/mpusz/mp-units/documentation.yml?branch=master&label=Documentation)](https://github.com/mpusz/mp-units/actions?query=workflow%3ADocumentation+branch%3Amaster) diff --git a/conanfile.py b/conanfile.py index de466486..50855bd9 100644 --- a/conanfile.py +++ b/conanfile.py @@ -193,6 +193,10 @@ class MPUnitsConan(ConanFile): def _skip_la(self): return bool(self.conf.get("user.mp-units.build:skip_la", default=False)) + @property + def _run_clang_tidy(self): + return bool(self.conf.get("user.mp-units.analyze:clang-tidy", default=False)) + def set_version(self): content = load(self, os.path.join(self.recipe_folder, "src/CMakeLists.txt")) version = re.search( @@ -230,6 +234,8 @@ class MPUnitsConan(ConanFile): tc.cache_variables["CMAKE_EXPORT_COMPILE_COMMANDS"] = True tc.cache_variables["CMAKE_VERIFY_INTERFACE_HEADER_SETS"] = True tc.cache_variables["MP_UNITS_DEV_BUILD_LA"] = not self._skip_la + if self._run_clang_tidy: + tc.cache_variables["MP_UNITS_DEV_CLANG_TIDY"] = True if self._build_cxx_modules: tc.cache_variables["CMAKE_CXX_SCAN_FOR_MODULES"] = True tc.cache_variables["MP_UNITS_BUILD_CXX_MODULES"] = str( diff --git a/docs/getting_started/installation_and_usage.md b/docs/getting_started/installation_and_usage.md index e21dd6ce..20d3c788 100644 --- a/docs/getting_started/installation_and_usage.md +++ b/docs/getting_started/installation_and_usage.md @@ -303,6 +303,14 @@ tools.build:compiler_executables={"c": "gcc-12", "cpp": "g++-12"} [conan skip la support]: https://github.com/mpusz/mp-units/releases/tag/v2.2.0 +[`user.mp-units.analyze:clang-tidy`](#user.mp-units.analyze-clang-tidy){ #user.mp-units.analyze-clang-tidy } + +: [:octicons-tag-24: 2.2.0][conan clang-tidy support] ยท :octicons-milestone-24: `True`/`False` (Default: `False`) + + Enables clang-tidy analysis. + + [conan clang-tidy support]: https://github.com/mpusz/mp-units/releases/tag/v2.2.0 + ### CMake options [`MP_UNITS_BUILD_AS_SYSTEM_HEADERS`](#MP_UNITS_BUILD_AS_SYSTEM_HEADERS){ #MP_UNITS_BUILD_AS_SYSTEM_HEADERS }