qcdx 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- qcdx/__init__.py +5 -0
- qcdx/__main__.py +5 -0
- qcdx/_commit.py +1 -0
- qcdx/cli.py +105 -0
- qcdx/data/kit/.github/actions/pk-setup/action.yml +157 -0
- qcdx/data/kit/cmake/QCDXConfig.cmake +17 -0
- qcdx/data/kit/cmake/QCDXConfigVersion.cmake +46 -0
- qcdx/data/kit/cmake/projectkit/ApplicationCreator.cmake +262 -0
- qcdx/data/kit/cmake/projectkit/CompilerWarnings.cmake +54 -0
- qcdx/data/kit/cmake/projectkit/ConanBuildDir.cmake +84 -0
- qcdx/data/kit/cmake/projectkit/Dependencies.cmake +601 -0
- qcdx/data/kit/cmake/projectkit/FileCollection.cmake +115 -0
- qcdx/data/kit/cmake/projectkit/HostTools.cmake +74 -0
- qcdx/data/kit/cmake/projectkit/LibraryCreator.cmake +561 -0
- qcdx/data/kit/cmake/projectkit/Packaging.cmake +291 -0
- qcdx/data/kit/cmake/projectkit/ProjectKit.cmake +21 -0
- qcdx/data/kit/cmake/projectkit/ProjectOptions.cmake +250 -0
- qcdx/data/kit/cmake/projectkit/ProjectSetup.cmake +218 -0
- qcdx/data/kit/cmake/projectkit/StaticAnalysis.cmake +159 -0
- qcdx/data/kit/cmake/projectkit/TestCreator.cmake +146 -0
- qcdx/data/kit/cmake/projectkit/ToolCreator.cmake +139 -0
- qcdx/data/kit/cmake/projectkit/Tooling.cmake +150 -0
- qcdx/data/kit/cmake/projectkit/VERSION +1 -0
- qcdx/data/kit/cmake/projectkit/docs/ANALYSER_LAUNCHER.md +154 -0
- qcdx/data/kit/cmake/projectkit/docs/PACKAGE.md +257 -0
- qcdx/data/kit/cmake/projectkit/docs/PK.md +254 -0
- qcdx/data/kit/cmake/projectkit/docs/PK_DEP.md +430 -0
- qcdx/data/kit/cmake/projectkit/docs/RELEASE.md +194 -0
- qcdx/data/kit/cmake/projectkit/docs/VERIFY.md +312 -0
- qcdx/data/kit/cmake/projectkit/scripts/analyser_launcher.py +65 -0
- qcdx/data/kit/cmake/projectkit/scripts/helpers/pk/deps.py +1534 -0
- qcdx/data/kit/cmake/projectkit/scripts/helpers/pk/presets.cmake +142 -0
- qcdx/data/kit/cmake/projectkit/scripts/pklib/__init__.py +0 -0
- qcdx/data/kit/cmake/projectkit/scripts/pklib/bootstrap.py +289 -0
- qcdx/data/kit/cmake/projectkit/scripts/pklib/common.py +472 -0
- qcdx/data/kit/cmake/projectkit/scripts/pklib/package.py +268 -0
- qcdx/data/kit/cmake/projectkit/scripts/pklib/pk.py +1750 -0
- qcdx/data/kit/cmake/projectkit/scripts/pklib/release.py +928 -0
- qcdx/data/kit/cmake/projectkit/scripts/pklib/targets.py +117 -0
- qcdx/data/kit/cmake/projectkit/scripts/pklib/verify.py +209 -0
- qcdx/data/kit/cmake/projectkit/scripts/pklib/verify_base.py +428 -0
- qcdx/data/kit/cmake/projectkit/templates/PackageConfig.cmake.in +7 -0
- qcdx/data/kit/cmake/projectkit/templates/pkgconfig.pc.in +11 -0
- qcdx/data/kit/cmake/projectkit/test_package/CMakeLists.txt +24 -0
- qcdx/data/kit/cmake/projectkit/test_package/conanfile.py +42 -0
- qcdx/data/kit/cmake/projectkit/test_package/src/example.cpp +1 -0
- qcdx/data/kit/scripts/bootstrap.py +10 -0
- qcdx/data/kit/scripts/package.py +10 -0
- qcdx/data/kit/scripts/pk.py +10 -0
- qcdx/data/kit/scripts/release.py +10 -0
- qcdx/data/kit/scripts/verify.py +10 -0
- qcdx/data/template/.clang-format +27 -0
- qcdx/data/template/.clang-tidy +26 -0
- qcdx/data/template/.clangd +6 -0
- qcdx/data/template/.gitattributes +1 -0
- qcdx/data/template/.github/workflows/release.yml +241 -0
- qcdx/data/template/.github/workflows/verify.yml +74 -0
- qcdx/data/template/.gitignore +168 -0
- qcdx/data/template/CMakeLists.txt +53 -0
- qcdx/data/template/CMakePresets.json +593 -0
- qcdx/data/template/README.md +56 -0
- qcdx/data/template/apps/CMakeLists.txt +4 -0
- qcdx/data/template/apps/qcdx/main.cpp +8 -0
- qcdx/data/template/cmake/qcdxConfig.cmake.in +38 -0
- qcdx/data/template/cmake/toolchains/aarch64-linux-gnu.cmake +40 -0
- qcdx/data/template/cmake/toolchains/aarch64-mingw-llvm-w64.cmake +28 -0
- qcdx/data/template/cmake/toolchains/x86_64-linux-gnu.cmake +20 -0
- qcdx/data/template/cmake/toolchains/x86_64-mingw-w64.cmake +20 -0
- qcdx/data/template/conan.lock +11 -0
- qcdx/data/template/conanfile.py +142 -0
- qcdx/data/template/deps.json +25 -0
- qcdx/data/template/include/qcdx/core.hpp +9 -0
- qcdx/data/template/profiles/aarch64-linux-gnu +43 -0
- qcdx/data/template/profiles/aarch64-mingw-llvm-w64 +42 -0
- qcdx/data/template/profiles/ci-linux-armv8 +19 -0
- qcdx/data/template/profiles/ci-linux-x86_64 +19 -0
- qcdx/data/template/profiles/ci-macos-armv8 +17 -0
- qcdx/data/template/profiles/ci-macos-x86_64 +17 -0
- qcdx/data/template/profiles/ci-windows-clang64 +12 -0
- qcdx/data/template/profiles/ci-windows-clangarm64 +12 -0
- qcdx/data/template/profiles/ci-windows-ucrt64 +12 -0
- qcdx/data/template/profiles/native +32 -0
- qcdx/data/template/profiles/x86_64-linux-gnu +43 -0
- qcdx/data/template/profiles/x86_64-mingw-w64 +44 -0
- qcdx/data/template/scripts/helpers/package/package.conf +3 -0
- qcdx/data/template/scripts/helpers/release/release.conf +99 -0
- qcdx/data/template/scripts/helpers/verify/consumer.cpp +7 -0
- qcdx/data/template/scripts/helpers/verify/verify.conf +1 -0
- qcdx/data/template/src/CMakeLists.txt +5 -0
- qcdx/data/template/src/qcdx/core.cpp +13 -0
- qcdx/data/template/tests/CMakeLists.txt +4 -0
- qcdx/data/template/tests/qcdx/tests_core.cpp +10 -0
- qcdx/data/template/tools/CMakeLists.txt +4 -0
- qcdx/data/template/tools/codegen.cpp +137 -0
- qcdx/new.py +224 -0
- qcdx/resources.py +131 -0
- qcdx-0.1.0.dist-info/METADATA +298 -0
- qcdx-0.1.0.dist-info/RECORD +101 -0
- qcdx-0.1.0.dist-info/WHEEL +4 -0
- qcdx-0.1.0.dist-info/entry_points.txt +3 -0
- qcdx-0.1.0.dist-info/licenses/LICENSE +21 -0
qcdx/__init__.py
ADDED
qcdx/__main__.py
ADDED
qcdx/_commit.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
COMMIT = "5b7e37c25528c05ec84e1be4a7c21d4c9a6168e1"
|
qcdx/cli.py
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"""The global 'pk' command.
|
|
2
|
+
|
|
3
|
+
Outside a project it creates one ('pk new'). Inside a project every command
|
|
4
|
+
runs that project's own scripts/pk.py, so the kit version the project
|
|
5
|
+
vendored decides what 'pk build' does, never the installed QCDX version.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import os
|
|
11
|
+
import subprocess
|
|
12
|
+
import sys
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
from typing import List, Optional
|
|
15
|
+
|
|
16
|
+
from . import new, resources
|
|
17
|
+
|
|
18
|
+
HELP = """\
|
|
19
|
+
pk - QCDX {version}: create and build C and C++ projects with CMake and Conan
|
|
20
|
+
|
|
21
|
+
usage:
|
|
22
|
+
pk new NAME [DIR] [flag...] create a project ('pk new --help')
|
|
23
|
+
pk cmake-dir print the QCDX CMake package directory, for
|
|
24
|
+
-DQCDX_DIR=... or CMAKE_PREFIX_PATH
|
|
25
|
+
pk --version QCDX version, and the kit version of this project
|
|
26
|
+
|
|
27
|
+
Inside a project every other command (build, run, test, sync, ...) runs the
|
|
28
|
+
project's own scripts/pk.py; 'pk help' there lists them all.{where}"""
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def find_project(start: Path) -> Optional[Path]:
|
|
32
|
+
for directory in (start, *start.parents):
|
|
33
|
+
if (directory / "scripts" / "pk.py").is_file() and (directory / "CMakePresets.json").is_file():
|
|
34
|
+
return directory
|
|
35
|
+
return None
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def project_kit_version(project: Path) -> str:
|
|
39
|
+
try:
|
|
40
|
+
return (project / "cmake" / "projectkit" / "VERSION").read_text(encoding="utf-8").strip()
|
|
41
|
+
except OSError:
|
|
42
|
+
return "unknown (older than 0.1.0)"
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def tool_path(env: dict) -> None:
|
|
46
|
+
"""Append this Python's scripts folder to PATH, as a fallback.
|
|
47
|
+
|
|
48
|
+
pipx and uv keep a package's dependencies in a private environment, so
|
|
49
|
+
the conan, cmake and ninja of "qcdx[tools]" are only reachable this way.
|
|
50
|
+
Appended, not prepended: tools the user installed always win.
|
|
51
|
+
"""
|
|
52
|
+
folder = os.path.dirname(os.path.abspath(sys.executable))
|
|
53
|
+
found = [name for name in ("conan", "cmake", "ninja")
|
|
54
|
+
if any(os.path.isfile(os.path.join(folder, name + ext)) for ext in ("", ".exe"))]
|
|
55
|
+
paths = env.get("PATH", "").split(os.pathsep)
|
|
56
|
+
if found and folder not in paths:
|
|
57
|
+
env["PATH"] = os.pathsep.join([*paths, folder])
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def delegate(project: Path, argv: List[str]) -> int:
|
|
61
|
+
env = dict(os.environ, PK_SELF_NAME="pk")
|
|
62
|
+
tool_path(env)
|
|
63
|
+
script = str(project / "scripts" / "pk.py")
|
|
64
|
+
try:
|
|
65
|
+
return subprocess.call([sys.executable, script, *argv], env=env)
|
|
66
|
+
except KeyboardInterrupt:
|
|
67
|
+
return 130
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def main(argv: Optional[List[str]] = None) -> int:
|
|
71
|
+
try:
|
|
72
|
+
return run(list(sys.argv[1:] if argv is None else argv))
|
|
73
|
+
except BrokenPipeError: # 'pk ... | head'
|
|
74
|
+
os.dup2(os.open(os.devnull, os.O_WRONLY), sys.stdout.fileno())
|
|
75
|
+
return 141
|
|
76
|
+
except KeyboardInterrupt:
|
|
77
|
+
return 130
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def run(argv: List[str]) -> int:
|
|
81
|
+
project = find_project(Path.cwd())
|
|
82
|
+
command = argv[0] if argv else ""
|
|
83
|
+
|
|
84
|
+
if command == "new":
|
|
85
|
+
return new.main(argv[1:])
|
|
86
|
+
if command in ("--version", "-V", "version"):
|
|
87
|
+
print(f"QCDX {resources.version()}")
|
|
88
|
+
if project is not None:
|
|
89
|
+
print(f"kit {project_kit_version(project)} in {project}")
|
|
90
|
+
return 0
|
|
91
|
+
if command == "cmake-dir":
|
|
92
|
+
print(resources.cmake_dir())
|
|
93
|
+
return 0
|
|
94
|
+
if project is not None:
|
|
95
|
+
return delegate(project, argv)
|
|
96
|
+
if command in ("", "help", "-h", "--help"):
|
|
97
|
+
print(HELP.format(version=resources.version(), where="\n\n(no project here)"))
|
|
98
|
+
return 0
|
|
99
|
+
sys.stderr.write(f"pk: '{command}' needs a project, and there is none in {Path.cwd()} or above.\n"
|
|
100
|
+
" 'pk new NAME' creates one.\n")
|
|
101
|
+
return 2
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
if __name__ == "__main__":
|
|
105
|
+
sys.exit(main())
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
name: pk-setup
|
|
2
|
+
description: >-
|
|
3
|
+
Toolchain, Conan and the Conan cache for a verify/release target. Used by
|
|
4
|
+
verify.yml and release.yml to only have to set up target once in one place.
|
|
5
|
+
|
|
6
|
+
inputs:
|
|
7
|
+
target:
|
|
8
|
+
description: A target name from cmake/projectkit/scripts/pklib/targets.py.
|
|
9
|
+
required: true
|
|
10
|
+
msystem:
|
|
11
|
+
description: MSYS2 environment (UCRT64, CLANG64, CLANGARM64), Windows only.
|
|
12
|
+
default: ''
|
|
13
|
+
cache:
|
|
14
|
+
description: "'save' restores & saves Conan cache, 'restore' doesn't save."
|
|
15
|
+
default: save
|
|
16
|
+
conan-version:
|
|
17
|
+
default: '2.33.0'
|
|
18
|
+
llvm-mingw-tag:
|
|
19
|
+
default: '20260616'
|
|
20
|
+
llvm-mingw-asset:
|
|
21
|
+
# Linux x86_64 UCRT build of the pinned release.
|
|
22
|
+
default: llvm-mingw-20260616-ucrt-ubuntu-22.04-x86_64.tar.xz
|
|
23
|
+
llvm-mingw-sha256:
|
|
24
|
+
default: 534b92e067b22a6b4441f48ae9240a3341b17825d04d577eab0cf85c44b4deda
|
|
25
|
+
|
|
26
|
+
runs:
|
|
27
|
+
using: composite
|
|
28
|
+
steps:
|
|
29
|
+
# -------------------------------------------------------------------------
|
|
30
|
+
# Linux and macOS
|
|
31
|
+
# -------------------------------------------------------------------------
|
|
32
|
+
|
|
33
|
+
- if: runner.os != 'Windows'
|
|
34
|
+
uses: lukka/get-cmake@fffaaafeea488556c2c12dad60690008bc1caacb # v4.4.2
|
|
35
|
+
|
|
36
|
+
- if: runner.os != 'Windows'
|
|
37
|
+
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
38
|
+
with:
|
|
39
|
+
python-version: '3.12'
|
|
40
|
+
|
|
41
|
+
- name: Install Conan
|
|
42
|
+
if: runner.os != 'Windows'
|
|
43
|
+
shell: bash
|
|
44
|
+
run: python -m pip install --disable-pip-version-check "conan==${{ inputs.conan-version }}"
|
|
45
|
+
|
|
46
|
+
# Conan only accepts compiler.cstd=23 from GCC 14. apt should only run when
|
|
47
|
+
# something is missing.
|
|
48
|
+
- name: Install Linux packages
|
|
49
|
+
if: runner.os == 'Linux'
|
|
50
|
+
shell: bash
|
|
51
|
+
env:
|
|
52
|
+
TARGET: ${{ inputs.target }}
|
|
53
|
+
run: |
|
|
54
|
+
packages=()
|
|
55
|
+
command -v g++-14 >/dev/null || packages+=(g++-14)
|
|
56
|
+
case "$TARGET" in
|
|
57
|
+
cross-x86_64-mingw-w64) packages+=(g++-mingw-w64-x86-64) ;;
|
|
58
|
+
cross-aarch64-linux-gnu) command -v aarch64-linux-gnu-gcc >/dev/null || packages+=(g++-aarch64-linux-gnu) ;;
|
|
59
|
+
cross-x86_64-linux-gnu) command -v x86_64-linux-gnu-gcc >/dev/null || packages+=(g++-x86-64-linux-gnu) ;;
|
|
60
|
+
esac
|
|
61
|
+
if [ ${#packages[@]} -gt 0 ]; then
|
|
62
|
+
sudo apt-get update -qq
|
|
63
|
+
sudo apt-get install -y -qq --no-install-recommends "${packages[@]}"
|
|
64
|
+
fi
|
|
65
|
+
if [ "$TARGET" = cross-x86_64-mingw-w64 ]; then
|
|
66
|
+
sudo update-alternatives --set x86_64-w64-mingw32-gcc /usr/bin/x86_64-w64-mingw32-gcc-posix
|
|
67
|
+
sudo update-alternatives --set x86_64-w64-mingw32-g++ /usr/bin/x86_64-w64-mingw32-g++-posix
|
|
68
|
+
fi
|
|
69
|
+
echo "CC=gcc-14" >> "$GITHUB_ENV"
|
|
70
|
+
echo "CXX=g++-14" >> "$GITHUB_ENV"
|
|
71
|
+
|
|
72
|
+
- name: Install llvm-mingw
|
|
73
|
+
if: inputs.target == 'cross-aarch64-mingw-llvm-w64'
|
|
74
|
+
shell: bash
|
|
75
|
+
env:
|
|
76
|
+
TAG: ${{ inputs.llvm-mingw-tag }}
|
|
77
|
+
ASSET: ${{ inputs.llvm-mingw-asset }}
|
|
78
|
+
SHA256: ${{ inputs.llvm-mingw-sha256 }}
|
|
79
|
+
run: |
|
|
80
|
+
archive="$RUNNER_TEMP/$ASSET"
|
|
81
|
+
curl -fsSL -o "$archive" "https://github.com/mstorsjo/llvm-mingw/releases/download/${TAG}/${ASSET}"
|
|
82
|
+
echo "${SHA256} ${archive}" | sha256sum -c -
|
|
83
|
+
mkdir -p "$RUNNER_TEMP/llvm-mingw"
|
|
84
|
+
tar -xJf "$archive" -C "$RUNNER_TEMP/llvm-mingw" --strip-components=1
|
|
85
|
+
rm -f "$archive"
|
|
86
|
+
echo "$RUNNER_TEMP/llvm-mingw/bin" >> "$GITHUB_PATH"
|
|
87
|
+
|
|
88
|
+
- name: Point Conan at the runner temp directory
|
|
89
|
+
if: runner.os != 'Windows'
|
|
90
|
+
shell: bash
|
|
91
|
+
run: echo "CONAN_HOME=$RUNNER_TEMP/conan2" >> "$GITHUB_ENV"
|
|
92
|
+
|
|
93
|
+
# -------------------------------------------------------------------------
|
|
94
|
+
# Windows (MSYS2)
|
|
95
|
+
# -------------------------------------------------------------------------
|
|
96
|
+
|
|
97
|
+
- if: runner.os == 'Windows'
|
|
98
|
+
uses: msys2/setup-msys2@66cd2cce69caa17b53920067426061ca1de3a884 # v2.32.0
|
|
99
|
+
with:
|
|
100
|
+
msystem: ${{ inputs.msystem }}
|
|
101
|
+
update: true
|
|
102
|
+
install: git
|
|
103
|
+
pacboy: >-
|
|
104
|
+
toolchain:p
|
|
105
|
+
cmake:p
|
|
106
|
+
ninja:p
|
|
107
|
+
python-pip:p
|
|
108
|
+
pkgconf:p
|
|
109
|
+
|
|
110
|
+
# Visual Studio is installed on the runner used, Conan prefers
|
|
111
|
+
# MSVC on Windows, CC/CXX override it.
|
|
112
|
+
- name: Select the MSYS2 compiler
|
|
113
|
+
if: runner.os == 'Windows'
|
|
114
|
+
shell: pwsh
|
|
115
|
+
env:
|
|
116
|
+
MSYSTEM_NAME: ${{ inputs.msystem }}
|
|
117
|
+
run: |
|
|
118
|
+
if ($env:MSYSTEM_NAME -like 'CLANG*') { $cc = 'clang'; $cxx = 'clang++' } else { $cc = 'gcc'; $cxx = 'g++' }
|
|
119
|
+
"CC=$cc" >> $env:GITHUB_ENV
|
|
120
|
+
"CXX=$cxx" >> $env:GITHUB_ENV
|
|
121
|
+
"CONAN_HOME=$env:RUNNER_TEMP\conan2" >> $env:GITHUB_ENV
|
|
122
|
+
|
|
123
|
+
- name: Install Conan
|
|
124
|
+
if: runner.os == 'Windows'
|
|
125
|
+
shell: msys2 {0}
|
|
126
|
+
run: python -m pip install --disable-pip-version-check --break-system-packages "conan==${{ inputs.conan-version }}"
|
|
127
|
+
|
|
128
|
+
# -------------------------------------------------------------------------
|
|
129
|
+
# Conan cache
|
|
130
|
+
# -------------------------------------------------------------------------
|
|
131
|
+
|
|
132
|
+
# The key is shared with verify.yml, and caches saved on main can be read
|
|
133
|
+
# from every branch and tag: release runs will reuse verify's packages,
|
|
134
|
+
# NEVER storing a wasteful second copy.
|
|
135
|
+
- if: inputs.cache == 'save'
|
|
136
|
+
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
|
137
|
+
with:
|
|
138
|
+
path: ${{ runner.temp }}/conan2/p
|
|
139
|
+
key: conan-${{ inputs.target }}-${{ hashFiles('conanfile.py', 'deps.json', 'conan.lock', 'profiles/**') }}
|
|
140
|
+
restore-keys: conan-${{ inputs.target }}-
|
|
141
|
+
|
|
142
|
+
- if: inputs.cache == 'restore'
|
|
143
|
+
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
|
144
|
+
with:
|
|
145
|
+
path: ${{ runner.temp }}/conan2/p
|
|
146
|
+
key: conan-${{ inputs.target }}-${{ hashFiles('conanfile.py', 'deps.json', 'conan.lock', 'profiles/**') }}
|
|
147
|
+
restore-keys: conan-${{ inputs.target }}-
|
|
148
|
+
|
|
149
|
+
- name: Detect the default Conan profile
|
|
150
|
+
if: runner.os != 'Windows'
|
|
151
|
+
shell: bash
|
|
152
|
+
run: conan profile detect --force
|
|
153
|
+
|
|
154
|
+
- name: Detect the default Conan profile
|
|
155
|
+
if: runner.os == 'Windows'
|
|
156
|
+
shell: msys2 {0}
|
|
157
|
+
run: conan profile detect --force
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# find_package(QCDX) puts ProjectKit on the module path:
|
|
2
|
+
#
|
|
3
|
+
# find_package(QCDX 0.1 REQUIRED)
|
|
4
|
+
# include(ProjectKit)
|
|
5
|
+
#
|
|
6
|
+
# The same file works installed (share/qcdx/cmake), inside the Python package
|
|
7
|
+
# ('pk cmake-dir') and in a source tree or FetchContent download (cmake/), since
|
|
8
|
+
# everything is found relative to this file.
|
|
9
|
+
|
|
10
|
+
get_filename_component(QCDX_MODULE_DIR "${CMAKE_CURRENT_LIST_DIR}/projectkit" ABSOLUTE)
|
|
11
|
+
file(STRINGS "${QCDX_MODULE_DIR}/VERSION" QCDX_VERSION LIMIT_COUNT 1)
|
|
12
|
+
|
|
13
|
+
if(NOT QCDX_MODULE_DIR IN_LIST CMAKE_MODULE_PATH)
|
|
14
|
+
list(APPEND CMAKE_MODULE_PATH "${QCDX_MODULE_DIR}")
|
|
15
|
+
endif()
|
|
16
|
+
|
|
17
|
+
set(QCDX_FOUND TRUE)
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Version check for find_package(QCDX ...). Before 1.0 a minor release may
|
|
2
|
+
# break things, so 0.1 matches 0.1.x only; from 1.0 the major version decides.
|
|
3
|
+
# Version ranges (find_package(QCDX 0.1...<0.3)) are checked against the bounds.
|
|
4
|
+
|
|
5
|
+
file(STRINGS "${CMAKE_CURRENT_LIST_DIR}/projectkit/VERSION" PACKAGE_VERSION LIMIT_COUNT 1)
|
|
6
|
+
|
|
7
|
+
set(PACKAGE_VERSION_COMPATIBLE FALSE)
|
|
8
|
+
set(PACKAGE_VERSION_EXACT FALSE)
|
|
9
|
+
|
|
10
|
+
if(PACKAGE_FIND_VERSION_RANGE)
|
|
11
|
+
set(_qcdx_ok TRUE)
|
|
12
|
+
if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION_MIN)
|
|
13
|
+
set(_qcdx_ok FALSE)
|
|
14
|
+
endif()
|
|
15
|
+
if(PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "INCLUDE")
|
|
16
|
+
if(PACKAGE_VERSION VERSION_GREATER PACKAGE_FIND_VERSION_MAX)
|
|
17
|
+
set(_qcdx_ok FALSE)
|
|
18
|
+
endif()
|
|
19
|
+
elseif(PACKAGE_VERSION VERSION_GREATER_EQUAL PACKAGE_FIND_VERSION_MAX)
|
|
20
|
+
set(_qcdx_ok FALSE)
|
|
21
|
+
endif()
|
|
22
|
+
set(PACKAGE_VERSION_COMPATIBLE ${_qcdx_ok})
|
|
23
|
+
unset(_qcdx_ok)
|
|
24
|
+
elseif(NOT PACKAGE_FIND_VERSION)
|
|
25
|
+
set(PACKAGE_VERSION_COMPATIBLE TRUE)
|
|
26
|
+
elseif(PACKAGE_VERSION VERSION_GREATER_EQUAL PACKAGE_FIND_VERSION)
|
|
27
|
+
string(REGEX MATCH "^[0-9]+" _qcdx_major "${PACKAGE_VERSION}")
|
|
28
|
+
string(REGEX MATCH "^[0-9]+\\.[0-9]+" _qcdx_minor "${PACKAGE_VERSION}")
|
|
29
|
+
if(_qcdx_major STREQUAL "0")
|
|
30
|
+
set(_qcdx_have "${_qcdx_minor}")
|
|
31
|
+
set(_qcdx_want "${PACKAGE_FIND_VERSION_MAJOR}.${PACKAGE_FIND_VERSION_MINOR}")
|
|
32
|
+
else()
|
|
33
|
+
set(_qcdx_have "${_qcdx_major}")
|
|
34
|
+
set(_qcdx_want "${PACKAGE_FIND_VERSION_MAJOR}")
|
|
35
|
+
endif()
|
|
36
|
+
if(_qcdx_have STREQUAL _qcdx_want)
|
|
37
|
+
set(PACKAGE_VERSION_COMPATIBLE TRUE)
|
|
38
|
+
endif()
|
|
39
|
+
if(PACKAGE_VERSION VERSION_EQUAL PACKAGE_FIND_VERSION)
|
|
40
|
+
set(PACKAGE_VERSION_EXACT TRUE)
|
|
41
|
+
endif()
|
|
42
|
+
unset(_qcdx_major)
|
|
43
|
+
unset(_qcdx_minor)
|
|
44
|
+
unset(_qcdx_have)
|
|
45
|
+
unset(_qcdx_want)
|
|
46
|
+
endif()
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
include_guard(GLOBAL)
|
|
2
|
+
|
|
3
|
+
function(pk_create_app)
|
|
4
|
+
set(options
|
|
5
|
+
DEFAULT_DIRS
|
|
6
|
+
REQUIRE_SOURCES
|
|
7
|
+
REQUIRE_PUBLIC_HEADERS
|
|
8
|
+
REQUIRE_PRIVATE_HEADERS
|
|
9
|
+
NO_DEFAULT_LINKS
|
|
10
|
+
NO_INSTALL)
|
|
11
|
+
|
|
12
|
+
set(one_value_args
|
|
13
|
+
NAME
|
|
14
|
+
LANGUAGE
|
|
15
|
+
SOURCE_DIR
|
|
16
|
+
INCLUDE_DIR)
|
|
17
|
+
|
|
18
|
+
set(multi_value_args
|
|
19
|
+
TARGET_NAME
|
|
20
|
+
OUTPUT_NAME
|
|
21
|
+
SOURCES
|
|
22
|
+
PUBLIC_HEADERS
|
|
23
|
+
PRIVATE_HEADERS
|
|
24
|
+
LINK_PRIVATE
|
|
25
|
+
LINK_INTERFACE
|
|
26
|
+
DEPS)
|
|
27
|
+
|
|
28
|
+
cmake_parse_arguments(ARG
|
|
29
|
+
"${options}" "${one_value_args}" "${multi_value_args}" ${ARGN})
|
|
30
|
+
|
|
31
|
+
pk_project_prefix(prefix)
|
|
32
|
+
|
|
33
|
+
if(NOT ARG_NAME)
|
|
34
|
+
message(FATAL_ERROR "pk_create_app requires a 'NAME' argument.")
|
|
35
|
+
endif()
|
|
36
|
+
if(ARG_UNPARSED_ARGUMENTS)
|
|
37
|
+
message(FATAL_ERROR
|
|
38
|
+
"pk_create_app (func): unrecognized arguments for '${ARG_NAME}': "
|
|
39
|
+
"${ARG_UNPARSED_ARGUMENTS}")
|
|
40
|
+
endif()
|
|
41
|
+
|
|
42
|
+
if(NOT ARG_TARGET_NAME)
|
|
43
|
+
set(ARG_TARGET_NAME "${ARG_NAME}_app")
|
|
44
|
+
endif()
|
|
45
|
+
list(LENGTH ARG_TARGET_NAME target_count)
|
|
46
|
+
|
|
47
|
+
if(NOT ARG_OUTPUT_NAME)
|
|
48
|
+
if(target_count EQUAL 1)
|
|
49
|
+
set(ARG_OUTPUT_NAME "${ARG_NAME}")
|
|
50
|
+
else()
|
|
51
|
+
set(ARG_OUTPUT_NAME ${ARG_TARGET_NAME})
|
|
52
|
+
endif()
|
|
53
|
+
endif()
|
|
54
|
+
list(LENGTH ARG_OUTPUT_NAME output_count)
|
|
55
|
+
|
|
56
|
+
if(NOT output_count EQUAL target_count)
|
|
57
|
+
message(FATAL_ERROR
|
|
58
|
+
"pk_create_app (func): '${ARG_NAME}' has ${target_count} "
|
|
59
|
+
"'TARGET_NAME' values but ${output_count} 'OUTPUT_NAME' values, one "
|
|
60
|
+
"'OUTPUT_NAME' is required per target.")
|
|
61
|
+
endif()
|
|
62
|
+
|
|
63
|
+
set(unique_targets ${ARG_TARGET_NAME})
|
|
64
|
+
set(unique_outputs ${ARG_OUTPUT_NAME})
|
|
65
|
+
list(REMOVE_DUPLICATES unique_targets)
|
|
66
|
+
list(REMOVE_DUPLICATES unique_outputs)
|
|
67
|
+
list(LENGTH unique_targets unique_target_count)
|
|
68
|
+
list(LENGTH unique_outputs unique_output_count)
|
|
69
|
+
|
|
70
|
+
if(NOT unique_target_count EQUAL target_count)
|
|
71
|
+
message(FATAL_ERROR
|
|
72
|
+
"pk_create_app (func): '${ARG_NAME}' has duplicate 'TARGET_NAME' "
|
|
73
|
+
"values: ${ARG_TARGET_NAME}")
|
|
74
|
+
endif()
|
|
75
|
+
if(NOT unique_output_count EQUAL output_count)
|
|
76
|
+
message(FATAL_ERROR
|
|
77
|
+
"pk_create_app (func): '${ARG_NAME}' has duplicate 'OUTPUT_NAME' "
|
|
78
|
+
"values: ${ARG_OUTPUT_NAME}")
|
|
79
|
+
endif()
|
|
80
|
+
|
|
81
|
+
pk_resolve_files(ARG_SOURCES "'${ARG_NAME}' SOURCES"
|
|
82
|
+
"\\.(c|cc|cpp|cxx)$" ${ARG_SOURCES})
|
|
83
|
+
pk_resolve_files(ARG_PUBLIC_HEADERS "'${ARG_NAME}' PUBLIC_HEADERS"
|
|
84
|
+
"\\.(h|hh|hpp|hxx)$" ${ARG_PUBLIC_HEADERS})
|
|
85
|
+
pk_resolve_files(ARG_PRIVATE_HEADERS "'${ARG_NAME}' PRIVATE_HEADERS"
|
|
86
|
+
"\\.(h|hh|hpp|hxx)$" ${ARG_PRIVATE_HEADERS})
|
|
87
|
+
|
|
88
|
+
foreach(header IN LISTS ARG_PUBLIC_HEADERS)
|
|
89
|
+
if(header IN_LIST ARG_PRIVATE_HEADERS)
|
|
90
|
+
message(FATAL_ERROR
|
|
91
|
+
"pk_create_app (func): '${ARG_NAME}' header passed as both "
|
|
92
|
+
"'PUBLIC_HEADERS' and 'PRIVATE_HEADERS': '${header}'.")
|
|
93
|
+
endif()
|
|
94
|
+
endforeach()
|
|
95
|
+
|
|
96
|
+
set(source_dir_given FALSE)
|
|
97
|
+
set(include_dir_given FALSE)
|
|
98
|
+
|
|
99
|
+
if(ARG_SOURCE_DIR)
|
|
100
|
+
cmake_path(ABSOLUTE_PATH ARG_SOURCE_DIR
|
|
101
|
+
BASE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" NORMALIZE)
|
|
102
|
+
string(REGEX REPLACE "(.)/+$" "\\1" ARG_SOURCE_DIR "${ARG_SOURCE_DIR}")
|
|
103
|
+
if(NOT IS_DIRECTORY "${ARG_SOURCE_DIR}")
|
|
104
|
+
message(FATAL_ERROR
|
|
105
|
+
"pk_create_app (func): 'SOURCE_DIR' for '${ARG_NAME}' is not a "
|
|
106
|
+
"directory: '${ARG_SOURCE_DIR}'.")
|
|
107
|
+
endif()
|
|
108
|
+
set(source_dir_given TRUE)
|
|
109
|
+
elseif(ARG_DEFAULT_DIRS)
|
|
110
|
+
set(ARG_SOURCE_DIR "${PROJECT_SOURCE_DIR}/apps/${ARG_NAME}")
|
|
111
|
+
else()
|
|
112
|
+
set(ARG_SOURCE_DIR "")
|
|
113
|
+
endif()
|
|
114
|
+
|
|
115
|
+
if(ARG_INCLUDE_DIR)
|
|
116
|
+
cmake_path(ABSOLUTE_PATH ARG_INCLUDE_DIR
|
|
117
|
+
BASE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" NORMALIZE)
|
|
118
|
+
string(REGEX REPLACE "(.)/+$" "\\1" ARG_INCLUDE_DIR "${ARG_INCLUDE_DIR}")
|
|
119
|
+
if(NOT IS_DIRECTORY "${ARG_INCLUDE_DIR}")
|
|
120
|
+
message(FATAL_ERROR
|
|
121
|
+
"pk_create_app (func): 'INCLUDE_DIR' for '${ARG_NAME}' is not a "
|
|
122
|
+
"directory: '${ARG_INCLUDE_DIR}'.")
|
|
123
|
+
endif()
|
|
124
|
+
set(include_dir_given TRUE)
|
|
125
|
+
else()
|
|
126
|
+
set(ARG_INCLUDE_DIR "")
|
|
127
|
+
endif()
|
|
128
|
+
|
|
129
|
+
if(ARG_SOURCE_DIR)
|
|
130
|
+
set(source_where "'${ARG_SOURCE_DIR}'")
|
|
131
|
+
else()
|
|
132
|
+
set(source_where "no 'SOURCE_DIR'")
|
|
133
|
+
endif()
|
|
134
|
+
if(ARG_INCLUDE_DIR)
|
|
135
|
+
set(include_where "'${ARG_INCLUDE_DIR}'")
|
|
136
|
+
else()
|
|
137
|
+
set(include_where "no 'INCLUDE_DIR'")
|
|
138
|
+
endif()
|
|
139
|
+
|
|
140
|
+
pk_collect_components(${ARG_NAME}
|
|
141
|
+
SOURCE_DIR "${ARG_SOURCE_DIR}"
|
|
142
|
+
INCLUDE_DIR "${ARG_INCLUDE_DIR}"
|
|
143
|
+
OUT_SOURCES globbed_sources
|
|
144
|
+
OUT_PUBLIC_HEADERS globbed_public_headers
|
|
145
|
+
OUT_PRIVATE_HEADERS globbed_private_headers)
|
|
146
|
+
|
|
147
|
+
if(source_dir_given AND NOT globbed_sources AND NOT globbed_private_headers)
|
|
148
|
+
message(FATAL_ERROR
|
|
149
|
+
"pk_create_app (func): 'SOURCE_DIR' for '${ARG_NAME}' contains no "
|
|
150
|
+
"sources or headers: '${ARG_SOURCE_DIR}'.")
|
|
151
|
+
endif()
|
|
152
|
+
if(include_dir_given AND NOT globbed_public_headers)
|
|
153
|
+
message(FATAL_ERROR
|
|
154
|
+
"pk_create_app (func): 'INCLUDE_DIR' for '${ARG_NAME}' contains no "
|
|
155
|
+
"headers: '${ARG_INCLUDE_DIR}'.")
|
|
156
|
+
endif()
|
|
157
|
+
|
|
158
|
+
set(explicit_files ${ARG_SOURCES} ${ARG_PUBLIC_HEADERS} ${ARG_PRIVATE_HEADERS})
|
|
159
|
+
if(explicit_files)
|
|
160
|
+
foreach(globbed IN ITEMS
|
|
161
|
+
globbed_sources globbed_public_headers globbed_private_headers)
|
|
162
|
+
if(${globbed})
|
|
163
|
+
list(REMOVE_ITEM ${globbed} ${explicit_files})
|
|
164
|
+
endif()
|
|
165
|
+
endforeach()
|
|
166
|
+
endif()
|
|
167
|
+
|
|
168
|
+
list(APPEND ARG_SOURCES ${globbed_sources})
|
|
169
|
+
list(APPEND ARG_PUBLIC_HEADERS ${globbed_public_headers})
|
|
170
|
+
list(APPEND ARG_PRIVATE_HEADERS ${globbed_private_headers})
|
|
171
|
+
|
|
172
|
+
if(NOT ARG_SOURCES)
|
|
173
|
+
message(FATAL_ERROR
|
|
174
|
+
"pk_create_app (func): No sources found for '${ARG_NAME}' in "
|
|
175
|
+
"${source_where} and none were given via 'SOURCES'.")
|
|
176
|
+
endif()
|
|
177
|
+
if(ARG_REQUIRE_PUBLIC_HEADERS AND NOT ARG_PUBLIC_HEADERS)
|
|
178
|
+
message(FATAL_ERROR
|
|
179
|
+
"pk_create_app (func): Public headers are required for "
|
|
180
|
+
"'${ARG_NAME}', yet none were found in ${include_where} and none were "
|
|
181
|
+
"given via 'PUBLIC_HEADERS'.")
|
|
182
|
+
endif()
|
|
183
|
+
if(ARG_REQUIRE_PRIVATE_HEADERS AND NOT ARG_PRIVATE_HEADERS)
|
|
184
|
+
message(FATAL_ERROR
|
|
185
|
+
"pk_create_app (func): Private headers are required for "
|
|
186
|
+
"'${ARG_NAME}', yet none were found in ${source_where} and none were "
|
|
187
|
+
"given via 'PRIVATE_HEADERS'.")
|
|
188
|
+
endif()
|
|
189
|
+
|
|
190
|
+
pk_resolve_language(language source_languages "application '${ARG_NAME}'"
|
|
191
|
+
"${ARG_LANGUAGE}" ${ARG_SOURCES})
|
|
192
|
+
|
|
193
|
+
set(app_languages ${language} ${source_languages})
|
|
194
|
+
list(REMOVE_DUPLICATES app_languages)
|
|
195
|
+
|
|
196
|
+
set(std_C "c_std_${${prefix}_C_STANDARD}")
|
|
197
|
+
set(std_CXX "cxx_std_${${prefix}_CXX_STANDARD}")
|
|
198
|
+
|
|
199
|
+
foreach(target output IN ZIP_LISTS ARG_TARGET_NAME ARG_OUTPUT_NAME)
|
|
200
|
+
add_executable(${target} ${ARG_SOURCES})
|
|
201
|
+
|
|
202
|
+
set_target_properties(${target} PROPERTIES
|
|
203
|
+
OUTPUT_NAME "${output}")
|
|
204
|
+
|
|
205
|
+
if(ARG_PUBLIC_HEADERS)
|
|
206
|
+
target_sources(${target}
|
|
207
|
+
PRIVATE
|
|
208
|
+
FILE_SET ${ARG_NAME}_app_public_headers
|
|
209
|
+
TYPE HEADERS
|
|
210
|
+
BASE_DIRS "${PROJECT_SOURCE_DIR}/include"
|
|
211
|
+
FILES ${ARG_PUBLIC_HEADERS})
|
|
212
|
+
endif()
|
|
213
|
+
|
|
214
|
+
if(ARG_PRIVATE_HEADERS)
|
|
215
|
+
target_sources(${target}
|
|
216
|
+
PRIVATE
|
|
217
|
+
FILE_SET ${ARG_NAME}_app_private_headers
|
|
218
|
+
TYPE HEADERS
|
|
219
|
+
BASE_DIRS "${PROJECT_SOURCE_DIR}/apps"
|
|
220
|
+
FILES ${ARG_PRIVATE_HEADERS})
|
|
221
|
+
endif()
|
|
222
|
+
|
|
223
|
+
foreach(app_language IN LISTS app_languages)
|
|
224
|
+
target_compile_features(${target} PRIVATE ${std_${app_language}})
|
|
225
|
+
endforeach()
|
|
226
|
+
|
|
227
|
+
target_compile_definitions(${target} PRIVATE
|
|
228
|
+
${prefix}_VERSION_STRING="${PROJECT_VERSION}")
|
|
229
|
+
endforeach()
|
|
230
|
+
|
|
231
|
+
if(ARG_NO_DEFAULT_LINKS)
|
|
232
|
+
set(default_links NO_DEFAULT_LINKS)
|
|
233
|
+
else()
|
|
234
|
+
set(default_links "")
|
|
235
|
+
endif()
|
|
236
|
+
|
|
237
|
+
pk_link_targets(
|
|
238
|
+
${default_links}
|
|
239
|
+
TARGETS ${ARG_TARGET_NAME}
|
|
240
|
+
LINK_PRIVATE ${ARG_LINK_PRIVATE}
|
|
241
|
+
LINK_INTERFACE ${ARG_LINK_INTERFACE})
|
|
242
|
+
|
|
243
|
+
pk_deps_link(
|
|
244
|
+
ROLE APPLICATION
|
|
245
|
+
TARGETS ${ARG_TARGET_NAME}
|
|
246
|
+
PRIVATE ${ARG_DEPS})
|
|
247
|
+
|
|
248
|
+
foreach(target IN LISTS ARG_TARGET_NAME)
|
|
249
|
+
pk_enable_static_analysis(${target})
|
|
250
|
+
endforeach()
|
|
251
|
+
|
|
252
|
+
if(${prefix}_INSTALL AND NOT ARG_NO_INSTALL)
|
|
253
|
+
install(TARGETS ${ARG_TARGET_NAME}
|
|
254
|
+
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
|
|
255
|
+
endif()
|
|
256
|
+
|
|
257
|
+
pk_register_targets(APPLICATION TARGETS ${ARG_TARGET_NAME})
|
|
258
|
+
|
|
259
|
+
string(JOIN "', '" target_list ${ARG_TARGET_NAME})
|
|
260
|
+
message(STATUS "${PROJECT_NAME}: Application built for '${ARG_NAME}' "
|
|
261
|
+
"with executable target(s) named '${target_list}'.")
|
|
262
|
+
endfunction()
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
include_guard(GLOBAL)
|
|
2
|
+
|
|
3
|
+
function(pk_add_warnings_target)
|
|
4
|
+
pk_project_prefix(prefix)
|
|
5
|
+
set(target "${PROJECT_NAME}_warnings")
|
|
6
|
+
|
|
7
|
+
add_library(${target} INTERFACE)
|
|
8
|
+
add_library(${PROJECT_NAME}::warnings ALIAS ${target})
|
|
9
|
+
set_target_properties(${target} PROPERTIES EXPORT_NAME warnings)
|
|
10
|
+
|
|
11
|
+
set(gnu_ids "GNU,Clang,AppleClang,IntelLLVM")
|
|
12
|
+
|
|
13
|
+
set(gnu_common
|
|
14
|
+
-Wall
|
|
15
|
+
-Wextra
|
|
16
|
+
-Wpedantic
|
|
17
|
+
-Wshadow
|
|
18
|
+
-Wcast-align
|
|
19
|
+
-Wsign-conversion
|
|
20
|
+
-Wnull-dereference
|
|
21
|
+
-Wdouble-promotion
|
|
22
|
+
-Wformat=2
|
|
23
|
+
-Wimplicit-fallthrough)
|
|
24
|
+
|
|
25
|
+
set(gnu_c ${gnu_common}
|
|
26
|
+
-Wstrict-prototypes
|
|
27
|
+
-Wmissing-prototypes)
|
|
28
|
+
|
|
29
|
+
set(gnu_cxx ${gnu_common}
|
|
30
|
+
-Wnon-virtual-dtor
|
|
31
|
+
-Wold-style-cast)
|
|
32
|
+
|
|
33
|
+
set(msvc_c
|
|
34
|
+
/W4
|
|
35
|
+
/w14826)
|
|
36
|
+
|
|
37
|
+
set(msvc_cxx ${msvc_c}
|
|
38
|
+
/permissive-
|
|
39
|
+
/w14640)
|
|
40
|
+
|
|
41
|
+
target_compile_options(${target} INTERFACE
|
|
42
|
+
"$<$<COMPILE_LANG_AND_ID:C,${gnu_ids}>:${gnu_c}>"
|
|
43
|
+
"$<$<COMPILE_LANG_AND_ID:CXX,${gnu_ids}>:${gnu_cxx}>"
|
|
44
|
+
"$<$<COMPILE_LANG_AND_ID:C,MSVC>:${msvc_c}>"
|
|
45
|
+
"$<$<COMPILE_LANG_AND_ID:CXX,MSVC>:${msvc_cxx}>")
|
|
46
|
+
|
|
47
|
+
if(${prefix}_WERROR)
|
|
48
|
+
target_compile_options(${target} INTERFACE
|
|
49
|
+
"$<$<COMPILE_LANG_AND_ID:C,${gnu_ids}>:-Werror>"
|
|
50
|
+
"$<$<COMPILE_LANG_AND_ID:CXX,${gnu_ids}>:-Werror>"
|
|
51
|
+
"$<$<COMPILE_LANG_AND_ID:C,MSVC>:/WX>"
|
|
52
|
+
"$<$<COMPILE_LANG_AND_ID:CXX,MSVC>:/WX>")
|
|
53
|
+
endif()
|
|
54
|
+
endfunction()
|