diff --git a/.github/actions/parse_environment/action.yml b/.github/actions/parse_environment/action.yml new file mode 100644 index 0000000..7572835 --- /dev/null +++ b/.github/actions/parse_environment/action.yml @@ -0,0 +1,67 @@ +name: "parse_environment" +description: "Parse environment" +inputs: + os: + required: true + description: "Operating system" + compiler: + required: true + description: "Compiler" +outputs: + os_name: + description: "Operating system name (ubuntu converted to linux)" + value: ${{ steps.os.outputs.name }} + os_version: + description: "Operating system version (if not set in inputs.os, set to latest)" + value: ${{ steps.os.outputs.version }} + arch: + description: "Architecture" + value: ${{ steps.arch.outputs.value }} + compiler_name: + description: "Compiler name (llvm converted to clang)" + value: ${{ steps.compiler.outputs.name }} + compiler_version: + description: "Compiler version (if not set in inputs.compiler, set to latest)" + value: ${{ steps.compiler.outputs.version }} + gcov_executable: + description: "The corresponding gcov_executable (Available only for clang and gcc)" + value: ${{ steps.gcov.outputs.value }} + +runs: + using: "composite" + steps: + - name: Parse os and os version + id: os + shell: bash + env: + VALUE: ${{ contains(matrix.os, '-') && matrix.os || format('{0}-{1}', matrix.os, 'latest') }} + run: | + export NAME=${VALUE%%-*} + echo name=${NAME/ubuntu/linux} >> "$GITHUB_OUTPUT" + + export VERSION=${VALUE##*-} + echo version=$VERSION >> "$GITHUB_OUTPUT" + + - name: Parse architecture + id: arch + shell: bash + run: | + echo value=${{ steps.os.outputs.name == 'macos' && steps.os.outputs.version >= '14' && 'armv8' || 'x86_64' }} >> "$GITHUB_OUTPUT" + + - name: Parse compiler and compiler version + id: compiler + shell: bash + env: + VALUE: ${{ contains(matrix.compiler, '-') && matrix.compiler || format('{0}-{1}', matrix.compiler, 'latest') }} + run: | + export NAME=${VALUE%%-*} + echo name=${NAME/llvm/clang} >> "$GITHUB_OUTPUT" + + export VERSION=${VALUE##*-} + echo version=$VERSION >> "$GITHUB_OUTPUT" + + - name: Parse gcov + id: gcov + shell: bash + run: | + echo "value=${{ contains(matrix.compiler, 'llvm') && 'llvm-cov gcov' || contains(matrix.compiler, 'gcc') && format('{0}-{1}', 'gcov', steps.compiler.outputs.version) || '' }}" >> "$GITHUB_OUTPUT" diff --git a/.github/actions/setup_cache/action.yml b/.github/actions/setup_cache/action.yml index 4b187f0..a14622a 100644 --- a/.github/actions/setup_cache/action.yml +++ b/.github/actions/setup_cache/action.yml @@ -1,15 +1,11 @@ name: "setup_cache" description: "sets up the shared cache" inputs: - compiler: + key: required: true - description: "Compiler" - build_type: - required: true - description: "Build type" - developer_mode: - required: true - description: "Developer mode" + description: "Cache key" + restore_key: + description: "Restore key when cache misses" runs: using: "composite" @@ -20,14 +16,14 @@ runs: path: | ~/.cache/pip ~/.ccache - key: ${{ runner.os }}-${{ inputs.compiler }}-${{ inputs.build_type }}-${{ inputs.developer_mode }}-${{ hashFiles('**/CMakeLists.txt') }} + key: ${{ inputs.key }}-${{ hashFiles('**/CMakeLists.txt') }} restore-keys: | - ${{ runner.os }}-${{ inputs.compiler }}-${{ inputs.build_type }} + ${{ inputs.restore_key != '' && inputs.restore_key || inputs.key }} - name: Cache conan uses: actions/cache@v4.0.2 with: path: ~/.conan2/p - key: ${{ runner.os }}-${{ inputs.compiler }}-${{ inputs.build_type }}-${{ inputs.developer_mode }}-${{ hashFiles('conanfile.py', 'conanfile.txt') }} + key: ${{ inputs.key }}-${{ hashFiles('conanfile.py', 'conanfile.txt') }} restore-keys: | - ${{ runner.os }}-${{ inputs.compiler }}-${{ inputs.build_type }} + ${{ inputs.restore_key != '' && inputs.restore_key || inputs.key }} diff --git a/.github/actions/setup_conan/action.yml b/.github/actions/setup_conan/action.yml index 1777f44..c2d6c96 100644 --- a/.github/actions/setup_conan/action.yml +++ b/.github/actions/setup_conan/action.yml @@ -1,15 +1,21 @@ name: "setup_conan" description: "sets up conan" inputs: - os: + os_name: + required: true + description: "Operating system name" + os_version: required: true - description: "Operating system" + description: "Operating system version" arch: required: true - description: "Architecutre" - compiler: + description: "Architecture" + compiler_name: required: true - description: "Compiler" + description: "Compiler name" + compiler_version: + required: true + description: "Compiler version" build_type: required: true description: "Build type" @@ -32,18 +38,6 @@ outputs: args: description: "The corresponding args that should be used in conan commands afterwards" value: ${{ steps.output.outputs.args }} - os_name: - description: "Operating system name (ubuntu converted to linux)" - value: ${{ steps.parse_os.outputs.name }} - os_version: - description: "Operating system version (if not set in inputs.os, set to latest)" - value: ${{ steps.parse_os.outputs.version }} - compiler_name: - description: "Compiler name (llvm converted to clang)" - value: ${{ steps.parse_compiler.outputs.name }} - compiler_version: - description: "Compiler version (if not set in inputs.compiler, set to latest)" - value: ${{ steps.parse_compiler.outputs.version }} runs: using: "composite" @@ -58,44 +52,20 @@ runs: run: | conan profile detect - - name: Parse os and os version - id: parse_os - shell: bash - env: - VALUE: ${{ contains(matrix.os, '-') && matrix.os || format('{0}-{1}', matrix.os, 'latest') }} - run: | - export NAME=${VALUE%%-*} - echo name=${NAME/ubuntu/linux} >> "$GITHUB_OUTPUT" - - export VERSION=${VALUE##*-} - echo version=$VERSION >> "$GITHUB_OUTPUT" - - - name: Parse compiler and compiler version - id: parse_compiler - shell: bash - env: - VALUE: ${{ contains(matrix.compiler, '-') && matrix.compiler || format('{0}-{1}', matrix.compiler, 'latest') }} - run: | - export NAME=${VALUE%%-*} - echo name=${NAME/llvm/clang} >> "$GITHUB_OUTPUT" - - export VERSION=${VALUE##*-} - echo version=$VERSION >> "$GITHUB_OUTPUT" - - name: Output id: output shell: bash run: | echo "home=$(conan config home)" >> "$GITHUB_OUTPUT" - export HOST_PROFILE=$(python3 script/match_conan_profile.py "${{ steps.parse_os.outputs.name }}-${{ steps.parse_os.outputs.version }}-${{ inputs.arch }}-${{ steps.parse_compiler.outputs.name }}-${{ steps.parse_compiler.outputs.version }}-${{ inputs.build_type }}") + export HOST_PROFILE=$(python3 script/match_conan_profile.py "${{ inputs.os_name }}-${{ inputs.os_version }}-${{ inputs.arch }}-${{ inputs.compiler_name }}-${{ inputs.compiler_version }}-${{ inputs.build_type }}") echo "host_profile=$HOST_PROFILE" >> "$GITHUB_OUTPUT" export BUILD_PROFILE=default echo "build_profile=$BUILD_PROFILE" >> "$GITHUB_OUTPUT" export - echo "args=-pr:b '$BUILD_PROFILE' -pr:h '$HOST_PROFILE' -s:h 'build_type=${{ inputs.build_type }}' ${{ inputs.args }}" >> "$GITHUB_OUTPUT" + echo "args=-pr:b '$BUILD_PROFILE' -s:b 'build_type=Release' -pr:h '$HOST_PROFILE' -s:h 'build_type=${{ inputs.build_type }}' ${{ inputs.args }}" >> "$GITHUB_OUTPUT" - name: Install conan config folder shell: bash diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0b96aed..5577f23 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -66,52 +66,52 @@ jobs: developer_mode: ON include: - # Inject gcov_executable variable - - compiler: llvm - gcov_executable: "llvm-cov gcov" - - compiler: llvm-16.0.6 - gcov_executable: "llvm-cov gcov" - - compiler: gcc-13 - gcov_executable: gcov-13 - # Enable package for release build - build_type: Release developer_mode: OFF package_generator: ZIP steps: - - name: Linux - Maximize build disk space - uses: easimon/maximize-build-space@v10 - if: runner.os == 'Linux' - with: - root-reserve-mb: 30720 - swap-size-mb: 1024 - remove-android: "true" - remove-docker-images: "true" - remove-dotnet: "true" + # Use this if a fairly large library is requried, like building and using llvm as a library. + # - name: Linux - Maximize build disk space + # uses: easimon/maximize-build-space@v10 + # if: runner.os == 'Linux' + # with: + # root-reserve-mb: 30720 + # swap-size-mb: 1024 + # remove-android: "true" + # remove-docker-images: "true" + # remove-dotnet: "true" - uses: actions/checkout@v4 + - name: Parse environment + id: parsed + uses: ./.github/actions/parse_environment + with: + os: ${{ matrix.os }} + compiler: ${{ matrix.compiler }} + - name: Setup cache uses: ./.github/actions/setup_cache with: - compiler: ${{ matrix.compiler }} - build_type: ${{ matrix.build_type }} - developer_mode: ${{ matrix.developer_mode }} + key: ${{ steps.parsed.outputs.os_name }}-${{ steps.parsed.outputs.os_version }}-${{ steps.parsed.outputs.compiler_name }}-${{ steps.parsed.outputs.compiler_version }}-${{ matrix.build_type }}-${{ matrix.developer_mode }} + restore_key: ${{ steps.parsed.outputs.os_name }}-${{ steps.parsed.outputs.os_version }}-${{ steps.parsed.outputs.compiler_name }}-${{ steps.parsed.outputs.compiler_version }}-${{ matrix.build_type }} - name: Setup cpp uses: aminya/setup-cpp@v0.37.0 with: compiler: ${{ matrix.compiler }} - vcvarsall: ${{ contains(matrix.os, 'windows') }} + vcvarsall: ${{ runner.os == 'Windows' }} cmake: true ninja: true ccache: true python: true + # llvm and clang-tidy version should match according to https://github.com/aminya/setup-cpp/issues/249 + clangtidy: ${{ startsWith(matrix.compiler, 'llvm-') && steps.parsed.outputs.compiler_version || 'true' }} cppcheck: true - clangtidy: true gcovr: 7.2 # The default version 5.2 stucks on macos gcc opencppcoverage: true @@ -120,14 +120,16 @@ jobs: uses: ./.github/actions/setup_conan id: conan with: - os: ${{ matrix.os }} - arch: x86_64 - compiler: ${{ matrix.compiler }} + os_name: ${{ steps.parsed.outputs.os_name }} + os_version: ${{ steps.parsed.outputs.os_version }} + arch: ${{ steps.parsed.outputs.arch }} + compiler_name: ${{ steps.parsed.outputs.compiler_name }} + compiler_version: ${{ steps.parsed.outputs.compiler_version }} build_type: ${{ matrix.build_type }} - name: Configure cmake run: | - cmake --preset ${{ steps.conan.outputs.compiler_name }} ${{ steps.conan.outputs.compiler_name == 'msvc' && '-A x64 -T v143' || '' }} -D ENABLE_DEVELOPER_MODE:BOOL=${{ matrix.developer_mode }} -D OPT_ENABLE_COVERAGE:BOOL=${{ matrix.build_type == 'Debug' }} + cmake --preset ${{ steps.parsed.outputs.compiler_name }} ${{ steps.parsed.outputs.compiler_name == 'msvc' && '-A x64 -T v143' || '' }} -D ENABLE_DEVELOPER_MODE:BOOL=${{ matrix.developer_mode }} -D OPT_ENABLE_COVERAGE:BOOL=${{ matrix.build_type == 'Debug' }} - name: Build and test run: | @@ -135,21 +137,21 @@ jobs: - name: Unix - Coverage if: runner.os != 'Windows' - working-directory: build/${{ steps.conan.outputs.compiler_name }} + working-directory: build/${{ steps.parsed.outputs.compiler_name }} run: | ctest -C ${{ matrix.build_type }} - gcovr -j ${{ env.nproc }} --delete --root ../../ --print-summary --xml-pretty --xml coverage.xml . --gcov-executable '${{ matrix.gcov_executable }}' + gcovr -j ${{ env.nproc }} --delete --root ../../ --print-summary --xml-pretty --xml coverage.xml . --gcov-executable '${{ steps.parsed.outputs.gcov_executable }}' - name: Windows - Coverage if: runner.os == 'Windows' - working-directory: build/${{ steps.conan.outputs.compiler_name }} + working-directory: build/${{ steps.parsed.outputs.compiler_name }} run: | OpenCppCoverage.exe --export_type cobertura:coverage.xml --cover_children -- ctest -C ${{ matrix.build_type }} - name: Publish to codecov uses: codecov/codecov-action@v4.4.0 with: - files: ./build/${{ steps.conan.outputs.compiler_name }}/coverage.xml + files: ./build/${{ steps.parsed.outputs.compiler_name }}/coverage.xml flags: ${{ runner.os }} name: ${{ runner.os }}-coverage token: ${{ secrets.CODECOV_TOKEN }} @@ -157,7 +159,7 @@ jobs: - name: CPack if: matrix.package_generator != '' - working-directory: build/${{ steps.conan.outputs.compiler_name }} + working-directory: build/${{ steps.parsed.outputs.compiler_name }} run: | cpack -C ${{ matrix.build_type }} -G ${{ matrix.package_generator }} -B _package -V @@ -166,4 +168,4 @@ jobs: if: ${{ startsWith(github.ref, 'refs/tags/') && matrix.package_generator != '' }} with: files: | - build/${{ steps.conan.outputs.compiler_name }}/_package/*.* + build/${{ steps.parsed.outputs.compiler_name }}/_package/*.* diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 1ed2a81..d28591c 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -45,24 +45,31 @@ jobs: - ON steps: - - name: Linux - Maximize build disk space - uses: easimon/maximize-build-space@v10 - if: runner.os == 'Linux' - with: - root-reserve-mb: 30720 - swap-size-mb: 1024 - remove-android: "true" - remove-docker-images: "true" - remove-dotnet: "true" + # Use this if a fairly large library is requried, like building and using llvm as a library. + # - name: Linux - Maximize build disk space + # uses: easimon/maximize-build-space@v10 + # if: runner.os == 'Linux' + # with: + # root-reserve-mb: 30720 + # swap-size-mb: 1024 + # remove-android: "true" + # remove-docker-images: "true" + # remove-dotnet: "true" - uses: actions/checkout@v4 + - name: Parse environment + id: parsed + uses: ./.github/actions/parse_environment + with: + os: ${{ matrix.os }} + compiler: ${{ matrix.compiler }} + - name: Setup cache uses: ./.github/actions/setup_cache with: - compiler: ${{ matrix.compiler }} - build_type: ${{ matrix.build_type }} - developer_mode: ${{ matrix.developer_mode }} + key: ${{ steps.parsed.outputs.os_name }}-${{ steps.parsed.outputs.os_version }}-${{ steps.parsed.outputs.compiler_name }}-${{ steps.parsed.outputs.compiler_version }}-${{ matrix.build_type }}-${{ matrix.developer_mode }} + restore_key: ${{ steps.parsed.outputs.os_name }}-${{ steps.parsed.outputs.os_version }}-${{ steps.parsed.outputs.compiler_name }}-${{ steps.parsed.outputs.compiler_version }}-${{ matrix.build_type }} - name: Setup Cpp uses: aminya/setup-cpp@v0.37.0 @@ -85,9 +92,11 @@ jobs: uses: ./.github/actions/setup_conan id: conan with: - os: ${{ matrix.os }} - arch: x86_64 - compiler: ${{ matrix.compiler }} + os_name: ${{ steps.parsed.outputs.os_name }} + os_version: ${{ steps.parsed.outputs.os_version }} + arch: ${{ steps.parsed.outputs.arch }} + compiler_name: ${{ steps.parsed.outputs.compiler_name }} + compiler_version: ${{ steps.parsed.outputs.compiler_version }} build_type: ${{ matrix.build_type }} # Fix "ASan runtime does not come first in initial library list; you should either link runtime to your application or manually preload it with LD_PRELOAD." # Learnt from https://github.com/igraph/igraph/issues/1181 @@ -95,7 +104,7 @@ jobs: - name: Configure cmake run: | - cmake --preset ${{ steps.conan.outputs.compiler_name }} ${{ steps.conan.outputs.compiler_name == 'msvc' && '-A x64 -T v143' || '' }} -D ENABLE_DEVELOPER_MODE:BOOL=${{ matrix.developer_mode }} -D OPT_ENABLE_COVERAGE:BOOL=${{ matrix.build_type == 'Debug' }} -D OPT_ENABLE_CLANG_TIDY:BOOL=OFF -D OPT_ENABLE_CPPCHECK:BOOL=OFF -D OPT_ENABLE_INCLUDE_WHAT_YOU_USE:BOOL=OFF + cmake --preset ${{ steps.parsed.outputs.compiler_name }} ${{ steps.parsed.outputs.compiler_name == 'msvc' && '-A x64 -T v143' || '' }} -D ENABLE_DEVELOPER_MODE:BOOL=${{ matrix.developer_mode }} -D OPT_ENABLE_COVERAGE:BOOL=${{ matrix.build_type == 'Debug' }} -D OPT_ENABLE_CLANG_TIDY:BOOL=OFF -D OPT_ENABLE_CPPCHECK:BOOL=OFF -D OPT_ENABLE_INCLUDE_WHAT_YOU_USE:BOOL=OFF - name: Initialize CodeQL uses: github/codeql-action/init@v3 diff --git a/conan/profiles/windows-#-#-clang-16.0.6-# b/conan/profiles/windows-#-#-clang-16.0.6-# new file mode 100644 index 0000000..c330b8e --- /dev/null +++ b/conan/profiles/windows-#-#-clang-16.0.6-# @@ -0,0 +1,20 @@ +# An example on how to specialize a conan profile for the corresponding github action job +# +# The specialization sets compiler.version directly to detect the corresponding compiler +{% set arch = detect_api.detect_arch() %} +{% set os = detect_api.detect_os() %} + +[settings] +arch={{ arch }} +compiler=clang +compiler.cppstd=20 +# compiler.runtime=dynamic +# compiler.runtime_version=v143 +compiler.libcxx=libc++ +compiler.version=16 +os={{ os }} + +[conf] +&:tools.cmake.cmaketoolchain:generator=Ninja Multi-Config +tools.system.package_manager:mode=install +tools.system.package_manager:sudo=True \ No newline at end of file diff --git a/script/match_conan_profile.py b/script/match_conan_profile.py index 4f91ce6..2778639 100755 --- a/script/match_conan_profile.py +++ b/script/match_conan_profile.py @@ -2,9 +2,10 @@ import os import sys +import re -def match_file(file, target_name): +def match_sections(file_sections, target_sections): ''' Check if target can be matched by the file. By "match", we mean the corresponding file section is equal to the specified target section, or is wildcard '#'. @@ -12,7 +13,7 @@ def match_file(file, target_name): -> equal_count if matches, standing for sections that equals ''' equal_count = 0 - for file_section, target_section in zip(file.split('-'), target_name.split('-')): + for file_section, target_section in zip(file_sections.groups(), target_sections.groups()): if file_section == "#": continue elif file_section == target_section: @@ -33,10 +34,19 @@ def find_most_matched_file(directory, target_name): most_matched = "" max_count = -1 + REGEX = re.compile( + "([0-9a-zA-Z#_.]+)-([0-9a-zA-Z#_.]+)-([0-9a-zA-Z#_.]+)-([0-9a-zA-Z#_.]+)-([0-9a-zA-Z#_.]+)-([0-9a-zA-Z#_.]+)") + + target_sections = REGEX.match(target_name) + if not target_sections: + raise Exception( + "input dosen't match the pattern -----") + for file in os.listdir(directory): file_path = os.path.join(directory, file) - if os.path.isfile(file_path) and os.path.splitext(file_path)[1] == '': - count = match_file(file, target_name) + file_sections = REGEX.match(file) + if os.path.isfile(file_path) and file_sections: + count = match_sections(file_sections, target_sections) if count == -1: continue elif count > max_count: @@ -44,7 +54,7 @@ def find_most_matched_file(directory, target_name): max_count = count elif count == max_count: # If multiple files have the maximum count, choose the section-lexicographcially less one - if file.split('-') < most_matched.split('-'): + if file.groups() < most_matched.groups(): most_matched = file return most_matched