diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml deleted file mode 100644 index f41c108d..00000000 --- a/.github/workflows/linux.yml +++ /dev/null @@ -1,260 +0,0 @@ -name: Linux - -on: [push, pull_request] - -jobs: - compatibility: - runs-on: ubuntu-18.04 - container: streamhpc/opencl-sdk-intelcpu:ubuntu-18.04-20220127 - strategy: - matrix: - # TODO: CMake 3.22.1 is minimum because image lacks 3.11 (FetchContent) - # Replace once backport to C++14 happened - include: - # Unix Makefiles - # One CMake version - # For all compilers - # For all configurations - # For all target architectures - - C_COMPILER: gcc-7 - CXX_COMPILER: g++-7 - CMAKE: 3.22.1 - GEN: Unix Makefiles - CONFIG: Debug - BIN: 64 - - C_COMPILER: gcc-7 - CXX_COMPILER: g++-7 - CMAKE: 3.22.1 - GEN: Unix Makefiles - CONFIG: Release - BIN: 64 - - C_COMPILER: gcc-7 - CXX_COMPILER: g++-7 - CMAKE: 3.22.1 - GEN: Unix Makefiles - CONFIG: Debug - BIN: 32 - - C_COMPILER: gcc-7 - CXX_COMPILER: g++-7 - CMAKE: 3.22.1 - GEN: Unix Makefiles - CONFIG: Release - BIN: 32 - - C_COMPILER: gcc-11 - CXX_COMPILER: g++-11 - CMAKE: 3.22.1 - GEN: Unix Makefiles - CONFIG: Debug - BIN: 64 - - C_COMPILER: gcc-11 - CXX_COMPILER: g++-11 - CMAKE: 3.22.1 - GEN: Unix Makefiles - CONFIG: Release - BIN: 64 - - C_COMPILER: gcc-11 - CXX_COMPILER: g++-11 - CMAKE: 3.22.1 - GEN: Unix Makefiles - CONFIG: Debug - BIN: 32 - - C_COMPILER: gcc-11 - CXX_COMPILER: g++-11 - CMAKE: 3.22.1 - GEN: Unix Makefiles - CONFIG: Release - BIN: 32 - - C_COMPILER: clang-8 - CXX_COMPILER: clang++-8 - CMAKE: 3.22.1 - GEN: Unix Makefiles - CONFIG: Debug - BIN: 64 - - C_COMPILER: clang-8 - CXX_COMPILER: clang++-8 - CMAKE: 3.22.1 - GEN: Unix Makefiles - CONFIG: Release - BIN: 64 - - C_COMPILER: clang-8 - CXX_COMPILER: clang++-8 - CMAKE: 3.22.1 - GEN: Unix Makefiles - CONFIG: Debug - BIN: 32 - - C_COMPILER: clang-8 - CXX_COMPILER: clang++-8 - CMAKE: 3.22.1 - GEN: Unix Makefiles - CONFIG: Release - BIN: 32 - - C_COMPILER: clang-13 - CXX_COMPILER: clang++-13 - CMAKE: 3.22.1 - GEN: Unix Makefiles - CONFIG: Debug - BIN: 64 - - C_COMPILER: clang-13 - CXX_COMPILER: clang++-13 - CMAKE: 3.22.1 - GEN: Unix Makefiles - CONFIG: Release - BIN: 64 - - C_COMPILER: clang-13 - CXX_COMPILER: clang++-13 - CMAKE: 3.22.1 - GEN: Unix Makefiles - CONFIG: Debug - BIN: 32 - - C_COMPILER: clang-13 - CXX_COMPILER: clang++-13 - CMAKE: 3.22.1 - GEN: Unix Makefiles - CONFIG: Release - BIN: 32 - # Multi-config generators - # One CMake version - # For all compilers - # For all architectures - - C_COMPILER: gcc-7 - CXX_COMPILER: g++-7 - CMAKE: 3.22.1 - GEN: Ninja Multi-Config - BIN: 64 - - C_COMPILER: gcc-7 - CXX_COMPILER: g++-7 - CMAKE: 3.22.1 - GEN: Ninja Multi-Config - BIN: 32 - - C_COMPILER: gcc-11 - CXX_COMPILER: g++-11 - CMAKE: 3.22.1 - GEN: Ninja Multi-Config - BIN: 64 - - C_COMPILER: gcc-11 - CXX_COMPILER: g++-11 - CMAKE: 3.22.1 - GEN: Ninja Multi-Config - BIN: 32 - - C_COMPILER: clang-8 - CXX_COMPILER: clang++-8 - CMAKE: 3.22.1 - GEN: Ninja Multi-Config - BIN: 64 - - C_COMPILER: clang-8 - CXX_COMPILER: clang++-8 - CMAKE: 3.22.1 - GEN: Ninja Multi-Config - BIN: 32 - - C_COMPILER: clang-13 - CXX_COMPILER: clang++-13 - CMAKE: 3.22.1 - GEN: Ninja Multi-Config - BIN: 64 - - C_COMPILER: clang-13 - CXX_COMPILER: clang++-13 - CMAKE: 3.22.1 - GEN: Ninja Multi-Config - BIN: 32 - env: - CMAKE_EXE: /opt/Kitware/CMake/${{ matrix.CMAKE }}/bin/cmake - CTEST_EXE: /opt/Kitware/CMake/${{ matrix.CMAKE }}/bin/ctest - - - steps: - - name: Checkout OpenCL-Layers - uses: actions/checkout@v2 - with: - submodules: recursive - - - name: Checkout OpenCL-Headers - uses: actions/checkout@v2 - with: - repository: KhronosGroup/OpenCL-Headers - path: external/OpenCL-Headers - - - name: Checkout OpenCL-ICD-Loader - uses: actions/checkout@v2 - with: - repository: KhronosGroup/OpenCL-ICD-Loader - path: external/OpenCL-ICD-Loader - - - name: Build & install OpenCL-Headers - shell: bash - run: | - $CMAKE_EXE \ - -G "${{matrix.GEN}}" \ - `if [[ "${{matrix.GEN}}" == "Unix Makefiles" ]]; then echo -D CMAKE_BUILD_TYPE=${{matrix.CONFIG}}; fi;` \ - -D BUILD_TESTING=OFF \ - -D CMAKE_C_FLAGS="-w -m${{matrix.BIN}}" \ - -D CMAKE_C_COMPILER=${{matrix.C_COMPILER}} \ - -D CMAKE_C_EXTENSIONS=OFF \ - -D CMAKE_INSTALL_PREFIX=$GITHUB_WORKSPACE/external/OpenCL-Headers/install \ - -B$GITHUB_WORKSPACE/external/OpenCL-Headers/build \ - -H$GITHUB_WORKSPACE/external/OpenCL-Headers ; - $CMAKE_EXE \ - --build $GITHUB_WORKSPACE/external/OpenCL-Headers/build \ - `if [[ "${{matrix.GEN}}" == "Ninja Multi-Config" ]]; then echo --config Release; fi;` \ - --target install \ - -- \ - -j`nproc` - - - name: Build & install OpenCL-ICD-Loader - shell: bash - run: | - $CMAKE_EXE \ - -G "${{matrix.GEN}}" \ - `if [[ "${{matrix.GEN}}" == "Unix Makefiles" ]]; then echo -D CMAKE_BUILD_TYPE=${{matrix.CONFIG}}; fi;` \ - -D BUILD_TESTING=OFF \ - -D CMAKE_C_FLAGS="-w -m${{matrix.BIN}}" \ - -D CMAKE_C_COMPILER=${{matrix.C_COMPILER}} \ - -D CMAKE_C_EXTENSIONS=OFF \ - -D CMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/external/OpenCL-Headers/install \ - -D CMAKE_INSTALL_PREFIX=$GITHUB_WORKSPACE/external/OpenCL-ICD-Loader/install \ - -B$GITHUB_WORKSPACE/external/OpenCL-ICD-Loader/build \ - -H$GITHUB_WORKSPACE/external/OpenCL-ICD-Loader ; - $CMAKE_EXE \ - --build $GITHUB_WORKSPACE/external/OpenCL-ICD-Loader/build \ - `if [[ "${{matrix.GEN}}" == "Ninja Multi-Config" ]]; then echo --config Release; fi;` \ - --target install \ - -- \ - -j`nproc` - - - name: Configure - shell: bash - run: $CMAKE_EXE - -G "${{matrix.GEN}}" - -D OPENCL_LAYERS_BUILD_TESTING=ON - -D BUILD_TESTING=ON - `if [[ "${{matrix.GEN}}" == "Unix Makefiles" ]]; then echo -D CMAKE_BUILD_TYPE=${{matrix.CONFIG}}; fi;` - -D CMAKE_C_FLAGS="-Wall -Wextra -pedantic -Werror -m${{matrix.BIN}}" - -D CMAKE_C_COMPILER=${{matrix.C_COMPILER}} - -D CMAKE_C_EXTENSIONS=OFF - -D CMAKE_CXX_FLAGS="-Wall -Wextra -pedantic -Werror -m${{matrix.BIN}}" - -D CMAKE_CXX_COMPILER=${{matrix.CXX_COMPILER}} - -D CMAKE_CXX_EXTENSIONS=OFF - -D CMAKE_INSTALL_PREFIX=$GITHUB_WORKSPACE/install - -D CMAKE_PREFIX_PATH="$GITHUB_WORKSPACE/external/OpenCL-Headers/install;$GITHUB_WORKSPACE/external/OpenCL-ICD-Loader/install" - -B$GITHUB_WORKSPACE/build - -H$GITHUB_WORKSPACE - - - name: Build - shell: bash - run: if [[ "${{matrix.GEN}}" == "Unix Makefiles" ]]; - then - $CMAKE_EXE --build $GITHUB_WORKSPACE/build -- -j`nproc`; - else - $CMAKE_EXE --build $GITHUB_WORKSPACE/build --config Debug -- -j`nproc`; - $CMAKE_EXE --build $GITHUB_WORKSPACE/build --config Release -- -j`nproc`; - fi; - - - name: Test - shell: bash - working-directory: ${{runner.workspace}}/OpenCL-Layers/build - run: if [[ "${{matrix.GEN}}" == "Unix Makefiles" ]]; - then - $CTEST_EXE --output-on-failure --parallel `nproc`; - else - $CTEST_EXE --output-on-failure -C Debug --parallel `nproc`; - $CTEST_EXE --output-on-failure -C Release --parallel `nproc`; - fi; \ No newline at end of file diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml deleted file mode 100644 index 97c426d1..00000000 --- a/.github/workflows/macos.yml +++ /dev/null @@ -1,108 +0,0 @@ -name: MacOS - -on: [push, pull_request] - -jobs: - compatibility: - if: false - runs-on: macos-latest - strategy: - matrix: - VER: [9, 11] - EXT: [ON, OFF] - GEN: [Xcode, Ninja Multi-Config] - STD: [14, 17] - - steps: - - name: Checkout OpenCL-Layers - uses: actions/checkout@v2 - with: - submodules: recursive - - - name: Checkout OpenCL-Headers - uses: actions/checkout@v2 - with: - repository: KhronosGroup/OpenCL-Headers - path: external/OpenCL-Headers - - - name: Checkout OpenCL-ICD-Loader - uses: actions/checkout@v2 - with: - repository: KhronosGroup/OpenCL-ICD-Loader - path: external/OpenCL-ICD-Loader - - - name: Create Build Environment - shell: bash - run: | - cmake -E make_directory $GITHUB_WORKSPACE/build; - cmake -E make_directory $GITHUB_WORKSPACE/install; - if [[ "${{matrix.GEN}}" == "Ninja Multi-Config" && ! `which ninja` ]]; then brew install ninja; fi; - # Install Ninja only if it's the selected generator and it's not available. - cmake --version - - - name: Build & install OpenCL-Headers - shell: bash - run: | - cmake \ - -G "${{matrix.GEN}}" \ - -D BUILD_TESTING=OFF \ - -D CMAKE_C_FLAGS="-w" \ - -D CMAKE_C_COMPILER=/usr/local/bin/gcc-${{matrix.VER}} \ - -D CMAKE_C_EXTENSIONS=${{matrix.EXT}} \ - -D CMAKE_INSTALL_PREFIX=$GITHUB_WORKSPACE/external/OpenCL-Headers/install \ - -S $GITHUB_WORKSPACE/external/OpenCL-Headers \ - -B $GITHUB_WORKSPACE/external/OpenCL-Headers/build - cmake \ - --build $GITHUB_WORKSPACE/external/OpenCL-Headers/build \ - --target install \ - --config Release \ - --parallel `sysctl -n hw.logicalcpu` \ - `if [[ "${{matrix.GEN}}" == "Xcode" ]]; then echo "-- -quiet"; fi;` - - - name: Build & install OpenCL-ICD-Loader - shell: bash - run: | - cmake \ - -G "${{matrix.GEN}}" \ - -D BUILD_TESTING=OFF \ - -D CMAKE_C_FLAGS="-w -m64" \ - -D CMAKE_C_COMPILER=/usr/local/bin/gcc-${{matrix.VER}} \ - -D CMAKE_C_EXTENSIONS=${{matrix.EXT}} \ - -D CMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/external/OpenCL-Headers/install \ - -D CMAKE_INSTALL_PREFIX=$GITHUB_WORKSPACE/external/OpenCL-ICD-Loader/install \ - -S $GITHUB_WORKSPACE/external/OpenCL-ICD-Loader \ - -B $GITHUB_WORKSPACE/external/OpenCL-ICD-Loader/build - cmake \ - --build $GITHUB_WORKSPACE/external/OpenCL-ICD-Loader/build \ - --target install \ - --config Release \ - --parallel `sysctl -n hw.logicalcpu` - - - name: Configure CMake - shell: bash - run: cmake - -G "${{matrix.GEN}}" - -D OPENCL_LAYERS_BUILD_TESTING=ON - -D BUILD_TESTING=ON - -D CMAKE_CXX_FLAGS="-Wall -Wextra -pedantic -Wno-format -m64" - -D CMAKE_CXX_COMPILER=/usr/local/bin/g++-${{matrix.VER}} - -D CMAKE_CXX_STANDARD=${{matrix.STD}} - -D CMAKE_CXX_EXTENSIONS=${{matrix.EXT}} - -D CMAKE_INSTALL_PREFIX=$GITHUB_WORKSPACE/install - -D CMAKE_PREFIX_PATH="$GITHUB_WORKSPACE/external/OpenCL-Headers/install;$GITHUB_WORKSPACE/external/OpenCL-ICD-Loader/install" - -D CMAKE_FIND_PACKAGE_PREFER_CONFIG=ON - -S $GITHUB_WORKSPACE - -B $GITHUB_WORKSPACE/build - - - name: Build - shell: bash - run: | - cmake --build $GITHUB_WORKSPACE/build --config Release --parallel `sysctl -n hw.logicalcpu` `if [[ "${{matrix.GEN}}" == "Xcode" ]]; then echo "-- -quiet"; fi;` - cmake --build $GITHUB_WORKSPACE/build --config Debug --parallel `sysctl -n hw.logicalcpu` `if [[ "${{matrix.GEN}}" == "Xcode" ]]; then echo "-- -quiet"; fi;` - - - name: Test - working-directory: ${{runner.workspace}}/OpenCL-Layers/build - shell: bash - run: | - ctest -C Release --output-on-failure --parallel `sysctl -n hw.logicalcpu` - ctest -C Debug --output-on-failure --parallel `sysctl -n hw.logicalcpu` \ No newline at end of file diff --git a/.github/workflows/presubmit.yml b/.github/workflows/presubmit.yml new file mode 100644 index 00000000..ec0dfd1f --- /dev/null +++ b/.github/workflows/presubmit.yml @@ -0,0 +1,1076 @@ +name: Presubmit + +on: [push, pull_request] + +jobs: + linux: + runs-on: ubuntu-latest + defaults: + run: + shell: bash + strategy: + matrix: + CMAKE: [3.26.4] + COMPILER: + - C_NAME: gcc + CXX_NAME: g++ + VER: 11 + - C_NAME: gcc + CXX_NAME: g++ + VER: 13 + - C_NAME: clang + CXX_NAME: clang++ + VER: 14 + - C_NAME: clang + CXX_NAME: clang++ + VER: 16 + BIN: [64] + DEPS: [system, fetch, vcpkg] + CONF: + - GEN: Unix Makefiles + CONFIG: Debug + - GEN: Unix Makefiles + CONFIG: Release + - GEN: Ninja Multi-Config + CONFIG: Release + IMAGE: + - khronosgroup/docker-images:opencl-sdk-intelcpu-ubuntu-22.04.20230717 + include: + - CMAKE: system + COMPILER: + C_NAME: gcc + CXX_NAME: g++ + VER: 9 + BIN: 64 + DEPS: system + CONF: + GEN: Unix Makefiles + CONFIG: Debug + IMAGE: khronosgroup/docker-images:opencl-sdk-intelcpu-ubuntu-20.04.20230717 + - CMAKE: system + COMPILER: + C_NAME: gcc + CXX_NAME: g++ + VER: 9 + BIN: 64 + DEPS: system + CONF: + GEN: Unix Makefiles + CONFIG: Release + IMAGE: khronosgroup/docker-images:opencl-sdk-intelcpu-ubuntu-20.04.20230717 + - CMAKE: system + COMPILER: + C_NAME: gcc + CXX_NAME: g++ + VER: 9 + BIN: 32 + DEPS: vcpkg + CONF: + GEN: Unix Makefiles + CONFIG: Debug + IMAGE: khronosgroup/docker-images:opencl-sdk-intelcpu-ubuntu-20.04.20230717 + - CMAKE: system + COMPILER: + C_NAME: gcc + CXX_NAME: g++ + VER: 9 + BIN: 32 + DEPS: vcpkg + CONF: + GEN: Unix Makefiles + CONFIG: Release + IMAGE: khronosgroup/docker-images:opencl-sdk-intelcpu-ubuntu-20.04.20230717 + container: ${{matrix.IMAGE}} + env: + CMAKE_EXE: /opt/Kitware/CMake/${{ matrix.CMAKE }}/bin/cmake + CTEST_EXE: /opt/Kitware/CMake/${{ matrix.CMAKE }}/bin/ctest + CC: ${{matrix.COMPILER.C_NAME}}-${{matrix.COMPILER.VER}} + CXX: ${{matrix.COMPILER.CXX_NAME}}-${{matrix.COMPILER.VER}} + + steps: + - name: Set up vcpkg triplet + if: matrix.DEPS == 'vcpkg' + run: if [[ "${{ matrix.BIN }}" == "64" ]]; then + echo "VCPKG_TRIPLET=x64-linux" >> $GITHUB_ENV; + else + echo "VCPKG_TRIPLET=x86-linux" >> $GITHUB_ENV; + fi + + - name: Install system CMake + if: matrix.CMAKE == 'system' + run: apt-get update -qq && apt-get install -y cmake && + echo "CMAKE_EXE=cmake" >> "$GITHUB_ENV" && + echo "CTEST_EXE=ctest" >> "$GITHUB_ENV" + + - name: Install dependencies (apt) + if: matrix.DEPS == 'system' + run: apt-get update -qq && apt-get install -y + libboost-atomic-dev + libboost-chrono-dev + libboost-date-time-dev + libboost-thread-dev + libboost-wave-dev + libgtest-dev + librapidxml-dev + + - name: Cache dependencies (vcpkg) + if: matrix.DEPS == 'vcpkg' + id: vcpkg-install + uses: actions/cache@v4 + with: + path: /opt/Microsoft/vcpkg + key: vcpkg-linux-${{matrix.BIN}} + + - name: Install dependencies (vcpkg) + if: matrix.DEPS == 'vcpkg' + run: | + cd /opt/Microsoft/vcpkg + git pull + ./bootstrap-vcpkg.sh + ./vcpkg install boost-wave:$VCPKG_TRIPLET gtest:$VCPKG_TRIPLET rapidxml:$VCPKG_TRIPLET + + - name: Set up compiler flags + # -Werror omitted when fetching the dependencies. The dependencies emit warnings + # that are beyond our control. + run: | + if [[ "${{ matrix.DEPS }}" == "fetch" ]]; then + echo "CFLAGS=-Wall -Wextra -pedantic -m${{matrix.BIN}}" >> $GITHUB_ENV; + echo "CXXFLAGS=-Wall -Wextra -pedantic -m${{matrix.BIN}}" >> $GITHUB_ENV; + else + echo "CFLAGS=-Wall -Wextra -pedantic -Werror -m${{matrix.BIN}}" >> $GITHUB_ENV; + echo "CXXFLAGS=-Wall -Wextra -pedantic -Werror -m${{matrix.BIN}}" >> $GITHUB_ENV; + fi + + - name: Checkout OpenCL-Layers + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Checkout OpenCL-Headers + uses: actions/checkout@v4 + with: + repository: KhronosGroup/OpenCL-Headers + path: external/OpenCL-Headers + + - name: Checkout OpenCL-CLHPP + uses: actions/checkout@v4 + with: + repository: KhronosGroup/OpenCL-CLHPP + path: external/OpenCL-CLHPP + + - name: Checkout OpenCL-ICD-Loader + uses: actions/checkout@v4 + with: + repository: KhronosGroup/OpenCL-ICD-Loader + path: external/OpenCL-ICD-Loader + + - name: Build & install OpenCL-Headers + run: $CMAKE_EXE + -G "${{matrix.CONF.GEN}}" + `if [[ "${{matrix.CONF.GEN}}" == "Unix Makefiles" ]]; then echo "-D CMAKE_BUILD_TYPE=${{matrix.CONF.CONFIG}}"; fi` + -D BUILD_TESTING=OFF + -D CMAKE_INSTALL_PREFIX=$GITHUB_WORKSPACE/external/OpenCL-Headers/install + -S $GITHUB_WORKSPACE/external/OpenCL-Headers + -B $GITHUB_WORKSPACE/external/OpenCL-Headers/build && + $CMAKE_EXE + --build $GITHUB_WORKSPACE/external/OpenCL-Headers/build + --target install + --parallel `nproc` + `if [[ "${{matrix.CONF.GEN}}" == "Ninja Multi-Config" ]]; then echo "--config ${{matrix.CONF.CONFIG}}"; fi` + + - name: Build & install OpenCL-CLHPP + run: $CMAKE_EXE + -G "${{matrix.CONF.GEN}}" + `if [[ "${{matrix.CONF.GEN}}" == "Unix Makefiles" ]]; then echo "-D CMAKE_BUILD_TYPE=${{matrix.CONF.CONFIG}}"; fi` + -D BUILD_DOCS=OFF + -D BUILD_EXAMPLES=OFF + -D BUILD_TESTING=OFF + -D CMAKE_INSTALL_PREFIX=$GITHUB_WORKSPACE/external/OpenCL-CLHPP/install + -D CMAKE_PREFIX_PATH="$GITHUB_WORKSPACE/external/OpenCL-Headers/install" + -S $GITHUB_WORKSPACE/external/OpenCL-CLHPP + -B $GITHUB_WORKSPACE/external/OpenCL-CLHPP/build && + $CMAKE_EXE + --build $GITHUB_WORKSPACE/external/OpenCL-CLHPP/build + --target install + --parallel `nproc` + `if [[ "${{matrix.CONF.GEN}}" == "Ninja Multi-Config" ]]; then echo "--config ${{matrix.CONF.CONFIG}}"; fi` + + - name: Build & install OpenCL-ICD-Loader + run: $CMAKE_EXE + -G "${{matrix.CONF.GEN}}" + `if [[ "${{matrix.CONF.GEN}}" == "Unix Makefiles" ]]; then echo "-D CMAKE_BUILD_TYPE=${{matrix.CONF.CONFIG}}"; fi` + -D BUILD_TESTING=OFF + -D CMAKE_INSTALL_PREFIX=$GITHUB_WORKSPACE/external/OpenCL-ICD-Loader/install + -D CMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/external/OpenCL-Headers/install + -S $GITHUB_WORKSPACE/external/OpenCL-ICD-Loader + -B $GITHUB_WORKSPACE/external/OpenCL-ICD-Loader/build && + $CMAKE_EXE + --build $GITHUB_WORKSPACE/external/OpenCL-ICD-Loader/build + --target install + --parallel `nproc` + `if [[ "${{matrix.CONF.GEN}}" == "Ninja Multi-Config" ]]; then echo "--config ${{matrix.CONF.CONFIG}}"; fi` + + - name: Configure + run: $CMAKE_EXE + -G "${{matrix.CONF.GEN}}" + `if [[ "${{matrix.CONF.GEN}}" == "Unix Makefiles" ]]; then echo "-D CMAKE_BUILD_TYPE=${{matrix.CONF.CONFIG}}"; fi` + -D BUILD_TESTING=ON + -D CMAKE_INSTALL_PREFIX=$GITHUB_WORKSPACE/install + -D CMAKE_PREFIX_PATH="$GITHUB_WORKSPACE/external/OpenCL-Headers/install;$GITHUB_WORKSPACE/external/OpenCL-ICD-Loader/install;$GITHUB_WORKSPACE/external/OpenCL-CLHPP/install" + `if [[ "${{matrix.DEPS}}" == "vcpkg" ]]; then echo "-D CMAKE_TOOLCHAIN_FILE=/opt/Microsoft/vcpkg/scripts/buildsystems/vcpkg.cmake"; fi;` + `if [[ "${{matrix.DEPS}}" == "vcpkg" ]]; then echo "-D VCPKG_TARGET_TRIPLET=$VCPKG_TRIPLET"; fi;` + -S $GITHUB_WORKSPACE + -B $GITHUB_WORKSPACE/build + + - name: Build + run: if [[ "${{matrix.CONF.GEN}}" == "Unix Makefiles" ]]; + then + $CMAKE_EXE --build $GITHUB_WORKSPACE/build --parallel `nproc`; + else + $CMAKE_EXE --build $GITHUB_WORKSPACE/build --config Debug; + $CMAKE_EXE --build $GITHUB_WORKSPACE/build --config Release; + fi; + + - name: Test + working-directory: ${{runner.workspace}}/OpenCL-Layers/build + run: | + # The system's ICD loader can only be used from an x64 process + if [[ "${{matrix.BIN}}" == "32" ]]; then + export LABEL_EXCLUDE="system-icd"; + fi + if [[ "${{matrix.CONF.GEN}}" == "Unix Makefiles" ]]; + then + $CTEST_EXE --output-on-failure --no-tests=error --parallel `nproc` --label-exclude $LABEL_EXCLUDE; + else + $CTEST_EXE --output-on-failure --no-tests=error -C Debug --parallel `nproc` --label-exclude $LABEL_EXCLUDE; + $CTEST_EXE --output-on-failure --no-tests=error -C Release --parallel `nproc` --label-exclude $LABEL_EXCLUDE; + fi; + + - name: Install + run: $CMAKE_EXE --build $GITHUB_WORKSPACE/build --target install --config ${{matrix.CONF.CONFIG}} + + - name: Configure consume test + run: $CMAKE_EXE + -G "${{matrix.CONF.GEN}}" + `if [[ "${{matrix.CONF.GEN}}" == "Unix Makefiles" ]]; then echo "-D CMAKE_BUILD_TYPE=${{matrix.CONF.CONFIG}}"; fi` + -D CMAKE_PREFIX_PATH="$GITHUB_WORKSPACE/external/OpenCL-Headers/install;$GITHUB_WORKSPACE/external/OpenCL-ICD-Loader/install;$GITHUB_WORKSPACE/external/OpenCL-CLHPP/install;$GITHUB_WORKSPACE/install" + `if [[ "${{matrix.DEPS}}" == "vcpkg" ]]; then echo "-D CMAKE_TOOLCHAIN_FILE=/opt/Microsoft/vcpkg/scripts/buildsystems/vcpkg.cmake"; fi;` + `if [[ "${{matrix.DEPS}}" == "vcpkg" ]]; then echo "-D VCPKG_TARGET_TRIPLET=$VCPKG_TRIPLET"; fi;` + -S $GITHUB_WORKSPACE/program-cache/lib/test/package + -B $GITHUB_WORKSPACE/program-cache/lib/test/package/build + + - name: Build consume test + run: if [[ "${{matrix.CONF.GEN}}" == "Unix Makefiles" ]]; + then + $CMAKE_EXE --build $GITHUB_WORKSPACE/program-cache/lib/test/package/build --parallel `nproc`; + else + $CMAKE_EXE --build $GITHUB_WORKSPACE/program-cache/lib/test/package/build --config Debug; + $CMAKE_EXE --build $GITHUB_WORKSPACE/program-cache/lib/test/package/build --config Release; + fi; + + - name: Run consume test + # The consume test uses the system's ICD loader, which is not compatible with the x86 binary + if: matrix.BIN != 32 + working-directory: ${{runner.workspace}}/OpenCL-Layers/program-cache/lib/test/package/build + run: if [[ "${{matrix.CONF.GEN}}" == "Unix Makefiles" ]]; + then + $CTEST_EXE --output-on-failure --no-tests=error --parallel `nproc`; + else + $CTEST_EXE --output-on-failure --no-tests=error -C Debug --parallel `nproc`; + $CTEST_EXE --output-on-failure --no-tests=error -C Release --parallel `nproc`; + fi; + + windows: + runs-on: windows-latest + defaults: + run: + shell: pwsh + strategy: + matrix: + VER: [v142, v143, clangcl] + GEN: [Visual Studio 17 2022, Ninja Multi-Config] + BIN: [x64] + DEPS: [vcpkg, fetch] + exclude: + - VER: clangcl + GEN: Ninja Multi-Config + include: + - VER: v142 + GEN: Visual Studio 17 2022 + BIN: x86 + DEPS: vcpkg + env: + NINJA_URL: https://github.com/ninja-build/ninja/releases/download/v1.10.2/ninja-win.zip + NINJA_ROOT: C:\Tools\Ninja + VS_ROOT: 'C:\Program Files\Microsoft Visual Studio\2022\Enterprise' + UseMultiToolTask: 'true' # Better parallel MSBuild execution + EnforceProcessCountAcrossBuilds: 'true' # -=- + MultiProcMaxCount: '3' # -=- + INTEL_OCL_URL: https://github.com/intel/llvm/releases/download/2023-WW27/win-oclcpuexp-2023.16.6.0.28_rel.zip + INTEL_TBB_URL: https://github.com/oneapi-src/oneTBB/releases/download/v2021.10.0/oneapi-tbb-2021.10.0-win.zip + IMAGE_INTEL_PREFIX: C:\Tools\Intel + + steps: + - name: Install OpenCL runtime + if: matrix.BIN != 'x86' + run: | + $INTEL_OCL_ARCHIVE_NAME = Split-Path ${env:INTEL_OCL_URL} -Leaf; ` + Invoke-WebRequest ${env:INTEL_OCL_URL} -OutFile ${env:TEMP}\$INTEL_OCL_ARCHIVE_NAME; ` + Expand-Archive ${env:TEMP}\$INTEL_OCL_ARCHIVE_NAME -DestinationPath ${env:IMAGE_INTEL_PREFIX}\oclcpuexp; ` + Remove-Item ${env:TEMP}\$INTEL_OCL_ARCHIVE_NAME; ` + $INTEL_TBB_ARCHIVE_NAME = Split-Path ${env:INTEL_TBB_URL} -Leaf; ` + Invoke-WebRequest ${env:INTEL_TBB_URL} -OutFile ${env:TEMP}\$INTEL_TBB_ARCHIVE_NAME; ` + Expand-Archive ${env:TEMP}\$INTEL_TBB_ARCHIVE_NAME -DestinationPath ${env:IMAGE_INTEL_PREFIX}; ` + Get-ChildItem ${env:IMAGE_INTEL_PREFIX}\oneapi-tbb* | Rename-Item -NewName oneapi-tbb; ` + Remove-Item ${env:TEMP}\$INTEL_TBB_ARCHIVE_NAME; ` + New-Item -Type Directory ${env:IMAGE_INTEL_PREFIX}\oclcpuexp\tbb | Out-Null; ` + Get-ChildItem ${env:IMAGE_INTEL_PREFIX}\oneapi-tbb\redist\intel64\vc14\*.dll | ForEach-Object { New-Item -Type SymbolicLink -Path ${env:IMAGE_INTEL_PREFIX}\oclcpuexp\tbb -Name $_.Name -Value $_.FullName | Out-Null; }; ` + New-Item -Type Directory HKLM:\SOFTWARE\Khronos\OpenCL -Force | Out-Null; ` + New-Item -Type File HKLM:\SOFTWARE\Khronos\OpenCL\Vendors | Out-Null; ` + Set-ItemProperty -Path HKLM:\SOFTWARE\Khronos\OpenCL\Vendors -Name ${env:IMAGE_INTEL_PREFIX}\oclcpuexp\intelocl64.dll -Type DWord -Value 0; + + - name: Set up compiler flags + # -Werror omitted when fetching the dependencies. The dependencies emit warnings + # that are beyond our control. + run: | + if ('${{ matrix.DEPS }}' -eq 'fetch') + { + echo "CFLAGS=/W4" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + echo "CXXFLAGS=/W4" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + } + else + { + echo "CFLAGS=/W4 /WX" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + echo "CXXFLAGS=/W4 /WX" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + } + + - name: Cache dependencies (vcpkg) + if: matrix.DEPS == 'vcpkg' + id: vcpkg-install + uses: actions/cache@v4 + with: + path: | + C:\vcpkg + key: boost-wave:${{matrix.BIN}}-windows-static-md + + - name: Install dependencies (vcpkg) + if: matrix.DEPS == 'vcpkg' && steps.vcpkg-install.outputs.cache-hit != 'true' + run: | + cd ${env:VCPKG_INSTALLATION_ROOT} + git pull + .\vcpkg.exe install boost-wave:${{matrix.BIN}}-windows-static-md + + - name: Cache Ninja install + id: ninja-install + uses: actions/cache@v4 + with: + path: | + C:\Tools\Ninja + key: ${{runner.os}}-ninja-${{env.NINJA_URL}} + + - name: Install Ninja + if: steps.ninja-install.outputs.cache-hit != 'true' + run: | + Invoke-WebRequest ${env:NINJA_URL} -OutFile ~\Downloads\ninja-win.zip + Expand-Archive ~\Downloads\ninja-win.zip -DestinationPath C:\Tools\Ninja\ + Remove-Item ~\Downloads\* + + - name: Checkout OpenCL-Layers + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Checkout OpenCL-Headers + uses: actions/checkout@v4 + with: + repository: KhronosGroup/OpenCL-Headers + path: external/OpenCL-Headers + + - name: Checkout OpenCL-CLHPP + uses: actions/checkout@v4 + with: + repository: KhronosGroup/OpenCL-CLHPP + path: external/OpenCL-CLHPP + + - name: Checkout OpenCL-ICD-Loader + uses: actions/checkout@v4 + with: + repository: KhronosGroup/OpenCL-ICD-Loader + path: external/OpenCL-ICD-Loader + + - name: Build & install OpenCL-Headers + run: | + $BIN = if('${{matrix.BIN}}' -eq 'x86') {'Win32'} else {'x64'} + & cmake ` + -G "Visual Studio 17 2022" ` + -A $BIN ` + -T ${{matrix.VER}} ` + -D BUILD_TESTING=OFF ` + -S ${env:GITHUB_WORKSPACE}\external\OpenCL-Headers ` + -B ${env:GITHUB_WORKSPACE}\external\OpenCL-Headers\build + if ($LASTEXITCODE -ne 0) { throw "Configuring OpenCL-Headers failed." } + & cmake ` + --build ${env:GITHUB_WORKSPACE}\external\OpenCL-Headers\build ` + --config Release ` + -- ` + /verbosity:minimal ` + /maxCpuCount ` + /noLogo + if ($LASTEXITCODE -ne 0) { throw "Building OpenCL-Headers failed." } + & cmake ` + --install ${env:GITHUB_WORKSPACE}\external\OpenCL-Headers\build ` + --prefix ${env:GITHUB_WORKSPACE}\external\OpenCL-Headers\install ` + --config Release + if ($LASTEXITCODE -ne 0) { throw "Installing OpenCL-Headers failed." } + + - name: Build & install OpenCL-CLHPP + run: | + $BIN = if('${{matrix.BIN}}' -eq 'x86') {'Win32'} else {'x64'} + & cmake ` + -G "Visual Studio 17 2022" ` + -A $BIN ` + -T ${{matrix.VER}} ` + -D BUILD_DOCS=OFF ` + -D BUILD_EXAMPLES=OFF ` + -D BUILD_TESTING=OFF ` + -D CMAKE_PREFIX_PATH="${env:GITHUB_WORKSPACE}\external\OpenCL-Headers\install" ` + -S ${env:GITHUB_WORKSPACE}\external\OpenCL-CLHPP ` + -B ${env:GITHUB_WORKSPACE}\external\OpenCL-CLHPP\build + if ($LASTEXITCODE -ne 0) { throw "Configuring OpenCL-CLHPP failed." } + & cmake ` + --build ${env:GITHUB_WORKSPACE}\external\OpenCL-CLHPP\build ` + --config Release ` + -- ` + /verbosity:minimal ` + /maxCpuCount ` + /noLogo + if ($LASTEXITCODE -ne 0) { throw "Building OpenCL-CLHPP failed." } + & cmake ` + --install ${env:GITHUB_WORKSPACE}\external\OpenCL-CLHPP\build ` + --prefix ${env:GITHUB_WORKSPACE}\external\OpenCL-CLHPP\install ` + --config Release + if ($LASTEXITCODE -ne 0) { throw "Installing OpenCL-CLHPP failed." } + + - name: Build & install OpenCL-ICD-Loader + run: | + $BIN = if('${{matrix.BIN}}' -eq 'x86') {'Win32'} else {'x64'} + & cmake ` + -G "Visual Studio 17 2022" ` + -A $BIN ` + -T ${{matrix.VER}} ` + -D BUILD_TESTING=OFF ` + -D CMAKE_PREFIX_PATH="${env:GITHUB_WORKSPACE}\external\OpenCL-Headers\install" ` + -S ${env:GITHUB_WORKSPACE}\external\OpenCL-ICD-Loader ` + -B ${env:GITHUB_WORKSPACE}\external\OpenCL-ICD-Loader\build + if ($LASTEXITCODE -ne 0) { throw "Configuring OpenCL-ICD-Loader failed." } + & cmake ` + --build ${env:GITHUB_WORKSPACE}\external\OpenCL-ICD-Loader\build ` + --config Release ` + -- ` + /verbosity:minimal ` + /maxCpuCount ` + /noLogo + if ($LASTEXITCODE -ne 0) { throw "Building OpenCL-ICD-Loader failed." } + & cmake ` + --install ${env:GITHUB_WORKSPACE}\external\OpenCL-ICD-Loader\build ` + --prefix ${env:GITHUB_WORKSPACE}\external\OpenCL-ICD-Loader\install ` + --config Release + if ($LASTEXITCODE -ne 0) { throw "Installing OpenCL-ICD-Loader failed." } + + - name: Configure (MSBuild) + if: matrix.GEN == 'Visual Studio 17 2022' + run: | + $BIN = if('${{matrix.BIN}}' -eq 'x86') {'Win32'} else {'x64'} + & cmake ` + -G '${{matrix.GEN}}' ` + -A $BIN ` + -T ${{matrix.VER}} ` + -D BUILD_TESTING=ON ` + -D CMAKE_INSTALL_PREFIX="${env:GITHUB_WORKSPACE}\install" ` + -D CMAKE_PREFIX_PATH="${env:GITHUB_WORKSPACE}\external\OpenCL-Headers\install;${env:GITHUB_WORKSPACE}\external\OpenCL-ICD-Loader\install;${env:GITHUB_WORKSPACE}\external\OpenCL-CLHPP\install" ` + -D CMAKE_TOOLCHAIN_FILE=${env:VCPKG_INSTALLATION_ROOT}\scripts\buildsystems\vcpkg.cmake ` + -D VCPKG_TARGET_TRIPLET=${{matrix.BIN}}-windows-static-md ` + -S "${env:GITHUB_WORKSPACE}" ` + -B "${env:GITHUB_WORKSPACE}\build" + if ($LASTEXITCODE -ne 0) { throw "Configuring OpenCL-Layers failed." } + + - name: Configure (Ninja Multi-Config) + if: matrix.GEN == 'Ninja Multi-Config' + run: | + $VER = switch ('${{matrix.VER}}') { ` + 'v142' {'14.2'} ` + 'v143' {'14.4'} } + Import-Module 'C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\Tools\Microsoft.VisualStudio.DevShell.dll' + Enter-VsDevShell -VsInstallPath 'C:\Program Files\Microsoft Visual Studio\2022\Enterprise' -SkipAutomaticLocation -DevCmdArguments "-host_arch=x64 -arch=${{matrix.BIN}} -vcvars_ver=${VER}" + & cmake ` + -G '${{matrix.GEN}}' ` + -D CMAKE_MAKE_PROGRAM="${env:NINJA_ROOT}\ninja.exe" ` + -D OPENCL_LAYERS_BUILD_TESTING=ON ` + -D BUILD_TESTING=ON ` + -D CMAKE_EXE_LINKER_FLAGS='/INCREMENTAL' ` + -D CMAKE_INSTALL_PREFIX="${env:GITHUB_WORKSPACE}\install" ` + -D CMAKE_PREFIX_PATH="${env:GITHUB_WORKSPACE}\external\OpenCL-Headers\install;${env:GITHUB_WORKSPACE}\external\OpenCL-ICD-Loader\install;${env:GITHUB_WORKSPACE}\external\OpenCL-CLHPP\install" ` + -D CMAKE_TOOLCHAIN_FILE=${env:VCPKG_INSTALLATION_ROOT}\scripts\buildsystems\vcpkg.cmake ` + -D VCPKG_TARGET_TRIPLET=${{matrix.BIN}}-windows-static-md ` + -S "${env:GITHUB_WORKSPACE}" ` + -B "${env:GITHUB_WORKSPACE}\build" + if ($LASTEXITCODE -ne 0) { throw "Configuring OpenCL-Layers failed." } + + - name: Build (MSBuild) + if: matrix.GEN == 'Visual Studio 17 2022' + run: | + foreach ($Config in 'Release','Debug') { ` + & cmake ` + --build "${env:GITHUB_WORKSPACE}\build" ` + --config ${Config} ` + -- ` + /verbosity:minimal ` + /maxCpuCount ` + /noLogo + if ($LASTEXITCODE -ne 0) { throw "Building OpenCL-Layers in $Config failed." } + } + + - name: Build (Ninja Multi-Config) + if: matrix.GEN == 'Ninja Multi-Config' + run: | + $VER = switch ('${{matrix.VER}}') { ` + 'v142' {'14.2'} ` + 'v143' {'14.4'} } + Import-Module "${env:VS_ROOT}\Common7\Tools\Microsoft.VisualStudio.DevShell.dll" + Enter-VsDevShell -VsInstallPath ${env:VS_ROOT} -SkipAutomaticLocation -DevCmdArguments "-host_arch=x64 -arch=${{matrix.BIN}} -vcvars_ver=${VER}" + foreach ($Config in 'Release','Debug') { ` + & cmake ` + --build "${env:GITHUB_WORKSPACE}\build" ` + --config ${Config} ` + -- ` + -j ${env:NUMBER_OF_PROCESSORS} + if ($LASTEXITCODE -ne 0) { throw "Building OpenCL-Layers in $Config failed." } + } + + - name: Run tests on installed ICD + if: matrix.BIN != 'x86' + run: | + foreach ($Config in 'Release','Debug') { + & ctest ` + --test-dir ${env:GITHUB_WORKSPACE}\build ` + --build-config ${Config} ` + --label-regex system-icd ` + --output-on-failure ` + --no-tests=error ` + --parallel ${env:NUMBER_OF_PROCESSORS} + if ($LASTEXITCODE -ne 0) { throw "Running tests in ${Config} failed." } + } + + - name: Install + run: | + cmake ` + --install ${env:GITHUB_WORKSPACE}\build ` + --prefix ${env:GITHUB_WORKSPACE}\install ` + --config Release + if ($LASTEXITCODE -ne 0) { throw "Installing OpenCL-Layers failed." } + + - name: Configure consume test (MSBuild) + if: matrix.GEN == 'Visual Studio 17 2022' + run: | + $BIN = if('${{matrix.BIN}}' -eq 'x86') {'Win32'} else {'x64'} + & cmake ` + -G '${{matrix.GEN}}' ` + -A $BIN ` + -T ${{matrix.VER}} ` + -D CMAKE_PREFIX_PATH="${env:GITHUB_WORKSPACE}\external\OpenCL-Headers\install;${env:GITHUB_WORKSPACE}\external\OpenCL-ICD-Loader\install;${env:GITHUB_WORKSPACE}\external\OpenCL-CLHPP\install;${env:GITHUB_WORKSPACE}\install" ` + -D CMAKE_TOOLCHAIN_FILE=${env:VCPKG_INSTALLATION_ROOT}\scripts\buildsystems\vcpkg.cmake ` + -D VCPKG_TARGET_TRIPLET=${{matrix.BIN}}-windows-static-md ` + -S "${env:GITHUB_WORKSPACE}\program-cache\lib\test\package" ` + -B "${env:GITHUB_WORKSPACE}\program-cache\lib\test\package\build" + if ($LASTEXITCODE -ne 0) { throw "Configuring OpenCL-Layers consume test failed." } + + - name: Configure consume test (Ninja Multi-Config) + if: matrix.GEN == 'Ninja Multi-Config' + run: | + $VER = switch ('${{matrix.VER}}') { ` + 'v142' {'14.2'} ` + 'v143' {'14.4'} } + Import-Module 'C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\Tools\Microsoft.VisualStudio.DevShell.dll' + Enter-VsDevShell -VsInstallPath 'C:\Program Files\Microsoft Visual Studio\2022\Enterprise' -SkipAutomaticLocation -DevCmdArguments "-host_arch=x64 -arch=${{matrix.BIN}} -vcvars_ver=${VER}" + & cmake ` + -G '${{matrix.GEN}}' ` + -D CMAKE_MAKE_PROGRAM="${env:NINJA_ROOT}\ninja.exe" ` + -D CMAKE_EXE_LINKER_FLAGS='/INCREMENTAL' ` + -D CMAKE_PREFIX_PATH="${env:GITHUB_WORKSPACE}\external\OpenCL-Headers\install;${env:GITHUB_WORKSPACE}\external\OpenCL-ICD-Loader\install;${env:GITHUB_WORKSPACE}\external\OpenCL-CLHPP\install;${env:GITHUB_WORKSPACE}\install" ` + -D CMAKE_TOOLCHAIN_FILE=${env:VCPKG_INSTALLATION_ROOT}\scripts\buildsystems\vcpkg.cmake ` + -D VCPKG_TARGET_TRIPLET=${{matrix.BIN}}-windows-static-md ` + -S "${env:GITHUB_WORKSPACE}\program-cache\lib\test\package" ` + -B "${env:GITHUB_WORKSPACE}\program-cache\lib\test\package\build" + if ($LASTEXITCODE -ne 0) { throw "Configuring OpenCL-Layers consume test failed." } + + - name: Build consume test (MSBuild) + if: matrix.GEN == 'Visual Studio 17 2022' + run: | + cmake ` + --build "${env:GITHUB_WORKSPACE}\program-cache\lib\test\package\build" ` + --config Release ` + -- ` + /verbosity:minimal ` + /maxCpuCount ` + /noLogo + if ($LASTEXITCODE -ne 0) { throw "Building OpenCL-Layers consume test failed." } + + - name: Build consume test (Ninja Multi-Config) + if: matrix.GEN == 'Ninja Multi-Config' + run: | + $VER = switch ('${{matrix.VER}}') { ` + 'v142' {'14.2'} ` + 'v143' {'14.4'} } + Import-Module "${env:VS_ROOT}\Common7\Tools\Microsoft.VisualStudio.DevShell.dll" + Enter-VsDevShell -VsInstallPath ${env:VS_ROOT} -SkipAutomaticLocation -DevCmdArguments "-host_arch=x64 -arch=${{matrix.BIN}} -vcvars_ver=${VER}" + cmake ` + --build "${env:GITHUB_WORKSPACE}\program-cache\lib\test\package\build" ` + --config Release ` + -- ` + -j ${env:NUMBER_OF_PROCESSORS} + if ($LASTEXITCODE -ne 0) { throw "Building OpenCL-Layers consume test failed." } + + - name: Run consume test + if: matrix.BIN != 'x86' + working-directory: ${{runner.workspace}}/OpenCL-Layers/program-cache/lib/test/package/build + run: | + & ctest ` + --test-dir "${env:GITHUB_WORKSPACE}\program-cache\lib\test\package\build" ` + --build-config Release ` + --output-on-failure ` + --no-tests=error ` + --parallel ${env:NUMBER_OF_PROCESSORS} + + - name: Test layers with mock ICDs + run: | + $ICD_REG_PATH = if('${{matrix.BIN}}' -eq 'x86') { ` + 'HKLM:\SOFTWARE\WOW6432Node\Khronos\OpenCL\Vendors' } else { ` + 'HKLM:\SOFTWARE\Khronos\OpenCL\Vendors' } + $LAYER_REG_PATH = if('${{matrix.BIN}}' -eq 'x86') { ` + 'HKLM:\SOFTWARE\WOW6432Node\Khronos\OpenCL\Layers' } else { ` + 'HKLM:\SOFTWARE\Khronos\OpenCL\Layers' } + New-Item -Type Directory ${ICD_REG_PATH} -Force | Out-Null + New-Item -Type Directory ${LAYER_REG_PATH} -Force | Out-Null + foreach ($Config in 'Release','Debug') { + Copy-Item "${env:GITHUB_WORKSPACE}\external\OpenCL-ICD-Loader\install\bin\OpenCL.dll" "${env:GITHUB_WORKSPACE}\build\bin\${Config}\" + foreach ($Layer in 'PrintLayer','CLObjectLifetimeLayer','CLParamVerificationLayer','CLParamVerificationLayerObjectValidityOnly') { ` + $LayerPriority = 0 + Write-Host "Running CTest on ${Config} for ${Layer}" + $ICD = switch (${Layer}) { ` + 'PrintLayer' {""} ` + 'CLObjectLifetimeLayer' {"${env:GITHUB_WORKSPACE}\build\bin\${Config}\CLObjectLifetimeICD.dll"} ` + 'CLParamVerificationLayer' {"${env:GITHUB_WORKSPACE}\build\bin\${Config}\CLObjectLifetimeICD.dll"} ` + 'CLParamVerificationLayerObjectValidityOnly' {"${env:GITHUB_WORKSPACE}\build\bin\${Config}\CLObjectLifetimeICD.dll"} } + $TestsRegex = switch (${Layer}) { ` + 'PrintLayer' {'PrintLayer'} ` + 'CLObjectLifetimeLayer' {'ObjectLifetime'} ` + 'CLParamVerificationLayer' {'ParamVerification'} ` + 'CLParamVerificationLayerObjectValidityOnly' {'ObjectValidity'} } + $ExcludeRegex = switch (${Layer}) { ` + 'PrintLayer' {''} ` + 'CLObjectLifetimeLayer' {''} ` + 'CLParamVerificationLayer' {'ObjectValidity'} ` + 'CLParamVerificationLayerObjectValidityOnly' {''} } + $LayersToReg = switch (${Layer}) { ` + 'PrintLayer' {"${Layer}"} ` + 'CLObjectLifetimeLayer' {"${Layer}"} ` + 'CLParamVerificationLayer' {"${Layer}"} ` + 'CLParamVerificationLayerObjectValidityOnly' {"CLObjectLifetimeLayer;CLParamVerificationLayer"} } + if ($ICD) { Set-ItemProperty -Path ${ICD_REG_PATH} -Type DWord -Value 0 -Name $ICD } + foreach ($BaseName in ${LayersToReg}.Split(';')) { ` + Set-ItemProperty -Path ${LAYER_REG_PATH} -Type DWord -Value ($LayerPriority++) -Name ${env:GITHUB_WORKSPACE}\build\bin\${Config}\${BaseName}.dll } + & ctest ` + --test-dir ${env:GITHUB_WORKSPACE}\build ` + --build-config ${Config} ` + --tests-regex $TestsRegex ` + $(if ($ExcludeRegex) {'--exclude-regex',"${ExcludeRegex}"}) ` + --output-on-failure ` + --no-tests=error ` + --parallel ${env:NUMBER_OF_PROCESSORS} + if ($LASTEXITCODE -ne 0) { throw "Testing ${Layer} in ${Config} failed." } + if ($ICD) { Remove-ItemProperty -Path ${ICD_REG_PATH} -Name $ICD } + foreach ($BaseName in ${LayersToReg}.Split(';')) { ` + Remove-ItemProperty -Path ${LAYER_REG_PATH} -Name ${env:GITHUB_WORKSPACE}\build\bin\${Config}\${BaseName}.dll } + } + & ctest ` + --test-dir ${env:GITHUB_WORKSPACE}\build ` + --build-config ${Config} ` + --tests-regex SettingsLocation ` + --output-on-failure ` + --no-tests=error ` + --parallel ${env:NUMBER_OF_PROCESSORS} + if ($LASTEXITCODE -ne 0) { throw "Running additional tests in ${Config} failed." } + } + + macos: + runs-on: macos-latest + defaults: + run: + shell: bash + strategy: + matrix: + COMPILER: + - CC: /usr/bin/clang + CXX: /usr/bin/clang++ + - CC: gcc-11 + CXX: g++-11 + # gcc-13 has problems with the latest macos + # - CC: gcc-13 + # CXX: g++-13 + GEN: + - Xcode + - Ninja Multi-Config + DEPS: [system, vcpkg, fetch] + exclude: + # These entries are excluded, since XCode selects its own compiler + - COMPILER: + CC: gcc-11 + CXX: g++-11 + GEN: Xcode + - COMPILER: + CC: gcc-13 + CXX: g++-13 + GEN: Xcode + # These entries are excluded, since the GNU C++ binaries are not compatible + # with the ones pulled from Homebrew + - COMPILER: + CC: gcc-11 + CXX: g++-11 + DEPS: system + - COMPILER: + CC: gcc-13 + CXX: g++-13 + DEPS: system + env: + CC: ${{matrix.COMPILER.CC}} + CXX: ${{matrix.COMPILER.CXX}} + VCPKG_INSTALLATION_ROOT: ${{github.workspace}}/../vcpkg + steps: + - name: Create Build Environment + run: | + if [[ "${{matrix.GEN}}" == "Ninja Multi-Config" && ! `which ninja` ]]; then brew install ninja; fi; + # Install Ninja only if it's the selected generator and it's not available. + if [[ "${{matrix.DEPS}}" == "vcpkg" && ! `which pkg-config` ]]; then brew install pkg-config; fi; + # We need to provide an OpenCL driver for Intel CPU on mac + brew install pocl + echo "OCL_ICD_VENDORS=/opt/homebrew/Cellar/pocl/5.0/etc/OpenCL/vendors" >> $GITHUB_ENV + cmake --version + + - name: Install dependencies (Homebrew) + if: matrix.DEPS == 'system' + run: brew install boost googletest + + - name: Cache dependencies (vcpkg) + if: matrix.DEPS == 'vcpkg' + id: vcpkg-install + uses: actions/cache@v4 + with: + path: ${{env.VCPKG_INSTALLATION_ROOT}} + key: vcpkg-macos-${{matrix.COMPILER.CXX}} + + - name: Install dependencies (vcpkg) + if: matrix.DEPS == 'vcpkg' && steps.vcpkg-install.outputs.cache-hit != 'true' + # Important: the same compiler must be used with vcpkg as with the project build + # because apple-clang uses a different standard library implementation from GCC + run: | + git clone https://github.com/Microsoft/vcpkg.git $VCPKG_INSTALLATION_ROOT + $VCPKG_INSTALLATION_ROOT/bootstrap-vcpkg.sh + $VCPKG_INSTALLATION_ROOT/vcpkg install boost-wave gtest rapidxml + + - name: Set up compiler flags + # -Werror omitted when fetching the dependencies. The dependencies emit warnings + # that are beyond our control. + run: | + if [[ "${{ matrix.DEPS }}" == "fetch" ]]; then + echo "CFLAGS=-Wall -Wextra -pedantic" >> $GITHUB_ENV; + echo "CXXFLAGS=-Wall -Wextra -pedantic" >> $GITHUB_ENV; + else + echo "CFLAGS=-Wall -Wextra -pedantic -Werror" >> $GITHUB_ENV; + echo "CXXFLAGS=-Wall -Wextra -pedantic -Werror" >> $GITHUB_ENV; + fi + + - name: Checkout OpenCL-Layers + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Checkout OpenCL-Headers + uses: actions/checkout@v4 + with: + repository: KhronosGroup/OpenCL-Headers + path: external/OpenCL-Headers + + - name: Checkout OpenCL-CLHPP + uses: actions/checkout@v4 + with: + repository: KhronosGroup/OpenCL-CLHPP + path: external/OpenCL-CLHPP + + - name: Checkout OpenCL-ICD-Loader + uses: actions/checkout@v4 + with: + repository: KhronosGroup/OpenCL-ICD-Loader + path: external/OpenCL-ICD-Loader + + - name: Build & install OpenCL-Headers + run: cmake + -G "${{matrix.GEN}}" + -D BUILD_TESTING=OFF + -D CMAKE_INSTALL_PREFIX=$GITHUB_WORKSPACE/external/OpenCL-Headers/install + -S $GITHUB_WORKSPACE/external/OpenCL-Headers + -B $GITHUB_WORKSPACE/external/OpenCL-Headers/build && + cmake + --build $GITHUB_WORKSPACE/external/OpenCL-Headers/build + --target install + --config Release + --parallel `sysctl -n hw.logicalcpu` + + - name: Build & install OpenCL-CLHPP + run: cmake + -G "${{matrix.GEN}}" + -D BUILD_DOCS=OFF + -D BUILD_EXAMPLES=OFF + -D BUILD_TESTING=OFF + -D CMAKE_INSTALL_PREFIX=$GITHUB_WORKSPACE/external/OpenCL-CLHPP/install + -D CMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/external/OpenCL-Headers/install + -S $GITHUB_WORKSPACE/external/OpenCL-CLHPP + -B $GITHUB_WORKSPACE/external/OpenCL-CLHPP/build && + cmake + --build $GITHUB_WORKSPACE/external/OpenCL-CLHPP/build + --target install + --config Release + --parallel `sysctl -n hw.logicalcpu` + + - name: Build & install OpenCL-ICD-Loader + run: cmake + -G "${{matrix.GEN}}" + -D BUILD_TESTING=OFF + -D CMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/external/OpenCL-Headers/install + -D CMAKE_INSTALL_PREFIX=$GITHUB_WORKSPACE/external/OpenCL-ICD-Loader/install + -S $GITHUB_WORKSPACE/external/OpenCL-ICD-Loader + -B $GITHUB_WORKSPACE/external/OpenCL-ICD-Loader/build && + cmake + --build $GITHUB_WORKSPACE/external/OpenCL-ICD-Loader/build + --target install + --config Release + --parallel `sysctl -n hw.logicalcpu` + + - name: Configure + run: cmake + -G "${{matrix.GEN}}" + -D BUILD_TESTING=ON + -D CMAKE_INSTALL_PREFIX=$GITHUB_WORKSPACE/install + -D CMAKE_PREFIX_PATH="$GITHUB_WORKSPACE/external/OpenCL-Headers/install;$GITHUB_WORKSPACE/external/OpenCL-ICD-Loader/install;$GITHUB_WORKSPACE/external/OpenCL-CLHPP/install" + -D CMAKE_FIND_PACKAGE_PREFER_CONFIG=ON + `if [[ "${{matrix.DEPS}}" == "vcpkg" ]]; then echo "-D CMAKE_TOOLCHAIN_FILE=$VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake"; fi;` + -S $GITHUB_WORKSPACE + -B $GITHUB_WORKSPACE/build + + - name: Build + run: | + cmake --build $GITHUB_WORKSPACE/build --config Release --parallel `sysctl -n hw.logicalcpu` + cmake --build $GITHUB_WORKSPACE/build --config Debug --parallel `sysctl -n hw.logicalcpu` + + - name: Test + run: | + ctest --test-dir $GITHUB_WORKSPACE/build --output-on-failure --no-tests=error -C Debug --parallel `sysctl -n hw.logicalcpu` --label-exclude $LABEL_EXCLUDE + ctest --test-dir $GITHUB_WORKSPACE/build --output-on-failure --no-tests=error -C Release --parallel `sysctl -n hw.logicalcpu` --label-exclude $LABEL_EXCLUDE + + - name: Install + run: cmake --build $GITHUB_WORKSPACE/build --target install --config Release + + - name: Configure consume test + run: cmake + -G "${{matrix.GEN}}" + -D CMAKE_PREFIX_PATH="$GITHUB_WORKSPACE/external/OpenCL-Headers/install;$GITHUB_WORKSPACE/external/OpenCL-ICD-Loader/install;$GITHUB_WORKSPACE/external/OpenCL-CLHPP/install;$GITHUB_WORKSPACE/install" + `if [[ "${{matrix.DEPS}}" == "vcpkg" ]]; then echo "-D CMAKE_TOOLCHAIN_FILE=$VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake"; fi;` + -S $GITHUB_WORKSPACE/program-cache/lib/test/package + -B $GITHUB_WORKSPACE/program-cache/lib/test/package/build + + - name: Build consume test + run: | + cmake --build $GITHUB_WORKSPACE/program-cache/lib/test/package/build --config Debug --parallel `sysctl -n hw.logicalcpu` + cmake --build $GITHUB_WORKSPACE/program-cache/lib/test/package/build --config Release --parallel `sysctl -n hw.logicalcpu` + + - name: Run consume test + # For an unknown reason, there are test failures when compiled with g++ in the GitHub shared runner, and pocl is used. + if: matrix.COMPILER.CC == '/usr/bin/clang' + run: | + ctest --output-on-failure --no-tests=error --test-dir $GITHUB_WORKSPACE/program-cache/lib/test/package/build -C Debug --parallel `sysctl -n hw.logicalcpu` + ctest --output-on-failure --no-tests=error --test-dir $GITHUB_WORKSPACE/program-cache/lib/test/package/build -C Release --parallel `sysctl -n hw.logicalcpu` + + android: + runs-on: ubuntu-latest + defaults: + run: + shell: bash + strategy: + matrix: + ABI: + - arm64-v8a + - x86_64 + API_LEVEL: + - android-19 + - android-33 + CONF: + - GEN: Unix Makefiles + CONFIG: Debug + - GEN: Unix Makefiles + CONFIG: Release + - GEN: Ninja Multi-Config + CONFIG: Release + DEPS: + - vcpkg + - fetch + steps: + - name: Set up vcpkg triplet + if: matrix.DEPS == 'vcpkg' + run: if [[ "${{ matrix.ABI }}" == "arm64-v8a" ]]; then + echo "VCPKG_TRIPLET=arm64-android" >> $GITHUB_ENV; + else + echo "VCPKG_TRIPLET=x64-android" >> $GITHUB_ENV; + fi + + # Caching the vcpkg directory doesn't work due to permission problems on the Github Ubuntu image + - name: Install dependencies (vcpkg) + if: matrix.DEPS == 'vcpkg' + run: | + cd $VCPKG_INSTALLATION_ROOT + git fetch + git reset --hard origin/master + vcpkg install boost-wave:$VCPKG_TRIPLET gtest:$VCPKG_TRIPLET rapidxml:$VCPKG_TRIPLET + + - name: Set up compiler flags + # -Werror omitted when fetching the dependencies. The dependencies emit warnings + # that are beyond our control. + run: | + if [[ "${{ matrix.DEPS }}" == "fetch" ]]; then + echo "CFLAGS=-Wall -Wextra -pedantic" >> $GITHUB_ENV; + echo "CXXFLAGS=-Wall -Wextra -pedantic" >> $GITHUB_ENV; + else + echo "CFLAGS=-Wall -Wextra -pedantic -Werror" >> $GITHUB_ENV; + echo "CXXFLAGS=-Wall -Wextra -pedantic -Werror" >> $GITHUB_ENV; + fi + + - name: Checkout OpenCL-Layers + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Checkout OpenCL-Headers + uses: actions/checkout@v4 + with: + repository: KhronosGroup/OpenCL-Headers + path: external/OpenCL-Headers + + - name: Checkout OpenCL-CLHPP + uses: actions/checkout@v4 + with: + repository: KhronosGroup/OpenCL-CLHPP + path: external/OpenCL-CLHPP + + - name: Checkout OpenCL-ICD-Loader + uses: actions/checkout@v4 + with: + repository: KhronosGroup/OpenCL-ICD-Loader + path: external/OpenCL-ICD-Loader + + - name: Configure & install OpenCL-Headers + run: cmake + -G "Unix Makefiles" + `if [[ "${{matrix.CONF.GEN}}" == "Unix Makefiles" ]]; then echo "-D CMAKE_BUILD_TYPE=${{matrix.CONF.CONFIG}}"; fi` + -D CMAKE_INSTALL_PREFIX=$GITHUB_WORKSPACE/external/OpenCL-Headers/install + -D CMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake + -D ANDROID_ABI=${{matrix.ABI}} + -D ANDROID_PLATFORM=${{matrix.API_LEVEL}} + -D BUILD_TESTING=OFF + -S $GITHUB_WORKSPACE/external/OpenCL-Headers + -B $GITHUB_WORKSPACE/external/OpenCL-Headers/build && + cmake + --build $GITHUB_WORKSPACE/external/OpenCL-Headers/build + --target install + `if [[ "${{matrix.CONF.GEN}}" == "Ninja Multi-Config" ]]; then echo "--config ${{matrix.CONF.CONFIG}}"; fi` + --parallel `nproc` + + - name: Build & install OpenCL-CLHPP + run: cmake + -G "Unix Makefiles" + `if [[ "${{matrix.CONF.GEN}}" == "Unix Makefiles" ]]; then echo "-D CMAKE_BUILD_TYPE=${{matrix.CONF.CONFIG}}"; fi` + -D CMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake + -D CMAKE_INSTALL_PREFIX=$GITHUB_WORKSPACE/external/OpenCL-CLHPP/install + -D CMAKE_FIND_ROOT_PATH_MODE_PACKAGE=ONLY + -D CMAKE_FIND_ROOT_PATH=$GITHUB_WORKSPACE/external/OpenCL-Headers/install + -D BUILD_DOCS=OFF + -D BUILD_EXAMPLES=OFF + -D BUILD_TESTING=OFF + -D ANDROID_ABI=${{matrix.ABI}} + -D ANDROID_PLATFORM=${{matrix.API_LEVEL}} + -S $GITHUB_WORKSPACE/external/OpenCL-CLHPP + -B $GITHUB_WORKSPACE/external/OpenCL-CLHPP/build && + cmake + --build $GITHUB_WORKSPACE/external/OpenCL-CLHPP/build + --target install + `if [[ "${{matrix.CONF.GEN}}" == "Ninja Multi-Config" ]]; then echo "--config ${{matrix.CONF.CONFIG}}"; fi` + --parallel `nproc` + + - name: Build & install OpenCL-ICD-Loader + run: cmake + -G "Unix Makefiles" + `if [[ "${{matrix.CONF.GEN}}" == "Unix Makefiles" ]]; then echo "-D CMAKE_BUILD_TYPE=${{matrix.CONF.CONFIG}}"; fi` + -D CMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake + -D CMAKE_FIND_ROOT_PATH_MODE_PACKAGE=ONLY + -D CMAKE_FIND_ROOT_PATH=$GITHUB_WORKSPACE/external/OpenCL-Headers/install + -D CMAKE_INSTALL_PREFIX=$GITHUB_WORKSPACE/external/OpenCL-ICD-Loader/install + -D BUILD_TESTING=OFF + -D ANDROID_ABI=${{matrix.ABI}} + -D ANDROID_PLATFORM=${{matrix.API_LEVEL}} + -S $GITHUB_WORKSPACE/external/OpenCL-ICD-Loader + -B $GITHUB_WORKSPACE/external/OpenCL-ICD-Loader/build && + cmake + --build $GITHUB_WORKSPACE/external/OpenCL-ICD-Loader/build + --target install + `if [[ "${{matrix.CONF.GEN}}" == "Ninja Multi-Config" ]]; then echo "--config ${{matrix.CONF.CONFIG}}"; fi` + --parallel `nproc` + + - name: Configure (fetch dependencies) + if: matrix.DEPS != 'vcpkg' + run: cmake + -G "Unix Makefiles" + `if [[ "${{matrix.CONF.GEN}}" == "Unix Makefiles" ]]; then echo "-D CMAKE_BUILD_TYPE=${{matrix.CONF.CONFIG}}"; fi` + -D CMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake + -D CMAKE_FIND_ROOT_PATH_MODE_PACKAGE=ONLY + -D CMAKE_FIND_ROOT_PATH="$GITHUB_WORKSPACE/external/OpenCL-Headers/install;$GITHUB_WORKSPACE/external/OpenCL-ICD-Loader/install;$GITHUB_WORKSPACE/external/OpenCL-CLHPP/install" + -D CMAKE_FIND_PACKAGE_PREFER_CONFIG=ON + -D ANDROID_ABI=${{matrix.ABI}} + -D ANDROID_PLATFORM=${{matrix.API_LEVEL}} + -D BUILD_TESTING=ON + -S $GITHUB_WORKSPACE + -B $GITHUB_WORKSPACE/build + + - name: Configure (vcpkg dependencies) + if: matrix.DEPS == 'vcpkg' + run: cmake + -G "Unix Makefiles" + `if [[ "${{matrix.CONF.GEN}}" == "Unix Makefiles" ]]; then echo "-D CMAKE_BUILD_TYPE=${{matrix.CONF.CONFIG}}"; fi` + -D CMAKE_TOOLCHAIN_FILE=$VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake + -D VCPKG_TARGET_TRIPLET=$VCPKG_TRIPLET + -D VCPKG_CHAINLOAD_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake + -D CMAKE_FIND_ROOT_PATH_MODE_PACKAGE=ONLY + -D CMAKE_FIND_ROOT_PATH="$GITHUB_WORKSPACE/external/OpenCL-Headers/install;$GITHUB_WORKSPACE/external/OpenCL-ICD-Loader/install;$GITHUB_WORKSPACE/external/OpenCL-CLHPP/install" + -D CMAKE_FIND_PACKAGE_PREFER_CONFIG=ON + -D ANDROID_ABI=${{matrix.ABI}} + -D ANDROID_PLATFORM=${{matrix.API_LEVEL}} + -D BUILD_TESTING=ON + -S $GITHUB_WORKSPACE + -B $GITHUB_WORKSPACE/build + + - name: Build (Unix Makefiles) + if: matrix.CONF.GEN == 'Unix Makefiles' + run: | + cmake --build $GITHUB_WORKSPACE/build --parallel `nproc` + + - name: Build (Ninja Multi-Config) + if: matrix.CONF.GEN == 'Ninja Multi-Config' + run: | + cmake --build $GITHUB_WORKSPACE/build --config Debug + cmake --build $GITHUB_WORKSPACE/build --config Release diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml deleted file mode 100644 index 9ba0075c..00000000 --- a/.github/workflows/windows.yml +++ /dev/null @@ -1,339 +0,0 @@ -name: Windows - -on: [push, pull_request] - -jobs: - compatibility: - runs-on: windows-2022 - strategy: - matrix: - VER: [v142, v143, clangcl] - EXT: [ON, OFF] - GEN: [Visual Studio 17 2022] - BIN: [x64, x86] - STD: [14, 17] - # TODO: Re-enable v141 check. Track down compiler error causing cl.exe to exhaust runner memory - # D:\a\OpenCL-Layers\OpenCL-Layers\build\param-verification\res.cpp(2250): fatal error C1060: compiler is out of heap space - #include: - # - VER: v141 - # EXT: OFF - # GEN: Ninja Multi-Config - # BIN: x64 - # STD: 14 - env: - NINJA_URL: https://github.com/ninja-build/ninja/releases/download/v1.10.2/ninja-win.zip - NINJA_ROOT: C:\Tools\Ninja - VS_ROOT: 'C:\Program Files\Microsoft Visual Studio\2022\Enterprise' - UseMultiToolTask: 'true' # Better parallel MSBuild execution - EnforceProcessCountAcrossBuilds: 'true' # -=- - MultiProcMaxCount: '3' # -=- - - steps: - - name: Checkout OpenCL-Layers - uses: actions/checkout@v2 - with: - submodules: recursive - - - name: Checkout OpenCL-Headers - uses: actions/checkout@v2 - with: - repository: KhronosGroup/OpenCL-Headers - path: external/OpenCL-Headers - - - name: Checkout OpenCL-ICD-Loader - uses: actions/checkout@v2 - with: - repository: Kerilk/OpenCL-ICD-Loader - ref: system-layers - path: external/OpenCL-ICD-Loader - # Temporary redirection to external repo. Changes needed from there. - - - name: Cache Ninja install - id: ninja-install - uses: actions/cache@v2 - with: - path: | - C:\Tools\Ninja - key: ${{runner.os}}-ninja-${{env.NINJA_URL}} - - - name: Install Ninja - if: steps.ninja-install.outputs.cache-hit != 'true' - shell: pwsh - run: | - Invoke-WebRequest ${env:NINJA_URL} -OutFile ~\Downloads\ninja-win.zip - Expand-Archive ~\Downloads\ninja-win.zip -DestinationPath C:\Tools\Ninja\ - Remove-Item ~\Downloads\* - - - name: Build & install OpenCL-Headers (MSBuild) - if: matrix.GEN == 'Visual Studio 17 2022' - shell: pwsh - run: | - $BIN = if('${{matrix.BIN}}' -eq 'x86') {'Win32'} else {'x64'} - $C_FLAGS = '/w' - & cmake ` - -G '${{matrix.GEN}}' ` - -A $BIN ` - -T ${{matrix.VER}} ` - -D BUILD_TESTING=OFF ` - -D CMAKE_C_FLAGS="$C_FLAGS" ` - -D CMAKE_C_STANDARD=99 ` - -D CMAKE_C_EXTENSIONS=${{matrix.EXT}} ` - -S ${env:GITHUB_WORKSPACE}\external\OpenCL-Headers ` - -B ${env:GITHUB_WORKSPACE}\external\OpenCL-Headers\build - if ($LASTEXITCODE -ne 0) { throw "Configuring OpenCL-Headers failed." } - & cmake ` - --build ${env:GITHUB_WORKSPACE}\external\OpenCL-Headers\build ` - --config Release ` - -- ` - /verbosity:minimal ` - /maxCpuCount ` - /noLogo - if ($LASTEXITCODE -ne 0) { throw "Building OpenCL-Headers failed." } - & cmake ` - --install ${env:GITHUB_WORKSPACE}\external\OpenCL-Headers\build ` - --prefix ${env:GITHUB_WORKSPACE}\external\OpenCL-Headers\install ` - --config Release - if ($LASTEXITCODE -ne 0) { throw "Installing OpenCL-Headers failed." } - - - name: Build & install OpenCL-Headers (Ninja Multi-Config) - if: matrix.GEN == 'Ninja Multi-Config' - shell: pwsh - run: | - $VER = switch ('${{matrix.VER}}') { ` - 'v141' {'14.1'} ` - 'v142' {'14.2'} ` - 'v143' {'14.3'} } - Import-Module "${env:VS_ROOT}\Common7\Tools\Microsoft.VisualStudio.DevShell.dll" - Enter-VsDevShell -VsInstallPath ${env:VS_ROOT} -SkipAutomaticLocation -DevCmdArguments "-host_arch=x64 -arch=${{matrix.BIN}} -vcvars_ver=${VER}" - $C_FLAGS = '/w' - & cmake ` - -G '${{matrix.GEN}}' ` - -D BUILD_TESTING=OFF ` - -D CMAKE_MAKE_PROGRAM="${env:NINJA_ROOT}\ninja.exe" ` - -D CMAKE_C_FLAGS="${C_FLAGS}" ` - -D CMAKE_C_STANDARD=99 ` - -D CMAKE_C_EXTENSIONS='${{matrix.EXT}}' ` - -S ${env:GITHUB_WORKSPACE}\external\OpenCL-Headers ` - -B ${env:GITHUB_WORKSPACE}\external\OpenCL-Headers\build - if ($LASTEXITCODE -ne 0) { throw "Configuring OpenCL-Headers failed." } - & cmake ` - --build ${env:GITHUB_WORKSPACE}\external\OpenCL-Headers\build ` - --config Release ` - -- ` - -j ${env:NUMBER_OF_PROCESSORS} - & cmake ` - --install ${env:GITHUB_WORKSPACE}\external\OpenCL-Headers\build ` - --prefix ${env:GITHUB_WORKSPACE}\external\OpenCL-Headers\install ` - --config Release - if ($LASTEXITCODE -ne 0) { throw "Installing OpenCL-Headers failed." } - - - name: Build & install OpenCL-ICD-Loader (MSBuild) - if: matrix.GEN == 'Visual Studio 17 2022' - shell: pwsh - run: | - $BIN = if('${{matrix.BIN}}' -eq 'x86') {'Win32'} else {'x64'} - $C_FLAGS = '/w' - & cmake ` - -G '${{matrix.GEN}}' ` - -A $BIN ` - -T ${{matrix.VER}} ` - -D BUILD_TESTING=OFF ` - -D CMAKE_C_FLAGS="$C_FLAGS" ` - -D CMAKE_C_STANDARD=99 ` - -D CMAKE_C_EXTENSIONS=${{matrix.EXT}} ` - -D CMAKE_PREFIX_PATH="${env:GITHUB_WORKSPACE}\external\OpenCL-Headers\install" ` - -S ${env:GITHUB_WORKSPACE}\external\OpenCL-ICD-Loader ` - -B ${env:GITHUB_WORKSPACE}\external\OpenCL-ICD-Loader\build - if ($LASTEXITCODE -ne 0) { throw "Configuring OpenCL-ICD-Loader failed." } - & cmake ` - --build ${env:GITHUB_WORKSPACE}\external\OpenCL-ICD-Loader\build ` - --config Release ` - -- ` - /verbosity:minimal ` - /maxCpuCount ` - /noLogo - if ($LASTEXITCODE -ne 0) { throw "Building OpenCL-ICD-Loader failed." } - & cmake ` - --install ${env:GITHUB_WORKSPACE}\external\OpenCL-ICD-Loader\build ` - --prefix ${env:GITHUB_WORKSPACE}\external\OpenCL-ICD-Loader\install ` - --config Release - if ($LASTEXITCODE -ne 0) { throw "Installing OpenCL-ICD-Loader failed." } - - - name: Build & install OpenCL-ICD-Loader (Ninja Multi-Config) - if: matrix.GEN == 'Ninja Multi-Config' - shell: pwsh - run: | - $VER = switch ('${{matrix.VER}}') { ` - 'v141' {'14.1'} ` - 'v142' {'14.2'} ` - 'v143' {'14.3'} } - Import-Module "${env:VS_ROOT}\Common7\Tools\Microsoft.VisualStudio.DevShell.dll" - Enter-VsDevShell -VsInstallPath ${env:VS_ROOT} -SkipAutomaticLocation -DevCmdArguments "-host_arch=x64 -arch=${{matrix.BIN}} -vcvars_ver=${VER}" - $C_FLAGS = '/w' - & cmake ` - -G '${{matrix.GEN}}' ` - -D BUILD_TESTING=OFF ` - -D CMAKE_MAKE_PROGRAM="${env:NINJA_ROOT}\ninja.exe" ` - -D CMAKE_C_FLAGS="${C_FLAGS}" ` - -D CMAKE_C_STANDARD=99 ` - -D CMAKE_C_EXTENSIONS='${{matrix.EXT}}' ` - -D CMAKE_PREFIX_PATH="${env:GITHUB_WORKSPACE}\external\OpenCL-Headers\install" ` - -S ${env:GITHUB_WORKSPACE}\external\OpenCL-ICD-Loader ` - -B ${env:GITHUB_WORKSPACE}\external\OpenCL-ICD-Loader\build - if ($LASTEXITCODE -ne 0) { throw "Configuring OpenCL-ICD-Loader failed." } - & cmake ` - --build ${env:GITHUB_WORKSPACE}\external\OpenCL-ICD-Loader\build ` - --config Release ` - -- ` - -j ${env:NUMBER_OF_PROCESSORS} - if ($LASTEXITCODE -ne 0) { throw "Building OpenCL-ICD-Loader failed." } - & cmake ` - --install ${env:GITHUB_WORKSPACE}\external\OpenCL-ICD-Loader\build ` - --prefix ${env:GITHUB_WORKSPACE}\external\OpenCL-ICD-Loader\install ` - --config Release - if ($LASTEXITCODE -ne 0) { throw "Installing OpenCL-ICD-Loader failed." } - - - name: Configure (MSBuild) - if: matrix.GEN == 'Visual Studio 17 2022' - shell: pwsh - run: | - $BIN = if('${{matrix.BIN}}' -eq 'x86') {'Win32'} else {'x64'} - $C_FLAGS = '/W4 /WX' - $CXX_FLAGS = '/W4 /WX /EHsc' - & cmake ` - -G '${{matrix.GEN}}' ` - -A $BIN ` - -T ${{matrix.VER}} ` - -D OPENCL_LAYERS_BUILD_TESTING=ON ` - -D BUILD_TESTING=ON ` - -D CMAKE_C_FLAGS="${C_FLAGS}" ` - -D CMAKE_C_EXTENSIONS='${{matrix.EXT}}' ` - -D CMAKE_CXX_FLAGS="${CXX_FLAGS}" ` - -D CMAKE_CXX_EXTENSIONS='${{matrix.EXT}}' ` - -D CMAKE_INSTALL_PREFIX="${env:GITHUB_WORKSPACE}\install" ` - -D CMAKE_PREFIX_PATH="${env:GITHUB_WORKSPACE}\external\OpenCL-Headers\install;${env:GITHUB_WORKSPACE}\external\OpenCL-ICD-Loader\install" ` - -S "${env:GITHUB_WORKSPACE}" ` - -B "${env:GITHUB_WORKSPACE}\build" - - - name: Configure (Ninja Multi-Config) - if: matrix.GEN == 'Ninja Multi-Config' - shell: pwsh - run: | - $VER = switch ('${{matrix.VER}}') { ` - 'v140' {'14.0'} ` - 'v141' {'14.1'} ` - 'v142' {'14.2'} ` - 'v143' {'14.3'} } - Import-Module 'C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\Tools\Microsoft.VisualStudio.DevShell.dll' - Enter-VsDevShell -VsInstallPath 'C:\Program Files\Microsoft Visual Studio\2022\Enterprise' -SkipAutomaticLocation -DevCmdArguments "-host_arch=x64 -arch=${{matrix.BIN}} -vcvars_ver=${VER}" - $C_FLAGS = '/W4 /WX' - $CXX_FLAGS = '/W4 /WX /EHsc' - & cmake ` - -G '${{matrix.GEN}}' ` - -D CMAKE_MAKE_PROGRAM="${env:NINJA_ROOT}\ninja.exe" ` - -D OPENCL_LAYERS_BUILD_TESTING=ON ` - -D BUILD_TESTING=ON ` - -D CMAKE_C_FLAGS="${C_FLAGS}" ` - -D CMAKE_C_EXTENSIONS='${{matrix.EXT}}' ` - -D CMAKE_CXX_FLAGS="${CXX_FLAGS}" ` - -D CMAKE_CXX_EXTENSIONS='${{matrix.EXT}}' ` - -D CMAKE_EXE_LINKER_FLAGS='/INCREMENTAL' ` - -D CMAKE_INSTALL_PREFIX="${env:GITHUB_WORKSPACE}\install" ` - -D CMAKE_PREFIX_PATH="${env:GITHUB_WORKSPACE}\external\OpenCL-Headers\install;${env:GITHUB_WORKSPACE}\external\OpenCL-ICD-Loader\install" ` - -S "${env:GITHUB_WORKSPACE}" ` - -B "${env:GITHUB_WORKSPACE}\build" - - - name: Build (MSBuild) - if: matrix.GEN == 'Visual Studio 17 2022' - shell: pwsh - run: | - foreach ($Config in 'Release','Debug') { ` - & cmake ` - --build "${env:GITHUB_WORKSPACE}\build" ` - --config ${Config} ` - -- ` - /verbosity:minimal ` - /maxCpuCount ` - /noLogo - if ($LASTEXITCODE -ne 0) { throw "Building OpenCL-ICD-Loader in ${Config} failed." } - } - - - name: Build (Ninja) - if: matrix.GEN == 'Ninja Multi-Config' - shell: pwsh - run: | - $VER = switch ('${{matrix.VER}}') { ` - 'v141' {'14.1'} ` - 'v142' {'14.2'} ` - 'v143' {'14.3'} } - Import-Module "${env:VS_ROOT}\Common7\Tools\Microsoft.VisualStudio.DevShell.dll" - Enter-VsDevShell -VsInstallPath ${env:VS_ROOT} -SkipAutomaticLocation -DevCmdArguments "-host_arch=x64 -arch=${{matrix.BIN}} -vcvars_ver=${VER}" - foreach ($Config in 'Release','Debug') { ` - & cmake ` - --build "${env:GITHUB_WORKSPACE}\build" ` - --config ${Config} ` - -- ` - -j ${env:NUMBER_OF_PROCESSORS} - if ($LASTEXITCODE -ne 0) { throw "Building OpenCL-ICD-Loader in ${Config} failed." } - } - - - name: Test - shell: pwsh - run: | - $ICD_REG_PATH = if('${{matrix.BIN}}' -eq 'x86') { ` - 'HKLM:\SOFTWARE\WOW6432Node\Khronos\OpenCL\Vendors' } else { ` - 'HKLM:\SOFTWARE\Khronos\OpenCL\Vendors' } - $LAYER_REG_PATH = if('${{matrix.BIN}}' -eq 'x86') { ` - 'HKLM:\SOFTWARE\WOW6432Node\Khronos\OpenCL\Layers' } else { ` - 'HKLM:\SOFTWARE\Khronos\OpenCL\Layers' } - New-Item -Type Directory ${ICD_REG_PATH} -Force | Out-Null - New-Item -Type Directory ${LAYER_REG_PATH} -Force | Out-Null - foreach ($Config in 'Release','Debug') { ` - Copy-Item "${env:GITHUB_WORKSPACE}\external\OpenCL-ICD-Loader\install\bin\OpenCL.dll" "${env:GITHUB_WORKSPACE}\build\bin\${Config}\" - foreach ($Layer in 'PrintLayer','CLObjectLifetimeLayer','CLParamVerificationLayer','CLParamVerificationLayerObjectValidityOnly') { ` - $LayerPriority = 0 - Write-Host "Running CTest on ${Config} for ${Layer}" - $ICD = switch (${Layer}) { ` - 'PrintLayer' {""} ` - 'CLObjectLifetimeLayer' {"${env:GITHUB_WORKSPACE}\build\bin\${Config}\CLObjectLifetimeICD.dll"} ` - 'CLParamVerificationLayer' {"${env:GITHUB_WORKSPACE}\build\bin\${Config}\CLObjectLifetimeICD.dll"} ` - 'CLParamVerificationLayerObjectValidityOnly' {"${env:GITHUB_WORKSPACE}\build\bin\${Config}\CLObjectLifetimeICD.dll"} } - $TestsRegex = switch (${Layer}) { ` - 'PrintLayer' {'PrintLayer'} ` - 'CLObjectLifetimeLayer' {'ObjectLifetime'} ` - 'CLParamVerificationLayer' {'ParamVerification'} ` - 'CLParamVerificationLayerObjectValidityOnly' {'ObjectValidity'} } - $ExcludeRegex = switch (${Layer}) { ` - 'PrintLayer' {''} ` - 'CLObjectLifetimeLayer' {''} ` - 'CLParamVerificationLayer' {'ObjectValidity'} ` - 'CLParamVerificationLayerObjectValidityOnly' {''} } - $LayersToReg = switch (${Layer}) { ` - 'PrintLayer' {"${Layer}"} ` - 'CLObjectLifetimeLayer' {"${Layer}"} ` - 'CLParamVerificationLayer' {"${Layer}"} ` - 'CLParamVerificationLayerObjectValidityOnly' {"CLObjectLifetimeLayer;CLParamVerificationLayer"} } - if ($ICD) { Set-ItemProperty -Path ${ICD_REG_PATH} -Type DWord -Value 0 -Name $ICD } - foreach ($BaseName in ${LayersToReg}.Split(';')) { ` - Set-ItemProperty -Path ${LAYER_REG_PATH} -Type DWord -Value ($LayerPriority++) -Name ${env:GITHUB_WORKSPACE}\build\bin\${Config}\${BaseName}.dll } - & ctest ` - --test-dir ${env:GITHUB_WORKSPACE}\build ` - --build-config ${Config} ` - --tests-regex $TestsRegex ` - $(if ($ExcludeRegex) {'--exclude-regex',"${ExcludeRegex}"}) ` - --output-on-failure ` - --no-tests=error ` - --parallel ${env:NUMBER_OF_PROCESSORS} - if ($LASTEXITCODE -ne 0) { throw "Testing ${Layer} in ${Config} failed." } - if ($ICD) { Remove-ItemProperty -Path ${ICD_REG_PATH} -Name $ICD } - foreach ($BaseName in ${LayersToReg}.Split(';')) { ` - Remove-ItemProperty -Path ${LAYER_REG_PATH} -Name ${env:GITHUB_WORKSPACE}\build\bin\${Config}\${BaseName}.dll } - } - & ctest ` - --test-dir ${env:GITHUB_WORKSPACE}\build ` - --build-config ${Config} ` - --tests-regex SettingsLocation ` - --output-on-failure ` - --no-tests=error ` - --parallel ${env:NUMBER_OF_PROCESSORS} - } diff --git a/.gitignore b/.gitignore index 2304f789..91e4dc60 100644 --- a/.gitignore +++ b/.gitignore @@ -51,4 +51,25 @@ Module.symvers Mkfile.old dkms.conf -build +# Build dir +[Bb]uild/ + +# Install dir +[Ii]nstall/ + +# External dir +[Ee]xternal/ + +# Package dir +[Pp]ackage[-_\s\d]*/ + +# Tackage dir +[T]esting/ + +# inc subdirs +inc/CL/ +inc/EGL/ +inc/KHR/ + +# Visual Studio Code +.vscode diff --git a/CMakeLists.txt b/CMakeLists.txt index a2a0587d..cee617d2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ -cmake_minimum_required (VERSION 3.3) -cmake_policy(VERSION 3.3...3.22) +cmake_minimum_required (VERSION 3.16) +cmake_policy(VERSION 3.16...3.26) # Include guard for including this project multiple times if (TARGET PrintLayer) @@ -14,27 +14,17 @@ project (OpenCL-Layers set (OPENCL_ICD_LOADER_HEADERS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/inc CACHE PATH "Path to OpenCL Headers") option (OPENCL_LAYERS_BUILD_TESTING "Enable support for OpenCL layers testing." OFF) -# Search for dependencies -if (EXISTS ${OPENCL_ICD_LOADER_HEADERS_DIR}/CL/cl.h) - if (NOT TARGET OpenCL::Headers) - message (STATUS "Defining OpenCL::Headers through OPENCL_ICD_LOADER_HEADERS_DIR") - endif () - add_library (OpenCLHeaders INTERFACE) - add_library (OpenCL::Headers ALIAS OpenCLHeaders) - target_include_directories (OpenCLHeaders INTERFACE ${OPENCL_ICD_LOADER_HEADERS_DIR}) -else () - if (NOT TARGET OpenCL::Headers) - find_package (OpenCLHeaders REQUIRED) - endif () -endif () - -if(CMAKE_VERSION VERSION_LESS 3.7) - add_library(OpenCL_lib INTERFACE) - target_include_directories(OpenCL_lib INTERFACE ${OpenCL_INCLUDE_DIRS}) - target_link_libraries(OpenCL_lib INTERFACE ${OpenCL_LIBRARIES}) - add_library(OpenCL::OpenCL ALIAS OpenCL_lib) +if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME OR OPENCL_LAYERS_BUILD_TESTING) + include(CTest) +endif() +if((CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME OR OPENCL_LAYERS_BUILD_TESTING) AND BUILD_TESTING) + set(LAYERS_BUILD_TESTS ON) endif() +# Search for dependencies +list (APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) +include(Dependencies) + set(CMAKE_C_EXTENSIONS OFF) set(CMAKE_CXX_EXTENSIONS OFF) @@ -42,14 +32,7 @@ set(CMAKE_CXX_EXTENSIONS OFF) add_library (LayersCommon INTERFACE) # C and C++ standard, -if (CMAKE_VERSION VERSION_LESS 3.8) - set(CMAKE_C_STANDARD 11) - set(CMAKE_C_STANDARD_REQUIRED ON) - set(CMAKE_CXX_STANDARD 14) - set(CMAKE_CXX_STANDARD_REQUIRED ON) -else() - target_compile_features(LayersCommon INTERFACE c_std_11 cxx_std_14) -endif() +target_compile_features(LayersCommon INTERFACE c_std_11 cxx_std_14) target_link_libraries (LayersCommon INTERFACE OpenCL::Headers) @@ -64,13 +47,6 @@ target_compile_definitions (LayersCommon CL_USE_DEPRECATED_OPENCL_2_2_APIS ) -if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME OR OPENCL_LAYERS_BUILD_TESTING) - include(CTest) -endif() -if((CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME OR OPENCL_LAYERS_BUILD_TESTING) AND BUILD_TESTING) - set(LAYERS_BUILD_TESTS ON) -endif() - if (LAYERS_BUILD_TESTS) if (NOT TARGET OpenCL) if(APPLE) # Apple's own loader can't load layers. We have to avoid it. @@ -80,30 +56,12 @@ if (LAYERS_BUILD_TESTS) endif() endif () endif () -if ((CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME OR OPENCL_LAYERS_BUILD_TESTING) AND BUILD_TESTING) - set (LAYERS_BUILD_TESTS ON) -endif () -if ((CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME OR OPENCL_LAYERS_BUILD_TESTING) AND BUILD_TESTING) - set (LAYERS_BUILD_TESTS ON) -endif () - -if(LAYERS_BUILD_TESTS) - if (NOT TARGET OpenCL) - if(APPLE) # Apple's own loader can't load layers. We have to avoid it. - find_package (OpenCLICDLoader REQUIRED) - else() - find_package (OpenCL REQUIRED) - endif() - endif () -endif () include (GNUInstallDirs) -list (APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) -include(Dependencies) - add_subdirectory (simple-print) add_subdirectory (ocl-icd-compat) add_subdirectory (object-lifetime) add_subdirectory (param-verification) +add_subdirectory (program-cache) add_subdirectory (utils) diff --git a/cmake/BoostWave.cmake b/cmake/BoostWave.cmake new file mode 100644 index 00000000..416495d2 --- /dev/null +++ b/cmake/BoostWave.cmake @@ -0,0 +1,88 @@ +if (NOT DEPENDENCIES_FORCE_DOWNLOAD) + find_package(Boost COMPONENTS wave) +endif () + +if (NOT Boost_FOUND) + if (DEPENDENCIES_FORCE_DOWNLOAD) + message (STATUS "DEPENDENCIES_FORCE_DOWNLOAD is ON. Fetching Boost::format and Boost::wave") + else () + message (STATUS "Fetching Boost::format and Boost::wave") + endif () + include (FetchContent) + set(boost_dependencies + algorithm + align + array + assert + atomic + bind + chrono + concept_check + config + container + container_hash + conversion + core + date_time + describe + detail + endian + exception + filesystem + format + function + function_types + functional + fusion + integer + intrusive + io + iterator + lexical_cast + move + mp11 + mpl + multi_index + numeric_conversion + optional + phoenix + pool + predef + preprocessor + proto + range + ratio + rational + regex + serialization + smart_ptr + spirit + static_assert + system + thread + throw_exception + tokenizer + tuple + type_index + type_traits + typeof + unordered + utility + variant + variant2 + wave + winapi +) + foreach(dep ${boost_dependencies}) + FetchContent_Declare( + Boost_${dep} + GIT_REPOSITORY https://github.com/boostorg/${dep}.git + GIT_TAG boost-1.82.0 + ) + list(APPEND boost_names Boost_${dep}) + endforeach() + FetchContent_MakeAvailable(${boost_names}) + foreach(dep ${boost_dependencies}) + set_target_properties(boost_${dep} PROPERTIES POSITION_INDEPENDENT_CODE ON) + endforeach() +endif () diff --git a/cmake/Dependencies.cmake b/cmake/Dependencies.cmake index f76d7422..40636cb5 100644 --- a/cmake/Dependencies.cmake +++ b/cmake/Dependencies.cmake @@ -1 +1,7 @@ +include (OpenCLHeaders) +if (LAYERS_BUILD_TESTS) + include (gtest) + include (OpenCLHeadersCpp) +endif() +include (BoostWave) include (RapidXml) diff --git a/cmake/FindRapidXml.cmake b/cmake/FindRapidXml.cmake index 37a8390c..243922dc 100644 --- a/cmake/FindRapidXml.cmake +++ b/cmake/FindRapidXml.cmake @@ -34,8 +34,9 @@ find_package_handle_standard_args ( if (RapidXml_FOUND) set (RapidXml_INCLUDE_DIR ${RapidXml_INCLUDE_PATH}) - add_library (RapidXml::RapidXml INTERFACE IMPORTED) - target_include_directories (RapidXml::RapidXml INTERFACE ${RapidXml_INCLUDE_PATH}) + add_library (RapidXml INTERFACE) + target_include_directories (RapidXml INTERFACE ${RapidXml_INCLUDE_PATH}) + add_library (RapidXml::RapidXml ALIAS RapidXml) endif () mark_as_advanced(RapidXml_INCLUDE_PATH) diff --git a/cmake/OpenCLHeaders.cmake b/cmake/OpenCLHeaders.cmake new file mode 100644 index 00000000..d2b83c38 --- /dev/null +++ b/cmake/OpenCLHeaders.cmake @@ -0,0 +1,12 @@ +if (EXISTS ${OPENCL_ICD_LOADER_HEADERS_DIR}/CL/cl.h) + if (NOT TARGET OpenCL::Headers) + message (STATUS "Defining OpenCL::Headers through OPENCL_ICD_LOADER_HEADERS_DIR") + endif () + add_library (OpenCLHeaders INTERFACE) + add_library (OpenCL::Headers ALIAS OpenCLHeaders) + target_include_directories (OpenCLHeaders INTERFACE ${OPENCL_ICD_LOADER_HEADERS_DIR}) +else () + if (NOT TARGET OpenCL::Headers) + find_package (OpenCLHeaders REQUIRED) + endif () +endif () diff --git a/cmake/OpenCLHeadersCpp.cmake b/cmake/OpenCLHeadersCpp.cmake new file mode 100644 index 00000000..5f31d32f --- /dev/null +++ b/cmake/OpenCLHeadersCpp.cmake @@ -0,0 +1,33 @@ +if (NOT DEPENDENCIES_FORCE_DOWNLOAD) + find_package(OpenCLHeadersCpp) +endif () + +if (NOT OpenCLHeadersCpp_FOUND) + if (DEPENDENCIES_FORCE_DOWNLOAD) + message (STATUS "DEPENDENCIES_FORCE_DOWNLOAD is ON. Fetching OpenCLHeadersCpp") + else () + message (STATUS "Fetching OpenCLHeadersCpp") + endif () + include (FetchContent) + FetchContent_Declare( + OpenCLHeadersCpp + GIT_REPOSITORY https://github.com/KhronosGroup/OpenCL-CLHPP.git + GIT_TAG v2023.04.17 + ) + + # A workaround to disable the building of the examples + # which requires the OpenCL-ICD-Loader CMake project to be installed. + if(DEFINED CACHE{BUILD_EXAMPLES}) + set(BUILD_EXAMPLES_CACHE_VAL "${BUILD_EXAMPLES}") + endif() + set(BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) + + FetchContent_MakeAvailable(OpenCLHeadersCpp) + + # Restoring the original state + if(DEFINED BUILD_EXAMPLES_CACHE_VAL) + set(BUILD_EXAMPLES "${BUILD_EXAMPLES_CACHE_VAL}" CACHE BOOL "" FORCE) + else() + unset(BUILD_EXAMPLES CACHE) + endif() +endif () diff --git a/cmake/RapidXml.cmake b/cmake/RapidXml.cmake index 71bf835c..a8986270 100644 --- a/cmake/RapidXml.cmake +++ b/cmake/RapidXml.cmake @@ -10,7 +10,6 @@ if (NOT RapidXml_FOUND) message (STATUS "Fetching RapidXml.") endif () endif () - cmake_minimum_required(VERSION 3.11) include (FetchContent) FetchContent_Declare ( rapidxml-external @@ -19,5 +18,8 @@ if (NOT RapidXml_FOUND) ) FetchContent_MakeAvailable (rapidxml-external) list (APPEND CMAKE_PREFIX_PATH "${CMAKE_CURRENT_BINARY_DIR}/_deps/rapidxml-external-src") + if (CMAKE_CROSSCOMPILING) + list (APPEND CMAKE_FIND_ROOT_PATH "${CMAKE_CURRENT_BINARY_DIR}/_deps/rapidxml-external-src") + endif() find_package (RapidXml REQUIRED) endif () diff --git a/cmake/gtest.cmake b/cmake/gtest.cmake new file mode 100644 index 00000000..eee39f14 --- /dev/null +++ b/cmake/gtest.cmake @@ -0,0 +1,29 @@ +if (NOT DEPENDENCIES_FORCE_DOWNLOAD) + find_package(GTest CONFIG) + if (NOT GTest_FOUND) + find_package(GTest) + endif() +endif () + +if (NOT GTest_FOUND) + if (DEPENDENCIES_FORCE_DOWNLOAD) + message (STATUS "DEPENDENCIES_FORCE_DOWNLOAD is ON. Fetching googletest") + else () + message (STATUS "Fetching googletest") + endif () + include (FetchContent) + FetchContent_Declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG v1.12.0 + ) + FetchContent_MakeAvailable(googletest) +endif () +add_library(gtest_with_main INTERFACE) +if (TARGET GTest::GTest AND TARGET GTest::Main) + target_link_libraries(gtest_with_main INTERFACE GTest::GTest GTest::Main) +elseif(TARGET GTest::gtest AND TARGET GTest::gtest_main) + target_link_libraries(gtest_with_main INTERFACE GTest::gtest GTest::gtest_main) +else() + message(FATAL_ERROR "Did not find gtest targets") +endif() diff --git a/object-lifetime/CMakeLists.txt b/object-lifetime/CMakeLists.txt index 46c2bf88..430ab343 100644 --- a/object-lifetime/CMakeLists.txt +++ b/object-lifetime/CMakeLists.txt @@ -1,8 +1,6 @@ add_library (CLObjectLifetimeLayer SHARED object_lifetime.cpp -# PLATFORM_ID taking a comma-separated list is CMake 3.15 -# $<$,$>:object_lifetime.def> - $<$,$,$>>:object_lifetime.def> + $<$,$>:object_lifetime.def> $<$:object_lifetime.map> ) @@ -20,9 +18,7 @@ if (LAYERS_BUILD_TESTS) object_lifetime_test_icd.hpp object_lifetime_test_icd.cpp object_lifetime_test_icd_surface.cpp -# PLATFORM_ID taking a comma-separated list is CMake 3.15 -# $<$,$>:object_lifetime_test_icd.def> - $<$,$,$>>:object_lifetime_test_icd.def> + $<$,$>:object_lifetime_test_icd.def> $<$:object_lifetime_test_icd.map> ) target_link_libraries (CLObjectLifetimeICD @@ -33,11 +29,11 @@ if (LAYERS_BUILD_TESTS) ) add_subdirectory (test) -endif () -list (APPEND BUILD_TARGETS - CLObjectLifetimeICD -) + list (APPEND BUILD_TARGETS + CLObjectLifetimeICD + ) +endif () set_target_properties (${BUILD_TARGETS} PROPERTIES diff --git a/ocl-icd-compat/ocl_icd_compat.c b/ocl-icd-compat/ocl_icd_compat.c index 48d123c8..259cd800 100644 --- a/ocl-icd-compat/ocl_icd_compat.c +++ b/ocl-icd-compat/ocl_icd_compat.c @@ -92,8 +92,9 @@ static void _sort_platforms(struct platform_icd *picds, cl_uint npicds) { } } -static void _set_default_id() { - int num_default_platform = 0; +static void _set_default_id(void) +{ + long num_default_platform = 0; #ifndef _MSC_VER const char *default_platform = getenv("OCL_ICD_DEFAULT_PLATFORM"); if (default_platform) { @@ -114,12 +115,12 @@ static void _set_default_id() { if (*default_platform == '\0' || *end_scan != '\0') return; } - if (num_default_platform < 0 || num_default_platform >= (int)_num_platforms) - return; + if (num_default_platform < 0 || num_default_platform >= (long)_num_platforms) return; _default_id = _platforms[num_default_platform].pid; } -void _init_platforms() { +void _init_platforms(void) +{ cl_int err; cl_platform_id *ids = NULL; diff --git a/param-verification/CMakeLists.txt b/param-verification/CMakeLists.txt index a86e323f..c59df62a 100644 --- a/param-verification/CMakeLists.txt +++ b/param-verification/CMakeLists.txt @@ -1,21 +1,37 @@ -add_executable ( - CLParamVerificationGenerator - parser.cpp +# External project is used to build the tool CodeGen +# which generates the source file for target CLParamVerificationLayer +# This setup is required by cross-compilation scenarios, in which +# CodeGen must be run on the host system, whereas +# CLParamVerificationLayer is compiled to the target system +include(ExternalProject) +ExternalProject_Add( + CodeGen + SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/codegen" + INSTALL_COMMAND "" + CMAKE_CACHE_ARGS + -DDEPENDENCIES_FORCE_DOWNLOAD:STRING=${DEPENDENCIES_FORCE_DOWNLOAD} + "-DCMAKE_MODULE_PATH:STRING=${PROJECT_SOURCE_DIR}/cmake" ) -target_link_libraries (CLParamVerificationGenerator PRIVATE RapidXml::RapidXml) +ExternalProject_Get_Property(CodeGen BINARY_DIR) +get_cmake_property(GENERATOR_IS_MULTI_CONFIG GENERATOR_IS_MULTI_CONFIG) +if (GENERATOR_IS_MULTI_CONFIG) + set(CodeGen_EXE "${BINARY_DIR}/$/CodeGen") +else() + set(CodeGen_EXE "${BINARY_DIR}/CodeGen") +endif() add_custom_command ( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/res.cpp COMMAND - CLParamVerificationGenerator ${CMAKE_CURRENT_SOURCE_DIR}/cl-avl.xml + "${CodeGen_EXE}" "${CMAKE_CURRENT_SOURCE_DIR}/cl-avl.xml" DEPENDS - ${CMAKE_CURRENT_SOURCE_DIR}/cl-avl.xml - ${CMAKE_CURRENT_SOURCE_DIR}/param_verification.hpp - ${CMAKE_CURRENT_SOURCE_DIR}/object_is_valid.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/list_violation.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/struct_violation.cpp - CLParamVerificationGenerator + "${CMAKE_CURRENT_SOURCE_DIR}/cl-avl.xml" + "${CMAKE_CURRENT_SOURCE_DIR}/param_verification.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/object_is_valid.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/list_violation.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/struct_violation.cpp" + CodeGen ) add_library ( @@ -33,7 +49,7 @@ if (NOT WIN32 AND NOT APPLE) endif () set (INSTALL_TARGETS CLParamVerificationLayer) -set (BUILD_TARGETS ${INSTALL_TARGETS} CLParamVerificationGenerator) +set (BUILD_TARGETS ${INSTALL_TARGETS}) if (LAYERS_BUILD_TESTS) add_subdirectory (test) diff --git a/param-verification/codegen/CMakeLists.txt b/param-verification/codegen/CMakeLists.txt new file mode 100644 index 00000000..90712d61 --- /dev/null +++ b/param-verification/codegen/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.16) +# Project name is deliberately short: avoid long paths problem on Windows +project(CodeGen CXX) +include("${CMAKE_MODULE_PATH}/RapidXml.cmake") + +add_executable(${PROJECT_NAME} parser.cpp) +target_link_libraries(${PROJECT_NAME} PRIVATE RapidXml::RapidXml) +target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_14) diff --git a/param-verification/parser.cpp b/param-verification/codegen/parser.cpp similarity index 50% rename from param-verification/parser.cpp rename to param-verification/codegen/parser.cpp index 29dfb8fd..40a90154 100644 --- a/param-verification/parser.cpp +++ b/param-verification/codegen/parser.cpp @@ -15,50 +15,58 @@ bool generate_get_version; std::map func_params; // prototypes -std::string parse_expression(xml_node<> const * const node); -std::array parse_2expressions(xml_node<> const * const node); -std::vector parse_list_expressions(xml_node<> const * const node); -std::string parse_violation(xml_node<> const * const violation); -std::vector parse_list(xml_node<> const * const node); +std::string parse_expression(xml_node<> const* const node); +std::array parse_2expressions(xml_node<> const* const node); +std::vector parse_list_expressions(xml_node<> const* const node); +std::string parse_violation(xml_node<> const* const violation); +std::vector parse_list(xml_node<> const* const node); // realizations // Render a call to 'from' given a version string like `1.2`. -std::string render_from(const char * const version_str, bool call_get_version) { +std::string render_from(const char* const version_str, bool call_get_version) +{ std::stringstream ss; ss << version_str; std::string major; std::string minor; std::getline(ss, major, '.'); std::getline(ss, minor); - return std::string(call_get_version ? "(get_version()" : "(version") + " >= CL_MAKE_VERSION(" + major + ", " + minor + ", 0))"; + return std::string(call_get_version ? "(get_version()" : "(version") + " >= CL_MAKE_VERSION(" + + major + ", " + minor + ", 0))"; } -std::string parse_expression(xml_node<> const * const node) +std::string parse_expression(xml_node<> const* const node) { std::string res; - char const * const name = node->name(); + char const* const name = node->name(); - if (strcmp(name, "name") == 0) { + if (strcmp(name, "name") == 0) + { res = node->value(); } - else if (strcmp(name, "literal") == 0) { + else if (strcmp(name, "literal") == 0) + { res = node->value(); } - else if (strcmp(name, "literal_list") == 0) { + else if (strcmp(name, "literal_list") == 0) + { res = node->value(); res = "literal_list(get_version(), \"" + func_params[res] + "\", " + res + ")"; generate_get_version = true; } - else if (strcmp(name, "sizeof") == 0) { + else if (strcmp(name, "sizeof") == 0) + { res = "sizeof(" + std::string(node->value()) + ")"; } - else if (strcmp(name, "mod") == 0) { + else if (strcmp(name, "mod") == 0) + { auto list = parse_2expressions(node); res = "(" + list[0] + " % " + list[1] + ")"; } - else if (strcmp(name, "mult") == 0) { + else if (strcmp(name, "mult") == 0) + { std::vector list(parse_list_expressions(node)); int n = 0; for (auto a : list) @@ -69,7 +77,8 @@ std::string parse_expression(xml_node<> const * const node) } res += ")"; } - else if (strcmp(name, "add") == 0) { + else if (strcmp(name, "add") == 0) + { std::vector list(parse_list_expressions(node)); int n = 0; @@ -81,20 +90,22 @@ std::string parse_expression(xml_node<> const * const node) } res += ")"; } - else if (strcmp(name, "max") == 0) { + else if (strcmp(name, "max") == 0) + { auto list = parse_2expressions(node); res = "std::max(" + list[0] + ", " + list[1] + ")"; } - else if (strcmp(name, "query") == 0) { - res = "query<" + std::string(node->first_attribute("property")->value()) + ">(" + - node->first_attribute("object")->value() + ")"; + else if (strcmp(name, "query") == 0) + { + res = "query<" + std::string(node->first_attribute("property")->value()) + ">(" + + node->first_attribute("object")->value() + ")"; } return res; } -std::array parse_2expressions(xml_node<> const * const node) +std::array parse_2expressions(xml_node<> const* const node) { std::array res; @@ -104,13 +115,12 @@ std::array parse_2expressions(xml_node<> const * const node) return res; } -std::vector parse_list_expressions(xml_node<> const * const node) +std::vector parse_list_expressions(xml_node<> const* const node) { std::vector res; - for (xml_node<> const * list_node = node->first_node(); - list_node != nullptr; - list_node = list_node->next_sibling()) + for (xml_node<> const* list_node = node->first_node(); list_node != nullptr; + list_node = list_node->next_sibling()) { res.push_back(parse_expression(list_node)); } @@ -118,32 +128,31 @@ std::vector parse_list_expressions(xml_node<> const * const node) return res; } -std::vector parse_list(xml_node<> const * const node) +std::vector parse_list(xml_node<> const* const node) { std::vector res; - for (xml_node<> const * list_node = node->first_node(); - list_node != nullptr; - list_node = list_node->next_sibling()) + for (xml_node<> const* list_node = node->first_node(); list_node != nullptr; + list_node = list_node->next_sibling()) { res.push_back(parse_violation(list_node)); - //res.push_back(std::string(list_node->value())); + // res.push_back(std::string(list_node->value())); } return res; } -std::string parse_violation(xml_node<> const * const violation) +std::string parse_violation(xml_node<> const* const violation) { std::string test; if (violation != nullptr) { - char const * const name = violation->name(); + char const* const name = violation->name(); if (strcmp(name, "or") == 0) { - //printf("or:"); + // printf("or:"); std::vector list(parse_list(violation)); int n = 0; @@ -152,14 +161,14 @@ std::string parse_violation(xml_node<> const * const violation) test += (n == 0) ? "(" : " ||\n "; test += a; ++n; - //printf("%s ", a.c_str()); + // printf("%s ", a.c_str()); } test += ")"; - //printf("\n"); + // printf("\n"); } else if (strcmp(name, "and") == 0) { - //printf("and:"); + // printf("and:"); std::vector list(parse_list(violation)); int n = 0; @@ -168,10 +177,10 @@ std::string parse_violation(xml_node<> const * const violation) test += (n == 0) ? "(" : " &&\n "; test += a; ++n; - //printf("%s ", a.c_str()); + // printf("%s ", a.c_str()); } test += ")"; - //printf("\n"); + // printf("\n"); } else if (strcmp(name, "mutex_violation") == 0) { @@ -279,110 +288,81 @@ std::string parse_violation(xml_node<> const * const violation) } else if (strcmp(name, "any_zero") == 0) { - test = "(any_zero(" - + std::string(violation->first_attribute("array")->value()) - + ", " - + std::string(violation->first_attribute("elements")->value()) - + "))"; + test = "(any_zero(" + std::string(violation->first_attribute("array")->value()) + ", " + + std::string(violation->first_attribute("elements")->value()) + "))"; } else if (strcmp(name, "any_nullptr") == 0) { - test = "(any_nullptr(" - + std::string(violation->first_attribute("array")->value()) - + ", " - + std::string(violation->first_attribute("elements")->value()) - + "))"; + test = "(any_nullptr(" + std::string(violation->first_attribute("array")->value()) + + ", " + std::string(violation->first_attribute("elements")->value()) + "))"; } else if (strcmp(name, "any_invalid") == 0) { - test = "(any_invalid(" - + std::string(violation->first_attribute("array")->value()) - + ", " - + std::string(violation->first_attribute("elements")->value()) - + "))"; + test = "(any_invalid(" + std::string(violation->first_attribute("array")->value()) + + ", " + std::string(violation->first_attribute("elements")->value()) + "))"; } else if (strcmp(name, "any_non_null_invalid") == 0) { test = "(any_non_null_invalid(" - + std::string(violation->first_attribute("array")->value()) - + ", " - + std::string(violation->first_attribute("elements")->value()) - + "))"; + + std::string(violation->first_attribute("array")->value()) + ", " + + std::string(violation->first_attribute("elements")->value()) + "))"; } else if (strcmp(name, "any_not_available") == 0) { - test = "(any_not_available(" - + std::string(violation->first_attribute("array")->value()) - + ", " - + std::string(violation->first_attribute("elements")->value()) - + "))"; + test = "(any_not_available(" + std::string(violation->first_attribute("array")->value()) + + ", " + std::string(violation->first_attribute("elements")->value()) + "))"; } else if (strcmp(name, "object_not_in") == 0) { - test = "(object_not_in(" - + std::string(violation->first_attribute("object")->value()) - + ", " - + std::string(violation->first_attribute("in")->value()) - + "))"; + test = "(object_not_in(" + std::string(violation->first_attribute("object")->value()) + + ", " + std::string(violation->first_attribute("in")->value()) + "))"; } else if (strcmp(name, "any_object_not_in") == 0) { - test = "(any_object_not_in(" - + std::string(violation->first_attribute("array")->value()) - + ", " - + std::string(violation->first_attribute("elements")->value()) - + ", " - + std::string(violation->first_attribute("in")->value()) - + "))"; + test = "(any_object_not_in(" + std::string(violation->first_attribute("array")->value()) + + ", " + std::string(violation->first_attribute("elements")->value()) + ", " + + std::string(violation->first_attribute("in")->value()) + "))"; } else if ((strcmp(name, "for_all") == 0) || (strcmp(name, "for_any") == 0)) { if (violation->first_attribute("in") != nullptr) - test = std::string("(") + name + "<" - + violation->first_attribute("query")->value() - + ">(" - + violation->first_attribute("in")->value() - + ",\n [=](return_type<" + test = std::string("(") + name + "<" + violation->first_attribute("query")->value() + + ">(" + violation->first_attribute("in")->value() + ",\n [=](return_type<" + violation->first_attribute("query")->value() + "> query){\n return static_cast(" - + parse_violation(violation->first_node()) - + "); }))"; + + parse_violation(violation->first_node()) + "); }))"; else - test = std::string("(") + name + "<" - + violation->first_attribute("query")->value() - + ">(" - + violation->first_attribute("array")->value() - + ", " - + violation->first_attribute("elements")->value() - + ",\n [=](return_type<" + test = std::string("(") + name + "<" + violation->first_attribute("query")->value() + + ">(" + violation->first_attribute("array")->value() + ", " + + violation->first_attribute("elements")->value() + ",\n [=](return_type<" + violation->first_attribute("query")->value() + "> query){\n return static_cast(" - + parse_violation(violation->first_node()) - + "); }))"; + + parse_violation(violation->first_node()) + "); }))"; } else if (strcmp(name, "check_copy_overlap") == 0) { - test = "(check_copy_overlap(" + std::string(violation->first_attribute("param")->value()) + "))"; + test = "(check_copy_overlap(" + + std::string(violation->first_attribute("param")->value()) + "))"; } else if (strcmp(name, "from") == 0) { test = render_from(violation->first_attribute("version")->value(), true); generate_get_version = true; } -/* else if (strcmp(name, "name") == 0) - { - test = std::string(node->value()); - } - else if (strcmp(name, "literal") == 0) - { - test = std::string(node->value()); - }*/ + /* else if (strcmp(name, "name") == 0) + { + test = std::string(node->value()); + } + else if (strcmp(name, "literal") == 0) + { + test = std::string(node->value()); + }*/ } return test; } -void parse_enums(std::stringstream& code, xml_node<> *& root_node) +void parse_enums(std::stringstream& code, xml_node<>*& root_node) { /////////////////////////////////////////////////////////////////////// // enums @@ -393,71 +373,75 @@ void parse_enums(std::stringstream& code, xml_node<> *& root_node) << "{\n"; // Iterate over the versions - for (xml_node<> * version_node = root_node->first_node("feature"); - version_node != nullptr; - version_node = version_node->next_sibling("feature")) + for (xml_node<>* version_node = root_node->first_node("feature"); version_node != nullptr; + version_node = version_node->next_sibling("feature")) { - code << " if " << render_from(version_node->first_attribute("number")->value(), false) << " {\n"; - - std::vector enums_list = - {"cl_platform_info", - "cl_device_info", - "cl_context_info", - "cl_command_queue_info", - "cl_buffer_create_type", - "cl_image_info", - "cl_mem_info", - "cl_addressing_mode", - "cl_filter_mode", - "cl_sampler_info", - "cl_program_info", - "cl_program_build_info", - "cl_kernel_exec_info", - "cl_kernel_info", - "cl_kernel_work_group_info", - "cl_kernel_sub_group_info", - "cl_kernel_arg_info", - "cl_event_info", - "cl_profiling_info", - "cl_channel_order", - "cl_channel_type"}; - - for (auto a : enums_list) { - for (xml_node<> * enum_node = version_node->first_node("require"); - enum_node != nullptr; - enum_node = enum_node->next_sibling("require")) { - if (enum_node->first_attribute("comment") != nullptr) { - //printf("I have visited %s.\n", - // enum_node->first_attribute("comment")->value()); - if (strstr(enum_node->first_attribute("comment")->value(), a.c_str()) != nullptr) { - code << " if (strcmp(name, \"" << a << "\") == 0)\n" - << " switch (param) {\n"; - - for (xml_node<> * enum_val = enum_node->first_node("enum"); - enum_val; - enum_val = enum_val->next_sibling("enum")) { - code << " case " << enum_val->first_attribute("name")->value() << ":\n"; - } - - code << " return false;\n" - << " }\n\n"; + code << " if " << render_from(version_node->first_attribute("number")->value(), false) + << " {\n"; + + std::vector enums_list = { "cl_platform_info", + "cl_device_info", + "cl_context_info", + "cl_command_queue_info", + "cl_buffer_create_type", + "cl_image_info", + "cl_mem_info", + "cl_addressing_mode", + "cl_filter_mode", + "cl_sampler_info", + "cl_program_info", + "cl_program_build_info", + "cl_kernel_exec_info", + "cl_kernel_info", + "cl_kernel_work_group_info", + "cl_kernel_sub_group_info", + "cl_kernel_arg_info", + "cl_event_info", + "cl_profiling_info", + "cl_channel_order", + "cl_channel_type" }; + + for (auto a : enums_list) + { + for (xml_node<>* enum_node = version_node->first_node("require"); enum_node != nullptr; + enum_node = enum_node->next_sibling("require")) + { + if (enum_node->first_attribute("comment") != nullptr) + { + // printf("I have visited %s.\n", + // enum_node->first_attribute("comment")->value()); + if (strstr(enum_node->first_attribute("comment")->value(), a.c_str()) + != nullptr) + { + code << " if (strcmp(name, \"" << a << "\") == 0)\n" + << " switch (param) {\n"; + + for (xml_node<>* enum_val = enum_node->first_node("enum"); enum_val; + enum_val = enum_val->next_sibling("enum")) + { + code << " case " << enum_val->first_attribute("name")->value() + << ":\n"; } + + code << " return false;\n" + << " }\n\n"; } } + } } code << " }\n\n"; - //printf("I have visited %s.\n", - // version_node->first_attribute("number")->value()); - // version_node->value()); + // printf("I have visited %s.\n", + // version_node->first_attribute("number")->value()); + // version_node->value()); } code << " return true;\n" << "}\n\n"; - //printf("\n"); + // printf("\n"); } -void parse_bitfields(std::stringstream& code, xml_node<> *& root_node) +void parse_bitfields(std::stringstream& code, xml_node<>*& root_node) { /////////////////////////////////////////////////////////////////////// // bitfields @@ -471,58 +455,63 @@ void parse_bitfields(std::stringstream& code, xml_node<> *& root_node) << " T mask = 0;\n\n"; // Iterate over the versions - for (xml_node<> * version_node = root_node->first_node("feature"); - version_node != nullptr; - version_node = version_node->next_sibling("feature")) + for (xml_node<>* version_node = root_node->first_node("feature"); version_node != nullptr; + version_node = version_node->next_sibling("feature")) { - code << " if " << render_from(version_node->first_attribute("number")->value(), false) << " {\n"; - - std::vector bitfields_list = - {"cl_device_type", - "cl_command_queue_properties", - "cl_mem_flags", - "cl_map_flags", - "cl_mem_migration_flags", - "cl_svm_mem_flags", - "cl_device_affinity_domain", - "cl_command_queue_properties", - "cl_device_fp_config", - "cl_device_exec_capabilities" }; - - for (auto i : bitfields_list) { - for (xml_node<> * bitfield_node = version_node->first_node("require"); - bitfield_node != nullptr; - bitfield_node = bitfield_node->next_sibling("require")) { - if (bitfield_node->first_attribute("comment") != nullptr) { - //printf("I have visited %s.\n", - // bitfield_node->first_attribute("comment")->value()); - if (strstr(bitfield_node->first_attribute("comment")->value(), i.c_str()) != nullptr) { - code << " if (strcmp(name, \"" << i << "\") == 0) {\n"; - - for (xml_node<> * bitfield_val = bitfield_node->first_node("enum"); - bitfield_val != nullptr; - bitfield_val = bitfield_val->next_sibling("enum")) { - code << " mask |= " << bitfield_val->first_attribute("name")->value() << ";\n"; - } - - code << " }\n\n"; + code << " if " << render_from(version_node->first_attribute("number")->value(), false) + << " {\n"; + + std::vector bitfields_list = { "cl_device_type", + "cl_command_queue_properties", + "cl_mem_flags", + "cl_map_flags", + "cl_mem_migration_flags", + "cl_svm_mem_flags", + "cl_device_affinity_domain", + "cl_command_queue_properties", + "cl_device_fp_config", + "cl_device_exec_capabilities" }; + + for (auto i : bitfields_list) + { + for (xml_node<>* bitfield_node = version_node->first_node("require"); + bitfield_node != nullptr; bitfield_node = bitfield_node->next_sibling("require")) + { + if (bitfield_node->first_attribute("comment") != nullptr) + { + // printf("I have visited %s.\n", + // bitfield_node->first_attribute("comment")->value()); + if (strstr(bitfield_node->first_attribute("comment")->value(), i.c_str()) + != nullptr) + { + code << " if (strcmp(name, \"" << i << "\") == 0) {\n"; + + for (xml_node<>* bitfield_val = bitfield_node->first_node("enum"); + bitfield_val != nullptr; + bitfield_val = bitfield_val->next_sibling("enum")) + { + code << " mask |= " + << bitfield_val->first_attribute("name")->value() << ";\n"; } + + code << " }\n\n"; } } + } } code << " }\n\n"; - //printf("I have visited %s.\n", - // version_node->first_attribute("number")->value()); - // version_node->value()); + // printf("I have visited %s.\n", + // version_node->first_attribute("number")->value()); + // version_node->value()); } code << " return (param & ~mask);\n" << "}\n\n"; - //printf("\n"); + // printf("\n"); } -void parse_literal_lists(std::stringstream& code, xml_node<> *& root_node) +void parse_literal_lists(std::stringstream& code, xml_node<>*& root_node) { /////////////////////////////////////////////////////////////////////// // literal lists @@ -533,91 +522,98 @@ void parse_literal_lists(std::stringstream& code, xml_node<> *& root_node) << "{\n"; // Iterate over the versions - for (xml_node<> * version_node = root_node->first_node("feature"); - version_node != nullptr; - version_node = version_node->next_sibling("feature")) + for (xml_node<>* version_node = root_node->first_node("feature"); version_node != nullptr; + version_node = version_node->next_sibling("feature")) { - code << " if " << render_from(version_node->first_attribute("number")->value(), false) << " {\n"; - - std::vector enums_list = - {"cl_platform_info", - "cl_device_info", - "cl_context_info", - "cl_command_queue_info", - "cl_buffer_create_type", - "cl_image_info", - "cl_pipe_info", - "cl_mem_info", - "cl_sampler_info", - "cl_program_info", - "cl_program_build_info", - "cl_kernel_exec_info", - "cl_kernel_info", - "cl_kernel_work_group_info", - "cl_kernel_sub_group_info", - "cl_kernel_arg_info", - "cl_event_info", - "cl_profiling_info"}; - - for (auto i : enums_list) { - for (xml_node<> * enum_node = version_node->first_node("require"); - enum_node != nullptr; - enum_node = enum_node->next_sibling("require")) { - if (enum_node->first_attribute("comment") != nullptr) { - //printf("I have visited %s.\n", - // enum_node->first_attribute("comment")->value()); - if (strstr(enum_node->first_attribute("comment")->value(), i.c_str()) != nullptr) { - code << " if (strcmp(name, \"" << i << "\") == 0)\n" - << " switch (param) {\n"; - - for (xml_node<> * enum_val = enum_node->first_node("enum"); - enum_val != nullptr; - enum_val = enum_val->next_sibling("enum")) { - // remove [] from the type - we demand at least 1 element for any returned array - std::string type = enum_val->first_attribute("return_type")->value(); - type = std::regex_replace(type, std::regex("\\[\\]$"), "[1]"); - //type = std::regex_replace(type, std::regex("\\[\\]$"), ""); - - code << " case " << enum_val->first_attribute("name")->value() << ":\n" - << " return sizeof(" << type << ");\n"; - } - - code << " }\n\n"; + code << " if " << render_from(version_node->first_attribute("number")->value(), false) + << " {\n"; + + std::vector enums_list = { "cl_platform_info", + "cl_device_info", + "cl_context_info", + "cl_command_queue_info", + "cl_buffer_create_type", + "cl_image_info", + "cl_pipe_info", + "cl_mem_info", + "cl_sampler_info", + "cl_program_info", + "cl_program_build_info", + "cl_kernel_exec_info", + "cl_kernel_info", + "cl_kernel_work_group_info", + "cl_kernel_sub_group_info", + "cl_kernel_arg_info", + "cl_event_info", + "cl_profiling_info" }; + + for (auto i : enums_list) + { + for (xml_node<>* enum_node = version_node->first_node("require"); enum_node != nullptr; + enum_node = enum_node->next_sibling("require")) + { + if (enum_node->first_attribute("comment") != nullptr) + { + // printf("I have visited %s.\n", + // enum_node->first_attribute("comment")->value()); + if (strstr(enum_node->first_attribute("comment")->value(), i.c_str()) + != nullptr) + { + code << " if (strcmp(name, \"" << i << "\") == 0)\n" + << " switch (param) {\n"; + + for (xml_node<>* enum_val = enum_node->first_node("enum"); + enum_val != nullptr; enum_val = enum_val->next_sibling("enum")) + { + // remove [] from the type - we demand at least 1 element for any + // returned array + std::string type = enum_val->first_attribute("return_type")->value(); + type = std::regex_replace(type, std::regex("\\[\\]$"), "[1]"); + // type = std::regex_replace(type, std::regex("\\[\\]$"), ""); + + code << " case " << enum_val->first_attribute("name")->value() + << ":\n" + << " return sizeof(" << type << ");\n"; } + + code << " }\n\n"; } } + } } code << " }\n\n"; - //printf("I have visited %s.\n", - // version_node->first_attribute("number")->value()); - // version_node->value()); + // printf("I have visited %s.\n", + // version_node->first_attribute("number")->value()); + // version_node->value()); } - code << " *layer::log_stream << \"Unknown return type passed to literal_list(). This is a bug in the param_verification layer.\" << std::endl;\n" + code << " *layer::log_stream << \"Unknown return type passed to literal_list(). This is a bug " + "in the param_verification layer.\" << std::endl;\n" << " return 0;\n" << "}\n\n"; - //printf("\n"); + // printf("\n"); code << "// special case of cl_image_format *\n" << "template<>\n" - << "size_t literal_list(cl_version version, const char * name, cl_image_format * const param)\n" + << "size_t literal_list(cl_version version, const char * name, cl_image_format * const " + "param)\n" << "{\n" << " (void)version;\n" << " (void)name;\n" << " return pixel_size(param);\n" << "}\n" << "template<>\n" - << "size_t literal_list(cl_version version, const char * name, const cl_image_format * const param)\n" + << "size_t literal_list(cl_version version, const char * name, const cl_image_format * " + "const param)\n" << "{\n" << " (void)version;\n" << " (void)name;\n" << " return pixel_size(param);\n" << "}\n\n"; - } -void parse_queries(std::stringstream& code, xml_node<> *& root_node) +void parse_queries(std::stringstream& code, xml_node<>*& root_node) { /////////////////////////////////////////////////////////////////////// // queries @@ -628,53 +624,51 @@ void parse_queries(std::stringstream& code, xml_node<> *& root_node) std::string end = ";\n"; - std::vector enums_list = - {"cl_platform_info", - "cl_device_info", - "cl_context_info", - "cl_command_queue_info", - "cl_image_info", - "cl_pipe_info", - "cl_mem_info", - "cl_sampler_info", - "cl_program_info", - "cl_program_build_info", - "cl_kernel_exec_info", - "cl_kernel_info", - "cl_kernel_work_group_info", - "cl_kernel_sub_group_info", - "cl_kernel_arg_info", - "cl_event_info", - "cl_profiling_info"}; + std::vector enums_list = { "cl_platform_info", + "cl_device_info", + "cl_context_info", + "cl_command_queue_info", + "cl_image_info", + "cl_pipe_info", + "cl_mem_info", + "cl_sampler_info", + "cl_program_info", + "cl_program_build_info", + "cl_kernel_exec_info", + "cl_kernel_info", + "cl_kernel_work_group_info", + "cl_kernel_sub_group_info", + "cl_kernel_arg_info", + "cl_event_info", + "cl_profiling_info" }; // Iterate over the versions - for (xml_node<> * version_node = root_node->first_node("feature"); - version_node != nullptr; - version_node = version_node->next_sibling("feature")) + for (xml_node<>* version_node = root_node->first_node("feature"); version_node != nullptr; + version_node = version_node->next_sibling("feature")) { for (auto i : enums_list) { - for (xml_node<> * enum_node = version_node->first_node("require"); - enum_node != nullptr; - enum_node = enum_node->next_sibling("require")) + for (xml_node<>* enum_node = version_node->first_node("require"); enum_node != nullptr; + enum_node = enum_node->next_sibling("require")) { if (enum_node->first_attribute("comment") != nullptr) { - //printf("I have visited %s.\n", - // enum_node->first_attribute("comment")->value()); - if (strstr(enum_node->first_attribute("comment")->value(), i.c_str()) != nullptr) + // printf("I have visited %s.\n", + // enum_node->first_attribute("comment")->value()); + if (strstr(enum_node->first_attribute("comment")->value(), i.c_str()) + != nullptr) { - for (xml_node<> * enum_val = enum_node->first_node("enum"); - enum_val != nullptr; - enum_val = enum_val->next_sibling("enum")) + for (xml_node<>* enum_val = enum_node->first_node("enum"); + enum_val != nullptr; enum_val = enum_val->next_sibling("enum")) { - // remove [] from the type - we want only 1 element for any returned array + // remove [] from the type - we want only 1 element for any returned + // array std::string type = enum_val->first_attribute("return_type")->value(); type = std::regex_replace(type, std::regex("\\[\\]$"), ""); code << " std::conditional_tvalue() << ", " - << type << ",\n"; + << enum_val->first_attribute("name")->value() << ", " << type + << ",\n"; end = "> " + end; } } @@ -682,30 +676,42 @@ void parse_queries(std::stringstream& code, xml_node<> *& root_node) } } - //printf("I have visited %s.\n", - // version_node->first_attribute("number")->value()); - // version_node->value()); + // printf("I have visited %s.\n", + // version_node->first_attribute("number")->value()); + // version_node->value()); } code << " void" << end << "\n\n"; } -void render_fetch_version(std::stringstream& code, const std::string& handle, const std::string& name) +void render_fetch_version(std::stringstream& code, + const std::string& handle, + const std::string& name) { - // Logic replicated from https://github.com/KhronosGroup/OpenCL-ICD-Loader/blob/main/scripts/icd_dispatch_generated.c.mako#L136 + // Logic replicated from + // https://github.com/KhronosGroup/OpenCL-ICD-Loader/blob/main/scripts/icd_dispatch_generated.c.mako#L136 code << " auto get_version = [=] {\n"; - if (name == "clCreateContext") { - code << " return get_object_version(devices && num_devices > 0 ? devices[0] : nullptr)\n;"; - } else if (name == "clWaitForEvents") { - code << " return get_object_version(event_list && num_events > 0 ? event_list[0] : nullptr)\n;"; - } else if (name == "clCreateContextFromType") { + if (name == "clCreateContext") + { + code << " return get_object_version(devices && num_devices > 0 ? devices[0] : " + "nullptr)\n;"; + } + else if (name == "clWaitForEvents") + { + code << " return get_object_version(event_list && num_events > 0 ? event_list[0] : " + "nullptr)\n;"; + } + else if (name == "clCreateContextFromType") + { code << " return get_object_version(get_context_properties_platform(properties));\n"; - } else if (name != "clUnloadCompiler" && name != "clGetPlatformIDs") { + } + else if (name != "clUnloadCompiler" && name != "clGetPlatformIDs") + { code << " return get_object_version(" << handle << ");\n"; } code << " };\n"; } -void parse_commands(std::stringstream& code, xml_node<> *& root_node) +void parse_commands(std::stringstream& code, xml_node<>*& root_node) { /////////////////////////////////////////////////////////////////////// // commands @@ -714,67 +720,65 @@ void parse_commands(std::stringstream& code, xml_node<> *& root_node) std::stringstream init_dispatch; // Iterate over the commands - for (xml_node<> * commands_node = root_node->first_node("commands"); - commands_node != nullptr; - commands_node = commands_node->next_sibling("commands")) + for (xml_node<>* commands_node = root_node->first_node("commands"); commands_node != nullptr; + commands_node = commands_node->next_sibling("commands")) { - for (xml_node<> * command_node = commands_node->first_node("command"); - command_node != nullptr; - command_node = command_node->next_sibling("command")) - { - xml_node<> * proto_node = command_node->first_node("proto"); - std::string qual = (proto_node->value() != nullptr) ? std::regex_replace(proto_node->value(), std::regex("[ ]+"), " ") : ""; - const char * const name = proto_node->first_node("name")->value(); + for (xml_node<>* command_node = commands_node->first_node("command"); + command_node != nullptr; command_node = command_node->next_sibling("command")) + { + xml_node<>* proto_node = command_node->first_node("proto"); + std::string qual = (proto_node->value() != nullptr) + ? std::regex_replace(proto_node->value(), std::regex("[ ]+"), " ") + : ""; + const char* const name = proto_node->first_node("name")->value(); std::string type = proto_node->first_node("type")->value(); std::string invoke = std::string("tdispatch->") + name; invoke += "(\n"; - const std::string prefix{"CL_API_ENTRY"}, - suffix{"CL_API_CALL"}; - std::string proto = prefix + " " + type + " " + qual + " " + suffix + " " + name + "_layer(\n"; + const std::string prefix{ "CL_API_ENTRY" }, suffix{ "CL_API_CALL" }; + std::string proto = + prefix + " " + type + " " + qual + " " + suffix + " " + name + "_layer(\n"; proto = std::regex_replace(proto, std::regex("[ ]+"), " "); init_dispatch << " dispatch." << name << " = &" << name << "_layer;\n"; -// if (param_node->value()) - //printf("I have visited %s\n", proto.c_str()); -// code << proto; + // if (param_node->value()) + // printf("I have visited %s\n", proto.c_str()); + // code << proto; std::string handle; int n = 0; func_params.clear(); - for (xml_node<> * param_node = command_node->first_node("param"); - param_node != nullptr; - param_node = param_node->next_sibling("param")) + for (xml_node<>* param_node = command_node->first_node("param"); param_node != nullptr; + param_node = param_node->next_sibling("param")) { std::string tmp = (n != 0) ? ",\n " : " "; invoke += tmp + " "; - xml_node<> * node = param_node->first_node("type"); + xml_node<>* node = param_node->first_node("type"); if (node != nullptr) - func_params.insert( - std::pair( - param_node->first_node("name")->value(), - param_node->first_node("type")->value())); + func_params.insert(std::pair( + param_node->first_node("name")->value(), + param_node->first_node("type")->value())); - if (n == 0) { + if (n == 0) + { handle = param_node->first_node("name")->value(); } // read all the contents as text omitting tags - works for 1-level tags only node = param_node->first_node(); - while (node != nullptr) { - if (tmp.back() != ' ') - tmp += " "; + while (node != nullptr) + { + if (tmp.back() != ' ') tmp += " "; tmp += std::regex_replace(node->value(), std::regex("[ ]+"), " "); - if (strstr(node->name(), "name") != nullptr) - invoke += node->value(); - //printf("%s ", node->value()); + if (strstr(node->name(), "name") != nullptr) invoke += node->value(); + // printf("%s ", node->value()); node = node->next_sibling(); } tmp = std::regex_replace(tmp, std::regex(" \\)"), ")"); - //printf("%s", tmp.c_str()); + // printf("%s", tmp.c_str()); proto += tmp; ++n; @@ -788,20 +792,20 @@ void parse_commands(std::stringstream& code, xml_node<> *& root_node) generate_get_version = false; bool generate_label = false; - for (xml_node<> * violation_node = command_node->first_node("if"), - * result_node = command_node->first_node("then"); - (violation_node != nullptr) && (result_node != nullptr); - violation_node = violation_node->next_sibling("if"), + for (xml_node<>*violation_node = command_node->first_node("if"), + *result_node = command_node->first_node("then"); + (violation_node != nullptr) && (result_node != nullptr); + violation_node = violation_node->next_sibling("if"), result_node = result_node->next_sibling("then")) { body << " if " << parse_violation(violation_node->first_node()) << " {\n"; std::string log_ret; std::string log_param; - for (xml_node<> * name_node = result_node->first_node("name"), - * value_node = result_node->first_node("value"); - (name_node != nullptr) && (value_node != nullptr); - name_node = name_node->next_sibling("name"), + for (xml_node<>*name_node = result_node->first_node("name"), + *value_node = result_node->first_node("value"); + (name_node != nullptr) && (value_node != nullptr); + name_node = name_node->next_sibling("name"), value_node = value_node->next_sibling("value")) { if (strcmp(name, name_node->value()) == 0) @@ -810,25 +814,24 @@ void parse_commands(std::stringstream& code, xml_node<> *& root_node) } else { - if (log_param != "") - log_param += ", "; - log_param += std::string("*") + name_node->value() + " = " + value_node->value(); + if (log_param != "") log_param += ", "; + log_param += + std::string("*") + name_node->value() + " = " + value_node->value(); } } body << " *layer::log_stream << \"In " << name << ": \"\n"; - for (xml_node<> * log_node = result_node->first_node("log"); - log_node != nullptr; - log_node = log_node->next_sibling("log")) + for (xml_node<>* log_node = result_node->first_node("log"); log_node != nullptr; + log_node = log_node->next_sibling("log")) { body << " \"" << log_node->value() << ". \"\n"; } body << " \"Returning " << log_ret; - if (log_param != "") { - if (log_ret != "") - body << ", "; + if (log_param != "") + { + if (log_ret != "") body << ", "; } body << log_param << ".\" << std::endl;\n"; @@ -837,10 +840,10 @@ void parse_commands(std::stringstream& code, xml_node<> *& root_node) generate_label = true; std::string ret; - for (xml_node<> * name_node = result_node->first_node("name"), - * value_node = result_node->first_node("value"); - (name_node != nullptr) && (value_node != nullptr); - name_node = name_node->next_sibling("name"), + for (xml_node<>*name_node = result_node->first_node("name"), + *value_node = result_node->first_node("value"); + (name_node != nullptr) && (value_node != nullptr); + name_node = name_node->next_sibling("name"), value_node = value_node->next_sibling("value")) { if (strcmp(name, name_node->value()) == 0) @@ -850,26 +853,25 @@ void parse_commands(std::stringstream& code, xml_node<> *& root_node) else { body << " if (" << name_node->value() << " != NULL)\n" - << " *" << name_node->value() << " = " << value_node->value() << ";\n"; + << " *" << name_node->value() << " = " << value_node->value() + << ";\n"; } } - if (ret != "") - body << " return " << ret << ";\n"; + if (ret != "") body << " return " << ret << ";\n"; body << " }\n\n"; } - if (generate_label) - body << name << "_dispatch:\n"; + if (generate_label) body << name << "_dispatch:\n"; body << " return " << invoke << "}\n\n"; - if (generate_get_version) { - render_fetch_version(code, handle, name); + if (generate_get_version) + { + render_fetch_version(code, handle, name); } code << body.rdbuf(); } - } code << "void init_dispatch() {\n" << init_dispatch.rdbuf() << "}\n"; @@ -877,13 +879,15 @@ void parse_commands(std::stringstream& code, xml_node<> *& root_node) int main(int argc, char* argv[]) { - if (argc != 2) { + if (argc != 2) + { std::cerr << "Usage: " << argv[0] << " " << std::endl; return EXIT_FAILURE; } std::ifstream theFile(argv[1]); - if (!theFile) { + if (!theFile) + { std::cerr << "Error: failed to open '" << argv[1] << "'" << std::endl; return EXIT_FAILURE; } @@ -902,9 +906,10 @@ int main(int argc, char* argv[]) << "#include \"param_verification.hpp\"\n\n\n"; xml_document<> doc; - xml_node<> * root_node; + xml_node<>* root_node; // Read the xml file into a vector - std::vector buffer((std::istreambuf_iterator(theFile)), std::istreambuf_iterator());\ + std::vector buffer((std::istreambuf_iterator(theFile)), + std::istreambuf_iterator()); buffer.push_back('\0'); // Parse the buffer using the xml file parsing library into doc doc.parse<0>(&buffer[0]); @@ -966,7 +971,8 @@ int main(int argc, char* argv[]) << "{\n" << " cl_bool avail = false;\n" << " for (size_t i = 0; i < size; ++i) {\n" - << " tdispatch->clGetDeviceInfo(devices[i], CL_DEVICE_AVAILABLE, sizeof(cl_bool), &avail, NULL);\n" + << " tdispatch->clGetDeviceInfo(devices[i], CL_DEVICE_AVAILABLE, sizeof(cl_bool), " + "&avail, NULL);\n" << " if (!avail) return true;\n" << " avail = false;\n" << " }\n" @@ -987,6 +993,6 @@ int main(int argc, char* argv[]) std::ofstream file("res.cpp"); file << code.str(); file.close(); - //std::cout << code.str(); + // std::cout << code.str(); return 0; } diff --git a/program-cache/CMakeLists.txt b/program-cache/CMakeLists.txt new file mode 100644 index 00000000..44fc8f88 --- /dev/null +++ b/program-cache/CMakeLists.txt @@ -0,0 +1,31 @@ +add_subdirectory(lib) + +add_library (ProgramCacheLayer SHARED + program_cache_layer_surface.cpp + program_cache_layer.cpp + $<$,$>:program_cache_layer.def> + $<$:program_cache_layer.map> +) + +target_link_libraries(ProgramCacheLayer PRIVATE ProgramCache) +target_compile_definitions(ProgramCacheLayer PRIVATE CL_TARGET_OPENCL_VERSION=300) + +if (LAYERS_BUILD_TESTS) + add_subdirectory(test) +endif() + +set_target_properties (ProgramCacheLayer + PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}" + LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}" + RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}" + PDB_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}" + INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}" + FOLDER "Layers" +) +install ( + TARGETS ProgramCacheLayer + ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" +) diff --git a/program-cache/lib/CMakeLists.txt b/program-cache/lib/CMakeLists.txt new file mode 100644 index 00000000..f0d0afb3 --- /dev/null +++ b/program-cache/lib/CMakeLists.txt @@ -0,0 +1,87 @@ +add_library(ProgramCache "") + +target_sources(ProgramCache + PRIVATE + $<$,$,$,$>>>:src/instantiate_lexer.cpp> + src/preprocessor.cpp + src/preprocessor.hpp + src/program_cache.cpp + src/utils.hpp + PUBLIC + $ + $ + $ + $ +) + +target_include_directories(ProgramCache PUBLIC + $ + $ +) +target_link_libraries(ProgramCache + PUBLIC + OpenCL::Headers + PRIVATE + $ + # Boost::format is needed with newer Boost versions, because it is missing from the + # dependency list of Boost::wave, even though it depends on it. + $> +) +target_compile_features(ProgramCache PUBLIC cxx_std_17) +target_compile_definitions(ProgramCache PRIVATE + $<$,$,$,$>>>:BOOST_WAVE_SEPARATE_LEXER_INSTANTIATION=0> + $<$,$,$>>:NOMINMAX> + CL_TARGET_OPENCL_VERSION=300 +) +set_target_properties(ProgramCache PROPERTIES POSITION_INDEPENDENT_CODE ON) + +if (LAYERS_BUILD_TESTS) + add_subdirectory(test) +endif() + +set_target_properties (ProgramCache + PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}" + LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}" + RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}" + PDB_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}" + INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}" + FOLDER "Layers" +) +install ( + TARGETS ProgramCache EXPORT ProgramCacheTargets + ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" +) +install ( + FILES + include/common.hpp + include/program_cache.hpp + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/program_cache" +) +set(config_package_location "${CMAKE_INSTALL_DATADIR}/cmake/ProgramCache") +install ( + EXPORT ProgramCacheTargets + NAMESPACE OpenCL:: + DESTINATION "${config_package_location}" +) +file( + WRITE ${CMAKE_CURRENT_BINARY_DIR}/ProgramCache/ProgramCacheConfig.cmake + "include(\"\${CMAKE_CURRENT_LIST_DIR}/ProgramCacheTargets.cmake\")\n" +) +install( + FILES + "${CMAKE_CURRENT_BINARY_DIR}/ProgramCache/ProgramCacheConfig.cmake" + DESTINATION "${config_package_location}" +) +include(CMakePackageConfigHelpers) +write_basic_package_version_file( + ${CMAKE_CURRENT_BINARY_DIR}/ProgramCache/ProgramCacheConfigVersion.cmake + VERSION ${PROJECT_VERSION} + COMPATIBILITY AnyNewerVersion +) +install( + FILES ${CMAKE_CURRENT_BINARY_DIR}/ProgramCache/ProgramCacheConfigVersion.cmake + DESTINATION ${config_package_location} +) diff --git a/program-cache/lib/include/common.hpp b/program-cache/lib/include/common.hpp new file mode 100644 index 00000000..4a637f15 --- /dev/null +++ b/program-cache/lib/include/common.hpp @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2023 The Khronos Group Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * OpenCL is a trademark of Apple Inc. used under license by Khronos. + */ + +/// @file common.hpp +/// @brief Common definitions for program-cache. +/// +/// Contains common definitions which are shared between multiple compilation units of +/// program-cache. + +#ifndef OCL_PROGRAM_CACHE_LIB_INCLUDE_OCL_PROGRAM_CACHE_COMMON_HPP_ +#define OCL_PROGRAM_CACHE_LIB_INCLUDE_OCL_PROGRAM_CACHE_COMMON_HPP_ + +#include + +#include +#include + +namespace ocl::program_cache { + +/// @brief Error thrown when the path for the cache cannot be accessed. +struct cache_access_error : public std::runtime_error +{ + cache_access_error(const std::string& what_arg): std::runtime_error(what_arg) {} +}; + +/// @brief Error thrown when the OpenCL runtime returns an error. +struct opencl_error : public std::runtime_error +{ + opencl_error(cl_int error, const std::string& prefix = "An OpenCL error occured: ") + : std::runtime_error(prefix + std::to_string(error)), error_(error) + {} + + [[nodiscard]] cl_int err() const { return error_; } + +private: + cl_int error_; +}; + +/// @brief Error thrown when the passed OpenCL program could not be built. +struct opencl_build_error : public opencl_error +{ + opencl_build_error(cl_int error): opencl_error(error, "An OpenCL kernel build error occured: ") + {} +}; + +/// @brief Error thrown when a cl_program is passed which should have been built previously. +struct unbuilt_program_error : public std::runtime_error +{ + unbuilt_program_error(): std::runtime_error("The passed program has not been built") {} +}; + +/// @brief Error thrown if the OpenCL version string queried from the OpenCL runtime is invalid. +struct bad_opencl_version_format : public std::runtime_error +{ + bad_opencl_version_format() + : std::runtime_error("Got invalid OpenCL version string from the runtime") + {} +}; + +/// @brief Error thrown when the C preprocessor executed on the OpenCL kernel encounters an +/// unrecoverable problem. +struct preprocess_exception : public std::runtime_error +{ + preprocess_exception(const std::string& what): std::runtime_error(what) {} +}; + +/// @brief OpenCL function dispatch table used by \ref program_cache. +struct program_cache_dispatch +{ + clBuildProgram_t* clBuildProgram{}; + clCreateContextFromType_t* clCreateContextFromType{}; + clCreateProgramWithBinary_t* clCreateProgramWithBinary{}; + clCreateProgramWithIL_t* clCreateProgramWithIL{}; + clCreateProgramWithSource_t* clCreateProgramWithSource{}; + clGetContextInfo_t* clGetContextInfo{}; + clGetDeviceInfo_t* clGetDeviceInfo{}; + clGetPlatformIDs_t* clGetPlatformIDs{}; + clGetPlatformInfo_t* clGetPlatformInfo{}; + clGetProgramBuildInfo_t* clGetProgramBuildInfo{}; + clGetProgramInfo_t* clGetProgramInfo{}; + clReleaseDevice_t* clReleaseDevice{}; + clReleaseProgram_t* clReleaseProgram{}; + clReleaseContext_t* clReleaseContext{}; +}; + +} // namespace ocl::program_cache + +#endif // OCL_PROGRAM_CACHE_LIB_INCLUDE_OCL_PROGRAM_CACHE_COMMON_HPP_ diff --git a/program-cache/lib/include/program_cache.hpp b/program-cache/lib/include/program_cache.hpp new file mode 100644 index 00000000..9682a5da --- /dev/null +++ b/program-cache/lib/include/program_cache.hpp @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2023 The Khronos Group Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * OpenCL is a trademark of Apple Inc. used under license by Khronos. + */ + +/// @file program_cache.hpp +/// @brief Definition of class \c program_cache. + +#ifndef OCL_PROGRAM_CACHE_LIB_INCLUDE_OCL_PROGRAM_CACHE_PROGRAM_CACHE_HPP_ +#define OCL_PROGRAM_CACHE_LIB_INCLUDE_OCL_PROGRAM_CACHE_PROGRAM_CACHE_HPP_ + +#include "common.hpp" + +#include + +#include +#include +#include +#include +#include +#include + +namespace ocl::program_cache { + +/// @brief Store and fetch OpenCL program binaries to/from the filesystem. +class program_cache { +public: + /// @brief Creates a new instance of the \c program_cache. + /// @param dispatch The function dispatch table that contains the pointers for the OpenCL + /// runtime functions that are used by the \c program_cache. + /// @param context OpenCL context to build the programs for. If \c nullptr is passed, then the + /// default context is used. + /// @param cache_root Path to the program cache root on the filesystem. If \c nullopt is passed, + /// the platform dependent default location is used. + program_cache(const program_cache_dispatch& dispatch, + cl_context context = nullptr, + const std::optional& cache_root = std::nullopt); + + /// @brief Loads cached binaries for all devices associated with the \c cl_context passed in the + /// constructor and builds a \c cl_program. + /// @param key Key to the cache entries. The key must be equal to the key passed to a previous + /// \c store call to retrieve the same binaries. + /// @return The built \c cl_program if a cache entry was found for all devices, \c NULL + /// otherwise. + [[nodiscard]] cl_program fetch(std::string_view key) const; + + /// @brief Loads cached binaries for all devices passed and returns a built \c cl_program. + /// @param key Key to the cache entries. The key must be equal to the key passed to a previous + /// \c store call to retrieve the same binaries. + /// @param devices The devices to load the programs for. + /// @return The built \c cl_program if a cache entry was found for all devices, \c NULL + /// otherwise. + [[nodiscard]] cl_program fetch(std::string_view key, + const std::vector& devices) const; + + /// @brief Stores the binary representation of a \c cl_program in the cache. + /// @param program The program to store. It must be built previously, otherwise \c + /// unbuilt_program_error is thrown. + /// @param key The key to the cache entry, which can be used to retrieve the cache entry later + /// via \c fetch. + void store(cl_program program, std::string_view key) const; + + /// @brief Builds OpenCL source code to a \c cl_program and stores it in the cache. If the + /// program existed in the cache previously, loads it back from the cache without building. + /// @param source Source code of the program. + /// @param options Build options that are passed to the OpenCL compiler. + /// @return The built OpenCL program. + /// @note The cache lookup considers the passed source code, the passed options, the platform's + /// version and the devices to which the code is compiled. In this overload, the code is + /// compiled to all devices associated with the \c cl_context passed in the constructor. + [[nodiscard]] cl_program fetch_or_build_source(std::string_view source, + std::string_view options = {}) const; + + /// @brief Builds OpenCL source code to a \c cl_program and stores it in the cache. If the + /// program existed in the cache previously, loads it back from the cache without building. + /// @param source Source code of the program. + /// @param context The OpenCL context to compile for. + /// @param options Build options that are passed to the OpenCL compiler. + /// @return The built OpenCL program. + /// @note The cache lookup considers the passed source code, the passed options, the platform's + /// version and the devices to which the code is compiled. In this overload, the code is + /// compiled to all devices associated with the \c cl_context passed. + [[nodiscard]] cl_program fetch_or_build_source(std::string_view source, + cl_context context, + std::string_view options = {}) const; + + /// @brief Builds OpenCL source code to a \c cl_program and stores it in the cache. If the + /// program existed in the cache previously, loads it back from the cache without building. + /// @param source Source code of the program. + /// @param context The OpenCL context to compile for. + /// @param devices The OpenCL devices associated with the \c context to compile for. + /// @param options Build options that are passed to the OpenCL compiler. + /// @return The built OpenCL program. + /// @note The cache lookup considers the passed source code, the passed options, the platform's + /// version and the devices to which the code is compiled. + [[nodiscard]] cl_program fetch_or_build_source(std::string_view source, + cl_context context, + const std::vector& devices, + std::string_view options = {}) const; + + /// @brief Builds OpenCL IL code to a \c cl_program and stores it in the cache. If the program + /// existed in the cache previously, loads it back from the cache without building. + /// @param il IL code of the program. + /// @param options Build options that are passed to the OpenCL compiler. + /// @return The built OpenCL program. + /// @note The cache lookup considers the passed IL code, the passed options, the platform's + /// version and the devices to which the code is compiled. In this overload, the code is + /// compiled to all devices associated with the \c cl_context passed in the constructor. + [[nodiscard]] cl_program fetch_or_build_il(const std::vector& il, + std::string_view options = {}) const; + + /// @brief Builds OpenCL IL code to a \c cl_program and stores it in the cache. If the program + /// existed in the cache previously, loads it back from the cache without building. + /// @param il IL code of the program. + /// @param context The OpenCL context to compile for. + /// @param options Build options that are passed to the OpenCL compiler. + /// @return The built OpenCL program. + /// @note The cache lookup considers the passed IL code, the passed options, the platform's + /// version and the devices to which the code is compiled. In this overload, the code is + /// compiled to all devices associated with the \c cl_context passed. + [[nodiscard]] cl_program fetch_or_build_il(const std::vector& il, + cl_context context, + std::string_view options = {}) const; + + /// @brief Builds OpenCL IL code to a \c cl_program and stores it in the cache. If the program + /// existed in the cache previously, loads it back from the cache without building. + /// @param il IL code of the program. + /// @param context The OpenCL context to compile for. + /// @param devices The OpenCL devices associated with the \c context to compile for. + /// @param options Build options that are passed to the OpenCL compiler. + /// @return The built OpenCL program. + /// @note The cache lookup considers the passed IL code, the passed options, the platform's + /// version and the devices to which the code is compiled. + [[nodiscard]] cl_program fetch_or_build_il(const std::vector& il, + cl_context context, + const std::vector& devices, + std::string_view options = {}) const; + +private: + template + cl_program fetch_or_build_impl(const T& input, + cl_context context, + const std::vector& devices, + std::string_view options) const; + + std::filesystem::path get_path_for_device_binary(cl_device_id device, + std::string_view key_hash) const; + + template + std::vector build_program_to_binary(cl_context context, + cl_device_id device, + const T& source, + std::string_view options) const; + + [[nodiscard]] cl_context get_default_context() const; + + std::vector get_devices(cl_context context) const; + + program_cache_dispatch dispatch_; + cl_context context_; + std::filesystem::path cache_root_; +}; + +} + +#endif // OCL_PROGRAM_CACHE_LIB_INCLUDE_OCL_PROGRAM_CACHE_PROGRAM_CACHE_HPP_ diff --git a/program-cache/lib/src/instantiate_lexer.cpp b/program-cache/lib/src/instantiate_lexer.cpp new file mode 100644 index 00000000..95d47538 --- /dev/null +++ b/program-cache/lib/src/instantiate_lexer.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2023 The Khronos Group Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * OpenCL is a trademark of Apple Inc. used under license by Khronos. + */ + +/// @file instantiate_lexer.cpp +/// @brief Explicit template specializations for the Boost::Wave lexer. +/// +/// This file is needed on Windows and mac OS. \c std::string_view::iterator is \c char* on other +/// platforms which is already instantiated in Boost::Wave. + +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4100) // \W4 - unreferenced formal parameter +#pragma warning(disable : 4702) // \W4 - unreachable code +#pragma warning(disable : 4706) // \W4 - assignment within conditional expression +#endif + +#include + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + +#include + +template struct boost::wave::cpplexer::new_lexer_gen; diff --git a/program-cache/lib/src/preprocessor.cpp b/program-cache/lib/src/preprocessor.cpp new file mode 100644 index 00000000..048cf981 --- /dev/null +++ b/program-cache/lib/src/preprocessor.cpp @@ -0,0 +1,345 @@ +/* + * Copyright (c) 2023 The Khronos Group Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * OpenCL is a trademark of Apple Inc. used under license by Khronos. + */ + +/// @file preprocessor.cpp +/// @brief Implementation of C preprocessor utilities. +/// +/// Boost::Wave is used to implement a C preprocessor which is conformant with the OpenCL standard. + +#include "preprocessor.hpp" + +#include "utils.hpp" + +// See https://github.com/boostorg/wave/issues/159 +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfree-nonheap-object" +#endif +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4100) // \W4 - unreferenced formal parameter +#pragma warning(disable : 4706) // \W4 - assignment within conditional expression +#endif + +#include +#include +#include + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic pop +#endif + +#include +#include +#include +#include +#include +#include +#include + +namespace { + +namespace pc = ocl::program_cache; +using lex_iterator_t = boost::wave::cpplexer::lex_iterator>; +using context_t = boost::wave::context; + +void undefine_default_macros(context_t& context) +{ + using string_type = context_t::string_type; + static const std::array not_removable_macros{ + "__LINE__", "__FILE__", "__BASE_FILE__", "__DATE__", + "__TIME__", "__STDC__", "__INCLUDE_LEVEL__", "__cplusplus", + }; + std::vector macro_names; + std::copy(context.macro_names_begin(), context.macro_names_end(), + std::back_inserter(macro_names)); + for (const auto& macro : macro_names) + { + if (std::find(not_removable_macros.begin(), not_removable_macros.end(), macro) + == not_removable_macros.end()) + { + context.remove_macro_definition(macro, true); + } + } +} + +int get_device_opencl_c_id(cl_device_id device, const pc::program_cache_dispatch& dispatch) +{ + const auto device_opencl_c_version = + pc::utils::get_info_str(device, dispatch.clGetDeviceInfo, CL_DEVICE_OPENCL_C_VERSION); + const auto [device_c_major, device_c_minor] = + pc::utils::parse_device_opencl_c_version(device_opencl_c_version); + return 100 * device_c_major + 10 * device_c_minor; +} + +void add_opencl_macro_defs(cl_device_id device, + context_t& context, + pc::LanguageVersion language, + const pc::program_cache_dispatch& dispatch) +{ + cl_platform_id platform{}; + pc::utils::check_cl_error( + dispatch.clGetDeviceInfo(device, CL_DEVICE_PLATFORM, sizeof(platform), &platform, nullptr)); + const auto platform_opencl_version = + pc::utils::get_info_str(platform, dispatch.clGetPlatformInfo, CL_PLATFORM_VERSION); + const auto [platform_major, platform_minor] = + pc::utils::parse_platform_opencl_version(platform_opencl_version); + const int platform_id = 100 * platform_major + 10 * platform_minor; + const int device_c_id = get_device_opencl_c_id(device, dispatch); + + context.add_macro_definition("__kernel_exec(X, typen)=__kernel " + "__attribute__((work_group_size_hint(X, 1, " + "1))) __attribute__((vec_type_hint(typen)))"); + context.add_macro_definition( + "kernel_exec(X, typen)=__kernel __attribute__((work_group_size_hint(X, " + "1, 1))) __attribute__((vec_type_hint(typen)))"); + context.add_macro_definition("__OPENCL_VERSION__=" + std::to_string(device_c_id)); + if (device_c_id >= 110) + { + context.add_macro_definition("CL_VERSION_1_0=100"); + context.add_macro_definition("CL_VERSION_1_1=110"); + } + if (device_c_id >= 120) + { + context.add_macro_definition("CL_VERSION_1_2=120"); + if (!language.is_cpp()) + { + context.add_macro_definition("__OPENCL_C_VERSION__=" + std::to_string(language.id())); + } + } + if (device_c_id >= 200) + { + context.add_macro_definition("CL_VERSION_2_0=200"); + } + if (device_c_id >= 300) + { + context.add_macro_definition("CL_VERSION_3_0=300"); + } + cl_bool endian_little{}; + pc::utils::check_cl_error(dispatch.clGetDeviceInfo( + device, CL_DEVICE_ENDIAN_LITTLE, sizeof(endian_little), &endian_little, nullptr)); + if (endian_little) + { + context.add_macro_definition("__ENDIAN_LITTLE__=1"); + } + cl_bool image_support{}; + pc::utils::check_cl_error(dispatch.clGetDeviceInfo( + device, CL_DEVICE_IMAGE_SUPPORT, sizeof(image_support), &image_support, nullptr)); + if (image_support) + { + context.add_macro_definition("__IMAGE_SUPPORT__=1"); + } + if (language.is_cpp()) + { + context.add_macro_definition("__OPENCL_CPP_VERSION__=" + std::to_string(language.id())); + context.add_macro_definition("__CL_CPP_VERSION_1_0__=100"); + context.add_macro_definition("__CL_CPP_VERSION_2021__=202100"); + } + const auto extension_list = + pc::utils::get_info_str(device, dispatch.clGetDeviceInfo, CL_DEVICE_EXTENSIONS); + for (const auto& extension_name : pc::utils::split(extension_list)) + { + context.add_macro_definition(std::string(extension_name.begin(), extension_name.end()) + + "=1"); + } + if (platform_id >= 300) + { + std::size_t feature_bytes{}; + pc::utils::check_cl_error(dispatch.clGetDeviceInfo(device, CL_DEVICE_OPENCL_C_FEATURES, 0, + nullptr, &feature_bytes)); + std::vector features(feature_bytes / sizeof(cl_name_version)); + pc::utils::check_cl_error(dispatch.clGetDeviceInfo( + device, CL_DEVICE_OPENCL_C_FEATURES, feature_bytes, features.data(), nullptr)); + for (const auto& feature : features) + { + context.add_macro_definition(std::string(&feature.name[0]) + "=1"); + } + } +} + +void process_option(const pc::Option& option, context_t& context, pc::LanguageVersion& language) +{ + using namespace pc; + std::visit( + utils::overloads{ [&](const DefinitionOpt& opt) { + context.add_macro_definition(std::string(opt.definition_)); + }, + [&](const IncludeOpt& opt) { + const std::string path(opt.path_); + context.add_include_path(path.c_str()); + context.add_sysinclude_path(path.c_str()); + }, + [&](const LanguageVersionOpt& opt) { language = opt.get_language(); }, + [&](const FastRelaxedMathOpt&) { + context.add_macro_definition("__FAST_RELAXED_MATH__=1"); + } }, + option); +} + +pc::LanguageVersion get_default_language(cl_device_id device, + const pc::program_cache_dispatch& dispatch) +{ + return { std::min(120, get_device_opencl_c_id(device, dispatch)) }; +} + +} // namespace + +std::string_view pc::remove_empty_pragmas(std::string_view kernel_source, + std::string& allocated_str) +{ + auto pragma_newline_idx = kernel_source.find("#pragma\n"); + const auto last_pragma_idx = kernel_source.rfind("#pragma"); + const bool ends_with_pragma = + last_pragma_idx == (kernel_source.size() - std::string_view("#pragma").size()); + if (pragma_newline_idx == std::string_view::npos) + { + if (ends_with_pragma) + { + return kernel_source.substr(0, last_pragma_idx); + } + else + { + return kernel_source; + } + } + // At this point, #pragma\n is somewhere in the middle of the string + // To remove them, we must make a copy of the entire source. + if (ends_with_pragma) + { + allocated_str = std::string(kernel_source.begin(), kernel_source.begin() + last_pragma_idx); + } + else + { + allocated_str = std::string(kernel_source.begin(), kernel_source.end()); + } + while (pragma_newline_idx != std::string::npos) + { + allocated_str.erase(pragma_newline_idx, std::string_view("#pragma\n").size()); + pragma_newline_idx = allocated_str.find("#pragma\n"); + } + return allocated_str; +} + +pc::LanguageVersionOpt::LanguageVersionOpt(std::string_view version_str): language_(100) +{ + std::string version_str_upper; + std::transform(version_str.begin(), version_str.end(), std::back_inserter(version_str_upper), + [](const auto c) { return std::toupper(c); }); + if (version_str_upper == "CL1.1") + language_ = LanguageVersion(110, false); + else if (version_str_upper == "CL1.2") + language_ = LanguageVersion(120, false); + else if (version_str_upper == "CL2.0") + language_ = LanguageVersion(200, false); + else if (version_str_upper == "CL3.0") + language_ = LanguageVersion(300, false); + else if (version_str_upper == "CLC++1.0") + language_ = LanguageVersion(100, true); + else if (version_str_upper == "CLC++2021") + language_ = LanguageVersion(2021, true); + else + throw preprocess_exception("Invalid -cl-std specification"); +} + +std::vector pc::parse_options(std::string_view options) +{ + std::vector