[
  {
    "path": ".github/workflows/build_cmake.yml",
    "content": "name: CMake Build Matrix\n\non: [push, pull_request]\n\nenv:\n  CMAKE_VERSION: \"3.29.6\"\n  NINJA_VERSION: \"1.12.1\"\n  BUILD_TYPE: Release\n  CCACHE_VERSION: \"4.10\"\n\njobs:\n  build:\n    name: ${{ matrix.config.name }}\n    runs-on: ${{ matrix.config.os }}\n    outputs:\n        tag: ${{ steps.git.outputs.tag }}\n    strategy:\n      fail-fast: false\n      matrix:\n        config:\n        - {\n            name: \"Windows Latest MSVC\", artifact: \"Windows-MSVC\",\n            os: windows-latest,\n            cc: \"cl\", cxx: \"cl\",\n            environment_script: \"C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Auxiliary/Build/vcvars64.bat\"\n          }\n        - {\n            name: \"Windows Latest MinGW\", artifact: \"Windows-MinGW\",\n            os: windows-latest,\n            cc: \"gcc\", cxx: \"g++\"\n          }\n        - {\n            name: \"Ubuntu Latest GCC\", artifact: \"Linux\",\n            os: ubuntu-latest,\n            cc: \"gcc\", cxx: \"g++\"\n          }\n        - {\n            name: \"macOS Latest Clang\", artifact: \"macOS\",\n            os: macos-latest,\n            cc: \"clang\", cxx: \"clang++\"\n          }\n\n    steps:\n    - uses: actions/checkout@v4\n    - name: Checkout submodules\n      id: git\n      shell: cmake -P {0}\n      run: |\n        if (${{github.ref}} MATCHES \"tags/v(.*)\")\n            file(APPEND \"$ENV{GITHUB_OUTPUT}\" \"tag=${CMAKE_MATCH_1}\\n\")\n        else()\n            file(APPEND \"$ENV{GITHUB_OUTPUT}\" \"tag=${{github.run_id}}\\n\")\n        endif()\n\n    - name: Download Ninja and CMake\n      shell: cmake -P {0}\n      run: |\n        set(cmake_version $ENV{CMAKE_VERSION})\n        set(ninja_version $ENV{NINJA_VERSION})\n\n        message(STATUS \"Using host CMake version: ${CMAKE_VERSION}\")\n\n        if (\"${{ runner.os }}\" STREQUAL \"Windows\")\n          set(ninja_suffix \"win.zip\")\n          set(cmake_suffix \"windows-x86_64.zip\")\n          set(cmake_dir \"cmake-${cmake_version}-windows-x86_64/bin\")\n        elseif (\"${{ runner.os }}\" STREQUAL \"Linux\")\n          set(ninja_suffix \"linux.zip\")\n          set(cmake_suffix \"linux-x86_64.tar.gz\")\n          set(cmake_dir \"cmake-${cmake_version}-linux-x86_64/bin\")\n        elseif (\"${{ runner.os }}\" STREQUAL \"macOS\")\n          set(ninja_suffix \"mac.zip\")\n          set(cmake_suffix \"macos-universal.tar.gz\")\n          set(cmake_dir \"cmake-${cmake_version}-macos-universal/CMake.app/Contents/bin\")\n        endif()\n\n        set(ninja_url \"https://github.com/ninja-build/ninja/releases/download/v${ninja_version}/ninja-${ninja_suffix}\")\n        file(DOWNLOAD \"${ninja_url}\" ./ninja.zip SHOW_PROGRESS)\n        execute_process(COMMAND ${CMAKE_COMMAND} -E tar xvf ./ninja.zip)\n\n        set(cmake_url \"https://github.com/Kitware/CMake/releases/download/v${cmake_version}/cmake-${cmake_version}-${cmake_suffix}\")\n        file(DOWNLOAD \"${cmake_url}\" ./cmake.zip SHOW_PROGRESS)\n        execute_process(COMMAND ${CMAKE_COMMAND} -E tar xvf ./cmake.zip)\n\n        # Add to PATH environment variable\n        file(TO_CMAKE_PATH \"$ENV{GITHUB_WORKSPACE}/${cmake_dir}\" cmake_dir)\n        set(path_separator \":\")\n        if (\"${{ runner.os }}\" STREQUAL \"Windows\")\n          set(path_separator \";\")\n        endif()\n        file(APPEND \"$ENV{GITHUB_PATH}\" \"$ENV{GITHUB_WORKSPACE}${path_separator}${cmake_dir}\")\n\n        if (NOT \"${{ runner.os }}\" STREQUAL \"Windows\")\n          execute_process(\n            COMMAND chmod +x ninja\n            COMMAND chmod +x ${cmake_dir}/cmake\n          )\n        endif()\n\n    - name: Download ccache\n      id: ccache\n      shell: cmake -P {0}\n      run: |\n        if (\"${{ runner.os }}\" STREQUAL \"Windows\")\n          set(ccache_dir \"ccache-$ENV{CCACHE_VERSION}-windows-x86_64\")\n          set(ccache_archive \"${ccache_dir}.zip\")\n        elseif (\"${{ runner.os }}\" STREQUAL \"Linux\")\n          set(ccache_dir \"ccache-$ENV{CCACHE_VERSION}-linux-x86_64\")\n          set(ccache_archive \"${ccache_dir}.tar.xz\")\n        elseif (\"${{ runner.os }}\" STREQUAL \"macOS\")\n          set(ccache_dir \"ccache-$ENV{CCACHE_VERSION}-darwin\")\n          set(ccache_archive \"${ccache_dir}.tar.gz\")\n        endif()\n\n        set(ccache_url \"https://github.com/ccache/ccache/releases/download/v$ENV{CCACHE_VERSION}/${ccache_archive}\")\n        file(DOWNLOAD \"${ccache_url}\" ./${ccache_archive} SHOW_PROGRESS)\n        execute_process(COMMAND ${CMAKE_COMMAND} -E tar xvf ./${ccache_archive})\n\n        # Add to PATH environment variable\n        file(TO_CMAKE_PATH \"$ENV{GITHUB_WORKSPACE}/${ccache_dir}\" ccache_dir)\n        set(path_separator \":\")\n        if (\"${{ runner.os }}\" STREQUAL \"Windows\")\n          set(path_separator \";\")\n        endif()\n        file(APPEND \"$ENV{GITHUB_PATH}\" \"$ENV{GITHUB_WORKSPACE}${path_separator}${ccache_dir}\")\n\n        if (NOT \"${{ runner.os }}\" STREQUAL \"Windows\")\n          execute_process(COMMAND chmod +x ${ccache_dir}/ccache)\n        endif()\n\n    - name: Prepare ccache timestamp\n      id: ccache_cache_timestamp\n      shell: cmake -P {0}\n      run: |\n        string(TIMESTAMP current_date \"%Y-%m-%d-%H;%M;%S\" UTC)\n        file(APPEND \"$ENV{GITHUB_OUTPUT}\" \"timestamp=${current_date}\")\n\n    - name: ccache cache files\n      uses: actions/cache@v4\n      with:\n        path: .ccache\n        key: ${{ matrix.config.name }}-ccache-${{ steps.ccache_cache_timestamp.outputs.timestamp }}\n        restore-keys: |\n          ${{ matrix.config.name }}-ccache-\n\n    - name: Configure\n      shell: cmake -P {0}\n      run: |\n        set(ENV{CC} ${{ matrix.config.cc }})\n        set(ENV{CXX} ${{ matrix.config.cxx }})\n\n        if (\"${{ runner.os }}\" STREQUAL \"Windows\" AND NOT \"x${{ matrix.config.environment_script }}\" STREQUAL \"x\")\n          execute_process(\n            COMMAND \"${{ matrix.config.environment_script }}\" && set\n            OUTPUT_FILE environment_script_output.txt\n          )\n          file(STRINGS environment_script_output.txt output_lines)\n          foreach(line IN LISTS output_lines)\n            if (line MATCHES \"^([a-zA-Z0-9_-]+)=(.*)$\")\n              set(ENV{${CMAKE_MATCH_1}} \"${CMAKE_MATCH_2}\")\n            endif()\n          endforeach()\n        endif()\n\n        set(path_separator \":\")\n        if (\"${{ runner.os }}\" STREQUAL \"Windows\")\n          set(path_separator \";\")\n        endif()\n        set(ENV{PATH} \"$ENV{GITHUB_WORKSPACE}${path_separator}$ENV{PATH}\")\n\n        execute_process(\n          COMMAND cmake\n            -S .\n            -B build\n            -D CMAKE_BUILD_TYPE=$ENV{BUILD_TYPE}\n            -G Ninja\n            -D CMAKE_MAKE_PROGRAM=ninja\n            -D CMAKE_C_COMPILER_LAUNCHER=ccache\n            -D CMAKE_CXX_COMPILER_LAUNCHER=ccache\n          RESULT_VARIABLE result\n        )\n        if (NOT result EQUAL 0)\n          message(FATAL_ERROR \"Bad exit status\")\n        endif()\n\n\n    - name: Build\n      shell: cmake -P {0}\n      run: |\n        set(ENV{NINJA_STATUS} \"[%f/%t %o/sec] \")\n\n        if (\"${{ runner.os }}\" STREQUAL \"Windows\" AND NOT \"x${{ matrix.config.environment_script }}\" STREQUAL \"x\")\n          file(STRINGS environment_script_output.txt output_lines)\n          foreach(line IN LISTS output_lines)\n            if (line MATCHES \"^([a-zA-Z0-9_-]+)=(.*)$\")\n              set(ENV{${CMAKE_MATCH_1}} \"${CMAKE_MATCH_2}\")\n            endif()\n          endforeach()\n        endif()\n\n        file(TO_CMAKE_PATH \"$ENV{GITHUB_WORKSPACE}\" ccache_basedir)\n        set(ENV{CCACHE_BASEDIR} \"${ccache_basedir}\")\n        set(ENV{CCACHE_DIR} \"${ccache_basedir}/.ccache\")\n        set(ENV{CCACHE_COMPRESS} \"true\")\n        set(ENV{CCACHE_COMPRESSLEVEL} \"6\")\n        set(ENV{CCACHE_MAXSIZE} \"400M\")\n        if (\"${{ matrix.config.cxx }}\" STREQUAL \"cl\")\n          set(ENV{CCACHE_MAXSIZE} \"600M\")\n        endif()\n\n        execute_process(COMMAND ccache -p)\n        execute_process(COMMAND ccache -z)\n\n        execute_process(\n          COMMAND cmake --build build\n          RESULT_VARIABLE result\n          OUTPUT_VARIABLE output\n          ERROR_VARIABLE output\n          ECHO_OUTPUT_VARIABLE ECHO_ERROR_VARIABLE\n        )\n        if (NOT result EQUAL 0)\n          string(REGEX MATCH \"FAILED:.*$\" error_message \"${output}\")\n          string(REPLACE \"\\n\" \"%0A\" error_message \"${error_message}\")\n          message(\"::error::${error_message}\")\n          message(FATAL_ERROR \"Build failed\")\n        endif()\n\n    - name: ccache statistics\n      shell: cmake -P {0}\n      run: |\n        file(TO_CMAKE_PATH \"$ENV{GITHUB_WORKSPACE}\" ccache_basedir)\n        set(ENV{CCACHE_BASEDIR} \"${ccache_basedir}\")\n        set(ENV{CCACHE_DIR} \"${ccache_basedir}/.ccache\")\n\n        execute_process(COMMAND ccache -s)\n\n    - name: Run tests\n      shell: cmake -P {0}\n      run: |\n        include(ProcessorCount)\n        ProcessorCount(N)\n\n        set(ENV{CTEST_OUTPUT_ON_FAILURE} \"ON\")\n\n        execute_process(\n          COMMAND ctest -j ${N}\n          WORKING_DIRECTORY build\n          RESULT_VARIABLE result\n          OUTPUT_VARIABLE output\n          ERROR_VARIABLE output\n          ECHO_OUTPUT_VARIABLE ECHO_ERROR_VARIABLE\n        )\n        if (NOT result EQUAL 0)\n          string(REGEX MATCH \"[0-9]+% tests.*[0-9.]+ sec.*$\" test_results \"${output}\")\n          string(REPLACE \"\\n\" \"%0A\" test_results \"${test_results}\")\n          message(\"::error::${test_results}\")\n          message(FATAL_ERROR \"Running tests failed!\")\n        endif()\n\n    - name: Install Strip\n      run: cmake --install build --prefix instdir --strip\n\n    - name: Pack\n      working-directory: instdir\n      run: cmake -E tar cfv ../${{ matrix.config.artifact }}-${{ steps.git.outputs.tag }}.7z --format=7zip .\n\n    - name: Upload\n      uses: actions/upload-artifact@v4\n      with:\n        path: ./${{ matrix.config.artifact }}-${{ steps.git.outputs.tag }}.7z\n        name: ${{ matrix.config.artifact }}-${{ steps.git.outputs.tag }}.7z\n\n\n  release:\n    if: contains(github.ref, 'tags/v')\n    runs-on: ubuntu-latest\n    needs: build\n\n    steps:\n    - name: Download artifacts\n      uses: actions/download-artifact@v4\n      with:\n        path: release-with-dirs\n\n    - name: Fixup artifacts\n      run: |\n        mkdir release\n        mv release-with-dirs/*/* release/\n\n    - name: Create Release\n      id: create_release\n      uses: softprops/action-gh-release@v2\n      env:\n        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n      with:\n        tag_name: v${{ needs.build.outputs.tag }}\n        files: release/*\n        draft: false\n        prerelease: false\n"
  },
  {
    "path": "CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.16)\n\nproject(main)\n\nadd_executable(main main.cpp)\n\ninstall(TARGETS main)\n\nenable_testing()\nadd_test(NAME main COMMAND main)\n"
  },
  {
    "path": "LICENSE.md",
    "content": "MIT License\n\nCopyright (c) 2019-2024 Cristian Adam\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# HelloWorld\nA C++ Hello World project, using CMake, ninja, ccache, and GitHub Actions.\n\n# Documentation\nThis project was used as an example for these two blog entries:\n\n* [Using GitHub Actions with C++ and CMake](https://cristianadam.eu/20191222/using-github-actions-with-c-plus-plus-and-cmake/)\n* [Speeding up C++ GitHub Actions using ccache](https://cristianadam.eu/20200113/speeding-up-c-plus-plus-github-actions-using-ccache/) \n"
  },
  {
    "path": "main.cpp",
    "content": "#include <iostream>\n\nint main()\n{\n  std::cout << \"Hello world\\n\";\n}\n"
  }
]