Large diffs are not rendered by default.

@@ -0,0 +1,95 @@
name: emscripten

defaults:
#if: "!contains(github.event.head_commit.message, 'skip ci')" # SKIP
run:
# Use a bash shell so we can use the same syntax for environment variable
# access regardless of the host operating system
shell: bash -e -x {0}

on:
# https://github.community/t/how-to-trigger-an-action-on-push-or-pull-request-but-not-both/16662
workflow_dispatch:
push:
branches:
- master
pull_request:
branches:
- master

env:
PROJ_PFX_TARGET: c4core-
PROJ_PFX_CMAKE: C4CORE_
CMAKE_FLAGS:
NUM_JOBS_BUILD: # 4
EMSCRIPTEN_CACHE_FOLDER: 'emsdk-cache'


# ubuntu-20.04:
# # https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu2004-README.md
# gcc: 7.5.0, 8.4.0, 9.3.0, 10.2.0
# clang: 8.0.1, 9.0.1, 10.0.0
# ubuntu-18.04:
# # https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu1804-README.md
# gcc: 7.5.0, 8.4.0, 9.3.0, 10.1.0
# clang: 6.0.0, 8.0.0, 9.0.0
# macos-11.0: macOS Big Sur 11.0
# # https://github.com/actions/virtual-environments/blob/main/images/macos/macos-11.0-Readme.md
# Xcode 12.1 11.7
# clang/LLVM 10.0.1
# gcc-8 gcc-9
# macos-10.15: macOS Catalina 10.15
# # https://github.com/actions/virtual-environments/blob/main/images/macos/macos-10.15-Readme.md
# Xcode 12.1 11.7
# clang/LLVM 11.0.0
# gcc-8 gcc-9
# windows-2019:
# # https://github.com/actions/virtual-environments/blob/main/images/win/Windows2019-Readme.md
# vs2019
# windows-2016:
# # https://github.com/actions/virtual-environments/blob/main/images/win/Windows2016-Readme.md
# vs2017

jobs:

#----------------------------------------------------------------------------
emscripten:
name: emscripten/${{matrix.emver}}/c++${{matrix.std}}/${{matrix.bt}}
continue-on-error: true
if: always() # https://stackoverflow.com/questions/62045967/github-actions-is-there-a-way-to-continue-on-error-while-still-getting-correct
runs-on: ${{matrix.os}}
strategy:
fail-fast: false
matrix:
include:
- {std: 11, cxx: em++, emver: 2.0.34, bt: Debug , os: ubuntu-latest, bitlinks: static32}
- {std: 11, cxx: em++, emver: 2.0.34, bt: Release, os: ubuntu-latest, bitlinks: static32}
- {std: 20, cxx: em++, emver: 2.0.34, bt: Debug , os: ubuntu-latest, bitlinks: static32}
- {std: 20, cxx: em++, emver: 2.0.34, bt: Release, os: ubuntu-latest, bitlinks: static32}
- {std: 11, cxx: em++, emver: 3.0.0 , bt: Debug , os: ubuntu-latest, bitlinks: static32}
- {std: 11, cxx: em++, emver: 3.0.0 , bt: Release, os: ubuntu-latest, bitlinks: static32}
- {std: 20, cxx: em++, emver: 3.0.0 , bt: Debug , os: ubuntu-latest, bitlinks: static32}
- {std: 20, cxx: em++, emver: 3.0.0 , bt: Release, os: ubuntu-latest, bitlinks: static32}
env:
STD: "${{matrix.std}}"
CXX_: "${{matrix.cxx}}"
BT: "${{matrix.bt}}"
BITLINKS: "${{matrix.bitlinks}}"
VG: "${{matrix.vg}}"
SAN: "${{matrix.san}}"
LINT: "${{matrix.lint}}"
OS: "${{matrix.os}}"
steps:
- {name: checkout, uses: actions/checkout@v2, with: {submodules: recursive}}
- name: setup emscripten cache
id: cache-system-libraries
uses: actions/cache@v2
with: {path: "${{env.EMSCRIPTEN_CACHE_FOLDER}}", key: "${{matrix.emver}}-${{runner.os}}"}
- name: setup emscripten
uses: mymindstorm/setup-emsdk@v11
with: {version: "${{matrix.emver}}", actions-cache-folder: "${{env.EMSCRIPTEN_CACHE_FOLDER}}"}
- {name: show info, run: source .github/setenv.sh && c4_show_info}
- name: static32-configure---------------------------------------------------
run: source .github/setenv.sh && c4_cfg_test static32
- {name: static32-build, run: source .github/setenv.sh && c4_build_test static32}
- {name: static32-run, run: source .github/setenv.sh && c4_run_test static32}
@@ -0,0 +1,111 @@
name: libcxx

defaults:
#if: "!contains(github.event.head_commit.message, 'skip ci')" # SKIP
run:
# Use a bash shell so we can use the same syntax for environment variable
# access regardless of the host operating system
shell: bash -e -x {0}

on:
# https://github.community/t/how-to-trigger-an-action-on-push-or-pull-request-but-not-both/16662
workflow_dispatch:
push:
branches:
- master
pull_request:
branches:
- master

env:
PROJ_PFX_TARGET: c4core-
PROJ_PFX_CMAKE: C4CORE_
CMAKE_FLAGS:
NUM_JOBS_BUILD: # 4


# ubuntu-20.04:
# # https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu2004-README.md
# gcc: 7.5.0, 8.4.0, 9.3.0, 10.2.0
# clang: 8.0.1, 9.0.1, 10.0.0
# ubuntu-18.04:
# # https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu1804-README.md
# gcc: 7.5.0, 8.4.0, 9.3.0, 10.1.0
# clang: 6.0.0, 8.0.0, 9.0.0
# macos-11.0: macOS Big Sur 11.0
# # https://github.com/actions/virtual-environments/blob/main/images/macos/macos-11.0-Readme.md
# Xcode 12.1 11.7
# clang/LLVM 10.0.1
# gcc-8 gcc-9
# macos-10.15: macOS Catalina 10.15
# # https://github.com/actions/virtual-environments/blob/main/images/macos/macos-10.15-Readme.md
# Xcode 12.1 11.7
# clang/LLVM 11.0.0
# gcc-8 gcc-9
# windows-2019:
# # https://github.com/actions/virtual-environments/blob/main/images/win/Windows2019-Readme.md
# vs2019
# windows-2016:
# # https://github.com/actions/virtual-environments/blob/main/images/win/Windows2016-Readme.md
# vs2017

jobs:

#----------------------------------------------------------------------------
libcxx:
name: libc++/${{matrix.cxx}}/c++${{matrix.std}}/${{matrix.bt}}
continue-on-error: true
if: always() # https://stackoverflow.com/questions/62045967/github-actions-is-there-a-way-to-continue-on-error-while-still-getting-correct
runs-on: ${{matrix.os}}
strategy:
fail-fast: false
matrix:
include:
- {std: 20, cxx: clang++-10 , bt: Debug , os: ubuntu-18.04, bitlinks: shared64 static32}
- {std: 20, cxx: clang++-10 , bt: Release, os: ubuntu-18.04, bitlinks: shared64 static32}
- {std: 17, cxx: clang++-10 , bt: Debug , os: ubuntu-18.04, bitlinks: shared64 static32}
- {std: 17, cxx: clang++-10 , bt: Release, os: ubuntu-18.04, bitlinks: shared64 static32}
- {std: 14, cxx: clang++-10 , bt: Debug , os: ubuntu-18.04, bitlinks: shared64 static32}
- {std: 14, cxx: clang++-10 , bt: Release, os: ubuntu-18.04, bitlinks: shared64 static32}
- {std: 11, cxx: clang++-10 , bt: Debug , os: ubuntu-18.04, bitlinks: shared64 static32}
- {std: 11, cxx: clang++-10 , bt: Release, os: ubuntu-18.04, bitlinks: shared64 static32}
- {std: 17, cxx: clang++-6.0, bt: Debug , os: ubuntu-18.04, bitlinks: shared64 static32}
- {std: 17, cxx: clang++-6.0, bt: Release, os: ubuntu-18.04, bitlinks: shared64 static32}
- {std: 14, cxx: clang++-6.0, bt: Debug , os: ubuntu-18.04, bitlinks: shared64 static32}
- {std: 14, cxx: clang++-6.0, bt: Release, os: ubuntu-18.04, bitlinks: shared64 static32}
- {std: 11, cxx: clang++-6.0, bt: Debug , os: ubuntu-18.04, bitlinks: shared64 static32}
- {std: 11, cxx: clang++-6.0, bt: Release, os: ubuntu-18.04, bitlinks: shared64 static32}
env:
LIBCXX: ON # <---- enable libc++
STD: "${{matrix.std}}"
CXX_: "${{matrix.cxx}}"
BT: "${{matrix.bt}}"
BITLINKS: "${{matrix.bitlinks}}"
VG: "${{matrix.vg}}"
SAN: "${{matrix.san}}"
LINT: "${{matrix.lint}}"
OS: "${{matrix.os}}"
steps:
- {name: checkout, uses: actions/checkout@v2, with: {submodules: recursive}}
- {name: install requirements, run: source .github/reqs.sh && c4_install_test_requirements $OS}
- {name: show info, run: source .github/setenv.sh && c4_show_info}
- name: shared64-configure---------------------------------------------------
run: source .github/setenv.sh && c4_cfg_test shared64
- {name: shared64-build, run: source .github/setenv.sh && c4_build_test shared64}
- {name: shared64-run, run: source .github/setenv.sh && c4_run_test shared64}
- {name: shared64-pack, run: source .github/setenv.sh && c4_package shared64}
- name: static64-configure---------------------------------------------------
run: source .github/setenv.sh && c4_cfg_test static64
- {name: static64-build, run: source .github/setenv.sh && c4_build_test static64}
- {name: static64-run, run: source .github/setenv.sh && c4_run_test static64}
- {name: static64-pack, run: source .github/setenv.sh && c4_package static64}
- name: static32-configure---------------------------------------------------
run: source .github/setenv.sh && c4_cfg_test static32
- {name: static32-build, run: source .github/setenv.sh && c4_build_test static32}
- {name: static32-run, run: source .github/setenv.sh && c4_run_test static32}
- {name: static32-pack, run: source .github/setenv.sh && c4_package static32}
- name: shared32-configure---------------------------------------------------
run: source .github/setenv.sh && c4_cfg_test shared32
- {name: shared32-build, run: source .github/setenv.sh && c4_build_test shared32}
- {name: shared32-run, run: source .github/setenv.sh && c4_run_test shared32}
- {name: shared32-pack, run: source .github/setenv.sh && c4_package shared32}
@@ -0,0 +1,103 @@
name: macosx

defaults:
#if: "!contains(github.event.head_commit.message, 'skip ci')" # SKIP
run:
# Use a bash shell so we can use the same syntax for environment variable
# access regardless of the host operating system
shell: bash -e -x {0}

on:
# https://github.community/t/how-to-trigger-an-action-on-push-or-pull-request-but-not-both/16662
workflow_dispatch:
push:
branches:
- master
pull_request:
branches:
- master

env:
PROJ_PFX_TARGET: c4core-
PROJ_PFX_CMAKE: C4CORE_
CMAKE_FLAGS:
NUM_JOBS_BUILD: # 4


# ubuntu-20.04:
# # https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu2004-README.md
# gcc: 7.5.0, 8.4.0, 9.3.0, 10.2.0
# clang: 8.0.1, 9.0.1, 10.0.0
# ubuntu-18.04:
# # https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu1804-README.md
# gcc: 7.5.0, 8.4.0, 9.3.0, 10.1.0
# clang: 6.0.0, 8.0.0, 9.0.0
# macos-11.0: macOS Big Sur 11.0
# # https://github.com/actions/virtual-environments/blob/main/images/macos/macos-11.0-Readme.md
# Xcode 12.1 11.7
# clang/LLVM 10.0.1
# gcc-8 gcc-9
# macos-10.15: macOS Catalina 10.15
# # https://github.com/actions/virtual-environments/blob/main/images/macos/macos-10.15-Readme.md
# Xcode 12.1 11.7
# clang/LLVM 11.0.0
# gcc-8 gcc-9
# windows-2019:
# # https://github.com/actions/virtual-environments/blob/main/images/win/Windows2019-Readme.md
# vs2019
# windows-2016:
# # https://github.com/actions/virtual-environments/blob/main/images/win/Windows2016-Readme.md
# vs2017

jobs:

#----------------------------------------------------------------------------
xcode:
name: xcode${{matrix.xcver}}/c++${{matrix.std}}/${{matrix.bt}}
continue-on-error: true
if: always() # https://stackoverflow.com/questions/62045967/github-actions-is-there-a-way-to-continue-on-error-while-still-getting-correct
runs-on: ${{matrix.os}}
strategy:
fail-fast: false
matrix:
include:
- {std: 11, cxx: xcode, xcver: 13, bt: Debug , os: macos-11, bitlinks: shared64 static64}
- {std: 11, cxx: xcode, xcver: 13, bt: Release, os: macos-11, bitlinks: shared64 static64}
- {std: 17, cxx: xcode, xcver: 13, bt: Debug , os: macos-11, bitlinks: shared64 static64}
- {std: 17, cxx: xcode, xcver: 13, bt: Release, os: macos-11, bitlinks: shared64 static64}
#
- {std: 11, cxx: xcode, xcver: 12, bt: Debug , os: macos-11, bitlinks: shared64 static64}
- {std: 11, cxx: xcode, xcver: 12, bt: Release, os: macos-11, bitlinks: shared64 static64}
- {std: 17, cxx: xcode, xcver: 12, bt: Debug , os: macos-11, bitlinks: shared64 static64}
- {std: 17, cxx: xcode, xcver: 12, bt: Release, os: macos-11, bitlinks: shared64 static64}
#
- {std: 11, cxx: xcode, xcver: 11, bt: Debug , os: macos-11, bitlinks: shared64 static64}
- {std: 11, cxx: xcode, xcver: 11, bt: Release, os: macos-11, bitlinks: shared64 static64}
- {std: 17, cxx: xcode, xcver: 11, bt: Debug , os: macos-11, bitlinks: shared64 static64}
- {std: 17, cxx: xcode, xcver: 11, bt: Release, os: macos-11, bitlinks: shared64 static64}
env: {STD: "${{matrix.std}}", CXX_: "${{matrix.cxx}}", BT: "${{matrix.bt}}", BITLINKS: "${{matrix.bitlinks}}", VG: "${{matrix.vg}}", SAN: "${{matrix.san}}", LINT: "${{matrix.lint}}", OS: "${{matrix.os}}"}
steps:
- {name: checkout, uses: actions/checkout@v2, with: {submodules: recursive}}
- {name: xcode, uses: maxim-lobanov/setup-xcode@v1, with: {xcode-version: "${{matrix.xcver}}" }}
- {name: install requirements, run: source .github/reqs.sh && c4_install_test_requirements $OS}
- {name: show info, run: source .github/setenv.sh && c4_show_info}
- name: shared64-configure---------------------------------------------------
run: source .github/setenv.sh && c4_cfg_test shared64
- {name: shared64-build, run: source .github/setenv.sh && c4_build_test shared64}
- {name: shared64-run, run: source .github/setenv.sh && c4_run_test shared64}
- {name: shared64-pack, run: source .github/setenv.sh && c4_package shared64}
- name: static64-configure---------------------------------------------------
run: source .github/setenv.sh && c4_cfg_test static64
- {name: static64-build, run: source .github/setenv.sh && c4_build_test static64}
- {name: static64-run, run: source .github/setenv.sh && c4_run_test static64}
- {name: static64-pack, run: source .github/setenv.sh && c4_package static64}
- name: shared32-configure---------------------------------------------------
run: source .github/setenv.sh && c4_cfg_test shared32
- {name: shared32-build, run: source .github/setenv.sh && c4_build_test shared32}
- {name: shared32-run, run: source .github/setenv.sh && c4_run_test shared32}
- {name: shared32-pack, run: source .github/setenv.sh && c4_package shared32}
- name: static32-configure---------------------------------------------------
run: source .github/setenv.sh && c4_cfg_test static32
- {name: static32-build, run: source .github/setenv.sh && c4_build_test static32}
- {name: static32-run, run: source .github/setenv.sh && c4_run_test static32}
- {name: static32-pack, run: source .github/setenv.sh && c4_package static32}
@@ -0,0 +1,199 @@
name: release

defaults:
#if: "!contains(github.event.head_commit.message, 'skip ci')" # SKIP
run:
# Use a bash shell so we can use the same syntax for environment variable
# access regardless of the host operating system
shell: bash -e -x {0}

on:
# https://github.community/t/how-to-trigger-an-action-on-push-or-pull-request-but-not-both/16662
workflow_dispatch:
push:
tags:
- v0.*
- v1.*
- v2.*
branches:
- master
pull_request:
branches:
- master

env:
PROJ_PKG_NAME: c4core-
PROJ_PFX_TARGET: c4core-
PROJ_PFX_CMAKE: C4CORE_
CMAKE_FLAGS:
NUM_JOBS_BUILD: # 4


# useful to iterate when fixing the release:
# ver=0.2.1 ; ( set -x ; git tag -d v$ver ; git push origin :v$ver ) ; (set -x ; set -e ; tbump --only-patch --non-interactive $ver ; git add -u ; git commit --amend --no-edit ; git tag --annotate --message "v$ver" "v$ver" ; git push -f --tags origin )

jobs:

gettag:
runs-on: ubuntu-latest
steps:
# use fetch-depth to ensure all tags are fetched
- {name: checkout, uses: actions/checkout@v2, with: {submodules: recursive, fetch-depth: 0}}
- name: Variables (from tag)
if: contains(github.ref, 'tags/v')
run: |
# https://github.community/t/how-to-get-just-the-tag-name/16241/11
SRC_TAG=${GITHUB_REF#refs/tags/}
SRC_VERSION=${GITHUB_REF#refs/tags/v}
cat <<EOF > vars.sh
export SRC_TAG=$SRC_TAG
export SRC_VERSION=$SRC_VERSION
EOF
- name: Variables (from commit, no tag)
if: ${{ !contains(github.ref, 'tags/v') }}
run: |
set -x
branch_name=${GITHUB_REF#refs/heads/}
# builds triggered from PRs have the branch_name like this: refs/pull/150/merge
# so filter to eg pr0150_merge
branch_name=`echo $branch_name | sed "s:refs/pull/\([0-9]*\)/\(.*\):pr0\1_\2:"`
# sanitize the branch name; eg merge/foo-bar -> merge_foo_bar
branch_name=`echo $branch_name | sed 's:[/.-]:_:g'`
SRC_TAG=$(git describe || git rev-parse --short HEAD) # eg v0.2.0-110-gda837e0
SRC_VERSION="${branch_name}-${SRC_TAG}"
cat <<EOF > vars.sh
export SRC_TAG=$SRC_TAG
export SRC_VERSION=$SRC_VERSION
EOF
- name: Verify vars.sh
run: cat vars.sh ; source vars.sh ; echo $SRC_TAG ; echo $SRC_VERSION
- name: Save vars.sh
uses: actions/upload-artifact@v1
with: {name: vars.sh, path: ./vars.sh}

#----------------------------------------------------------------------------
# create source packages
src:
needs: gettag
runs-on: ubuntu-latest
steps:
- {name: checkout, uses: actions/checkout@v2, with: {submodules: recursive}}
- name: Download vars.sh
uses: actions/download-artifact@v1
with: {name: vars.sh, path: ./}
- name: Install python 3.9
uses: actions/setup-python@v2
with: { python-version: 3.9 }
- name: Install requirements
run: |
sudo -E pip install git-archive-all
- name: Create source packages
run: |
pwd
ls -lFhp
source vars.sh
echo SRC_TAG=$SRC_TAG
echo SRC_VERSION=$SRC_VERSION
id=${PROJ_PKG_NAME}${SRC_VERSION}
name=${id}-src
mkdir -p assets
git-archive-all --prefix $name assets/$name.tgz
git-archive-all --prefix $name assets/$name.zip
python --version
python tools/amalgamate.py assets/$id.hpp
- name: Save source artifacts
uses: actions/upload-artifact@v1
with: {name: assets, path: assets}

#----------------------------------------------------------------------------
# create c++ packages
cpp:
name: cpp/${{matrix.config.os}}/${{matrix.config.gen}}
needs: gettag
runs-on: ${{matrix.config.os}}
env: {DEV: OFF, BT: Release, OS: "${{matrix.config.os}}", CXX_: "${{matrix.config.cxx}}", GEN: "${{matrix.config.gen}}"}
strategy:
fail-fast: false
matrix:
config:
# name of the artifact | suffix (gen) | suffix (package) | cpack gen | mime type | os | cxx
# ubuntu 20.04 is disabled because of a problem installing libc++:i386:
#- {name: Ubuntu 20.04 deb , sfxg: unix64-shared-Release.deb, sfxp: ubuntu-20.04.deb , gen: DEB , mime: vnd.debian.binary-package, os: ubuntu-20.04 }
- {name: Ubuntu 18.04 deb , sfxg: unix64-shared-Release.deb, sfxp: ubuntu-18.04.deb , gen: DEB , mime: vnd.debian.binary-package, os: ubuntu-18.04 }
- {name: Windows VS2019 zip, sfxg: win64-shared-Release.zip , sfxp: windows-vs2019.zip , gen: ZIP , mime: zip , os: windows-2019, cxx: vs2019}
- {name: MacOSX sh , sfxg: apple64-shared-Release.sh, sfxp: macosx-xcode.sh , gen: STGZ , mime: x-sh , os: macos-11.0 , cxx: xcode }
steps:
- {name: checkout, uses: actions/checkout@v2, with: {submodules: recursive}}
- name: Download vars.sh
uses: actions/download-artifact@v1
with: {name: vars.sh, path: ./}
- {name: install requirements, run: source .github/reqs.sh && c4_install_test_requirements $OS}
- {name: show info, run: source .github/setenv.sh && c4_show_info }
- name: shared64-configure---------------------------------------------------
run: source .github/setenv.sh && c4_cfg_test shared64
- {name: shared64-build, run: source .github/setenv.sh && c4_build_target shared64}
- name: shared64-pack
run: source .github/setenv.sh && c4_package shared64 $GEN
- name: shared64-normalize
run: |
set -x
source vars.sh
mkdir -p assets
asset_src=`ls -1 ./build/shared64/${PROJ_PFX_TARGET}*-${{matrix.config.sfxg}}`
asset_dst=./assets/${PROJ_PKG_NAME}${SRC_VERSION}-${{matrix.config.sfxp}}
[ ! -f $asset_src ] && exit 1
cp -fav $asset_src $asset_dst
- name: Save artifacts
uses: actions/upload-artifact@v1
with: {name: assets, path: assets}

#----------------------------------------------------------------------------
release:
runs-on: ubuntu-latest
needs:
- src
- cpp
steps:
- {name: checkout, uses: actions/checkout@v2, with: {submodules: recursive}}
- name: Gather artifacts - ./assets
uses: actions/download-artifact@v2
with: {name: assets, path: assets}
- name: Verify existing artifacts
run: |
ls -lFhp assets/
#
# Github
- name: Restore vars.sh
if: contains(github.ref, 'tags/v')
uses: actions/download-artifact@v1
with: {name: vars.sh, path: ./}
- name: Save vars for following steps
if: contains(github.ref, 'tags/v')
id: vars
run: |
source vars.sh
version_body=${{github.workspace}}/changelog/$SRC_VERSION.md
if [ ! -f $version_body ] ; then
echo "version body file was not found: $version_body"
exit 1
fi
echo "::set-output name=VERSION::$SRC_VERSION"
echo "::set-output name=VERSION_BODY::$version_body"
- name: Create Github Release
if: contains(github.ref, 'tags/v')
id: create_release
uses: actions/create-release@v1
env: { GITHUB_TOKEN: "${{secrets.GITHUB_TOKEN}}" }
with:
tag_name: ${{github.ref}}
release_name: Release ${{steps.vars.outputs.VERSION}}
body_path: ${{steps.vars.outputs.VERSION_BODY}}
draft: true
prerelease: ${{contains(github.ref, 'rc')}}
- name: Upload assets to Github Release
if: contains(github.ref, 'tags/v')
uses: dwenegar/upload-release-assets@v1
env: { GITHUB_TOKEN: "${{secrets.GITHUB_TOKEN}}" }
with:
release_id: ${{steps.create_release.outputs.id}}
assets_path: ./assets/

Large diffs are not rendered by default.

@@ -0,0 +1,104 @@
name: test_install

defaults:
#if: "!contains(github.event.head_commit.message, 'skip ci')" # SKIP
run:
# Use a bash shell so we can use the same syntax for environment variable
# access regardless of the host operating system
shell: bash -e -x {0}

on:
# https://github.community/t/how-to-trigger-an-action-on-push-or-pull-request-but-not-both/16662
workflow_dispatch:
push:
branches:
- master
pull_request:
branches:
- master

env:
PROJ_PFX_TARGET: c4core-
PROJ_PFX_CMAKE: C4CORE_
CMAKE_FLAGS:
NUM_JOBS_BUILD: # 4

jobs:

#----------------------------------------------------------------------------
install_tests:
name: ${{matrix.name}}/${{matrix.bt}}
# if: github.ref == 'refs/heads/master'
continue-on-error: true
if: always() # https://stackoverflow.com/questions/62045967/github-actions-is-there-a-way-to-continue-on-error-while-still-getting-correct
runs-on: ${{matrix.os}}
strategy:
fail-fast: false
matrix:
include:
- {name: find_package/linux , sdir: test/test_install , os: ubuntu-18.04, cxx: g++-10 , gen: "-DCMAKE_CXX_COMPILER=g++-10" , tgt: all , bt: Release, vars: "-Dc4core_DIR=$GITHUB_WORKSPACE/$PDIR/lib/cmake/c4core -DC4CORE_TEST_INSTALL_PACKAGE_MODE=ON", commonvars: }
- {name: find_package/linux , sdir: test/test_install , os: ubuntu-18.04, cxx: g++-10 , gen: "-DCMAKE_CXX_COMPILER=g++-10" , tgt: all , bt: Debug , vars: "-Dc4core_DIR=$GITHUB_WORKSPACE/$PDIR/lib/cmake/c4core -DC4CORE_TEST_INSTALL_PACKAGE_MODE=ON", commonvars: }
- {name: find_package/linux/libcxx, sdir: test/test_install , os: ubuntu-18.04, cxx: clang++-9, gen: "-DCMAKE_CXX_COMPILER=clang++-9" , tgt: all , bt: Release, vars: "-Dc4core_DIR=$GITHUB_WORKSPACE/$PDIR/lib/cmake/c4core -DC4CORE_TEST_INSTALL_PACKAGE_MODE=ON", commonvars: "-DC4CORE_USE_LIBCXX=ON"}
- {name: find_package/linux/libcxx, sdir: test/test_install , os: ubuntu-18.04, cxx: clang++-9, gen: "-DCMAKE_CXX_COMPILER=clang++-9" , tgt: all , bt: Debug , vars: "-Dc4core_DIR=$GITHUB_WORKSPACE/$PDIR/lib/cmake/c4core -DC4CORE_TEST_INSTALL_PACKAGE_MODE=ON", commonvars: "-DC4CORE_USE_LIBCXX=ON"}
- {name: find_package/macos , sdir: test/test_install , os: macos-11.0 , cxx: xcode , gen: "-G Xcode -DCMAKE_OSX_ARCHITECTURES=x86_64", tgt: ALL_BUILD, bt: Release, vars: "-Dc4core_DIR=$GITHUB_WORKSPACE/$PDIR/lib/cmake/c4core -DC4CORE_TEST_INSTALL_PACKAGE_MODE=ON", commonvars: }
- {name: find_package/macos , sdir: test/test_install , os: macos-11.0 , cxx: xcode , gen: "-G Xcode -DCMAKE_OSX_ARCHITECTURES=x86_64", tgt: ALL_BUILD, bt: Debug , vars: "-Dc4core_DIR=$GITHUB_WORKSPACE/$PDIR/lib/cmake/c4core -DC4CORE_TEST_INSTALL_PACKAGE_MODE=ON", commonvars: }
- {name: find_package/win , sdir: test/test_install , os: windows-2019, cxx: vs2019 , gen: "-G 'Visual Studio 16 2019' -A x64" , tgt: ALL_BUILD, bt: Release, vars: "-Dc4core_DIR=$GITHUB_WORKSPACE/$PDIR/cmake -DC4CORE_TEST_INSTALL_PACKAGE_MODE=ON", commonvars: }
- {name: find_package/win , sdir: test/test_install , os: windows-2019, cxx: vs2019 , gen: "-G 'Visual Studio 16 2019' -A x64" , tgt: ALL_BUILD, bt: Debug , vars: "-Dc4core_DIR=$GITHUB_WORKSPACE/$PDIR/cmake -DC4CORE_TEST_INSTALL_PACKAGE_MODE=ON", commonvars: }
#
- {name: find_library/linux , sdir: test/test_install , os: ubuntu-18.04, cxx: g++-10 , gen: "-DCMAKE_CXX_COMPILER=g++-10" , tgt: all , bt: Release, vars: "-DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/$PDIR -DC4CORE_TEST_INSTALL_PACKAGE_MODE=OFF", commonvars: }
- {name: find_library/linux , sdir: test/test_install , os: ubuntu-18.04, cxx: g++-10 , gen: "-DCMAKE_CXX_COMPILER=g++-10" , tgt: all , bt: Debug , vars: "-DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/$PDIR -DC4CORE_TEST_INSTALL_PACKAGE_MODE=OFF", commonvars: }
- {name: find_library/linux/libcxx, sdir: test/test_install , os: ubuntu-18.04, cxx: clang++-9, gen: "-DCMAKE_CXX_COMPILER=clang++-9" , tgt: all , bt: Release, vars: "-DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/$PDIR -DC4CORE_TEST_INSTALL_PACKAGE_MODE=OFF", commonvars: "-DC4CORE_USE_LIBCXX=ON"}
- {name: find_library/linux/libcxx, sdir: test/test_install , os: ubuntu-18.04, cxx: clang++-9, gen: "-DCMAKE_CXX_COMPILER=clang++-9" , tgt: all , bt: Debug , vars: "-DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/$PDIR -DC4CORE_TEST_INSTALL_PACKAGE_MODE=OFF", commonvars: "-DC4CORE_USE_LIBCXX=ON"}
- {name: find_library/macos , sdir: test/test_install , os: macos-11.0 , cxx: xcode , gen: "-G Xcode -DCMAKE_OSX_ARCHITECTURES=x86_64", tgt: ALL_BUILD, bt: Release, vars: "-DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/$PDIR -DC4CORE_TEST_INSTALL_PACKAGE_MODE=OFF", commonvars: }
- {name: find_library/macos , sdir: test/test_install , os: macos-11.0 , cxx: xcode , gen: "-G Xcode -DCMAKE_OSX_ARCHITECTURES=x86_64", tgt: ALL_BUILD, bt: Debug , vars: "-DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/$PDIR -DC4CORE_TEST_INSTALL_PACKAGE_MODE=OFF", commonvars: }
- {name: find_library/win , sdir: test/test_install , os: windows-2019, cxx: vs2019 , gen: "-G 'Visual Studio 16 2019' -A x64" , tgt: ALL_BUILD, bt: Release, vars: "-DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/$PDIR -DC4CORE_TEST_INSTALL_PACKAGE_MODE=OFF", commonvars: }
- {name: find_library/win , sdir: test/test_install , os: windows-2019, cxx: vs2019 , gen: "-G 'Visual Studio 16 2019' -A x64" , tgt: ALL_BUILD, bt: Debug , vars: "-DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/$PDIR -DC4CORE_TEST_INSTALL_PACKAGE_MODE=OFF", commonvars: }
#
- {name: singleheader/linux , sdir: test/test_singleheader, os: ubuntu-18.04, cxx: g++-10 , gen: "-DCMAKE_CXX_COMPILER=g++-10" , tgt: all , bt: Release, vars: , commonvars: }
- {name: singleheader/linux , sdir: test/test_singleheader, os: ubuntu-18.04, cxx: g++-10 , gen: "-DCMAKE_CXX_COMPILER=g++-10" , tgt: all , bt: Debug , vars: , commonvars: }
- {name: singleheader/linux/libcxx, sdir: test/test_singleheader, os: ubuntu-18.04, cxx: clang++-9, gen: "-DCMAKE_CXX_COMPILER=clang++-9" , tgt: all , bt: Release, vars: , commonvars: "-DC4CORE_USE_LIBCXX=ON"}
- {name: singleheader/linux/libcxx, sdir: test/test_singleheader, os: ubuntu-18.04, cxx: clang++-9, gen: "-DCMAKE_CXX_COMPILER=clang++-9" , tgt: all , bt: Debug , vars: , commonvars: "-DC4CORE_USE_LIBCXX=ON"}
- {name: singleheader/macos , sdir: test/test_singleheader, os: macos-11.0 , cxx: xcode , gen: "-G Xcode -DCMAKE_OSX_ARCHITECTURES=x86_64", tgt: ALL_BUILD, bt: Release, vars: , commonvars: }
- {name: singleheader/macos , sdir: test/test_singleheader, os: macos-11.0 , cxx: xcode , gen: "-G Xcode -DCMAKE_OSX_ARCHITECTURES=x86_64", tgt: ALL_BUILD, bt: Debug , vars: , commonvars: }
- {name: singleheader/win , sdir: test/test_singleheader, os: windows-2019, cxx: vs2019 , gen: "-G 'Visual Studio 16 2019' -A x64" , tgt: ALL_BUILD, bt: Release, vars: , commonvars: }
- {name: singleheader/win , sdir: test/test_singleheader, os: windows-2019, cxx: vs2019 , gen: "-G 'Visual Studio 16 2019' -A x64" , tgt: ALL_BUILD, bt: Debug , vars: , commonvars: }
env:
CXX_: "${{matrix.cxx}}"
BT: "${{matrix.bt}}"
OS: "${{matrix.os}}"
BDIR: "build/${{matrix.name}}-${{matrix.bt}}"
IDIR: "install/${{matrix.name}}-${{matrix.bt}}"
PDIR: "prefix/${{matrix.name}}-${{matrix.bt}}"
steps:
- {name: checkout, uses: actions/checkout@v2, with: {submodules: recursive}}
- {name: install requirements, run: source .github/reqs.sh && c4_install_test_requirements $OS}
- {name: show info, run: source .github/setenv.sh && c4_show_info}
- name: Install python 3.9
uses: actions/setup-python@v2
with: { python-version: 3.9 }
- name: preinstall
run: |
if [ "${{matrix.sdir}}" == "test/test_install" ] ; then
mkdir -p $BDIR-staging
cmake -S . -B $BDIR-staging -DCMAKE_INSTALL_PREFIX=$PDIR -DCMAKE_BUILD_TYPE=${{matrix.bt}} ${{matrix.gen}} ${{matrix.commonvars}}
cmake --build $BDIR-staging --config ${{matrix.bt}} --target ${{matrix.tgt}} -j
cmake --build $BDIR-staging --config ${{matrix.bt}} --target install
fi
- name: configure
run: |
mkdir -p $BDIR
mkdir -p $IDIR
cmake -S ${{matrix.sdir}} -B $BDIR \
-DC4CORE_BUILD_TESTS=ON \
-DC4CORE_VALGRIND=OFF \
-DCMAKE_BUILD_TYPE=${{matrix.bt}} \
-DCMAKE_INSTALL_PREFIX=$IDIR \
${{matrix.gen}} \
${{matrix.vars}} \
${{matrix.commonvars}}
- name: build
run: |
cmake --build $BDIR --config ${{matrix.bt}} --target c4core-test-build -j
- name: run
run: |
cmake --build $BDIR --config ${{matrix.bt}} --target c4core-test-run
@@ -0,0 +1,34 @@
# text editor files
*.bck
\#*
*~
.ccls-cache/
.clangd/
.cache/
.cquery_cached_index/
__pycache__/

# Visual Studio files
.vs/
.vscode/
# QtCreator files
CMakeLists.txt.user
# Eclipse
.project
.cproject
/.settings/

# build files
build/
install/
.python-version
compile_commands.json

# test files
/Testing/

# continuous integration files
.github/vagrant/*.log
.github/vagrant/.vagrant
.github/vagrant/macos/.vagrant
src_singleheader/
@@ -0,0 +1,9 @@
[submodule "cmake"]
path = cmake
url = https://github.com/biojppm/cmake
[submodule "extern/debugbreak"]
path = src/c4/ext/debugbreak
url = https://github.com/biojppm/debugbreak
[submodule "src/c4/ext/fast_float"]
path = src/c4/ext/fast_float
url = https://github.com/fastfloat/fast_float
@@ -0,0 +1,107 @@
cmake_minimum_required(VERSION 3.13 FATAL_ERROR)
include(./cmake/c4Project.cmake)
project(c4core
DESCRIPTION "Multiplatform low-level C++ utilities"
HOMEPAGE_URL "https://github.com/biojppm/c4core"
LANGUAGES CXX)
include(./compat.cmake)

c4_project(VERSION 0.1.8
AUTHOR "Joao Paulo Magalhaes <dev@jpmag.me>")

option(C4CORE_WITH_FASTFLOAT "use fastfloat to parse floats" ON)

set(C4CORE_SRC_FILES
c4/allocator.hpp
c4/base64.hpp
c4/base64.cpp
c4/blob.hpp
c4/bitmask.hpp
c4/charconv.hpp
c4/c4_pop.hpp
c4/c4_push.hpp
c4/char_traits.cpp
c4/char_traits.hpp
c4/common.hpp
c4/compiler.hpp
c4/config.hpp
c4/cpu.hpp
c4/ctor_dtor.hpp
c4/dump.hpp
c4/enum.hpp
c4/error.cpp
c4/error.hpp
c4/export.hpp
c4/format.hpp
c4/format.cpp
c4/hash.hpp
c4/language.hpp
c4/language.cpp
c4/memory_resource.cpp
c4/memory_resource.hpp
c4/memory_util.cpp
c4/memory_util.hpp
c4/platform.hpp
c4/preprocessor.hpp
c4/restrict.hpp
c4/span.hpp
c4/std/std.hpp
c4/std/std_fwd.hpp
c4/std/string.hpp
c4/std/string_fwd.hpp
c4/std/tuple.hpp
c4/std/vector.hpp
c4/std/vector_fwd.hpp
c4/substr.hpp
c4/substr_fwd.hpp
c4/szconv.hpp
c4/type_name.hpp
c4/types.hpp
c4/unrestrict.hpp
c4/utf.hpp
c4/utf.cpp
c4/windows.hpp
c4/windows_pop.hpp
c4/windows_push.hpp
c4/c4core.natvis
#
c4/ext/debugbreak/debugbreak.h
c4/ext/rng/rng.hpp
c4/ext/sg14/inplace_function.h
)
if(C4CORE_WITH_FASTFLOAT)
list(APPEND C4CORE_SRC_FILES
c4/ext/fast_float.hpp
c4/ext/fast_float_all.h
)
endif()
set(C4CORE_AMALGAMATED ${C4CORE_SRC_DIR}/../src_singleheader/c4/c4core_all.hpp)
list(TRANSFORM C4CORE_SRC_FILES PREPEND "${C4CORE_SRC_DIR}/" OUTPUT_VARIABLE C4CORE_SRC_FILES_FULL)

add_custom_target(c4core-amalgamate
python ${CMAKE_CURRENT_LIST_DIR}/tools/amalgamate.py ${C4CORE_AMALGAMATED}
COMMENT "${CMAKE_CURRENT_LIST_DIR}/tools/amalgamate.py ${C4CORE_AMALGAMATED}"
BYPRODUCTS ${C4CORE_AMALGAMATED}
DEPENDS ${C4CORE_SRC_FILES_FULL}
)

c4_add_library(c4core
INC_DIRS
$<BUILD_INTERFACE:${C4CORE_SRC_DIR}> $<INSTALL_INTERFACE:include>
SOURCE_ROOT ${C4CORE_SRC_DIR}
SOURCES ${C4CORE_SRC_FILES}
)

if(NOT C4CORE_WITH_FASTFLOAT)
target_compile_definitions(c4core PUBLIC -DC4CORE_NO_FAST_FLOAT)
endif()


#-------------------------------------------------------

c4_install_target(c4core)
c4_install_exports()

c4_add_dev_targets()

c4_pack_project(TYPE LIBRARY)
@@ -0,0 +1,26 @@
src/c4/ext/sg14/inplace_function.h is distributed under the following terms:
----------------------------------------------------------------------------

Boost Software License - Version 1.0 - August 17th, 2003

Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:

The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,20 @@
Copyright (c) 2018, Joao Paulo Magalhaes <dev@jpmag.me>

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

@@ -0,0 +1,232 @@
# c4core - C++ core utilities

[![MIT Licensed](https://img.shields.io/badge/License-MIT-green.svg)](https://github.com/biojppm/c4core/blob/master/LICENSE.txt)
[![Docs](https://img.shields.io/badge/docs-docsforge-blue)](https://c4core.docsforge.com/)
[![ci](https://github.com/biojppm/c4core/workflows/ci/badge.svg)](https://github.com/biojppm/c4core/actions?query=ci)
[![Coveralls](https://coveralls.io/repos/github/biojppm/c4core/badge.svg)](https://coveralls.io/github/biojppm/c4core)
[![Codecov](https://codecov.io/gh/biojppm/c4core/branch/master/graph/badge.svg)](https://codecov.io/gh/biojppm/c4core)
[![LGTM alerts](https://img.shields.io/lgtm/alerts/g/biojppm/c4core.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/biojppm/c4core/alerts/)
[![LGTM grade: C/C++](https://img.shields.io/lgtm/grade/cpp/g/biojppm/c4core.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/biojppm/c4core/context:cpp)


c4core is a library of low-level C++ utilities, written with low-latency
projects in mind.

Some of the utilities provided by c4core have already equivalent
functionality in the C++ standard, but they are provided as the existing C++
equivalent may be insufficient (eg, std::string_view), inefficient (eg,
std::string), heavy (eg streams), or plainly unusable on some
platforms/projects, (eg exceptions); some other utilities have equivalent
under consideration for C++ standardisation; and yet some other utilities
have (to my knowledge) no equivalent under consideration. Be that as it may,
I've been using these utilities in this or similar forms for some years now,
and I've found them incredibly useful in my projects. I'm packing these as a
separate library, as all of my projects use it.

c4core is [extensively unit-tested in Linux, Windows and
MacOS](https://github.com/biojppm/c4core/actions). The tests cover
x64, x86, arm, wasm (emscripten), aarch64, ppc64le and s390x
architectures, and include analysing c4core with:
* valgrind
* clang-tidy
* clang sanitizers:
* memory
* address
* undefined behavior
* thread
* [LGTM.com](https://lgtm.com/projects/g/biojppm/c4core)

c4core also works [in
bare-metal](https://github.com/biojppm/c4core/issues/63) as well as
[in RISC-V](https://github.com/biojppm/c4core/pull/69) but at the
moment it's not easy to add automated tests to the CI, so for now
these are not in the list of official architectures.


## Obtaining c4core

c4core uses git submodules. It is best to clone c4core with the `--recursive`
option:

```bash
# using --recursive makes sure git submodules are also cloned at the same time
git clone --recursive https://github.com/biojppm/c4core
```

If you ommit the `--recursive` option, then after cloning you will have to
make git checkout the current version of the submodules, using `git submodule
init` followed by `git submodule update`.


## Using c4core in your project

c4core is built with cmake, and assumes you also use cmake. Although c4core
is NOT header-only, and currently has no install target, you can very easily
use c4core in your project by using
`add_subdirectory(${path_to_c4core_root})` in your CMakeLists.txt; this will
add c4core as a subproject of your project. Doing this is not intrusive to
your cmake project because c4core is fast to build (typically under 10s), and
it also prefixes every cmake variable with `C4CORE_`. But more importantly
this will enable you to compile c4core with the exact same compile settings
used by your project.

Here's a very quick complete example of setting up your project to use
c4core:

```cmake
project(foo)
add_subdirectory(c4core)
add_library(foo foo.cpp)
target_link_libraries(foo PUBLIC c4core) # that's it!
```

Note above that the call to `target_link_libraries()` is using PUBLIC
linking. This is required to make sure the include directories from `c4core`
are transitively used.


## Quick tour

All of the utilities in this library are under the namespace `c4`; any
exposed macros use the prefix `C4_`: eg `C4_ASSERT()`.

### Multi-platform / multi-compiler utilities

```c++
// TODO: elaborate on the topics:
#include <c4/error.hpp>
C4_LIKELY()/C4_UNLIKELY()
C4_RESTRICT, $, c$, $$, c$$
#include <c4/restrict.hpp>
#include <c4/unrestrict.hpp>
#include <c4/windows_push.hpp>
#include <c4/windows_pop.hpp>
C4_UNREACHABLE()
c4::type_name()
```
### Runtime assertions and error handling
```c++
// TODO: elaborate on the topics:
error callback
C4_ASSERT()
C4_XASSERT()
C4_CHECK()
C4_ERROR()
C4_NOT_IMPLEMENTED()
```
### Memory allocation
```c++
// TODO: elaborate on the topics:
c4::aalloc(), c4::afree() // aligned allocation
c4::MemoryResource // global and scope
c4::Allocator
```
### Mass initialization/construction/destruction
```c++
// TODO: elaborate on the topics:
c4::construct()/c4::construct_n()
c4::destroy()/c4::destroy_n()
c4::copy_construct()/c4::copy_construct_n()
c4::copy_assign()/c4::copy_assign_n()
c4::move_construct()/c4::move_construct_n()
c4::move_assign()/c4::move_assign_n()
c4::make_room()/c4::destroy_room()
```
### Writeable string views: c4::substr and c4::csubstr
Here: [`#include <c4/substr.hpp>`](src/c4/substr.hpp)
### Value <-> character interoperation
Here: [`#include <c4/charconv.hpp>`](src/c4/charconv.hpp)
```c++
// TODO: elaborate on the topics:
c4::utoa(), c4::atou()
c4::itoa(), c4::atoi()
c4::ftoa(), c4::atof()
c4::dtoa(), c4::atod()
c4::to_chars(), c4::from_chars()
c4::to_chars_sub()
c4::to_chars_first()
```
### String formatting and parsing
* [`#include <c4/format.hpp>`](src/c4/format.hpp)
```c++
// TODO: elaborate on the topics:
c4::cat(), c4::uncat()
c4::catsep(), c4::uncatsep()
c4::format(), c4::unformat()
// formatting:
c4::raw, c4::craw
```
### `c4::span` and `c4::blob`
* [`#include <c4/span.hpp>`](src/c4/span.hpp)
* [`#include <c4/blob.hpp>`](src/c4/blob.hpp)
### Enums and enum symbols
[`#include <c4/enum.hpp>`](src/c4/enum.hpp)
```c++
// TODO: elaborate on the topics:
c4::e2str(), c4::str2e()
```
### Bitmasks and bitmask symbols
[`#include <c4/bitmask.hpp>`](src/c4/bitmask.hpp)
```c++
// TODO: elaborate on the topics:
c4::bm2str(), c4::str2bm()
```
### Base64 encoding / decoding
[`#include <c4/base64.hpp>`](src/c4/base64.hpp)
### Fuzzy float comparison
@@ -0,0 +1,23 @@
# ROADMAP

## New features

These changes will provide new features, and client code can be kept
unchanged.


## API changes

These changes will require client code to be updated.

* [breaking] drop use of C-style sprintf() formats in error messages and
assertions. Change the implementation to use c4::format()
```c++
C4_ASSERT_MSG(sz > s.size(), "sz=%zu s.size()=%zu", sz, s.size());
// ... the above changes to:
C4_ASSERT_MSG(sz > s.size(), "sz={} s.size()={}", sz, s.size());
```
## Implementation changes
* drop calls to sprintf() in charconv.hpp.
@@ -0,0 +1,3 @@
# 0.1.0

First release.
@@ -0,0 +1,5 @@
# 0.1.1

- Fix parsing of hexadecimal floats ([2d5c3f0](https://github.com/biojppm/c4core/commits/2d5c3f0))
- Fix `csubstr::reverse_sub()` ([902c5b9](https://github.com/biojppm/c4core/commits/902c5b9))
- Fix [#35](https://github.com/biojppm/c4core/issues/35): add SO_VERSION
@@ -0,0 +1,4 @@
- Fix error macros (ie `C4_ERROR()`, `C4_CHECK()`, `C4_ASSERT()`, etc) such that they are a single statement
- `is_debugger_attached()`: add MacOSX version
- Add support for Visual Studio 2022
- Ensure `C4_LITTLE_ENDIAN` is always defined, even with mixed endianness
@@ -0,0 +1 @@
- Update fast_float to [3.2.1](https://github.com/fastfloat/fast_float/releases/tag/v3.2.0)
@@ -0,0 +1,6 @@
- [PR #38](https://github.com/biojppm/c4core/pull/38): add s390x architecture feature macros.
- Fix compiler warnings after update of fast_float to [3.2.1](https://github.com/fastfloat/fast_float/releases/tag/v3.2.0).

### Thanks

@musicinmybrain
@@ -0,0 +1,2 @@
- Add support for aarch64, s390x, ppc64le CPU architectures
- Update debugbreak header (added support for the above architectures)
@@ -0,0 +1,2 @@
- Fix wrong version names in version 0.1.5 (was saying 0.1.4, should be 0.1.5)

@@ -0,0 +1,5 @@
- Fix build with C4CORE_NO_FAST_FLOAT ([#42](https://github.com/biojppm/c4core/pull/42)).
- Fix clang warning in AIX/xlclang ([#44](https://github.com/biojppm/c4core/pull/44)).

### Thanks
--- @mbs-c
@@ -0,0 +1,45 @@

### New features

- Add amalgamation into a single header file ([PR #48](https://github.com/biojppm/c4core/pull/48)):
- The amalgamated header will be available together with the deliverables from each release.
- To generate the amalgamated header:
```
$ python tools/amalgamate.py c4core_all.hpp
```
- To use the amalgamated header:
- Include at will in any header of your project.
- In one - and only one - of your project source files, `#define C4CORE_SINGLE_HDR_DEFINE_NOW` and then `#include <c4core_all.hpp>`. This will enable the function and class definitions in the header file. For example, here's a sample program:
```c++
#include <iostream>
#define C4CORE_SINGLE_HDR_DEFINE_NOW // do this before the include
#include <c4core_all.hpp>
int main()
{
for(c4::csubstr s : c4::csubstr("a/b/c/d").split('/'))
std::cout << s << "\n";
}
```
- Add `csubstr::is_unsigned_integer()` and `csubstr::is_real()` ([PR #49](https://github.com/biojppm/c4core/pull/49)).
- CMake: add alias target c4core::c4core, guaranteeing that the same code can be used with `add_subdirectory()` and `find_package()`. (see [rapidyaml #173](https://github.com/biojppm/rapidyaml/issues/173))
- Add support for compilation with emscripten (WebAssembly+javascript) ([PR #52](https://github.com/biojppm/c4core/pull/52)).


### Fixes

- Fix edge cases with empty strings in `span::first()`, `span::last()` and `span::range()` ([PR #49](https://github.com/biojppm/c4core/pull/49)).
- Accept octal numbers in `substr::first_real_span()` and `substr::is_real()` ([PR #49](https://github.com/biojppm/c4core/pull/49)).
- `substr`: fix coverage misses in number query methods ([PR #49](https://github.com/biojppm/c4core/pull/49)).
- Use single-header version of fast_float ([PR #49](https://github.com/biojppm/c4core/pull/47)).
- Suppress warnings triggered from fast_float in clang (`-Wfortify-source`) ([PR #49](https://github.com/biojppm/c4core/pull/47)).
- Add missing `inline` in [src/c4/ext/rng/rng.hpp](src/c4/ext/rng/rng.hpp) ([PR #49](https://github.com/biojppm/c4core/pull/47)).
- Fix compilation of [src/c4/ext/rng/inplace_function.h](src/c4/ext/inplace_function.h) in C++11 ([PR #49](https://github.com/biojppm/c4core/pull/47)).
- Change order of headers, notably in `windows_push.hpp` ([PR #47](https://github.com/biojppm/c4core/pull/47)).
- In `c4/charconv.hpp`: do not use C4_ASSERT in `to_c_fmt()`, which is `constexpr`.
- Fix [#53](https://github.com/biojppm/c4core/issues/53): cmake install targets were missing call to `export()` ([PR #55](https://github.com/biojppm/c4core/pull/55)).
- Fix linking of subprojects with libc++: flags should be forwarded through `CMAKE_***_FLAGS` instead of being set explicitly per-target ([PR #54](https://github.com/biojppm/c4core/pull/54)).


### Thanks

- @cschreib
@@ -0,0 +1,31 @@
### Breaking changes

- fix [#63](https://github.com/biojppm/c4core/issues/63): remove `c4/time.hpp` and `c4/time.cpp` which prevented compilation in bare-metal mode ([PR #64](https://github.com/biojppm/c4core/issues/64)).

### New features

- Added decoding of UTF codepoints: `c4::decode_code_point()` ([PR #65](https://github.com/biojppm/c4core/issues/65)).
- Experimental feature: add formatted-dumping facilities: using semantics like `c4::cat()`, `c4::catsep()` and `c4::format()`, where the subject is not a string buffer but a dump callback accepting strings. This still requires a string buffer for serialization of non-string types, but the buffer's required size is now limited to the max serialized size of non-string arguments, in contrast to the requirement in `c4::cat()` et al which is the total serialized size of every argument. This enables very efficient and generic printf-like semantics with reuse of a single small buffer, and allows direct-printing to terminal or file ([PR #67](https://github.com/biojppm/c4core/issues/67)). This feature is still experimental and a minor amount of changes to the API is possible.
- Added macro `C4_IF_CONSTEXPR` resolving to `if constexpr (...)` if the c++ standard is at least c++17.
- `csubstr`: add `count(csubstr)` overload.
- Add support for RISC-V architectures ([PR #69](https://github.com/biojppm/c4core/issues/69)).
- Add support for bare-metal compilation ([PR #64](https://github.com/biojppm/c4core/issues/64)).
- gcc >= 4.8 support using polyfills for missing templates and features ([PR #74](https://github.com/biojppm/c4core/pull/74) and [PR #68](https://github.com/biojppm/c4core/pull/68)).

### Fixes

- `csubstr::operator==(std::nullptr_t)` now returns true if either `.str==nullptr` or `.len==0`.
- Fix: `bool operator==(const char (&s)[N], csubstr)` and `operator==(const char (&s)[N], substr)`. The template declaration for these functions had an extra `const` which prevented these functions to participate in overload resolution, which in some cases resulted in calls resolving to `operator==(std::string const&, csubstr)` if that header was visible ([PR #64](https://github.com/biojppm/c4core/issues/64)).
- Fix `csubstr::last_not_of()`: optional positional parameter was ignored [PR #62](https://github.com/biojppm/c4core/pull/62).
- `atof()`, `atod()`, `atox()`, `substr::is_real()`, `substr::first_real_span()`: accept `infinity`, `inf` and `nan` as valid reals [PR #60](https://github.com/biojppm/c4core/pull/60).
- Add missing export symbols [PR #56](https://github.com/biojppm/c4core/pull/56), [PR #57](https://github.com/biojppm/c4core/pull/57).
- `c4/substr_fwd.hpp`: fix compilation failure in Xcode 12 and earlier, where the forward declaration for `std::allocator` is inside the `inline namespace __1`, unlike later versions [PR #61](https://github.com/biojppm/c4core/pull/61), reported in [rapidyaml#185](https://github.com/biojppm/rapidyaml/issues/185).
- `c4/error.hpp`: fix compilation failure in debug mode in Xcode 12 and earlier: `__clang_major__` does not mean the same as in the common clang, and as a result the warning `-Wgnu-inline-cpp-without-extern` does not exist there.


### Thanks

- @danngreen
- @Xeonacid
- @aviktorov
- @fargies
@@ -0,0 +1 @@
__pycache__
@@ -0,0 +1,120 @@


# this function works both with multiconfig and single-config generators.
function(set_default_build_type which)
# CMAKE_CONFIGURATION_TYPES is available only for multiconfig generators.
# so set the build type only if CMAKE_CONFIGURATION_TYPES does not exist.
if(NOT CMAKE_CONFIGURATION_TYPES) # not a multiconfig generator?
if(NOT CMAKE_BUILD_TYPE)
if(NOT which)
set(which RelWithDebInfo)
endif()
message("Defaulting to ${which} build.")
set(CMAKE_BUILD_TYPE ${which} CACHE STRING "")
endif()
endif()
endfunction()


# https://stackoverflow.com/questions/31546278/where-to-set-cmake-configuration-types-in-a-project-with-subprojects
function(setup_configuration_types)
set(options0arg
)
set(options1arg
DEFAULT
)
set(optionsnarg
TYPES
)
cmake_parse_arguments("" "${options0arg}" "${options1arg}" "${optionsnarg}" ${ARGN})

if(NOT TYPES)
set(TYPES Release Debug RelWithDebInfo MinSizeRel)
endif()

# make it safe to call repeatedly
if(NOT _setup_configuration_types_done)
set(_setup_configuration_types_done 1 CACHE INTERNAL "")

# No reason to set CMAKE_CONFIGURATION_TYPES if it's not a multiconfig generator
# Also no reason mess with CMAKE_BUILD_TYPE if it's a multiconfig generator.

if(CMAKE_CONFIGURATION_TYPES) # multiconfig generator?
set(CMAKE_CONFIGURATION_TYPES "${TYPES}" CACHE STRING "")
else() # single-config generator
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY HELPSTRING "Choose the type of build")
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "${TYPES}")
# set the valid options for cmake-gui drop-down list
endif()
endif()
endfunction()


# https://stackoverflow.com/questions/31546278/where-to-set-cmake-configuration-types-in-a-project-with-subprojects
function(add_configuration_type name)
set(flag_vars
C_FLAGS
CXX_FLAGS
SHARED_LINKER_FLAGS
STATIC_LINKER_FLAGS
MODULE_LINKER_FLAGS
EXE_LINKER_FLAGS
RC_FLAGS
)

set(options0arg
PREPEND # when defaulting to a config, prepend to it instead of appending to it
SET_MAIN_FLAGS # eg, set CMAKE_CXX_FLAGS from CMAKE_CXX_FLAGS_${name}
)
set(options1arg
DEFAULT_FROM # take the initial value of the flags from this config
)
set(optionsnarg
C_FLAGS
CXX_FLAGS
SHARED_LINKER_FLAGS
STATIC_LINKER_FLAGS
MODULE_LINKER_FLAGS
EXE_LINKER_FLAGS
RC_FLAGS
)
cmake_parse_arguments(_act "${options0arg}" "${options1arg}" "${optionsnarg}" ${ARGN})

string(TOUPPER ${name} UNAME)

# make it safe to call repeatedly
if(NOT _add_configuration_type_${name})
set(_add_configuration_type_${name} 1 CACHE INTERNAL "")

setup_configuration_types()

if(CMAKE_CONFIGURATION_TYPES) # multiconfig generator?
set(CMAKE_CONFIGURATION_TYPES "${CMAKE_CONFIGURATION_TYPES};${name}" CACHE STRING "" FORCE)
else() # single-config generator
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY HELPSTRING "Choose the type of build" FORCE)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "${CMAKE_BUILD_TYPES};${name}" FORCE)
# set the valid options for cmake-gui drop-down list
endif()

# now set up the configuration
message(STATUS "config: CMAKE_${f}_${UNAME} --- ${val}")
foreach(f ${flag_vars})
set(val ${_act_${f}})
message(STATUS "config: ${name}: ${f} --- ${val}")
if(_act_DEFAULT_FROM)
if(_act_PREPEND)
set(val "${val} ${CMAKE_${f}_${_act_DEFAULT_FROM}}")
else()
set(val "${CMAKE_${f}_${_act_DEFAULT_FROM}} ${val}")
endif()
endif()
message(STATUS "config: CMAKE_${f}_${UNAME} --- ${val}")
set(CMAKE_${f}_${UNAME} "${val}" CACHE STRING "" FORCE)
mark_as_advanced(CMAKE_${f}_${UNAME})
if(_act_SET_MAIN_FLAGS)
set(CMAKE_${f} "${CMAKE_${f}_${UNAME}}" CACHE STRING "" FORCE)
endif()
endforeach()
endif()

endfunction()
@@ -0,0 +1,30 @@
# create hierarchical source groups based on a dir tree
#
# EXAMPLE USAGE:
#
# create_source_group("src" "${SRC_ROOT}" "${SRC_LIST}")
#
# Visual Studio usually has the equivalent to this:
#
# create_source_group("Header Files" ${PROJ_SRC_DIR} "${PROJ_HEADERS}")
# create_source_group("Source Files" ${PROJ_SRC_DIR} "${PROJ_SOURCES}")
#
# TODO: <jpmag> this was taken from a stack overflow answer. Need to find it
# and add a link here.

macro(create_source_group GroupPrefix RootDir ProjectSources)
set(DirSources ${ProjectSources})
foreach(Source ${DirSources})
#message(STATUS "s=${Source}")
string(REGEX REPLACE "${RootDir}" "" RelativePath "${Source}")
#message(STATUS " ${RelativePath}")
string(REGEX REPLACE "[\\\\/][^\\\\/]*$" "" RelativePath "${RelativePath}")
#message(STATUS " ${RelativePath}")
string(REGEX REPLACE "^[\\\\/]" "" RelativePath "${RelativePath}")
#message(STATUS " ${RelativePath}")
string(REGEX REPLACE "/" "\\\\\\\\" RelativePath "${RelativePath}")
#message(STATUS " ${RelativePath}")
source_group("${GroupPrefix}\\${RelativePath}" FILES ${Source})
#message(STATUS " ${Source}")
endforeach(Source)
endmacro(create_source_group)

Large diffs are not rendered by default.

Large diffs are not rendered by default.

@@ -0,0 +1,215 @@
# (C) 2017 Joao Paulo Magalhaes <dev@jpmag.me>

include(CMakeParseArguments)

#------------------------------------------------------------------------------
# Usage:
#
# ExternalProject_GetFwdArgs(output_var
# [NO_DEFAULTS]
# [VARS var1 var2 ...]
# [EXCLUDE xvar1 xvar2 ...]
# [QUIET]
# )
#
# Get the current cmake environment in a sequence of -DVAR=${VAR}
# tokens so that the environment can be forwarded to an external
# cmake project through CMAKE_ARGS.
#
# Example:
# ExternalProject_GetFwdArgs(FWD_ARGS)
# ExternalProject_Add(foo SOURCE_DIR ../foo
# CMAKE_ARGS ${FWD_ARGS}
# ... etc)
#
# Use this function to enable forwarding the current cmake environment
# to an external project. It outputs all the needed variables in the
# form of a sequence of -DVAR=value, suitable for use in the CMAKE_ARGS
# clause of ExternalProject_Add().
#
# This function uses ExternalProject_GetFwdVarNames() to find out the
# list of variables to export. If this behaviour does not fit your
# needs you can:
#
# * append more of your own variables (using the VARS
# argument). The vars specified in this option will each be
# added to the output in the form of -Dvar=${var}
#
# * you can also avoid any defaults obtained through usage of
# ExternalProject_GetFwdNames() by specifying NO_DEFAULTS.
#
# Example with custom variable names (adding more):
# ExternalProject_GetFwdVarNames(FWD_ARGS VARS USER_VAR1 USER_VAR2)
# ExternalProjectAdd(foo SOURCE_DIR ../foo CMAKE_ARGS ${FWD_ARGS})
#
# Example with custom variable names (just your own):
# ExternalProject_GetFwdVarNames(FWD_ARGS NO_DEFAULTS VARS USER_VAR1 USER_VAR2)
# ExternalProjectAdd(foo SOURCE_DIR ../foo CMAKE_ARGS ${FWD_ARGS})
#
function(ExternalProject_GetFwdArgs output_var)
set(options0arg
NO_DEFAULTS
QUIET
)
set(options1arg
)
set(optionsnarg
VARS
EXCLUDE
)
cmake_parse_arguments(_epgfa "${options0arg}" "${options1arg}" "${optionsnarg}" ${ARGN})
if(NOT _epfga_NO_DEFAULTS)
ExternalProject_GetFwdVarNames(_fwd_names)
endif()
if(_epgfa_VARS)
list(APPEND _fwd_names ${_epgfa_VARS})
endif()
if(_epgfa_EXCLUDE)
list(REMOVE_ITEM _fwd_names ${_epgfa_EXCLUDE})
endif()
set(_epgfa_args)
foreach(_f ${_fwd_names})
if(${_f})
list(APPEND _epgfa_args -D${_f}=${${_f}})
if(NOT _epfga_QUIET)
message(STATUS "ExternalProject_GetFwdArgs: ${_f}=${${_f}}")
endif()
endif()
endforeach()
set(${output_var} "${_epgfa_args}" PARENT_SCOPE)
endfunction(ExternalProject_GetFwdArgs)


#------------------------------------------------------------------------------
# Gets a default list with the names of variables to forward to an
# external project. This function creates a list of common cmake
# variable names which have an impact in the output binaries or their
# placement.
function(ExternalProject_GetFwdVarNames output_var)
# these common names are irrespective of build type
set(names
CMAKE_GENERATOR
CMAKE_INSTALL_PREFIX
CMAKE_ARCHIVE_OUTPUT_DIRECTORY
CMAKE_LIBRARY_OUTPUT_DIRECTORY
CMAKE_RUNTIME_OUTPUT_DIRECTORY
CMAKE_AR
CMAKE_BUILD_TYPE
CMAKE_INCLUDE_PATH
CMAKE_LIBRARY_PATH
#CMAKE_MODULE_PATH # this is dangerous as it can override the external project's build files.
CMAKE_PREFIX_PATH
BUILD_SHARED_LIBS
CMAKE_CXX_COMPILER
CMAKE_C_COMPILER
CMAKE_LINKER
CMAKE_MAKE_PROGRAM
CMAKE_NM
CMAKE_OBJCOPY
CMAKE_RANLIB
CMAKE_STRIP
CMAKE_TOOLCHAIN_FILE
#CMAKE_CONFIGURATION_TYPES # not this. external projects will have their own build configurations
)
# these names have per-build type values;
# use CMAKE_CONFIGURATION_TYPES to construct the list
foreach(v
CMAKE_CXX_FLAGS
CMAKE_C_FLAGS
CMAKE_EXE_LINKER_FLAGS
CMAKE_MODULE_LINKER_FLAGS
CMAKE_SHARED_LINKER_FLAGS)
list(APPEND names ${v})
foreach(t ${CMAKE_CONFIGURATION_TYPES})
string(TOUPPER ${t} u)
list(APPEND names ${v}_${u})
endforeach()
endforeach()
set(${output_var} "${names}" PARENT_SCOPE)
endfunction(ExternalProject_GetFwdVarNames)


#------------------------------------------------------------------------------
macro(ExternalProject_Import name)
set(options0arg
)
set(options1arg
PREFIX # look only here when findind
)
set(optionsnarg
INCLUDE_PATHS # use these dirs for searching includes
LIBRARY_PATHS # use these dirs for searching libraries
INCLUDES # find these includes and append them to ${name}_INCLUDE_DIRS
INCLUDE_DIR_SUFFIXES
LIBRARIES # find these libs and append them to ${name}_LIBRARIES
LIBRARY_DIR_SUFFIXES
)
cmake_parse_arguments(_eep "${options0arg}" "${options1arg}" "${optionsnarg}" ${ARGN})

if(NOT _eep_PREFIX)
message(FATAL_ERROR "no prefix was given")
endif()

include(FindPackageHandleStandardArgs)

#----------------------------------------------------------------
# includes

# the list of paths to search for includes
set(_eep_ipaths ${_eep_PREFIX})
foreach(_eep_i ${_eep_INCLUDE_DIRS})
list(APPEND _eep_ipaths ${__eep_PREFIX}/${_eep_i})
endforeach()

# find the includes that were asked for, and add
# their paths to the includes list
set(_eep_idirs)
foreach(_eep_i ${_eep_INCLUDES})
find_path(_eep_path_${_eep_i} ${_eep_i}
PATHS ${_eep_ipaths}
PATH_SUFFIXES include ${_eep_INCLUDE_DIR_SUFFIXES}
NO_DEFAULT_PATH
)
if(NOT _eep_path_${_eep_i})
message(FATAL_ERROR "could not find include: ${_eep_i}")
endif()
#message(STATUS "include: ${_eep_i} ---> ${_eep_path_${_eep_i}}")
list(APPEND _eep_idirs ${_eep_path_${_eep_i}})
find_package_handle_standard_args(${_eep_i}_INCLUDE_DIR DEFAULT_MSG _eep_path_${_eep_i})
endforeach()
if(_eep_idirs)
list(REMOVE_DUPLICATES _eep_idirs)
endif()

# save the include list
set(${name}_INCLUDE_DIRS "${_eep_idirs}" CACHE STRING "" FORCE)

#----------------------------------------------------------------
# libraries

# the list of paths to search for libraries
set(_eep_lpaths ${_eep_PREFIX})
foreach(_eep_i ${_eep_LIBRARIES})
list(APPEND _eep_lpaths ${__eep_PREFIX}/${_eep_i})
endforeach()

# find any libraries that were asked for
set(_eep_libs)
foreach(_eep_i ${_eep_LIBRARIES})
find_library(_eep_lib_${_eep_i} ${_eep_i}
PATHS ${_eep_lpaths}
PATH_SUFFIXES lib ${_eep_LIBRARY_DIR_SUFFIXES}
NO_DEFAULT_PATH
)
if(NOT _eep_lib_${_eep_i})
message(FATAL_ERROR "could not find library: ${_eep_i}")
endif()
#message(STATUS "lib: ${_eep_i} ---> ${_eep_lib_${_eep_i}}")
list(APPEND _eep_libs ${_eep_lib_${_eep_i}})
find_package_handle_standard_args(${_eep_i}_LIBRARY DEFAULT_MSG _eep_lib_${_eep_i})
endforeach()

# save the include list
set(${name}_LIBRARIES ${_eep_libs} CACHE STRING "")

endmacro(ExternalProject_Import)
@@ -0,0 +1,75 @@
# Find the win10 SDK path.
if ("$ENV{WIN10_SDK_PATH}$ENV{WIN10_SDK_VERSION}" STREQUAL "" )
get_filename_component(WIN10_SDK_PATH "[HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\Microsoft\\Microsoft SDKs\\Windows\\v10.0;InstallationFolder]" ABSOLUTE CACHE)
get_filename_component(TEMP_WIN10_SDK_VERSION "[HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\Microsoft\\Microsoft SDKs\\Windows\\v10.0;ProductVersion]" ABSOLUTE CACHE)
get_filename_component(WIN10_SDK_VERSION ${TEMP_WIN10_SDK_VERSION} NAME)
elseif(TRUE)
set (WIN10_SDK_PATH $ENV{WIN10_SDK_PATH})
set (WIN10_SDK_VERSION $ENV{WIN10_SDK_VERSION})
endif ("$ENV{WIN10_SDK_PATH}$ENV{WIN10_SDK_VERSION}" STREQUAL "" )

# WIN10_SDK_PATH will be something like C:\Program Files (x86)\Windows Kits\10
# WIN10_SDK_VERSION will be something like 10.0.14393 or 10.0.14393.0; we need the
# one that matches the directory name.

if (IS_DIRECTORY "${WIN10_SDK_PATH}/Include/${WIN10_SDK_VERSION}.0")
set(WIN10_SDK_VERSION "${WIN10_SDK_VERSION}.0")
endif (IS_DIRECTORY "${WIN10_SDK_PATH}/Include/${WIN10_SDK_VERSION}.0")


# Find the d3d12 and dxgi include path, it will typically look something like this.
# C:\Program Files (x86)\Windows Kits\10\Include\10.0.10586.0\um\d3d12.h
# C:\Program Files (x86)\Windows Kits\10\Include\10.0.10586.0\shared\dxgi1_4.h
find_path(D3D12_INCLUDE_DIR # Set variable D3D12_INCLUDE_DIR
d3d12.h # Find a path with d3d12.h
HINTS "${WIN10_SDK_PATH}/Include/${WIN10_SDK_VERSION}/um"
DOC "path to WIN10 SDK header files"
HINTS
)

find_path(DXGI_INCLUDE_DIR # Set variable DXGI_INCLUDE_DIR
dxgi1_4.h # Find a path with dxgi1_4.h
HINTS "${WIN10_SDK_PATH}/Include/${WIN10_SDK_VERSION}/shared"
DOC "path to WIN10 SDK header files"
HINTS
)

if ("${DXC_BUILD_ARCH}" STREQUAL "x64" )
find_library(D3D12_LIBRARY NAMES d3d12.lib
HINTS ${WIN10_SDK_PATH}/Lib/${WIN10_SDK_VERSION}/um/x64 )
elseif (CMAKE_GENERATOR MATCHES "Visual Studio.*ARM" OR "${DXC_BUILD_ARCH}" STREQUAL "ARM")
find_library(D3D12_LIBRARY NAMES d3d12.lib
HINTS ${WIN10_SDK_PATH}/Lib/${WIN10_SDK_VERSION}/um/arm )
elseif (CMAKE_GENERATOR MATCHES "Visual Studio.*ARM64" OR "${DXC_BUILD_ARCH}" STREQUAL "ARM64")
find_library(D3D12_LIBRARY NAMES d3d12.lib
HINTS ${WIN10_SDK_PATH}/Lib/${WIN10_SDK_VERSION}/um/arm64 )
elseif ("${DXC_BUILD_ARCH}" STREQUAL "Win32" )
find_library(D3D12_LIBRARY NAMES d3d12.lib
HINTS ${WIN10_SDK_PATH}/Lib/${WIN10_SDK_VERSION}/um/x86 )
endif ("${DXC_BUILD_ARCH}" STREQUAL "x64" )

if ("${DXC_BUILD_ARCH}" STREQUAL "x64" )
find_library(DXGI_LIBRARY NAMES dxgi.lib
HINTS ${WIN10_SDK_PATH}/Lib/${WIN10_SDK_VERSION}/um/x64 )
elseif (CMAKE_GENERATOR MATCHES "Visual Studio.*ARM" OR "${DXC_BUILD_ARCH}" STREQUAL "ARM")
find_library(DXGI_LIBRARY NAMES dxgi.lib
HINTS ${WIN10_SDK_PATH}/Lib/${WIN10_SDK_VERSION}/um/arm )
elseif (CMAKE_GENERATOR MATCHES "Visual Studio.*ARM64" OR "${DXC_BUILD_ARCH}" STREQUAL "ARM64")
find_library(DXGI_LIBRARY NAMES dxgi.lib
HINTS ${WIN10_SDK_PATH}/Lib/${WIN10_SDK_VERSION}/um/arm64 )
elseif ("${DXC_BUILD_ARCH}" STREQUAL "Win32" )
find_library(DXGI_LIBRARY NAMES dxgi.lib
HINTS ${WIN10_SDK_PATH}/Lib/${WIN10_SDK_VERSION}/um/x86 )
endif ("${DXC_BUILD_ARCH}" STREQUAL "x64" )

set(D3D12_LIBRARIES ${D3D12_LIBRARY} ${DXGI_LIBRARY})
set(D3D12_INCLUDE_DIRS ${D3D12_INCLUDE_DIR} ${DXGI_INCLUDE_DIR})


include(FindPackageHandleStandardArgs)
# handle the QUIETLY and REQUIRED arguments and set D3D12_FOUND to TRUE
# if all listed variables are TRUE
find_package_handle_standard_args(D3D12 DEFAULT_MSG
D3D12_INCLUDE_DIRS D3D12_LIBRARIES)

mark_as_advanced(D3D12_INCLUDE_DIRS D3D12_LIBRARIES)
@@ -0,0 +1,76 @@
# Attempt to find the D3D12 libraries
# Defines:
#
# DX12_FOUND - system has DX12
# DX12_INCLUDE_PATH - path to the DX12 headers
# DX12_LIBRARIES - path to the DX12 libraries
# DX12_LIB - d3d12.lib

set(DX12_FOUND "NO")

if(WIN32)
set(WIN10_SDK_DIR "C:/Program Files (x86)/Windows Kits/10")
#set(WIN10_SDK_VERSION "10.0.10069.0")
file(GLOB WIN10_SDK_VERSIONS
LIST_DIRECTORIES TRUE
RELATIVE "${WIN10_SDK_DIR}/Lib"
"${WIN10_SDK_DIR}/Lib/*")
list(SORT WIN10_SDK_VERSIONS)
list(GET WIN10_SDK_VERSIONS -1 WIN10_SDK_VERSION)

if(CMAKE_CL_64)
set(w10ARCH x64)
elseif(CMAKE_GENERATOR MATCHES "Visual Studio.*ARM" OR "${DXC_BUILD_ARCH}" STREQUAL "ARM")
set(w10ARCH arm)
elseif(CMAKE_GENERATOR MATCHES "Visual Studio.*ARM64" OR "${DXC_BUILD_ARCH}" STREQUAL "ARM64")
set(w10ARCH arm64)
else()
set(w10ARCH x86)
endif()

# Look for the windows 8 sdk
find_path(DX12_INC_DIR
NAMES d3d12.h
PATHS "${WIN10_SDK_DIR}/Include/${WIN10_SDK_VERSION}/um"
DOC "Path to the d3d12.h file"
)
find_path(DXGI_INC_DIR
NAMES dxgi1_4.h
PATHS "${WIN10_SDK_DIR}/Include/${WIN10_SDK_VERSION}/shared"
DOC "Path to the dxgi header file"
)

if(DX12_INC_DIR AND DXGI_INC_DIR)
find_library(DX12_LIB
NAMES d3d12
PATHS "${WIN10_SDK_DIR}/Lib/${WIN10_SDK_VERSION}/um/${w10ARCH}"
NO_DEFAULT_PATH
DOC "Path to the d3d12.lib file"
)
find_library(DXGI_LIB
NAMES dxgi
PATHS "${WIN10_SDK_DIR}/Lib/${WIN10_SDK_VERSION}/um/${w10ARCH}"
NO_DEFAULT_PATH
DOC "Path to the dxgi.lib file"
)
if(DX12_LIB AND DXGI_LIB)
set(DX12_FOUND "YES")
set(DX12_LIBRARIES ${DX12_LIB} ${DXGI_LIB})
mark_as_advanced(DX12_INC_DIR DX12_LIB)
mark_as_advanced(DXGI_INC_DIR DXGI_LIB)
endif()
endif()
endif(WIN32)

if(DX12_FOUND)
if(NOT DX12_FIND_QUIETLY)
message(STATUS "DX12 headers found at ${DX12_INC_DIR}")
endif()
else()
if(DX12_FIND_REQUIRED)
message(FATAL_ERROR "Could NOT find Direct3D12")
endif()
if(NOT DX12_FIND_QUIETLY)
message(STATUS "Could NOT find Direct3D12")
endif()
endif()
@@ -0,0 +1,53 @@

function(_c4_intersperse_with_flag outvar flag)
if(MSVC AND "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") # it may be clang as well
set(f "/${flag}")
else()
set(f "-${flag}")
endif()
set(out)
foreach(i ${ARGN})
if(NOT "${i}" STREQUAL "")
set(out "${out} ${f} '${i}'")

# ... Following this are several unsuccessful attempts to make
# sure that an empty generator expression passed as part of the
# arguments won't be expanded to nothing between successive
# flags. For example, -I /some/include -I -I /other/include,
# which is wrong as it misses an empty quote. This causes
# clang-tidy in particular to fail. Maybe this is happening
# because the result is passed to separate_arguments() which
# prevents the lists from being evaluated correctly. Also, note
# that add_custom_target() has the following options which may
# help: COMMAND_EXPAND_LISTS and VERBATIM.

# Anyway -- for now it is working, but maybe the generator
# expression approach turns out to work while being much cleaner
# than the current approach.

#set(c $<GENEX_EVAL,$<BOOL:${i}>>)
#set(c $<BOOL:${i}>) # i may be a generator expression the evaluates to empty
#set(s "${f} ${i}")
#set(e "${f} aaaaaaWTF")
#list(APPEND out $<IF:${c},${s},${e}>)
#list(APPEND out $<${c},${s}>)
#list(APPEND out $<GENEX_EVAL:${c},${s}>)
#list(APPEND out $<TARGET_GENEX_EVAL:${tgt},${c},${s}>)
endif()
endforeach()
## https://cmake.org/cmake/help/latest/manual/cmake-generator-expressions.7.html#string-valued-generator-expressions
#if(ARGN)
# set(out "${f}$<JOIN:${ARGN},;${f}>")
#endif()
set(${outvar} ${out} PARENT_SCOPE)
endfunction()

function(c4_get_define_flags outvar)
_c4_intersperse_with_flag(out D ${ARGN})
set(${outvar} ${out} PARENT_SCOPE)
endfunction()

function(c4_get_include_flags outvar)
_c4_intersperse_with_flag(out I ${ARGN})
set(${outvar} ${out} PARENT_SCOPE)
endfunction()
@@ -0,0 +1,51 @@
function(get_lib_names lib_names base)
set(${lib_names})
foreach(__glnname ${ARGN})
if(WIN32)
set(__glnn ${__glnname}.lib)
else()
set(__glnn lib${__glnname}.a)
endif()
list(APPEND ${lib_names} "${base}${__glnn}")
endforeach()
set(lib_names ${lib_names} PARENT_SCOPE)
endfunction()

function(get_dll_names dll_names base)
set(${dll_names})
foreach(__glnname ${ARGN})
if(WIN32)
set(__glnn ${__glnname}.dll)
else()
set(__glnn lib${__glnname}.so)
endif()
list(APPEND ${dll_names} "${base}${__glnn}")
endforeach()
set(dll_names ${dll_names} PARENT_SCOPE)
endfunction()

function(get_script_names script_names base)
set(${script_names})
foreach(__glnname ${ARGN})
if(WIN32)
set(__glnn ${__glnname}.bat)
else()
set(__glnn ${__glnname}.sh)
endif()
list(APPEND ${script_names} "${base}${__glnn}")
endforeach()
set(script_names ${script_names} PARENT_SCOPE)
endfunction()

function(get_exe_names exe_names base)
set(${exe_names})
foreach(__glnname ${ARGN})
if(WIN32)
set(__glnn ${__glnname}.exe)
else()
set(__glnn ${__glnname})
endif()
list(APPEND ${exe_names} "${base}${__glnn}")
endforeach()
set(exe_names ${exe_names} PARENT_SCOPE)
endfunction()
@@ -0,0 +1,20 @@
Copyright (c) 2018, Joao Paulo Magalhaes <dev@jpmag.me>

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

@@ -0,0 +1,275 @@
# 2006-2008 (c) Viva64.com Team
# 2008-2016 (c) OOO "Program Verification Systems"
#
# Version 2

function (pvs_studio_relative_path VAR ROOT FILEPATH)
set("${VAR}" "${FILEPATH}" PARENT_SCOPE)
if ("${FILEPATH}" MATCHES "^/.*$")
file(RELATIVE_PATH RPATH "${ROOT}" "${FILEPATH}")
if (NOT "${RPATH}" MATCHES "^\\.\\..*$")
set("${VAR}" "${RPATH}" PARENT_SCOPE)
endif ()
endif ()
endfunction ()

function (pvs_studio_join_path VAR DIR1 DIR2)
if ("${DIR2}" MATCHES "^(/|~).*$" OR "${DIR1}" STREQUAL "")
set("${VAR}" "${DIR2}" PARENT_SCOPE)
else ()
set("${VAR}" "${DIR1}/${DIR2}" PARENT_SCOPE)
endif ()
endfunction ()

macro (pvs_studio_append_flags_from_property CXX C DIR PREFIX)
if (NOT "${PROPERTY}" STREQUAL "NOTFOUND" AND NOT "${PROPERTY}" STREQUAL "PROPERTY-NOTFOUND")
foreach (PROP ${PROPERTY})
pvs_studio_join_path(PROP "${DIR}" "${PROP}")
list(APPEND "${CXX}" "${PREFIX}${PROP}")
list(APPEND "${C}" "${PREFIX}${PROP}")
endforeach ()
endif ()
endmacro ()

macro (pvs_studio_append_standard_flag FLAGS STANDARD)
if ("${STANDARD}" MATCHES "^(99|11|14|17)$")
if ("${PVS_STUDIO_PREPROCESSOR}" MATCHES "gcc|clang")
list(APPEND "${FLAGS}" "-std=c++${STANDARD}")
endif ()
endif ()
endmacro ()

function (pvs_studio_set_directory_flags DIRECTORY CXX C)
set(CXX_FLAGS "${${CXX}}")
set(C_FLAGS "${${C}}")

get_directory_property(PROPERTY DIRECTORY "${DIRECTORY}" INCLUDE_DIRECTORIES)
pvs_studio_append_flags_from_property(CXX_FLAGS C_FLAGS "${DIRECTORY}" "-I")

get_directory_property(PROPERTY DIRECTORY "${DIRECTORY}" COMPILE_DEFINITIONS)
pvs_studio_append_flags_from_property(CXX_FLAGS C_FLAGS "" "-D")

set("${CXX}" "${CXX_FLAGS}" PARENT_SCOPE)
set("${C}" "${C_FLAGS}" PARENT_SCOPE)
endfunction ()

function (pvs_studio_set_target_flags TARGET CXX C)
set(CXX_FLAGS "${${CXX}}")
set(C_FLAGS "${${C}}")

get_target_property(PROPERTY "${TARGET}" INCLUDE_DIRECTORIES)
pvs_studio_append_flags_from_property(CXX_FLAGS C_FLAGS "${DIRECTORY}" "-I")

get_target_property(PROPERTY "${TARGET}" COMPILE_DEFINITIONS)
pvs_studio_append_flags_from_property(CXX_FLAGS C_FLAGS "" "-D")

get_target_property(PROPERTY "${TARGET}" CXX_STANDARD)
pvs_studio_append_standard_flag(CXX_FLAGS "${PROPERTY}")

set("${CXX}" "${CXX_FLAGS}" PARENT_SCOPE)
set("${C}" "${C_FLAGS}" PARENT_SCOPE)
endfunction ()

function (pvs_studio_set_source_file_flags SOURCE)
set(LANGUAGE "")

string(TOLOWER "${SOURCE}" SOURCE_LOWER)
if ("${LANGUAGE}" STREQUAL "" AND "${SOURCE_LOWER}" MATCHES "^.*\\.(c|cpp|cc|cx|cxx|cp|c\\+\\+)$")
if ("${SOURCE}" MATCHES "^.*\\.c$")
set(LANGUAGE C)
else ()
set(LANGUAGE CXX)
endif ()
endif ()

if ("${LANGUAGE}" STREQUAL "C")
set(CL_PARAMS ${PVS_STUDIO_C_FLAGS} ${PVS_STUDIO_TARGET_C_FLAGS} -DPVS_STUDIO)
elseif ("${LANGUAGE}" STREQUAL "CXX")
set(CL_PARAMS ${PVS_STUDIO_CXX_FLAGS} ${PVS_STUDIO_TARGET_CXX_FLAGS} -DPVS_STUDIO)
endif ()

set(PVS_STUDIO_LANGUAGE "${LANGUAGE}" PARENT_SCOPE)
set(PVS_STUDIO_CL_PARAMS "${CL_PARAMS}" PARENT_SCOPE)
endfunction ()

function (pvs_studio_analyze_file SOURCE SOURCE_DIR BINARY_DIR)
set(PLOGS ${PVS_STUDIO_PLOGS})
pvs_studio_set_source_file_flags("${SOURCE}")

get_filename_component(SOURCE "${SOURCE}" REALPATH)
pvs_studio_relative_path(SOURCE_RELATIVE "${SOURCE_DIR}" "${SOURCE}")
pvs_studio_join_path(SOURCE "${SOURCE_DIR}" "${SOURCE}")

set(LOG "${BINARY_DIR}/PVS-Studio/${SOURCE_RELATIVE}.plog")
get_filename_component(LOG "${LOG}" REALPATH)
get_filename_component(PARENT_DIR "${LOG}" DIRECTORY)

if (EXISTS "${SOURCE}" AND NOT TARGET "${LOG}" AND NOT "${PVS_STUDIO_LANGUAGE}" STREQUAL "")
add_custom_command(OUTPUT "${LOG}"
COMMAND mkdir -p "${PARENT_DIR}"
COMMAND rm -f "${LOG}"
COMMAND "${PVS_STUDIO_BIN}" analyze
--output-file "${LOG}"
--source-file "${SOURCE}"
${PVS_STUDIO_ARGS}
--cl-params ${PVS_STUDIO_CL_PARAMS} "${SOURCE}"
WORKING_DIRECTORY "${BINARY_DIR}"
DEPENDS "${SOURCE}" "${PVS_STUDIO_CONFIG}"
VERBATIM
COMMENT "Analyzing ${PVS_STUDIO_LANGUAGE} file ${SOURCE_RELATIVE}")
list(APPEND PLOGS "${LOG}")
endif ()
set(PVS_STUDIO_PLOGS "${PLOGS}" PARENT_SCOPE)
endfunction ()

function (pvs_studio_analyze_target TARGET DIR)
set(PVS_STUDIO_PLOGS "${PVS_STUDIO_PLOGS}")
set(PVS_STUDIO_TARGET_CXX_FLAGS "")
set(PVS_STUDIO_TARGET_C_FLAGS "")

get_target_property(PROPERTY "${TARGET}" SOURCES)
pvs_studio_relative_path(BINARY_DIR "${CMAKE_SOURCE_DIR}" "${DIR}")
if ("${BINARY_DIR}" MATCHES "^/.*$")
pvs_studio_join_path(BINARY_DIR "${CMAKE_BINARY_DIR}" "PVS-Studio/__${BINARY_DIR}")
else ()
pvs_studio_join_path(BINARY_DIR "${CMAKE_BINARY_DIR}" "${BINARY_DIR}")
endif ()

file(MAKE_DIRECTORY "${BINARY_DIR}")

pvs_studio_set_directory_flags("${DIR}" PVS_STUDIO_TARGET_CXX_FLAGS PVS_STUDIO_TARGET_C_FLAGS)
pvs_studio_set_target_flags("${TARGET}" PVS_STUDIO_TARGET_CXX_FLAGS PVS_STUDIO_TARGET_C_FLAGS)

if (NOT "${PROPERTY}" STREQUAL "NOTFOUND" AND NOT "${PROPERTY}" STREQUAL "PROPERTY-NOTFOUND")
foreach (SOURCE ${PROPERTY})
pvs_studio_join_path(SOURCE "${DIR}" "${SOURCE}")
pvs_studio_analyze_file("${SOURCE}" "${DIR}" "${BINARY_DIR}")
endforeach ()
endif ()

set(PVS_STUDIO_PLOGS "${PVS_STUDIO_PLOGS}" PARENT_SCOPE)
endfunction ()

function (pvs_studio_add_target)
macro (default VAR VALUE)
if ("${${VAR}}" STREQUAL "")
set("${VAR}" "${VALUE}")
endif ()
endmacro ()

set(PVS_STUDIO_SUPPORTED_PREPROCESSORS "gcc|clang")
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
set(DEFAULT_PREPROCESSOR "clang")
else ()
set(DEFAULT_PREPROCESSOR "gcc")
endif ()

set(OPTIONAL OUTPUT ALL)
set(SINGLE LICENSE CONFIG TARGET LOG FORMAT BIN CONVERTER PLATFORM PREPROCESSOR CFG_TEXT)
set(MULTI SOURCES C_FLAGS CXX_FLAGS ARGS DEPENDS ANALYZE)
cmake_parse_arguments(PVS_STUDIO "${OPTIONAL}" "${SINGLE}" "${MULTI}" ${ARGN})

if ("${PVS_STUDIO_CFG}" STREQUAL "" OR NOT "${PVS_STUDIO_CFG_TEXT}" STREQUAL "")
set(PVS_STUDIO_EMPTY_CONFIG ON)
else ()
set(PVS_STUDIO_EMPTY_CONFIG OFF)
endif ()

default(PVS_STUDIO_CFG_TEXT "analysis-mode=4")
default(PVS_STUDIO_CONFIG "${CMAKE_BINARY_DIR}/PVS-Studio.cfg")
default(PVS_STUDIO_C_FLAGS "")
default(PVS_STUDIO_CXX_FLAGS "")
default(PVS_STUDIO_TARGET "pvs")
default(PVS_STUDIO_LOG "PVS-Studio.log")
default(PVS_STUDIO_BIN "pvs-studio-analyzer")
default(PVS_STUDIO_CONVERTER "plog-converter")
default(PVS_STUDIO_PREPROCESSOR "${DEFAULT_PREPROCESSOR}")
default(PVS_STUDIO_PLATFORM "linux64")

if (PVS_STUDIO_EMPTY_CONFIG)
set(PVS_STUDIO_CONFIG_COMMAND echo "${PVS_STUDIO_CFG_TEXT}" > "${PVS_STUDIO_CONFIG}")
else ()
set(PVS_STUDIO_CONFIG_COMMAND touch "${PVS_STUDIO_CONFIG}")
endif ()

add_custom_command(OUTPUT "${PVS_STUDIO_CONFIG}"
COMMAND ${PVS_STUDIO_CONFIG_COMMAND}
WORKING_DIRECTORY "${BINARY_DIR}"
COMMENT "Generating PVS-Studio.cfg")


if (NOT "${PVS_STUDIO_PREPROCESSOR}" MATCHES "^${PVS_STUDIO_SUPPORTED_PREPROCESSORS}$")
message(FATAL_ERROR "Preprocessor ${PVS_STUDIO_PREPROCESSOR} isn't supported. Available options: ${PVS_STUDIO_SUPPORTED_PREPROCESSORS}.")
endif ()

pvs_studio_append_standard_flag(PVS_STUDIO_CXX_FLAGS "${CMAKE_CXX_STANDARD}")
pvs_studio_set_directory_flags("${CMAKE_CURRENT_SOURCE_DIR}" PVS_STUDIO_CXX_FLAGS PVS_STUDIO_C_FLAGS)

if (NOT "${PVS_STUDIO_LICENSE}" STREQUAL "")
pvs_studio_join_path(PVS_STUDIO_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}" "${PVS_STUDIO_LICENSE}")
list(APPEND PVS_STUDIO_ARGS --lic-file "${PVS_STUDIO_LICENSE}")
endif ()
list(APPEND PVS_STUDIO_ARGS --cfg "${PVS_STUDIO_CONFIG}"
--platform "${PVS_STUDIO_PLATFORM}"
--preprocessor "${PVS_STUDIO_PREPROCESSOR}")

set(PVS_STUDIO_PLOGS "")

foreach (TARGET ${PVS_STUDIO_ANALYZE})
set(DIR "${CMAKE_CURRENT_SOURCE_DIR}")
string(FIND "${TARGET}" ":" DELIM)
if ("${DELIM}" GREATER "-1")
math(EXPR DELIMI "${DELIM}+1")
string(SUBSTRING "${TARGET}" "${DELIMI}" "-1" DIR)
string(SUBSTRING "${TARGET}" "0" "${DELIM}" TARGET)
pvs_studio_join_path(DIR "${CMAKE_CURRENT_SOURCE_DIR}" "${DIR}")
endif ()
pvs_studio_analyze_target("${TARGET}" "${DIR}")
list(APPEND PVS_STUDIO_DEPENDS "${TARGET}")
endforeach ()

set(PVS_STUDIO_TARGET_CXX_FLAGS "")
set(PVS_STUDIO_TARGET_C_FLAGS "")
foreach (SOURCE ${PVS_STUDIO_SOURCES})
pvs_studio_analyze_file("${SOURCE}" "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_BINARY_DIR}")
endforeach ()

pvs_studio_relative_path(LOG_RELATIVE "${CMAKE_BINARY_DIR}" "${PVS_STUDIO_LOG}")
if (PVS_STUDIO_PLOGS)
set(COMMANDS COMMAND cat ${PVS_STUDIO_PLOGS} > "${PVS_STUDIO_LOG}")
set(COMMENT "Generating ${LOG_RELATIVE}")
if (NOT "${PVS_STUDIO_FORMAT}" STREQUAL "" OR PVS_STUDIO_OUTPUT)
if ("${PVS_STUDIO_FORMAT}" STREQUAL "")
set(PVS_STUDIO_FORMAT "errorfile")
endif ()
list(APPEND COMMANDS
COMMAND mv "${PVS_STUDIO_LOG}" "${PVS_STUDIO_LOG}.pvs.raw"
COMMAND "${PVS_STUDIO_CONVERTER}" -t "${PVS_STUDIO_FORMAT}" "${PVS_STUDIO_LOG}.pvs.raw" -o "${PVS_STUDIO_LOG}"
COMMAND rm -f "${PVS_STUDIO_LOG}.pvs.raw")
endif ()
else ()
set(COMMANDS COMMAND touch "${PVS_STUDIO_LOG}")
set(COMMENT "Generating ${LOG_RELATIVE}: no sources found")
endif ()

add_custom_command(OUTPUT "${PVS_STUDIO_LOG}"
${COMMANDS}
COMMENT "${COMMENT}"
DEPENDS ${PVS_STUDIO_PLOGS}
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}")

if (PVS_STUDIO_ALL)
set(ALL "ALL")
else ()
set(ALL "")
endif ()

if (PVS_STUDIO_OUTPUT)
set(COMMANDS COMMAND cat "${PVS_STUDIO_LOG}" 1>&2)
else ()
set(COMMANDS "")
endif ()

add_custom_target("${PVS_STUDIO_TARGET}" ${ALL} ${COMMANDS} WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" DEPENDS ${PVS_STUDIO_DEPENDS} "${PVS_STUDIO_LOG}")
endfunction ()

@@ -0,0 +1,25 @@
# create a script that applies a patch (it's different in windows)

# to generate a patch:
# subversion: svn diff --patch-compatible > path/to/the/patch.diff


function(apply_patch patch where mark)
if(NOT EXISTS "${mark}")
if(NOT Patch_EXECUTABLE)
find_package(Patch REQUIRED)
endif()
file(TO_NATIVE_PATH ${patch} patch_native)
get_filename_component(patch_name "${patch}" NAME)
message(STATUS "Applying patch: ${patch_name}")
execute_process(
COMMAND "${Patch_EXECUTABLE}" "-p0" "--input=${patch_native}"
WORKING_DIRECTORY "${where}"
RESULT_VARIABLE status)
if(NOT status STREQUAL "0")
message(FATAL_ERROR "could not apply patch: ${patch} ---> ${where}")
else()
file(TOUCH "${mark}")
endif()
endif()
endfunction()
@@ -0,0 +1,27 @@
function(status)
message(STATUS "${ARGV}")
endfunction()

function(print_var var)
message(STATUS "${var}=${${var}} ${ARGN}")
endfunction()

function(print_vars)
foreach(a ${ARGN})
message(STATUS "${a}=${${a}}")
endforeach(a)
endfunction()

function(debug_var debug var)
if(${debug})
message(STATUS "${var}=${${var}} ${ARGN}")
endif()
endfunction()

function(debug_vars debug)
if(${debug})
foreach(a ${ARGN})
message(STATUS "${a}=${${a}}")
endforeach(a)
endif()
endfunction()
@@ -0,0 +1,25 @@
# cmake project utilities

Useful cmake scripts, at [c4Project.cmake](c4Project.cmake).

## Project utilities

## Adding targets

### Target types

## Downloading and configuring third-party projects at configure time

## Setting up tests

### Coverage
### Static analysis
### Valgrind

## Setting up benchmarks

## License

MIT License


@@ -0,0 +1,176 @@


function(c4_get_architecture_defines output_var)
c4_get_target_cpu_architecture(arch)
if("${arch}" STREQUAL "x86_64")
set(defines __x86_64__)
elseif("${arch}" STREQUAL "i386")
set(defines __i386__)
elseif("${arch}" STREQUAL "armv8_64")
set(defines __arm__ __aarch64__)
elseif("${arch}" STREQUAL "armv8")
set(defines __arm__ __ARM_ARCH_8__)
elseif("${arch}" STREQUAL "armv7")
set(defines __arm__ __ARM_ARCH_7__)
elseif("${arch}" STREQUAL "armv6")
set(defines __arm__ __ARM_ARCH_6__)
elseif("${arch}" STREQUAL "armv5")
set(defines __arm__ __ARM_ARCH_5__)
elseif("${arch}" STREQUAL "armv4")
set(defines __arm__ __ARM_ARCH_4T__)
elseif("${arch}" STREQUAL "ia64")
set(defines __ia64__)
elseif("${arch}" STREQUAL "ppc64")
set(defines __ppc64__)
elseif("${arch}" STREQUAL "ia64")
set(defines __ia64__)
elseif("${arch}" STREQUAL "riscv64")
set(defines __riscv64__)
elseif("${arch}" STREQUAL "riscv32")
set(defines __riscv32__)
else()
message(FATAL_ERROR "unknown target architecture: ${arch}")
endif()
set(${output_var} ${defines} PARENT_SCOPE)
endfunction()


# adapted from https://github.com/axr/solar-cmake/blob/master/TargetArch.cmake
# Set ppc_support to TRUE before including this file or ppc and ppc64
# will be treated as invalid architectures since they are no longer supported by Apple
function(c4_get_target_cpu_architecture output_var)
# this should be more or less in line with c4core/cpu.hpp
set(archdetect_c_code "
#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(_M_X64)
#error cmake_ARCH x86_64
#elif defined(__i386) || defined(__i386__) || defined(_M_IX86)
#error cmake_ARCH i386
#elif defined(__arm__) || defined(_M_ARM) \
|| defined(__TARGET_ARCH_ARM) || defined(__aarch64__) || defined(_M_ARM64)
#if defined(__aarch64__) || defined(_M_ARM64)
#error cmake_ARCH armv8_64
#else
#if defined(__ARM_ARCH_8__) || (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM >= 8)
#error cmake_ARCH armv8
#elif defined(__ARM_ARCH_7__) || defined(_ARM_ARCH_7) \
|| defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) \
|| defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) \
|| (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM >= 7) \
|| (defined(_M_ARM) && _M_ARM >= 7)
#error cmake_ARCH armv7
#elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
|| defined(__ARM_ARCH_6T2__) || defined(__ARM_ARCH_6Z__) \
|| defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6ZK__) \
|| defined(__ARM_ARCH_6M__) \
|| (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM >= 6)
#error cmake_ARCH armv6
#elif defined(__ARM_ARCH_5TEJ__) \
|| (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM >= 5)
#error cmake_ARCH armv5
#elif defined(__ARM_ARCH_4T__) \
|| (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM >= 4)
#error cmake_ARCH armv4
#else
#error cmake_ARCH arm
#endif
#endif
#elif defined(__ia64) || defined(__ia64__) || defined(_M_IA64)
#error cmake_ARCH ia64
#elif defined(__ppc__) || defined(__ppc) || defined(__powerpc__) \
|| defined(_ARCH_COM) || defined(_ARCH_PWR) || defined(_ARCH_PPC) \
|| defined(_M_MPPC) || defined(_M_PPC)
#if defined(__ppc64__) || defined(__powerpc64__) || defined(__64BIT__)
#error cmake_ARCH ppc64
#else
#error cmake_ARCH ppc32
#endif
#elif defined(__riscv)
#if __riscv_xlen == 64
#error cmake_ARCH riscv64
#else
#error cmake_ARCH riscv32
#endif
#endif
#error cmake_ARCH unknown
")
if(APPLE AND CMAKE_OSX_ARCHITECTURES)
# On OS X we use CMAKE_OSX_ARCHITECTURES *if* it was set
# First let's normalize the order of the values

# Note that it's not possible to compile PowerPC applications if you are using
# the OS X SDK version 10.6 or later - you'll need 10.4/10.5 for that, so we
# disable it by default
# See this page for more information:
# http://stackoverflow.com/questions/5333490/how-can-we-restore-ppc-ppc64-as-well-as-full-10-4-10-5-sdk-support-to-xcode-4

# Architecture defaults to i386 or ppc on OS X 10.5 and earlier, depending on the CPU type detected at runtime.
# On OS X 10.6+ the default is x86_64 if the CPU supports it, i386 otherwise.

foreach(osx_arch ${CMAKE_OSX_ARCHITECTURES})
if("${osx_arch}" STREQUAL "ppc" AND ppc_support)
set(osx_arch_ppc TRUE)
elseif("${osx_arch}" STREQUAL "i386")
set(osx_arch_i386 TRUE)
elseif("${osx_arch}" STREQUAL "x86_64")
set(osx_arch_x86_64 TRUE)
elseif("${osx_arch}" STREQUAL "ppc64" AND ppc_support)
set(osx_arch_ppc64 TRUE)
else()
message(FATAL_ERROR "Invalid OS X arch name: ${osx_arch}")
endif()
endforeach()

# Now add all the architectures in our normalized order
if(osx_arch_ppc)
list(APPEND ARCH ppc)
endif()

if(osx_arch_i386)
list(APPEND ARCH i386)
endif()

if(osx_arch_x86_64)
list(APPEND ARCH x86_64)
endif()

if(osx_arch_ppc64)
list(APPEND ARCH ppc64)
endif()
else()
file(WRITE "${CMAKE_BINARY_DIR}/detect_cpu_arch.c" "${archdetect_c_code}")

enable_language(C)

# Detect the architecture in a rather creative way...
# This compiles a small C program which is a series of ifdefs that selects a
# particular #error preprocessor directive whose message string contains the
# target architecture. The program will always fail to compile (both because
# file is not a valid C program, and obviously because of the presence of the
# #error preprocessor directives... but by exploiting the preprocessor in this
# way, we can detect the correct target architecture even when cross-compiling,
# since the program itself never needs to be run (only the compiler/preprocessor)
try_run(
run_result_unused
compile_result_unused
"${CMAKE_BINARY_DIR}"
"${CMAKE_BINARY_DIR}/detect_cpu_arch.c"
COMPILE_OUTPUT_VARIABLE ARCH
CMAKE_FLAGS CMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES}
)

# Parse the architecture name from the compiler output
string(REGEX MATCH "cmake_ARCH ([a-zA-Z0-9_]+)" ARCH "${ARCH}")

# Get rid of the value marker leaving just the architecture name
string(REPLACE "cmake_ARCH " "" ARCH "${ARCH}")

# If we are compiling with an unknown architecture this variable should
# already be set to "unknown" but in the case that it's empty (i.e. due
# to a typo in the code), then set it to unknown
if (NOT ARCH)
set(ARCH unknown)
endif()
endif()

set(${output_var} "${ARCH}" PARENT_SCOPE)
endfunction()
@@ -0,0 +1,29 @@
SET(CMAKE_SYSTEM_NAME Linux)
SET(CMAKE_SYSTEM_PROCESSOR arm)
SET(CMAKE_SYSTEM_VERSION 1)
set(CMAKE_CROSSCOMPILING TRUE)

find_program(CC_GCC arm-linux-gnueabihf-gcc REQUIRED)

set(CMAKE_FIND_ROOT_PATH /usr/arm-gnueabihf)

# Cross compiler
SET(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
SET(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
set(CMAKE_LIBRARY_ARCHITECTURE arm-linux-gnueabihf)

# Search for programs in the build host directories
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)

# Libraries and headers in the target directories
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

set(THREADS_PTHREAD_ARG "0" CACHE STRING "Result from TRY_RUN" FORCE)

get_filename_component(TOOLCHAIN_DIR "${CC_GCC}" DIRECTORY)
get_filename_component(TOOLCHAIN_DIR "${TOOLCHAIN_DIR}" DIRECTORY)
set(TOOLCHAIN_SO_DIR "${TOOLCHAIN_DIR}/arm-linux-gnueabihf/")
#/home/jpmag/local/arm/gcc-arm-9.2-2019.12-x86_64-arm-none-linux-gnueabihf
set(CMAKE_CROSSCOMPILING_EMULATOR qemu-arm -L ${TOOLCHAIN_SO_DIR})